Tokens

zeppelin-solidity 眾包契約不起作用

  • June 27, 2018

我從 Zeppelin-Solidity GitHub https://github.com/OpenZeppelin/zeppelin-solidity獲取智能合約範常式式碼

我使用與 Remix (remix.ethereum.org) 上 Zeppelin 範例完全相同的程式碼創建和部署 SimpleToken。在 Rinkeby 測試網路中部署成功並驗證成功。

  • 令牌名稱 = TestMyToken
  • 代幣符號 = TMT
  • 令牌小數 = 18 令牌
  • 合約地址 = 0x6Ca65510ec3F91b591027EDc60ea119d0984844a

接下來,我使用 Zeppelin 範例中完全相同的 Crowdsale.sol 進行測試和學習。

輸入以下內容以使用 Remix 創建 Crowdsale 合約

1500,"0xbb3937D3cd7c391e373df560c94f73098499A4E2", "0x6Ca65510ec3F91b591027EDc60ea119d0984844a"

在 Rinkeby 測試網路中部署成功並驗證成功。

眾售智能合約地址:0xf8D5ce2E1721c8e6914a623e6444ecA584119b41

  • 我登錄 MyEtherWallet 並選擇 Rinkeby (Etherscan.io) 網路
  • 點擊契約
  • 粘貼 Crowdsales 智能合約地址
  • 粘貼 Crowdsales 智能合約地址中的 ABI 程式碼
  • 我可以看到功能
  • 選擇buyToken功能
  • 輸入 0.1 Ether 以測試購買
  • MetaMask 顯示錯誤“交易錯誤。合約程式碼中引發異常”以及 Gas Limit 顯示 EXTREMELY High 6,915,218

我不知道我做錯了什麼。

  1. 為什麼氣體限制如此之高?
  2. 什麼功能導致拋出?

請幫助和建議。

在此處輸入圖像描述

以下是代幣合約程式碼:(與 Zeppelin 範例完全相同,但刪除了註釋行)

library SafeMath {
   function mul(uint256 a, uint256 b) internal pure returns (uint256) {
      if (a == 0) {
         return 0;
      }
      uint256 c = a * b;
      assert(c / a == b);
      return c;
   }

   function div(uint256 a, uint256 b) internal pure returns (uint256) {
      uint256 c = a / b;
      return c;
   }

   function sub(uint256 a, uint256 b) internal pure returns (uint256) {
      assert(b <= a);
      return a - b;
   }

   function add(uint256 a, uint256 b) internal pure returns (uint256) {
      uint256 c = a + b;
      assert(c >= a);
      return c;
   }
}

contract ERC20Basic {
   function totalSupply() public view returns (uint256);
   function balanceOf(address who) public view returns (uint256);
   function transfer(address to, uint256 value) public returns (bool);
   event Transfer(address indexed from, address indexed to, uint256 value);
}

contract ERC20 is ERC20Basic {
   function allowance(address owner, address spender) public view returns (uint256);
   function transferFrom(address from, address to, uint256 value) public returns (bool);
   function approve(address spender, uint256 value) public returns (bool);
   event Approval(address indexed owner, address indexed spender, uint256 value);
}

contract BasicToken is ERC20Basic {
   using SafeMath for uint256;
   mapping(address => uint256) balances;
   uint256 totalSupply_;

   function totalSupply() public view returns (uint256) {
      return totalSupply_;
   }

   function transfer(address _to, uint256 _value) public returns (bool) {
      require(_to != address(0));
      require(_value <= balances[msg.sender]);
      balances[msg.sender] = balances[msg.sender].sub(_value);
      balances[_to] = balances[_to].add(_value);
      Transfer(msg.sender, _to, _value);
      return true;
   }

   function balanceOf(address _owner) public view returns (uint256 balance) {
      return balances[_owner];
   }
}

contract StandardToken is ERC20, BasicToken {
   mapping (address => mapping (address => uint256)) internal allowed;
   function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
      require(_to != address(0));
      require(_value <= balances[_from]);
      require(_value <= allowed[_from][msg.sender]);
      balances[_from] = balances[_from].sub(_value);
      balances[_to] = balances[_to].add(_value);
      allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
      Transfer(_from, _to, _value);
      return true;
}

   function approve(address _spender, uint256 _value) public returns (bool) {
       allowed[msg.sender][_spender] = _value;
       Approval(msg.sender, _spender, _value);
       return true;
   }

   function allowance(address _owner, address _spender) public view returns (uint256) {
       return allowed[_owner][_spender];
   }

   function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
       allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
       Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
       return true;
   }

   function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
      uint oldValue = allowed[msg.sender][_spender];
      if (_subtractedValue > oldValue) {
          allowed[msg.sender][_spender] = 0;
      } else {
          allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
      }
      Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
      return true;
   }
}

