11

I create a smart contract to sell my token.I am following the Dapp University(youtube channel) course.

I have done unit testing of smart contract.All test cases pass.

And I am trying to buy token on my client side application.So there is transaction failed.And this error comes VM Exception while processing transaction: revert:

Then I test buyTokens() function in truffle console.So,The same error comes.

Here is my solidity code:-

pragma solidity ^0.4.2;

import "./DappToken.sol";

    contract DappTokenSale {
        address admin;
        DappToken public tokenContract;
        uint256 public tokenPrice;
        uint256 public tokensSold;

        event Sell(address _buyer, uint256 _amount);

        function DappTokenSale(DappToken _tokenContract, uint256 _tokenPrice) public {
            admin = msg.sender;
            tokenContract = _tokenContract;
            tokenPrice = _tokenPrice;
        }

        function multiply(uint x, uint y) internal pure returns (uint z) {
            require(y == 0 || (z = x * y) / y == x);
        }

        function buyTokens(uint256 _numberOfTokens) public payable {
            require(msg.value == multiply(_numberOfTokens, tokenPrice));
            require(tokenContract.balanceOf(this) >= _numberOfTokens);
            require(tokenContract.transfer(msg.sender, _numberOfTokens));

            tokensSold += _numberOfTokens;

            Sell(msg.sender, _numberOfTokens);
        }

      // Ending Token DappTokenSale
        function endSale() public {
                // Require admin
                require (msg.sender == admin);

                 // Transfer remaing DappToken to admin
                require(tokenContract.transfer(admin,tokenContract.balanceOf(this)));


                // Destroy Contract
                selfdestruct(admin);

        }
 }

Here is my "DappToken" solidity code:-

pragma solidity ^0.4.2;

/**
 * The contractName contract does this and that...
 */
contract DappToken {
    // Name
    string public name = "DappToken";
    // Symbol
    string public symbol = 'DAPP';
    //standard
    string public standard = 'DApp Token v1.0';
    uint256 public totalSupply;

    event Transfer(
        address indexed _form,
        address indexed _to,
        uint256 _value
        );

    event Approval(
            address indexed _owner,
            address indexed _spender,
            uint256 _value
        );


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


    function DappToken (uint256 _intialSupply) public {
        balanceOf[msg.sender] = _intialSupply;
        totalSupply = _intialSupply;
        //allcate the intial supply

    }   

    //Transfar
    function transfer(address _to,uint256 _value) public returns (bool success){
    // Exception if account does not enough
    require (balanceOf[msg.sender] >= _value);
    // Transfar the balance
    balanceOf[msg.sender] -= _value;
    balanceOf[_to] += _value; 

    // Transfar Event
    Transfer(msg.sender,_to,_value);

    // Return a boolean
    return true;
    } 

    // approve
    function approve(address _spender,uint256 _value) public returns (bool success){
        //allowence
        allowance[msg.sender][_spender] = _value;

        // Approve event
        Approval(msg.sender,_spender,_value);


             return true;

    }
    // transfer form
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        require(_value <= balanceOf[_from]);
        require(_value <= allowance[_from][msg.sender]);
        // change the balance
        balanceOf[_from] -= _value;

        //update the balance
       balanceOf[_to] += _value; 

       allowance[_from][msg.sender] -= _value;

       emit Transfer(_from,_to,_value);


        return true;
    }
}

Here is my "test.js" code:-

var DappToken = artifacts.require('./DappToken.sol');
var DappTokenSale = artifacts.require('./DappTokenSale.sol');

