Tokens
zeppelin-solidity 眾包契約不起作用
我從 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
我不知道我做錯了什麼。
- 為什麼氣體限制如此之高?
- 什麼功能導致拋出?
請幫助和建議。
以下是代幣合約程式碼:(與 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 以進行合約。