Solidity

ERC20Token - 眾籌,沒有足夠的代幣進行轉賬

  • March 29, 2022

我正在嘗試創建一個 ICO 契約(Crowdsale),這將促進 ERC20Token 的銷售。在遷移契約時,我遇到了一個錯誤

“SAMTokenSale”命中了 require 或 revert 語句,原因如下:

  • 沒有足夠的代幣進行轉移

在 TokenSale 合約的建構子中,我正在初始化一些東西,並將一些預定義數量的代幣轉移到智能合約中。這就是失敗的地方。但是契約的管理員擁有初始總供應量。所以這不應該失敗,種類卡在這個問題上。這是程式碼

  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. 代幣銷售合約
//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');
       _;
   }

}

由於管理員擁有所需數量的令牌,因此有點迷失了為什麼在轉移功能上出現此錯誤。任何幫助都感激不盡。

謝謝,山姆

問題在於transfer()您建議的功能。特別是,當您部署 SAMTokenSale 並呼叫它時tokenContract.transfer(address(this), tokensForSale);,它會呼叫 SAMToken 中的transfer()函式,但msg.sender它是 SAMTokenSale 的地址(不是 SAMToken 的地址!)。然後當它檢查這個條件時require(balances[msg.sender] >= amount, 'not enough tokens for transfer');給出錯誤,因為它正在控制 SAMTokenSale 的餘額!要解決此錯誤,請嘗試從您的 metamask 錢包向 SAMTokenSale 發送一定數量的 SAMToken 或更改transfer()函式中的邏輯(我不推薦您的方法)

引用自:https://ethereum.stackexchange.com/questions/124959