I've been going through 'Building Cryptocurrency and its ICO' by DappUniversity. I know many have questioned this issue and I've been through all the post but couldn't resolve it. The problem is self-destruct. Self-destruct needs and argument (address to which the remaining ether(tokens) are transferred. So in this the remaining tokens are to be returned to admin

Here's the sol code..

pragma solidity ^0.5.8;
import "./DappToken.sol";

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

    event Sell(address _buyer, uint256 _amount);

    constructor(DappToken _tokenContract, uint256 _tokenPrice)public{
        // assign an admin
        // only admin can end the token sale
        admin = msg.sender;

        // token contract
        tokenContract = _tokenContract;

        // token Price
        tokenPrice = _tokenPrice;

    //library used DSMath
    // internal - visiblity confined to contract
    // pure -- takes same return type and returns same type
    function multiply(uint x, uint y) internal pure returns(uint z) {
        require( y == 0|| (z = x* y ) / y == x);

    // Buying tokens
    function buyTokens(uint256 _numberOfTokens) public payable{
        // require that value is equal to tokens
        // msg.value amount of wei the function is sending in metadata....
        require(msg.value == multiply(_numberOfTokens, tokenPrice));

        //require that the contract has enough tokens.
        require(tokenContract.balanceOf(address(this)) >= _numberOfTokens);

        // require trasnfer is successful 
        require(tokenContract.transfer(msg.sender, _numberOfTokens));  
        //actual buy functionlaity
        // keep track of no. of tokens sold..
        tokensSold += _numberOfTokens;

        // emit a sell event
        emit Sell(msg.sender, _numberOfTokens);

    //Ending DappSale
    function endSale() public {
        // only admin can do this
        require(msg.sender == admin);
        // transfer the amount of tokens in sale back to admin
        require(tokenContract.transfer(admin, tokenContract.balanceOf(address(this))));
        // Destroy contract
            //self-destruct in solidity
            //returns ether left in contract to the adddress in the argument
            //on deletion static variables is reinitailized to zero


The error encountered on testing is

1) Contract: DappTokenSale
       Ends Token Sale:
     Error: Returned values aren't valid, did it run Out of Gas?
      at ABICoder.decodeParameters (/home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/web3-eth-abi/src/index.js:226:1)
      at Contract._decodeMethodReturn (/home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/web3-eth-contract/src/index.js:465:1)
      at Method.outputFormatter (/home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/web3-eth-contract/src/index.js:818:1)
      at Method.formatOutput (/home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/web3-eth-contract/~/web3-core-method/src/index.js:163:1)
      at sendTxCallback (/home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/web3-eth-contract/~/web3-core-method/src/index.js:473:1)
      at /home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/web3-eth-contract/~/web3-core-requestmanager/src/index.js:147:1
      at /home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/packages/truffle-provider/wrapper.js:112:1
      at XMLHttpRequest.request.onreadystatechange (/home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/web3/~/web3-providers-http/src/index.js:96:1)
      at XMLHttpRequestEventTarget.dispatchEvent (/home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/xhr2-cookies/dist/xml-http-request-event-target.js:34:1)
      at XMLHttpRequest._setReadyState (/home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/xhr2-cookies/dist/xml-http-request.js:208:1)
      at XMLHttpRequest._onHttpResponseEnd (/home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/xhr2-cookies/dist/xml-http-request.js:318:1)
      at IncomingMessage.<anonymous> (/home/leo/.nvm/versions/node/v8.16.0/lib/node_modules/truffle/build/webpack:/~/xhr2-cookies/dist/xml-http-request.js:289:47)
      at endReadableNT (_stream_readable.js:1064:12)
      at _combinedTickCallback (internal/process/next_tick.js:139:11)
      at process._tickCallback (internal/process/next_tick.js:181:9)

Also, passing [admin] to self-destruct raised a compilation error..So, i've passed [msg.sender] as it'd be same since it executes only after passing [require] statement..

If anyone has a workaround kindly help, Is this a bug? How come a function runs out of gas??

Dependencies used are below:

ganache-cli 6.4.3 [email protected] npm 6.9.0 [email protected](extraneous)

  • My guess is that Truffle doesn't know how to handle selfdestructs. Typically when ICOs end they are simply closed and not selfdestructed, although I can see why selfdestruct might be preferable. Commented Jun 14, 2019 at 12:16
  • 1
    Passing admin to selfdestruct raised a compilation error because admin must be payable.
    – alberto
    Commented Jun 14, 2019 at 12:21

1 Answer 1


selfdestruct get a payable address

selfdestruct(address payable recipient) 

you should change the parameter in that method to payable

here is a way to do this

Casting from address to address payable address can only be explicitly cast to address payable. Casting any integer type like uint160 to address produces an address payable.

address payable secondAddress = address(uint160(admin));

see this question What's the difference between 'address' and 'address payable'?

change last line to :

address payable adminAddress = address(uint160(admin));
  • I tried casting the address to address payable but it didn't work..I got the exact same error Commented Jun 14, 2019 at 14:14
  • weird, i see that the guy from Dapp university removed selfdestruct from his code
    – Majd TL
    Commented Jun 15, 2019 at 7:12
  • try it on rinkeby, maybe it is a bug in ganache or truffle test
    – Majd TL
    Commented Jun 15, 2019 at 7:36
  • You mean Rinkey Public Network? It'd take hours to download the chiandata...I'm currently not equipped with an unlimitred wifi.. Is there any way to test it on rinkeby local development network(idk if it's there one) or any other local development environment beside Truffle& Ganache??? Commented Jun 16, 2019 at 3:38
  • you dont need to download anything, you can use infura to connect and truffle-hdwallet-provider to manage accounts and signing. infura.io/login , github.com/trufflesuite/truffle-hdwallet-provider
    – Majd TL
    Commented Jun 16, 2019 at 9:26

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.