contract('DappTokenSale', function(accounts) {
  var tokenInstance;
  var tokenSaleInstance;
  var admin = accounts[0];
  var buyer = accounts[1];
  var tokenPrice = 1000000000000000; // in wei
  var tokensAvailable = 750000;
  var numberOfTokens;

  it('initializes the contract with the correct values', function() {
    return DappTokenSale.deployed().then(function(instance) {
      tokenSaleInstance = instance;
      return tokenSaleInstance.address
    }).then(function(address) {
      assert.notEqual(address, 0x0, 'has contract address');
      return tokenSaleInstance.tokenContract();
    }).then(function(address) {
      assert.notEqual(address, 0x0, 'has token contract address');
      return tokenSaleInstance.tokenPrice();
    }).then(function(price) {
      assert.equal(price, tokenPrice, 'token price is correct');
    });
  });

  it('facilitates token buying', function() {
    return DappToken.deployed().then(function(instance) {
      // Grab token instance first
      tokenInstance = instance;
      return DappTokenSale.deployed();
    }).then(function(instance) {
      // Then grab token sale instance
      tokenSaleInstance = instance;
      // Provision 75% of all tokens to the token sale
      return tokenInstance.transfer(tokenSaleInstance.address, tokensAvailable, { from: admin })
    }).then(function(receipt) {
      numberOfTokens = 10;
      return tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: numberOfTokens * tokenPrice })
    }).then(function(receipt) {
      assert.equal(receipt.logs.length, 1, 'triggers one event');
      assert.equal(receipt.logs[0].event, 'Sell', 'should be the "Sell" event');
      assert.equal(receipt.logs[0].args._buyer, buyer, 'logs the account that purchased the tokens');
      assert.equal(receipt.logs[0].args._amount, numberOfTokens, 'logs the number of tokens purchased');
      return tokenSaleInstance.tokensSold();
    }).then(function(amount) {
      assert.equal(amount.toNumber(), numberOfTokens, 'increments the number of tokens sold');
      return tokenInstance.balanceOf(buyer);
    }).then(function(balance) {
      assert.equal(balance.toNumber(), numberOfTokens);
      return tokenInstance.balanceOf(tokenSaleInstance.address);
    }).then(function(balance) {
      assert.equal(balance.toNumber(), tokensAvailable - numberOfTokens);
      // Try to buy tokens different from the ether value
      return tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: 1 });
    }).then(assert.fail).catch(function(error) {
      assert(error.message.indexOf('revert') >= 0, 'msg.value must equal number of tokens in wei');
      return tokenSaleInstance.buyTokens(800000, { from: buyer, value: numberOfTokens * tokenPrice })
    }).then(assert.fail).catch(function(error) {
      assert(error.message.indexOf('revert') >= 0, 'cannot purchase more tokens than available');
    });
  });

  it('ends token sale', function() {
    return DappToken.deployed().then(function(instance) {
      // Grab token instance first
      tokenInstance = instance;
      return DappTokenSale.deployed();
    }).then(function(instance) {
      // Then grab token sale instance
      tokenSaleInstance = instance;
      // Try to end sale from account other than the admin
      return tokenSaleInstance.endSale({ from: buyer });
    }).then(assert.fail).catch(function(error) {
      assert(error.message.indexOf('revert' >= 0, 'must be admin to end sale'));
      // End sale as admin
      return tokenSaleInstance.endSale({ from: admin });
    }).then(function(receipt) {
      return tokenInstance.balanceOf(admin);
    }).then(function(balance) {
      assert.equal(balance.toNumber(), 999990, 'returns all unsold dapp tokens to admin');
      // Check that token price was reset when selfDestruct was called
    //   return tokenSaleInstance.tokenPrice();
    // }).then(function(price) {
    //   assert.equal(price.toNumber(), 0, 'token price was reset');
    });
  });

});

I am new in this field.What is this error mean and why this error comes??Any one tell me What I mistake in code??.

7
  • Are you sending enough ether with your transaction call, so that the requirement is met? (require(msg.value == multiply(_numberOfTokens, tokenPrice));)
    – Fischa7
    Apr 30, 2018 at 11:34
  • Hi Fischa,Yes,I am taking numberOfTokens = 10, and tokenPrice = 1000000000000000.//in wei Apr 30, 2018 at 11:49
  • Just to make clear: you are passing a function parameter of 10. And you are sending 10*1000000000000000 wei as the value of your function call from the console?
    – Fischa7
    Apr 30, 2018 at 12:38
  • Yes,I am doing the same.I am sure about it Apr 30, 2018 at 13:01
  • 1
    Start commenting out all require() in buyTokens() and try again. Does it fail? Then start uncommenting, when you determine which line is failing you can inspect it in more detail.
    – Ismael
    Apr 30, 2018 at 18:02

