以太坊公開(kāi)拍賣智能合約(truffle + ganache-cli)

本文主要介紹了如何使用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):

目錄結(jié)構(gòu).PNG

打開(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è)試智能合約的代碼放在這里,支持jssol測(cè)試柱彻。
  • truffle-config.jstruffle.jsTruffle的配置文件,需要配置要連接的以太坊網(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礁遵,acc3acc4分別進(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!沃琅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哗咆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子益眉,更是在濱河造成了極大的恐慌晌柬,老刑警劉巖姥份,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異年碘,居然都是意外死亡澈歉,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門屿衅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)埃难,“玉大人,你說(shuō)我怎么就攤上這事涤久∥谐荆” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵响迂,是天一觀的道長(zhǎng)考抄。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蔗彤,這世上最難降的妖魔是什么川梅? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮然遏,結(jié)果婚禮上贫途,老公的妹妹穿的比我還像新娘。我一直安慰自己待侵,他們只是感情好丢早,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著诫给,像睡著了一般香拉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上中狂,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音扑毡,去河邊找鬼胃榕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛瞄摊,可吹牛的內(nèi)容都是我干的勋又。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼换帜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼楔壤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起惯驼,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蹲嚣,失蹤者是張志新(化名)和其女友劉穎递瑰,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體隙畜,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抖部,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了议惰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慎颗。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖言询,靈堂內(nèi)的尸體忽然破棺而出俯萎,到底是詐尸還是另有隱情,我是刑警寧澤运杭,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布讯屈,位于F島的核電站,受9級(jí)特大地震影響县习,放射性物質(zhì)發(fā)生泄漏涮母。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一躁愿、第九天 我趴在偏房一處隱蔽的房頂上張望叛本。 院中可真熱鬧,春花似錦彤钟、人聲如沸来候。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)营搅。三九已至,卻和暖如春梆砸,著一層夾襖步出監(jiān)牢的瞬間转质,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工帖世, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留休蟹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓日矫,卻偏偏與公主長(zhǎng)得像赂弓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哪轿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容