0

I am trying to create a ICO contract (Crowdsale) which will fecilitate the sale of ERC20Token. While migrating the contract, I am getting stuck at an error

"SAMTokenSale" hit a require or revert statement with the following reason given:

  • not enough tokens for transfer

In the constructor of TokenSale contract, I am initializing few things and also transferring some pre-defined amount of tokens to the Smart Contract. That's where, it's failing. But the admin of the contract has the initial total supply with it. So that should not fail, kinds stuck in this issue. Here are the code

  1. ERC20Token.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ERC20Interface {
  function totalSupply() external view returns (uint);
  function balanceOf(address account) external view returns (uint);
  function transfer(address recipient, uint amount) external returns (bool);
  function allowance(address owner, address spender) external view returns (uint);
  function approve(address spender, uint amount) external returns (bool);
  function transferFrom(address sender,address recipient,uint amount) external returns (bool);

  event Transfer(address indexed from, address indexed to, uint value);
  event Approval(address indexed owner, address indexed spender, uint value);
}

contract SAMToken is ERC20Interface {

  string public name;
  string public symbol;
  uint8 public decimals;
  uint public totalSupply;
  address public admin;

  mapping(address => uint) public balances;
  mapping(address => mapping(address=>uint)) public allowances;

  constructor(){
    name = 'SAM Token';
    symbol = "SAM";
    decimals = 18;
    totalSupply = 1000000 * 10 ** 18; // 1 million Tokens
    admin = msg.sender;
    balances[msg.sender] = totalSupply;
  }

  function transfer(address recipient, uint amount) external override returns(bool) {
    require(balances[msg.sender] >= amount, 'not enough tokens for transfer');
    balances[msg.sender] -= amount;
    balances[recipient] += amount;
    emit Transfer(msg.sender, recipient, amount);
    return true;
  }

  function transferFrom(address sender, address recipient, uint amount) external override returns(bool) {
    uint allowed = allowances[sender][msg.sender];
    require(allowed >= amount && balances[sender] >=amount, 'allowance too low');
    allowances[sender][msg.sender] -= amount;
    balances[sender] -= amount;
    balances[recipient] += amount;
    emit Transfer(sender, recipient, amount);
    return true;
  }

  function approve(address spender, uint amount) external override returns(bool){
    require(spender != msg.sender);
    allowances[msg.sender][spender] = amount;
    emit Approval(msg.sender, spender, amount);
    return true;
  }

  function burn(uint amount) external returns(bool){
    require(balances[msg.sender] >= amount, 'not enought tokens to burn');
    balances[msg.sender] -= amount;
    totalSupply -= amount;
    emit Transfer(msg.sender, address(0), amount);
    return true;
  }

  function allowance(address owner, address spender) external override view returns(uint){
    return allowances[owner][spender];
  }

  function balanceOf(address account) external override view returns(uint){
    return balances[account];
  }


}

  1. TokenSaleContract
//SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;
import {SAMToken} from './SAMToken.sol';

contract SAMTokenSale { 
    address admin;
    SAMToken public tokenContract;
    uint public tokenPrice;
    uint public tokenSold;
    uint tokensForSale = 100; // 100 tokens for sale

    event Sell(address _address, uint _amount);

    constructor(SAMToken _tokenContract, uint _tokenPrice){
        admin = msg.sender;
        tokenContract = _tokenContract;
        tokenPrice = _tokenPrice;
        tokenContract.transfer(address(this), tokensForSale);  //sending tokens to the smart contract initially
    }

    function buyTokens(uint _tokenAmount) external payable {
        require(msg.value == tokenPrice * _tokenAmount);
        require(_tokenAmount <= tokenContract.balanceOf(address(this)),'not enough tokens left for sale');
        require(tokenContract.transfer(msg.sender, _tokenAmount)); //immediate release, which should not be the case
        
        tokenSold +=_tokenAmount;

        emit Sell(msg.sender, _tokenAmount);
    }

    function endSale() external onlyAdmin() {
        
        // transfer all the un-sold tokens back to admin
        tokenContract.transfer(admin, tokenContract.balanceOf(address(this)));

        //destroy the sale contract and transfer all ether balance to admin
        selfdestruct(payable(admin));
    }

    modifier onlyAdmin(){
        require(msg.sender == admin, 'only admin can do this');
        _;
    }

}

Kind of lost why this error on transfer function as the admin has the required amount of tokens. Any help will be much appreciated.

Thanks, Sam

1 Answer 1

1

The problem is in transfer() function as you suggested. In particular, when you deploy SAMTokenSale and is calling tokenContract.transfer(address(this), tokensForSale); it'll call the transfer() function in SAMToken but msg.sender is the address of SAMTokenSale (not SAMToken's address!). Then when it check this condition require(balances[msg.sender] >= amount, 'not enough tokens for transfer'); give error because it is controlling the balance of SAMTokenSale! To resolve this error, try to send from your metamask wallet to SAMTokenSale an amount of SAMToken or change the logic in transfer() function (method that I don't reccomend you)

0

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.