I use the openzeppelin library: https://github.com/OpenZeppelin/openzeppelin-solidity/tree/v1.12.0


I create a BurnableToken:

pragma solidity 0.4.24;

import 'openzeppelin-solidity/contracts/token/ERC20/StandardBurnableToken.sol';

contract TestBurnableToken is StandardBurnableToken {
    string public name = "TestCoinBurnable";
    string public symbol = "tcb";
    uint8 public decimals = 18;

    uint256 public totalSupply;
    mapping (address => uint256) public balanceOf;

    constructor (
        uint256 initialSupply
    ) public {
        totalSupply = initialSupply * 10 ** uint256(decimals);  // Update total supply with the decimal amount
        balanceOf[msg.sender] = totalSupply;                // Give the creator all initial tokens

the creator receives all the tokens.


pragma solidity 0.4.24;

import './TestBurnableToken.sol';
import 'openzeppelin-solidity/contracts/crowdsale/emission/AllowanceCrowdsale.sol';
import 'openzeppelin-solidity/contracts/crowdsale/validation/TimedCrowdsale.sol';

contract TestBurnableCrowdsale is TimedCrowdsale, AllowanceCrowdsale {
            uint256 _openingTime,
            uint256 _closingTime,
            uint256 _rate,
            address _wallet,
            StandardBurnableToken _token
        Crowdsale(_rate, _wallet, _token)
        TimedCrowdsale(_openingTime, _closingTime)
        AllowanceCrowdsale(_wallet) {


const TestBurnableToken = artifacts.require("./TestBurnableToken.sol");
const TestBurnableCrowdsale = artifacts.require("./TestBurnableCrowdsale.sol");

module.exports = function(deployer, network, accounts) {

const openingTime = web3.eth.getBlock('latest').timestamp + 30; // two secs in the future
const closingTime = openingTime + 60 *15 // 15min
const rate = new web3.BigNumber(1000); // only ints > 0, rate seems not to be inverse
const wallet = accounts[0];

console.log("Deploying openingTime: ", openingTime, " closingTime ", closingTime, " rate ", rate, " wallet ", wallet);

return deployer
    .then(() => {
        return deployer.deploy(TestBurnableToken, 10000);
    .then(() => {
        return deployer.deploy(

truffle console

// The account that created the tokens
creator = web3.eth.accounts[0]

// The account that will buy Test tokens.
purchaser = web3.eth.accounts[2]

// The address of the Test token instance that was created when the crowdsaleInstance contract was deployed
// assign the result of TestBurnableCrowdsale.deployed() to the variable crowdsaleInstance
TestBurnableCrowdsale.deployed().then(inst => { crowdsaleInstance = inst })

crowdsaleInstance.token().then(addr => { tokenAddress = addr } )

TestBurnableTokenInstance = TestBurnableToken.at(tokenAddress)

//balances before
TestBurnableTokenInstance.balanceOf(creator).then(balance => web3.fromWei(balance.toString(10)))
//this shows 10000 because 10000 tokens have been created by account[0]

TestBurnableTokenInstance.balanceOf(purchaser).then(balance => web3.fromWei(balance.toString(10)))
//this shows 0, no tokens have been bought yet

//account 0 now approves tokens to be sold
TestBurnableTokenInstance.approve(crowdsaleInstance.address,web3.toWei(1000, "ether"))
crowdsaleInstance.remainingTokens().then(balance => web3.fromWei(balance.toString(10)))
//shows that 1000 tokens of 10000 have been approved for selling

//buy and balances after buying
crowdsaleInstance.sendTransaction({ from: purchaser, value: web3.toWei(1, "ether")})
// Here I get an error: Error: VM Exception while processing transaction: revert // I also tried 0.1 and 10000 to make sure it has nothing to do with the rate

Question: Why is the last console call failing, the tokens have been approved by account[0] to be accessed by the crowdsale contract.


I used truffles debug function with a weird result:

31:     returns (bool)
32:   {
33:     require(_value <= balances[_from]);

debug(develop:0xefe253c5...)> v

   _from: '0x627306090abab3a6e1400e9345bc60c78a8bef57'
     _to: '0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef'
  _value: 1000000000000000000
        : true



35:     require(_to != address(0));
37:     balances[_from] = balances[_from].sub(_value);

debug(develop:0xefe253c5...)> v

   _from: '0x0de0b6b3a7640000'
     _to: '0x0de0b6b3a7640000'
  _value: 816
        : true

Basically the values of _from, to, _value change between the lines 33 and 37.

require(_value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]);
require(_to != address(0));

balances[_from] = balances[_from].sub(_value);

2 Answers 2


I believe you are confusing how the approve function works. The approve is basically only used in combination with the transferFrom function to approve transfer of tokens - not the purchase.

You can either play around with Truffle's debug functionality or just simply comment out require statements until you find the culprit.

I don't have experience with the AllowanceCrowdsale (https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v1.12.0/contracts/crowdsale/emission/AllowanceCrowdsale.sol) but my guess is that a require fails somewhere around there (probaby around _deliverTokens ).

  • The number of remainingTokens in the crowdsale contract is the same amount as the number I specified in the approve call, so I think it enables the crowdsale contract to transferFrom the approving wallet, which would make sense. I will look into debug function.
    – Andi Giga
    Aug 31, 2018 at 14:30
  • I debugged the contract but now I'm even more confused. Everything looks fine so far but in the end values seem to change. I think solidity is synchronous so there should be no problem with race conditions etc.
    – Andi Giga
    Sep 5, 2018 at 13:59

It was required to change balanceOf to balances otherwise the fn is overwritten.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.