5 Answers 5

2

it could be a token provision issue: dappTokenSale contract address doesn't have any DAPP token being provisioned yet, which results to this following line of code failed in DappTokenSale.sol file

require(tokenContract.balanceOf(this) >= _numberOfTokens);
  1. you can go to truffle console to check if this is the case:
    • type truffle console in the terminal
    • type this in the truffle console, DappToken.deployed().then(function(instance) { return instance.balanceOf(tokenSaleAddress) }) where tokenSaleAddress is displayed when you run truffle migrate --reset
  2. To provision Dapp token, type this in truffle console:DappToken.deployed().then(function(instance) { instance.transfer(tokenSaleAddress, 750000, { from:admin }) }), where admin is the 1st account in Ganche, assuming you are going to provision 750000 out of 1000000 to the tokenSaleAddress
1

Is the pragma version correct? the pure keyword is something for a later version. maybe you meant 0.4.23?

The revert would have occurred if one of those requires failed in buyTokens, probably because you are not passing the same amount in eth to equal satisfy.

require(msg.value == multiply(_numberOfTokens, tokenPrice)); 

are you passing a value in your dapp? as you do in the test js?

hope this helps

Phill

7
  • Yes I am passing value like numberOfTokens = 10, and tokenPrice = 1000000000000000.//in wei in buyToken function Apr 30, 2018 at 12:25
  • Just to confirm: 1. you pass the values 10 and 1000000000000000 to the function and 2. you pass the value in wei(10 * 1000000000000000) as a separate option when calling the send transaction? Apr 30, 2018 at 13:20
  • Yes I pass the values this way. Apr 30, 2018 at 13:32
  • The next thing to consider is how much gas you are using, perhaps pass that option along as well gas: 450000 or more. otherwise put the contact in remix and use the debug tool . Apr 30, 2018 at 14:09
  • I am using gas: 800000 May 1, 2018 at 4:16
1

Changing the this -> admin

require(tokenContract.balanceOf(this) >= _numberOfTokens); // of buyTokens in  DappToken.sol

to

require(tokenContract.balanceOf(admin) >= _numberOfTokens); // of buyTokens in  DappToken.sol

Worked for me

1

I faced exactly the same issue and I am totally a beginner. Even after going through the answers finally I decided to decrease the token count that are being transferred and it worked for me.

This is your total supply of tokens

uint256 public totalSupply = 1000000000000000000000000; // 1 million tokens

And in any other smart contract if you are trying to transfer it, try transferring a little less than the total supply. In my case I

await token.transfer(ethSwap.address, '1000000000000000000000'); // A little less than a million.

And the error is gone. Hopefully I update the answer with better reason. But with my current knowledge this is how I crossed the hurdle.

0

Like @shengwen-yu mentioned, all DappTokens created (1000000 - see migrations/2_deploy_contracts.js) are allocated to the msg.sender, that is account[0], and not to tokenContract. To alocate the amount to the tokensale adjust the deploy file (migrations/2_deploy_contracts.js):

module.exports = function(deployer) {
  deployer.deploy(DappToken, 1000000).then(function() {
    // Token price is 0.001 Ether
    var tokenPrice = 1000000000000000;
    return deployer.deploy(DappTokenSale, DappToken.address, tokenPrice);
    }).then(function() {
      var tokensAvailable = 750000;
      DappToken.deployed().then(function(instance) { instance.transfer(DappTokenSale.address, tokensAvailable, { from: adminAddress }); })
  });
};

You must replace adminAddress by the address of the user deploying the contract (1st account in Ganche, ex.: { from: "0xE96362E717EAF828B7Ee752a12bAa03C967D410c" }).

Your Answer

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

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