本文主要介紹了如何使用truffle + Atom
進(jìn)行以太坊公開(kāi)透明拍賣智能合約的編寫直焙,以及如何使用ganache-cli
進(jìn)行智能合約的交互測(cè)試诺核。
1 Trueffle框架編寫代碼
1.1 建立項(xiàng)目
新建項(xiàng)目文件夾SimpleAuction
開(kāi)啟另一個(gè)終端窗口梭伐,輸入以下命令建立項(xiàng)目:
PS H:\TestContract> mkdir SimpleAuction
目錄: H:\TestContract
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2018/7/12 12:01 SimpleAuction
PS H:\TestContract> cd SimpleAuction
PS H:\TestContract\SimpleAuction> truffle init
Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!
Commands:
Compile: truffle compile
Migrate: truffle migrate
Test contracts: truffle test
PS H:\TestContract\SimpleAuction>
目錄結(jié)構(gòu):
打開(kāi)contracts
文件夾暇昂,再通過(guò)truffle命令創(chuàng)建SimpleAuction
合約搭盾,必須通過(guò)命令行創(chuàng)建祷蝌。
PS H:\TestContract\SimpleAuction> cd contracts
PS H:\TestContract\SimpleAuction\contracts> truffle create contract SimpleAuction
-
\contracts
:存放智能合約源代碼的地方次伶,可以看到里面已經(jīng)有一個(gè)sol
文件痴昧,我們開(kāi)發(fā)的BlindAuction.sol
文件就存放在這個(gè)文件夾。 -
\migrations
:這是Truffle
用來(lái)部署智能合約的功能冠王,待會(huì)兒我們會(huì)新建一個(gè)類似1_initial_migration.js
的文件來(lái)部署BlindAuction.sol
赶撰。 -
\test
:測(cè)試智能合約的代碼放在這里,支持js
與sol
測(cè)試柱彻。 -
truffle-config.js
和truffle.js
:Truffle
的配置文件,需要配置要連接的以太坊網(wǎng)絡(luò)豪娜。
1.2 創(chuàng)建合約
在Atom中打開(kāi)項(xiàng)目文件夾SimpleAuction
,開(kāi)始編輯contracts
文件夾下的SimpleAuction.sol
文件哟楷。
整個(gè)流程如下:
- 我們首先要記錄拍賣的基本數(shù)據(jù):誰(shuí)是受益人瘤载,什么時(shí)候結(jié)束
- 我們開(kāi)啟拍賣,一個(gè)出價(jià)更高的人會(huì)替代之前出價(jià)最高的人
- 當(dāng)出現(xiàn)替代時(shí)卖擅,還要退還之前出價(jià)高的人的代幣
- 出于安全的考慮鸣奔,退還過(guò)程將由之前用戶主動(dòng)發(fā)起
pragma solidity ^0.4.22;
contract SimpleAuction {
// 定義參數(shù):受益人、拍賣結(jié)束時(shí)間
address public beneficiary;
uint public auctionEnd;
uint public biddingTime;
uint public auctionStart;
// 最高出價(jià)者
address public highestBidder;
// 最高出價(jià)
uint public highestBid;
mapping (address => uint) pendingReturns; // 用于取回之前的出價(jià)
// 拍賣是否結(jié)束惩阶,不允許被修改
bool ended;
// 最高出價(jià)變動(dòng)時(shí)調(diào)用事件
event HighestBidIncreased(address _bidder, uint _amount);
// 拍賣結(jié)束時(shí)調(diào)用事件
event AuctionEnded(address _winner, uint _amount);
// The following is a so-called natspec comment,
// recognizable by the three slashes.
// It will be shown when the user is asked to
// confirm a transaction.
// 構(gòu)造函數(shù)
// 創(chuàng)建一個(gè)拍賣對(duì)象挎狸,初始化參數(shù)值:受益人、拍賣持續(xù)時(shí)間
constructor(uint _biddingTime, address _beneficiary) public {
beneficiary = _beneficiary;
auctionStart = now;
biddingTime = _biddingTime;
auctionEnd = now + _biddingTime; // now: current block's timestamp
}
// 使用代幣進(jìn)行拍賣琳猫,當(dāng)拍賣失敗時(shí)伟叛,會(huì)退回代幣
// 出價(jià)功能:包括交易參數(shù)
// 當(dāng)出價(jià)不是最高,資金會(huì)被自動(dòng)退回
function bid() public payable{
// 不需要參數(shù)脐嫂,因?yàn)槎急蛔詣?dòng)處理了
// 當(dāng)一個(gè)函數(shù)要處理Ether時(shí)统刮,需要包含payable的修飾符
// 如果超過(guò)了截止期,交易撤回
if(now > auctionStart + biddingTime){
revert();
}
// 如果出價(jià)不夠账千,交易撤回
if (msg.value <= highestBid){
revert();
}
// 如果出價(jià)最高侥蒙,當(dāng)前出價(jià)者作為最高出價(jià)人
if (highestBidder != 0){
//highestBidder.send(highestBid); // send ether(in wei)to the address
// 調(diào)用highestBidder.send(highestBid)的方式是危險(xiǎn)的
// 因?yàn)闀?huì)執(zhí)行不知道的協(xié)議
// 因此最好讓用戶自己取回自己的代幣
pendingReturns[highestBidder] += highestBid;
}
highestBidder = msg.sender;
highestBid = msg.value;
emit HighestBidIncreased(msg.sender, msg.value);
}
// 取回被超出的拍賣前的出資
function withdraw() public returns (bool){
uint amount = pendingReturns[msg.sender];
if (amount > 0){
// 需要提前設(shè)置為0,因?yàn)榻邮照呖梢栽谶@個(gè)函數(shù)結(jié)束前再次調(diào)用它
pendingReturns[msg.sender] = 0;
if (!msg.sender.send(amount)){
// 不需要throw匀奏,直接重置代幣數(shù)量即可
pendingReturns[msg.sender] = amount;
return false;
}
}
return true;
}
// 結(jié)束拍賣鞭衩,將金額給予受益人
function auctionEnd() public {
// 與其他協(xié)議交互的最好遵循以下順序的三個(gè)步驟:
// 1.檢查狀況
// 2.修改狀態(tài)
// 3.合約交互
// 如果這三個(gè)步驟混在一起,那么攻擊者可能通過(guò)多次調(diào)用這個(gè)函數(shù)來(lái)進(jìn)行攻擊
// 1.檢查狀況
if (now <= auctionEnd) {
revert();
}
if(ended){
revert();
}
// require (now >= auctionEnd, "Auction not yet ended.");
// require (!ended, "auctionEnd has already called.");
// 2.修改狀態(tài)
ended = true;
emit AuctionEnded(highestBidder, highestBid);
// 3.合約交互
beneficiary.transfer(highestBid);
}
function () public{
revert();
}
}
Note:一定要有最后的function()
不然調(diào)用bid()
總會(huì)報(bào)錯(cuò)。
1.3 編譯合約
在項(xiàng)目根目錄SimpleAuction
的powershell中執(zhí)行truffle compile
命令:
PS H:\TestContract\SimpleAuction> truffle compile
Compiling .\contracts\Migrations.sol...
Compiling .\contracts\SimpleAuction.sol...
Compilation warnings encountered:
/H/TestContract/SimpleAuction/contracts/SimpleAuction.sol:32:5: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
function SimpleAuction(uint _biddingTime, address _beneficiary) public {
^ (Relevant source part starts here and spans across multiple lines).
Writing artifacts to .\build\contracts
PS H:\TestContract\SimpleAuction>
2 Ganache-cli 部署測(cè)試智能合約
2.1 啟動(dòng)ganache-cli
打開(kāi)powershell
終端论衍,可以看到ganache-cli
啟動(dòng)后自動(dòng)建立了10
個(gè)賬號(hào)(Accounts)瑞佩,與每個(gè)賬號(hào)對(duì)應(yīng)的私鑰(Private Key)。每個(gè)賬號(hào)中都有100
個(gè)測(cè)試用的以太幣(Ether)坯台。
Note. ganache-cli僅運(yùn)行在內(nèi)存中炬丸,因此每次重開(kāi)時(shí)都會(huì)回到全新的狀態(tài)。
C:\Users\aby>ganache-cli
Ganache CLI v6.1.6 (ganache-core: 2.1.5)
Available Accounts
==================
(0) 0x553cc75f3099ec4f6ba57e2580f65f982dfcbc67 (~100 ETH)
(1) 0xed700e53205af0b9daa4548cc48465cab55d376c (~100 ETH)
(2) 0x3fdcbf82e2343f3d88a5ec967800ee188b7bc440 (~100 ETH)
(3) 0x76757998260e9d7bb01e2761a4abacffd73162e2 (~100 ETH)
(4) 0x0e53c9c2cb04a7b46acd3e94703434c6e0b1e1c9 (~100 ETH)
(5) 0xfb7db3e68877e08df576d0071d1f68b1ad185d50 (~100 ETH)
(6) 0x0ff87726fac78f3675751fc67c3b2b174aa7ec68 (~100 ETH)
(7) 0x8bee12196d694c864b00c4b19295b0c0a067bb1a (~100 ETH)
(8) 0x14e498d9ca25b050e17fb702e1325135da21e9e7 (~100 ETH)
(9) 0x1aed5d4a441d50716313426bdc519b8263c37bfc (~100 ETH)
Private Keys
==================
(0) 0x260ed471ee7c4897c3b478a3ae36fb47f7b5dc4e2bfaeea2062e53edbc664f8e
(1) 0xbbaaf6be4797da3598ca72969b46a04569448a7d67185f96b55b2618327176b6
(2) 0xca9fd89f5c5ada96b35afd2b5782c14b2286894454178e9225df2aa3bed133d4
(3) 0x5e282a3ddb12f4f77318a30f2e653b1764b3fac52f43d575e5b1cd9564e6c6f6
(4) 0x17f336fbcc161a20f38979d787eb9f1ae33fea870acdd37142dc3be3bcf127e7
(5) 0x9521e42f1d3a03079883032a47a7146cd76275bf0bf206b5f0467c8a2249e553
(6) 0x4fd49f71649d35d9d93d5c9be03f554844ee68a7c45ae9c899f08ead8d2e0405
(7) 0x0221b4004e5b70684a0d19926739d5ed2e420d9e7c908a734763fbbf51d13133
(8) 0xd54daf5bfda3d3491ff5b3cefbba6a9e88b68d8ae322135337e9d530523308a6
(9) 0x73420d353ed74fd5939590dc30c2e7a966727f6561c84526ce71f04e0c668bec
HD Wallet
==================
Mnemonic: give sick brand tail farm mechanic fence flock submit boost fiction magnet
Base HD Path: m/44'/60'/0'/0/{account_index}
Gas Price
==================
20000000000
Gas Limit
==================
6721975
Listening on 127.0.0.1:8545
2.2 部署合約
(1)migrations
目錄下創(chuàng)建一個(gè)名字叫做2_deploy_contracts.js
的文件蜒蕾。文件中的內(nèi)容為:
var SimpleAuction = artifacts.require('./SimpleAuction.sol');
module.exports = function(deployer) {
deployer.deploy(SimpleAuction);
}
(2)修改truffle.js
文件稠炬,連接本地ganache-cli
環(huán)境。參數(shù)在最開(kāi)初始化ganache-cli
環(huán)境的窗口可以看到咪啡。
module.exports = {
// See <http://truffleframework.com/docs/advanced/configuration>
// to customize your Truffle configuration!
networks: {
development:{
host: "127.0.0.1",
port: 8545,
network_id: "*" // match any network id
}
}
};
(3)現(xiàn)在執(zhí)行truffle migrate
命令首启,我們可以將SimpleAuction.sol
原始碼編譯成Ethereum bytecode
。
PS H:\TestContract\SimpleAuction> truffle migrate
Using network 'development'.
Running migration: 2_deploy_contracts.js
Deploying SimpleAuction...
Error encountered, bailing. Network state unknown. Review successful transactions manually.
Error: SimpleAuction contract constructor expected 2 arguments, received 0
at C:\Users\aby\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-contract\contract.js:390:1
at new Promise (<anonymous>)
at C:\Users\aby\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-contract\contract.js:374:1
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
PS H:\TestContract\SimpleAuction>
發(fā)現(xiàn)報(bào)錯(cuò)撤摸,Error: SimpleAuction contract constructor expected 2 arguments, received 0
毅桃,可以在部署時(shí)進(jìn)行構(gòu)造函數(shù)的賦值,不必修改智能合約內(nèi)容:在2_deploy_contracts.js
中愁溜,修改deploy腳本疾嗅,deployer.deploy(SimpleAuction, 20, "0x553cc75f3099ec4f6ba57e2580f65f982dfcbc67");
即可外厂。
PS H:\TestContract\SimpleAuction> truffle migrate
Using network 'development'.
Running migration: 2_deploy_contracts.js
Deploying SimpleAuction...
... 0x3b611b5e12c85ba20b59c66b7a2b997a580fab7dbe1431be323fcdd3f9d07f62
SimpleAuction: 0x7307036020a33ae1996ff74a5044123eda03302c
Saving successful migration to network...
... 0xb646aa61fefa4933f6102d04e7af232c10c0c43f9384df49ab250f54a083c2c6
Saving artifacts...
PS H:\TestContract\SimpleAuction>
2.3 與合約交互
truffle
提供命令行工具冕象,執(zhí)行truffle console
命令后,可用Javascript
來(lái)和剛剛部署的合約互動(dòng)汁蝶。
PS H:\TestContract\SimpleAuction> truffle console
truffle(development)>
使用web3.eth.accounts
會(huì)輸出ganache-cli
網(wǎng)絡(luò)上的所有賬戶渐扮。
truffle(development)> web3.eth.accounts
[ '0x553cc75f3099ec4f6ba57e2580f65f982dfcbc67',
'0xed700e53205af0b9daa4548cc48465cab55d376c',
'0x3fdcbf82e2343f3d88a5ec967800ee188b7bc440',
'0x76757998260e9d7bb01e2761a4abacffd73162e2',
'0x0e53c9c2cb04a7b46acd3e94703434c6e0b1e1c9',
'0xfb7db3e68877e08df576d0071d1f68b1ad185d50',
'0x0ff87726fac78f3675751fc67c3b2b174aa7ec68',
'0x8bee12196d694c864b00c4b19295b0c0a067bb1a',
'0x14e498d9ca25b050e17fb702e1325135da21e9e7',
'0x1aed5d4a441d50716313426bdc519b8263c37bfc' ]
我們需要準(zhǔn)備一些測(cè)試賬戶。
它會(huì)把第一個(gè)帳戶的地址分配給變量account0
掖棉,第二個(gè)帳戶分配給變量account1
墓律。Web3
是一個(gè)JavaScript API
,它將RPC
調(diào)用包裝起來(lái)以方便我們與區(qū)塊鏈進(jìn)行交互幔亥。
truffle(development)> acc1 = web3.eth.accounts[1]
'0xed700e53205af0b9daa4548cc48465cab55d376c'
我們可以看一下拍賣發(fā)起人以及第一個(gè)賬戶的余額:
truffle(development)> web3.eth.getBalance(address)
BigNumber { s: 1, e: 19, c: [ 999060, 70900000000000 ] }
truffle(development)> web3.eth.getBalance(acc1)
BigNumber { s: 1, e: 20, c: [ 1000000 ] }
此時(shí)我們用acc1
調(diào)用bid()
耻讽,發(fā)送2 ether
。
truffle(development)> contract.bid({from:acc1, value:web3.toWei(2,"ether")})
{ tx: '0xfad44c38347ee56220bf3810c4e6904b6c1e10a3cbd6495da9008533ffc5a1ee',
receipt:
{ transactionHash: '0xfad44c38347ee56220bf3810c4e6904b6c1e10a3cbd6495da9008533ffc5a1ee',
transactionIndex: 0,
blockHash: '0xd9657a80fd84cb9a6582f560f3ce91dcc7f571932772d7f4ce4dd60ecd0f25c9',
blockNumber: 5,
gasUsed: 63946,
cumulativeGasUsed: 63946,
contractAddress: null,
logs: [ [Object] ],
status: '0x1',
logsBloom: '0x00004000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000' },
logs:
[ { logIndex: 0,
transactionIndex: 0,
transactionHash: '0xfad44c38347ee56220bf3810c4e6904b6c1e10a3cbd6495da9008533ffc5a1ee',
blockHash: '0xd9657a80fd84cb9a6582f560f3ce91dcc7f571932772d7f4ce4dd60ecd0f25c9',
blockNumber: 5,
address: '0x4faf92d14a7ac059b4fb97975376f52c32e1abe1',
type: 'mined',
event: 'HighestBidIncreased',
args: [Object] } ] }
并且查看此時(shí)acc1
余額帕棉,以及highestBid
针肥。
truffle(development)> contract.highestBid.call()
BigNumber { s: 1, e: 18, c: [ 20000 ] }
truffle(development)> web3.eth.getBalance(acc1)
BigNumber { s: 1, e: 19, c: [ 979936, 5400000000000 ] }
由于拍賣時(shí)間設(shè)置較短,所以結(jié)束拍賣香伴。
truffle(development)> contract.auctionEnd({from:address})
{ tx: '0x8701d85470423c67608d14eaa96e807a156981bf9d47826aa0bfcd69b4711fcc',
receipt:
{ transactionHash: '0x8701d85470423c67608d14eaa96e807a156981bf9d47826aa0bfcd69b4711fcc',
transactionIndex: 0,
blockHash: '0x5dc6e9b00d495f19b2e3427b128c5b70544191a2bf8c78d9deabf6a79deaf097',
blockNumber: 8,
gasUsed: 51912,
cumulativeGasUsed: 51912,
contractAddress: null,
logs: [ [Object] ],
status: '0x1',
logsBloom: '0x00004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000001000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000' },
logs:
[ { logIndex: 0,
transactionIndex: 0,
transactionHash: '0x8701d85470423c67608d14eaa96e807a156981bf9d47826aa0bfcd69b4711fcc',
blockHash: '0x5dc6e9b00d495f19b2e3427b128c5b70544191a2bf8c78d9deabf6a79deaf097',
blockNumber: 8,
address: '0x4faf92d14a7ac059b4fb97975376f52c32e1abe1',
type: 'mined',
event: 'AuctionEnded',
args: [Object] } ] }
2.4 拍賣過(guò)程
由于上面結(jié)束拍賣慰枕,我們現(xiàn)在重新設(shè)置拍賣時(shí)長(zhǎng),并連貫順序地進(jìn)行一次拍賣過(guò)程即纲。由于ganache-cli
每次都重新啟動(dòng)具帮,都會(huì)隨機(jī)創(chuàng)建10個(gè)賬戶,所以這里地址不同。
同樣創(chuàng)建其他賬戶
PS H:\TestContract\SimpleAuction> truffle console
truffle(development)> address = web3.eth.accounts[0]
'0x0bf5cd9a0313121dda0f91e2da6ff9479be4ec5c'
truffle(development)> acc1 = web3.eth.accounts[1]
'0xdfa9eca806498bcf1c083b14ab20c53b2a3815a5'
truffle(development)> acc2 = web3.eth.accounts[2]
'0xc8dd1ff47b6e7067f1b4c2ec18fc60f36da97c46'
truffle(development)> acc3 = web3.eth.accounts[3]
'0xf758b41d6bb008e6f64bea810ecc38be46299ae6'
truffle(development)> acc4 = web3.eth.accounts[4]
'0x0830f17d845b90d8dc965ddb73b43e0f46e06bb8'
address
調(diào)用創(chuàng)建一個(gè)拍賣:
truffle(development)> let contract
undefined
truffle(development)> SimpleAuction.deployed().then(instance => contract = instance)
我們可以看一下蜂厅,當(dāng)前創(chuàng)建拍賣的收益人匪凡,最高價(jià),以及各個(gè)賬戶的余額等掘猿。
truffle(development)> contract.beneficiary.call()
'0x0bf5cd9a0313121dda0f91e2da6ff9479be4ec5c'
truffle(development)> contract.auctionStart.call()
BigNumber { s: 1, e: 9, c: [ 1531385059 ] }
truffle(development)> contract.highestBid.call()
BigNumber { s: 1, e: 0, c: [ 0 ] }
truffle(development)> contract.highestBidder.call()
'0x0000000000000000000000000000000000000000'
truffle(development)> web3.eth.getBalance(address)
BigNumber { s: 1, e: 19, c: [ 999060, 70900000000000 ] }
truffle(development)> web3.eth.getBalance(acc1)
BigNumber { s: 1, e: 20, c: [ 1000000 ] }
truffle(development)> web3.eth.getBalance(acc2)
BigNumber { s: 1, e: 20, c: [ 1000000 ] }
使用acc1
進(jìn)行一次bid()
:
truffle(development)> contract.bid({from:acc1, value:web3.toWei(2,"ether")})
{ tx: '0x68d752b6afc9b1bbb5c987bf4c4faad3907ea312f552f9280573a22dca662f05',
receipt:
{ transactionHash: '0x68d752b6afc9b1bbb5c987bf4c4faad3907ea312f552f9280573a22dca662f05',
transactionIndex: 0,
blockHash: '0x30f1edf3689d8af7639c2bf2475e932d34155891d333512e3b97dffac25f5220',
blockNumber: 5,
gasUsed: 63946,
cumulativeGasUsed: 63946,
contractAddress: null,
logs: [ [Object] ],
status: '0x1',
logsBloom: '0x00000000000000000000000000800080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' },
logs:
[ { logIndex: 0,
transactionIndex: 0,
transactionHash: '0x68d752b6afc9b1bbb5c987bf4c4faad3907ea312f552f9280573a22dca662f05',
blockHash: '0x30f1edf3689d8af7639c2bf2475e932d34155891d333512e3b97dffac25f5220',
blockNumber: 5,
address: '0x55ac96c388568a6d2e233a8dbb9c1e5be1c3e4c8',
type: 'mined',
event: 'HighestBidIncreased',
args: [Object] } ] }
查看當(dāng)前acc1
的余額锹雏,以及highestBid
,可以看到acc1
減少了,highestBid
變成了2000
:
truffle(development)> web3.eth.getBalance(acc1)
BigNumber { s: 1, e: 19, c: [ 979936, 5400000000000 ] }
truffle(development)> contract.highestBid.call()
BigNumber { s: 1, e: 18, c: [ 20000 ] }
同樣的术奖,使用acc2
礁遵,acc3
,acc4
分別進(jìn)行bid
:
Account | Value |
---|---|
acc1 | 2 |
acc2 | 4 |
acc3 | 1 |
acc4 | 6 |
可以看到當(dāng)bid
價(jià)格比highestBid
高時(shí)會(huì)出現(xiàn)上面的結(jié)果采记,如果低佣耐,則會(huì)被revert()
拋出異常。
truffle(development)> contract.bid({from:acc3, value:web3.toWei(1,"ether")})
Error: VM Exception while processing transaction: revert
at XMLHttpRequest._onHttpResponseEnd (C:\Users\aby\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2\lib\xhr2.js:509:1)
at XMLHttpRequest._setReadyState (C:\Users\aby\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2\lib\xhr2.js:354:1)
at XMLHttpRequestEventTarget.dispatchEvent (C:\Users\aby\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2\lib\xhr2.js:64:1)
at XMLHttpRequest.request.onreadystatechange (C:\Users\aby\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3\lib\web3\httpprovider.js:128:1)
at C:\Users\aby\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-provider\wrapper.js:134:1
at C:\Users\aby\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3\lib\web3\requestmanager.js:86:1
at Object.InvalidResponse (C:\Users\aby\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3\lib\web3\errors.js:38:1)
此時(shí)唧龄,調(diào)用結(jié)束拍賣函數(shù)auctionEnd()
,也會(huì)被revert()
拋出異常兼砖,因?yàn)楫?dāng)前時(shí)間小于結(jié)束時(shí)間auctionEnd
。
過(guò)一段時(shí)間既棺,再次調(diào)用auctionEnd()
:
truffle(development)> contract.auctionEnd.sendTransaction({from:address})
'0xfe1ed3d6fb181d2f0bb122edcadb99c735abee31f4d620f25a7e8ca7c8677014'
再看看此時(shí)受益者讽挟,也就是address
地址的余額:
可以明顯看到他增加了6 ether
,得到收益丸冕。
truffle(development)> web3.eth.getBalance(address)
BigNumber { s: 1, e: 20, c: [ 1058987, 14600000000000 ] }
最后每個(gè)報(bào)價(jià)者取回自己的余額耽梅,競(jìng)拍失敗者可以取回錢。
truffle(development)> contract.withdraw({from:acc1})
{ tx: '0x44d9f709c52d2e2b27e0d075b2afbd3fb9f065a1d66b70026a6657bd48a3c1ef',
receipt:
{ transactionHash: '0x44d9f709c52d2e2b27e0d075b2afbd3fb9f065a1d66b70026a6657bd48a3c1ef',
transactionIndex: 0,
blockHash: '0xa5b1f3a0e2670e88462bd1c6338fe4eaa1afc6496a81fc508899fedc86d38e8a',
blockNumber: 11,
gasUsed: 19482,
cumulativeGasUsed: 19482,
contractAddress: null,
logs: [],
status: '0x1',
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' },
logs: [] }
acc1
查看自己當(dāng)前賬戶余額:
truffle(development)> web3.eth.getBalance(acc1)
BigNumber { s: 1, e: 19, c: [ 999916, 57200000000000 ] }
其他賬戶做同樣操作胖烛。
2.5 賬戶變化
最后可以總結(jié)一下眼姐,每個(gè)參與拍賣的賬戶余額變化:
賬戶 | 1.初始化 | 2.創(chuàng)建合約 | 3.bid | 4.拍賣結(jié)束及取回 |
---|---|---|---|---|
address | 1000000 | 999060, 70900000000000 | 999060, 70900000000000 | 1058987, 14600000000000 |
acc1 | 1000000 | 1000000 | 979936, 5400000000000(2) | 999916, 57200000000000 |
acc2 | 1000000 | 1000000 | 4 | 999925, 81300000000000 |
acc3 | 1000000 | 1000000 | 1 | 999956, 8300000000000 |
acc4 | 1000000 | 1000000 | 6 | 939923, 41400000000000 |
由于發(fā)起交易需要消耗gas
所以,賬戶1佩番,2众旗,3余額會(huì)比最開(kāi)始少一點(diǎn)。而acc4
則因?yàn)榕馁u成功趟畏,相對(duì)較少的較多贡歧。
本文作者:Joyce
文章來(lái)源:http://www.reibang.com/p/65c93265ad8e
版權(quán)聲明:轉(zhuǎn)載請(qǐng)注明出處!
2018年7月12日
參考:一個(gè)使用Atom赋秀,truffle利朵,ganache-cli創(chuàng)建部署智能合約的方法智能合約開(kāi)發(fā)之 Hello World!沃琅。