contract TestMyToken is StandardToken {
   string public constant name = "TestMyToken"; 
   string public constant symbol = "TMT";
   uint8 public constant decimals = 18;
   uint256 public constant INITIAL_SUPPLY = 1000000 * (10 ** uint256(decimals));

   function TestMyToken() public {
       totalSupply_ = INITIAL_SUPPLY;
       balances[msg.sender] = INITIAL_SUPPLY;
       Transfer(0x0, msg.sender, INITIAL_SUPPLY);
   }
}

以下是眾籌合約程式碼:(與 Zeppelin 範例完全相同,但刪除了註釋行)

   library SafeMath {
   function mul(uint256 a, uint256 b) internal pure returns (uint256) {
      if (a == 0) {
         return 0;
      }
      uint256 c = a * b;
      assert(c / a == b);
      return c;
   }

   function div(uint256 a, uint256 b) internal pure returns (uint256) {
      uint256 c = a / b;
      return c;
   }

   function sub(uint256 a, uint256 b) internal pure returns (uint256) {
      assert(b <= a);
      return a - b;
   }

   function add(uint256 a, uint256 b) internal pure returns (uint256) {
      uint256 c = a + b;
      assert(c >= a);
      return c;
   }
}

contract ERC20Basic {
   function totalSupply() public view returns (uint256);
   function balanceOf(address who) public view returns (uint256);
   function transfer(address to, uint256 value) public returns (bool);
   event Transfer(address indexed from, address indexed to, uint256 value);
}

contract ERC20 is ERC20Basic {
   function allowance(address owner, address spender) public view returns (uint256);
   function transferFrom(address from, address to, uint256 value) public returns (bool);
   function approve(address spender, uint256 value) public returns (bool);
   event Approval(address indexed owner, address indexed spender, uint256 value);
}

contract Crowdsale {
   using SafeMath for uint256;
   ERC20 public token;
   address public wallet;
   uint256 public rate;
   uint256 public weiRaised;

   event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);

   function Crowdsale(uint256 _rate, address _wallet, ERC20 _token) public {
      require(_rate > 0);
      require(_wallet != address(0));
      require(_token != address(0));
      rate = _rate;
      wallet = _wallet;
      token = _token;
   }

   function () external payable {
      buyTokens(msg.sender);
   }

   function buyTokens(address _beneficiary) public payable {
      uint256 weiAmount = msg.value;
      _preValidatePurchase(_beneficiary, weiAmount);
      uint256 tokens = _getTokenAmount(weiAmount);
      weiRaised = weiRaised.add(weiAmount);
      _processPurchase(_beneficiary, tokens);
      TokenPurchase(msg.sender, _beneficiary, weiAmount, tokens);
      _updatePurchasingState(_beneficiary, weiAmount);
      _forwardFunds();
      _postValidatePurchase(_beneficiary, weiAmount);
   }

   function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
      require(_beneficiary != address(0));
      require(_weiAmount != 0);
   }

   function _postValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
      // optional override
   }

   function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
      token.transfer(_beneficiary, _tokenAmount);
   }

   function _processPurchase(address _beneficiary, uint256 _tokenAmount) internal {
      _deliverTokens(_beneficiary, _tokenAmount);
   }

   function _updatePurchasingState(address _beneficiary, uint256 _weiAmount) internal {
      // optional override
   }

   function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
      return _weiAmount.mul(rate);
   }

   function _forwardFunds() internal {
      wallet.transfer(msg.value);
   }
}

buy功能中,您將計算出的代幣數量從眾籌合約轉移到代幣受益人。但是你的眾籌合約的餘額中沒有代幣,所以token.transfer(_beneficiary, _tokenAmount);第 162 行的這個呼叫會引發錯誤。

要完成這項工作,您應該將適量的代幣轉移到眾籌合約中,以便它能夠將它們發送給投資者。

除了將代幣轉移到Crowdsale合約之外,您還可以AllowanceCrowdsale在第一時間使用。它使代幣保留在您的錢包中,但您需要approve()先從錢包中執行 a 以進行合約。

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