Tokens
使用 Zeppelin-OS 契約創建和執行 AllowanceCrowdSale
我使用 openzeppelin 庫: https ://github.com/OpenZeppelin/openzeppelin-solidity/tree/v1.12.0
令牌
我創建了一個 BurnableToken:
pragma solidity 0.4.24; import 'openzeppelin-solidity/contracts/token/ERC20/StandardBurnableToken.sol'; contract TestBurnableToken is StandardBurnableToken { string public name = "TestCoinBurnable"; string public symbol = "tcb"; uint8 public decimals = 18; uint256 public totalSupply; mapping (address => uint256) public balanceOf; constructor ( uint256 initialSupply ) public { totalSupply = initialSupply * 10 ** uint256(decimals); // Update total supply with the decimal amount balanceOf[msg.sender] = totalSupply; // Give the creator all initial tokens } }
創建者收到所有代幣。
眾籌
pragma solidity 0.4.24; import './TestBurnableToken.sol'; import 'openzeppelin-solidity/contracts/crowdsale/emission/AllowanceCrowdsale.sol'; import 'openzeppelin-solidity/contracts/crowdsale/validation/TimedCrowdsale.sol'; contract TestBurnableCrowdsale is TimedCrowdsale, AllowanceCrowdsale { constructor ( uint256 _openingTime, uint256 _closingTime, uint256 _rate, address _wallet, StandardBurnableToken _token ) public Crowdsale(_rate, _wallet, _token) TimedCrowdsale(_openingTime, _closingTime) AllowanceCrowdsale(_wallet) { } }
部署
const TestBurnableToken = artifacts.require("./TestBurnableToken.sol"); const TestBurnableCrowdsale = artifacts.require("./TestBurnableCrowdsale.sol"); module.exports = function(deployer, network, accounts) { const openingTime = web3.eth.getBlock('latest').timestamp + 30; // two secs in the future const closingTime = openingTime + 60 *15 // 15min const rate = new web3.BigNumber(1000); // only ints > 0, rate seems not to be inverse const wallet = accounts[0]; console.log("Deploying openingTime: ", openingTime, " closingTime ", closingTime, " rate ", rate, " wallet ", wallet); return deployer .then(() => { return deployer.deploy(TestBurnableToken, 10000); }) .then(() => { return deployer.deploy( TestBurnableCrowdsale, openingTime, closingTime, rate, wallet, TestBurnableToken.address ); }); };
松露控制台
// The account that created the tokens creator = web3.eth.accounts[0] // The account that will buy Test tokens. purchaser = web3.eth.accounts[2] // The address of the Test token instance that was created when the crowdsaleInstance contract was deployed // assign the result of TestBurnableCrowdsale.deployed() to the variable crowdsaleInstance TestBurnableCrowdsale.deployed().then(inst => { crowdsaleInstance = inst }) crowdsaleInstance.token().then(addr => { tokenAddress = addr } ) tokenAddress TestBurnableTokenInstance = TestBurnableToken.at(tokenAddress) //balances before TestBurnableTokenInstance.balanceOf(creator).then(balance => web3.fromWei(balance.toString(10))) //this shows 10000 because 10000 tokens have been created by account[0] TestBurnableTokenInstance.balanceOf(purchaser).then(balance => web3.fromWei(balance.toString(10))) //this shows 0, no tokens have been bought yet //account 0 now approves tokens to be sold TestBurnableTokenInstance.approve(crowdsaleInstance.address,web3.toWei(1000, "ether")) crowdsaleInstance.remainingTokens().then(balance => web3.fromWei(balance.toString(10))) //shows that 1000 tokens of 10000 have been approved for selling //buy and balances after buying crowdsaleInstance.sendTransaction({ from: purchaser, value: web3.toWei(1, "ether")}) // Here I get an error: Error: VM Exception while processing transaction: revert // I also tried 0.1 and 10000 to make sure it has nothing to do with the rate
問題:為什麼最後一個控制台呼叫失敗,代幣已被眾籌合約批准
account[0]
訪問。編輯
我使用了 truffles 調試功能,結果很奇怪:
31: returns (bool) 32: { 33: require(_value <= balances[_from]); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ debug(develop:0xefe253c5...)> v _from: '0x627306090abab3a6e1400e9345bc60c78a8bef57' _to: '0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef' _value: 1000000000000000000 : true debug(develop:0xefe253c5...)> StandardToken.sol: 35: require(_to != address(0)); 36: 37: balances[_from] = balances[_from].sub(_value); ^^^^^^^^^^^^^^^ debug(develop:0xefe253c5...)> v _from: '0x0de0b6b3a7640000' _to: '0x0de0b6b3a7640000' _value: 816 : true
基本上
_from
,to
,的值在行和_value
之間變化。33``37
require(_value <= balances[_from]); require(_value <= allowed[_from][msg.sender]); require(_to != address(0)); balances[_from] = balances[_from].sub(_value);
需要更改
balanceOf
為balances
否則 fn 將被覆蓋。
我相信您對
approve
函式的工作方式感到困惑。approve
基本上只與transferFrom
批准代幣轉移的功能結合使用 - 而不是購買。您可以使用 Truffle 的調試功能,或者只是簡單地註釋掉
require
語句,直到找到罪魁禍首。我沒有使用
AllowanceCrowdsale
(https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v1.12.0/contracts/crowdsale/emission/AllowanceCrowdsale.sol)的經驗,但我的猜測是那裡的require
某個地方失敗了(大概_deliverTokens
)。