Solidity

氣體估算失敗:所需氣體超過限額或交易總是失敗

  • April 1, 2022

我有兩份契約,一份用於定義代幣,另一份用於眾籌。我正在使用混音 ide。

pragma solidity >=0.4.22 <0.6.0;

contract owned {
 address public owner;
 constructor () public {
   owner=msg.sender;
 }

 modifier onlyOwner {
   require (msg.sender == owner);
   _;
 }
}

contract EdCoin is owned {
 string public name;
 string public symbol;
 uint8 public decimals = 18;
 uint256 public totalSupply;

 mapping (address => bool) public frozenAccount;
 mapping (address => uint256) public balanceOf;

 event Transfer (address indexed from, address indexed to, uint256 value);
 event FrozenFunds (address target, bool frozen);
 event Burn(address indexed from, uint256 value);

 constructor(
   uint256 initialSupply,
   string memory tokenName,
   string memory tokenSymbol
 ) public {
   totalSupply = initialSupply * 10 ** uint256(decimals);  
   balanceOf[msg.sender] = totalSupply;                
   name = tokenName;                                   
   symbol = tokenSymbol;                               
 }

 function _transfer (address _from, address _to, uint _value) internal {
   require(_to != address(0x0));
   require(!frozenAccount[_to]);
   require(!frozenAccount[_from]);
   require(balanceOf[_from] >= _value);
   require(balanceOf[_to] + _value >= balanceOf[_to]);
   uint previousBalances = balanceOf[_from] + balanceOf[_to];
   balanceOf[_from] -= _value;
   balanceOf[_to] += _value;
   emit Transfer(_from, _to, _value);
   assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
 }

 function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
   require (_to != address(0x0));                          
   require (balanceOf[_from] >= _value);
   require (balanceOf[_to] + _value >= balanceOf[_to]);
   require(!frozenAccount[_from]);
   require(!frozenAccount[_to]);                           
   _transfer(_from, _to, _value);
   return true;
 }

 function transferN (address _to, uint256 _value) public returns (bool success) {
   require (_to != address(0x0));  
   require(balanceOf[msg.sender] >= _value);

   balanceOf[msg.sender] -= _value;
   balanceOf[_to] += _value;

   emit Transfer(msg.sender, _to, _value);

   return true;
 }

 function burn(uint256 _value) public returns (bool success) {
   require(balanceOf[msg.sender] >= _value);   
   balanceOf[msg.sender] -= _value;            
   totalSupply -= _value;                      
   emit Burn(msg.sender, _value);
   return true;
 }

 function burnFrom(address _from, uint256 _value) public returns (bool success) {
   require(balanceOf[_from] >= _value);                
   balanceOf[_from] -= _value;                         
   totalSupply -= _value;                              
   emit Burn(_from, _value);
   return true;
 }

 function freezeAccount(address target, bool freeze) public {
   frozenAccount[target] = freeze;
   emit FrozenFunds(target, freeze);
 }

 function distributeToken(address[] memory addresses, uint256[] memory _value) public returns (bool success) {
   for( uint256 i=1;i<addresses.length;i++){
     _transfer(addresses[0], addresses[i], _value[i]);
   }
   return true;
 }

 function mintToken(address target, uint256 mintedAmount) onlyOwner public {
   balanceOf[target] += mintedAmount;
   totalSupply += mintedAmount;
   emit Transfer(address(0), address(this), mintedAmount);
   emit Transfer(address(this), target, mintedAmount);
 }
} 

眾售合約:

pragma solidity >=0.4.22 <0.6.0;

import "./Ed.sol";

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

 event Sell(address _buyer, uint256 _amount);

 constructor(EdCoin _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(address(this)) >= _numberOfTokens);
   require(tokenContract.transferN(msg.sender, _numberOfTokens));

   tokensSold += _numberOfTokens;

   emit Sell(msg.sender, _numberOfTokens);
 }
}

兩個合約都已成功部署,但在嘗試購買代幣時,它會在下面拋出錯誤

Gas estimation failed
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
gas required exceeds allowance or always failing transaction

我正在使用 RopstenTest 網路進行測試。

您的程式碼中有幾條require語句,其中一些似乎失敗了。嘗試將錯誤消息添加到您的require語句中,以了解哪個實際失敗:

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

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

 tokensSold += _numberOfTokens;

 emit Sell(msg.sender, _numberOfTokens);
}

你的契約寫得很完美,但我認為你不了解基本的代幣操作。

首先,當您在代幣合約中將總供應量轉移給您的所有者時,您的代幣合約沒有代幣可以提供。

二:TransferN函式中的語句

require(balanceOf[msg.sender] >= _value);

在這種情況下,msg.sender 是試圖購買的人,餘額如何超過要求的價值?

如果你想以這種方式出售你的代幣,你應該刪除上面提到的 require 語句並從你的 transferN 中呼叫 _transfer。這不是一個好方法,但它會起作用。了解令牌的工作原理。

function transferN (address _to, uint256 _value) public returns (bool success) {
   require (_to != address(0x0));  

   _transfer(owner, _to, _value);

   emit Transfer(owmer, _to, _value);

   return true;
}

這又不是正確的方法。

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