以太坊事件log分析

合約調(diào)用的時(shí)候回產(chǎn)生event log(事件日志)逛犹,這個(gè)event log會(huì)記錄在一個(gè)調(diào)用合約的交易的receipt函數(shù)中蒋荚。通過對(duì)event log的分析可以得到跟多這個(gè)交易的一些詳細(xì)內(nèi)容

  1. 獲得event log
    首先獲得一個(gè)塊中的交易數(shù)組
        web3.eth.getBlock(blockHashOrNumber, true, function(error, blockData) {}
    其次根據(jù)返回的blockData.transactions獲得交易數(shù)組
    隨后可以根據(jù)交易數(shù)組獲得每個(gè)交易的hash
    最后
        var data = web3.eth.getTransactionReceipt(hash);
        獲得這個(gè)交易的更多交易細(xì)節(jié)
        var logsArr = data.logs;
        得到了event log
    
  2. 分析
    1. 規(guī)則
        例如:代幣的購買蜜唾,會(huì)觸發(fā)代幣的Transfer事件厨幻,這是ERC20標(biāo)準(zhǔn)的基本規(guī)定
        1. 對(duì)事件的基本定義
            event Transfer(address indexed from, address indexed to, uint256 value);
            事件名字:Transfer
            事件的參數(shù):address, address, uint256悲敷,且此事件的from和to參數(shù)前有indexed標(biāo)記怨酝,value沒有indexed標(biāo)記
            事件的規(guī)則是:
                topic[0]: keccak(Transfer(address,address,uint256)),對(duì)事件的字符做keccak散列運(yùn)算
                topic[1]: address類型from參數(shù)補(bǔ)齊64位
                topic[1]: address類型to參數(shù)補(bǔ)齊64位
                data: 沒有indexed標(biāo)記的value的值轉(zhuǎn)化為16進(jìn)制漆魔,并補(bǔ)齊64位
            具體的實(shí)現(xiàn)如下:
                // 從from這個(gè)賬戶發(fā)送 value個(gè)toekn(代幣) 到to這個(gè)賬戶
                Transfer(address indexed from, address indexed to, uint256 value)
                // 事件名字散列值
                topic[0] = keccak(Transfer(address,address,uint256)) = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
                // 后續(xù)的就是參數(shù)中有indexed標(biāo)志的參數(shù) 所傳遞的值
                // fromeAddress 補(bǔ)齊64位
                topic[1] = 0x0000000000000000000000000000000000000000000000000000000000000000
                topic[2] = 0x000000000000000000000000d53487c6b3a88dded611079b7ae7b377f4888550
                // 然后是另一個(gè)不帶indexed標(biāo)志的參數(shù)的 值傳入
                // 這就是一個(gè)數(shù)字轉(zhuǎn)化為16進(jìn)制 然后補(bǔ)齊64位
                data = 0x00000000000000000000000000000000000000000000002be4fb8c854544b555
    2. 具體的事件的分析
        1. 基本交易信息
            - 交易hash <https://etherscan.io/tx/0xd54e1fbc350dac428ca65a4abef6db4e343e1367e6cd9434bb14949a469cefc4>
            - 合約1的code <https://etherscan.io/address/0x20bf6672497941bd3e4ec5fd551de5c31e0a898a#code>
            - 合約2的code <https://etherscan.io/address/0x78b039921e84e726eb72e7b1212bb35504c645ca#code>
            事件的記錄由合約代碼決定
        2. 交易描述
            普通用戶地址向合約地址1轉(zhuǎn)賬1.75eth坷檩,所觸發(fā)的事件分析
        3.事件日志字段
            1. 第一個(gè)事件日志
                "address": "0x78b039921e84e726eb72e7b1212bb35504c645ca",
                "topics": [
                    "0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885",
                    "0x000000000000000000000000d53487c6b3a88dded611079b7ae7b377f4888550"
                ],
                "data": "0x00000000000000000000000000000000000000000000002be4fb8c854544b555"
                即合約地址為0x78b039921e84e726eb72e7b1212bb35504c645ca的合約觸發(fā)了事件,這個(gè)合約地址時(shí)合約2
                根據(jù)對(duì)代碼的分析以及keccak散列后的結(jié)果對(duì)比改抡,確定是
                Mint(address indexed to, uint256 amount)
                即對(duì)字符:Mint(address,uint256) 處理后的0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885
                這個(gè)日志矢炼,就是對(duì)第二個(gè)參數(shù)topics[1]的地址0xd53487c6b3a88dded611079b7ae7b377f4888550分發(fā)了data字段內(nèi)容(轉(zhuǎn)化后為809.709931333333333333),即轉(zhuǎn)了809.709931333333333333個(gè)Sether幣
            2. 第二個(gè)事件日志
                "address": "0x78b039921e84e726eb72e7b1212bb35504c645ca",
                "topics": [
                    "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
                    "0x0000000000000000000000000000000000000000000000000000000000000000",
                    "0x000000000000000000000000d53487c6b3a88dded611079b7ae7b377f4888550"
                ],
                "data": "0x00000000000000000000000000000000000000000000002be4fb8c854544b555"
                合約2觸發(fā)的事件阿纤,將代幣分配到某個(gè)地址的操作
                Transfer(address indexed from, address indexed to, uint256 value)
                對(duì)Transfer(address,address,uint256) 處理得0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
                從0x地址句灌,實(shí)際就是從空地址轉(zhuǎn)賬,也就是代幣增發(fā)(類似于系統(tǒng)又印了多少鈔票),然后分配給0xd53487c6b3a88dded611079b7ae7b377f4888550
                data字段是分配的具體數(shù)字: 809.709931333333333333
            3. 第三個(gè)事件日志
                "address": "0x20bf6672497941bd3e4ec5fd551de5c31e0a898a",
                "topics": [
                    "0xde080401e79886a3afdeac3fa6426ade55f095bfd9fbe1065b017f1e90479a86",
                    "0x000000000000000000000000d53487c6b3a88dded611079b7ae7b377f4888550",
                    "0x000000000000000000000000d53487c6b3a88dded611079b7ae7b377f4888550"
                ],
                "data": "0x000000000000000000000000000000000000000000000000181449a077eb7c0000000000000000000000000000000000000000000000002be4fb8c854544b555"
                這個(gè)是合約1觸發(fā)的事件日志
                SethTokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount)
                對(duì)字符:SethTokenPurchase(address,address,uint256,uint256) 處理后0xde080401e79886a3afdeac3fa6426ade55f095bfd9fbe1065b017f1e90479a86
                這件事我的理解就是胰锌,記錄了0xd53487c6b3a88dded611079b7ae7b377f4888550地址花了1.73509271 eth購買了809.709931333333333333 個(gè)Sether幣
                data字段是兩個(gè)字段骗绕,可以去除0x字符后,然后64位分割為兩個(gè)字段资昧,然后轉(zhuǎn)化為10進(jìn)制即可酬土。
    
  3. 遺留問題
    從普通地址轉(zhuǎn)賬給合約地址的eth,通過合約處理后格带,轉(zhuǎn)給了合約的錢包地址撤缴,這個(gè)交易信息,怎么獲燃蟆腹泌?
    被下面合約代碼處理了
    // 錢包地址調(diào)用transfer函數(shù),這個(gè)函數(shù)是一個(gè)公開函數(shù)尔觉,就是類似于evm中默認(rèn)有的
    wallet.transfer(msg.value);
    
    這種合約內(nèi)部的交易怎么處理凉袱?
    
    參考:合約內(nèi)部交易信息獲取

交易的真實(shí)數(shù)據(jù)信息如下

{
    "blockHash": "0xb385e463f51b3f482bf229fe8aa1a61ecfcd3a3619d617afe58517b42e56500a",
    "blockNumber": 4906655,
    "contractAddress": null,
    "cumulativeGasUsed": 2815773,
    "from": "0xd53487c6b3a88dded611079b7ae7b377f4888550",
    "gasUsed": 73886,
    "logs": [
        {
            "address": "0x78b039921e84e726eb72e7b1212bb35504c645ca",
            "topics": [
                "0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885",
                "0x000000000000000000000000d53487c6b3a88dded611079b7ae7b377f4888550"
            ],
            "data": "0x00000000000000000000000000000000000000000000002be4fb8c854544b555",
            "blockNumber": 4906655,
            "transactionHash": "0xd54e1fbc350dac428ca65a4abef6db4e343e1367e6cd9434bb14949a469cefc4",
            "transactionIndex": 105,
            "blockHash": "0xb385e463f51b3f482bf229fe8aa1a61ecfcd3a3619d617afe58517b42e56500a",
            "logIndex": 16,
            "removed": false
        },
        {
            "address": "0x78b039921e84e726eb72e7b1212bb35504c645ca",
            "topics": [
                "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
                "0x0000000000000000000000000000000000000000000000000000000000000000",
                "0x000000000000000000000000d53487c6b3a88dded611079b7ae7b377f4888550"
            ],
            "data": "0x00000000000000000000000000000000000000000000002be4fb8c854544b555",
            "blockNumber": 4906655,
            "transactionHash": "0xd54e1fbc350dac428ca65a4abef6db4e343e1367e6cd9434bb14949a469cefc4",
            "transactionIndex": 105,
            "blockHash": "0xb385e463f51b3f482bf229fe8aa1a61ecfcd3a3619d617afe58517b42e56500a",
            "logIndex": 17,
            "removed": false
        },
        {
            "address": "0x20bf6672497941bd3e4ec5fd551de5c31e0a898a",
            "topics": [
                "0xde080401e79886a3afdeac3fa6426ade55f095bfd9fbe1065b017f1e90479a86",
                "0x000000000000000000000000d53487c6b3a88dded611079b7ae7b377f4888550",
                "0x000000000000000000000000d53487c6b3a88dded611079b7ae7b377f4888550"
            ],
            "data": "0x000000000000000000000000000000000000000000000000181449a077eb7c0000000000000000000000000000000000000000000000002be4fb8c854544b555",
            "blockNumber": 4906655,
            "transactionHash": "0xd54e1fbc350dac428ca65a4abef6db4e343e1367e6cd9434bb14949a469cefc4",
            "transactionIndex": 105,
            "blockHash": "0xb385e463f51b3f482bf229fe8aa1a61ecfcd3a3619d617afe58517b42e56500a",
            "logIndex": 18,
            "removed": false
        }
    ],
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000800800000020008020000008000000000002000000000000200000000000000000000000020000000000000000000800000000000000400000000010000000000000000000000000000000200000000000000000000000000000000000000000000080000000000000000000000000000000002000000000000000000000000000000002000000000000000000000000000044000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000",
    "status": "0x1",
    "to": "0x20bf6672497941bd3e4ec5fd551de5c31e0a898a",
    "transactionHash": "0xd54e1fbc350dac428ca65a4abef6db4e343e1367e6cd9434bb14949a469cefc4",
    "transactionIndex": 105
}

合約1的代碼摘抄如下
合約1

....上半部分和合約2的代碼一樣....
部分代碼如下

contract MintableToken is StandardToken, Ownable {  
  // 定義的時(shí)間Mint
  event Mint(address indexed to, uint256 amount);
  event MintFinished();

  bool public mintingFinished = false;

  .....

  /**
   * @dev Function to mint tokens
   * @param _to The address that will receive the minted tokens.
   * @param _amount The amount of tokens to mint.
   * @return A boolean that indicates if the operation was successful.
   */
  // mint函數(shù)
  function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
    totalSupply = totalSupply.add(_amount);
    balances[_to] = balances[_to].add(_amount);
    // 調(diào)用Mint事件
    Mint(_to, _amount);
    // 調(diào)用Transfer事件進(jìn)行代幣分發(fā)
    Transfer(0x0, _to, _amount);
    return true;
  }

  ....
}

/**
 * @title SetherToken
 * @dev Sether ERC20 Token that can be minted.
 * It is meant to be used in sether crowdsale contract.
 */
// 繼承于MintableToken,可以使用它的函數(shù)調(diào)用
contract SetherToken is MintableToken {
    
    string public constant name = "Sether";
    string public constant symbol = "SETH";
    uint8 public constant decimals = 18;

    function getTotalSupply() public returns (uint256) {
        return totalSupply;
    }
}

/**
 * @title SetherBaseCrowdsale
 * @dev SetherBaseCrowdsale is a base contract for managing a sether token crowdsale.
 */
contract SetherBaseCrowdsale {
    using SafeMath for uint256;

    // The token being sold
    // 被分發(fā)的代幣
    SetherToken public token;

    ....

    // address where funds are collected
    // 募集的資金都轉(zhuǎn)到這個(gè)錢包地址
    address public wallet;

    ......

    /**
    * event for token purchase logging
    * @param purchaser who paid for the tokens
    * @param beneficiary who got the tokens
    * @param value weis paid for purchase
    * @param amount amount of tokens purchased
    */
    event SethTokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
    
    // 和合約名字一樣的函數(shù)侦铜,合約創(chuàng)建時(shí)自動(dòng)調(diào)用
    function SetherBaseCrowdsale(uint256 _rate, address _wallet) {
        require(_rate > 0);
        require(_wallet != address(0));
        // 創(chuàng)建代幣合約专甩,并存儲(chǔ)代幣合約地址
        token = createTokenContract();
        rate = _rate;
        // 錢包地址
        wallet = _wallet;
    }

    // fallback function can be used to buy tokens
    // fallback function 當(dāng)有賬戶向這個(gè)地址轉(zhuǎn)真實(shí)的eth時(shí),自動(dòng)觸發(fā)這個(gè)函數(shù)
    function () payable {
        // 調(diào)用buyTokens函數(shù)
        buyTokens(msg.sender);
    }

    // low level token purchase function
    function buyTokens(address beneficiary) public payable {
        ....
        // 代幣調(diào)用mint函數(shù)钉稍,進(jìn)而觸發(fā)這個(gè)函數(shù)中事件
        token.mint(beneficiary, tokens);
        // 觸發(fā)SethTokenPurchase事件
        SethTokenPurchase(msg.sender, beneficiary, weiAmount, tokens);
        // 調(diào)用forwardFunds函數(shù)
        forwardFunds();
    }
    
    // send ether to the fund collection wallet
    // 將收到的eth轉(zhuǎn)到錢包地址
    function forwardFunds() internal {
        // 錢包地址調(diào)用transfer函數(shù)涤躲,這個(gè)函數(shù)是一個(gè)公開函數(shù),就是類似于evm中默認(rèn)有的
        wallet.transfer(msg.value);
    }

    .....
}

/**
 * @title SetherMultiStepCrowdsale
 * @dev Multi-step payment policy contract that extends SetherBaseCrowdsale
 */
contract SetherMultiStepCrowdsale is SetherBaseCrowdsale {
    .....
}

/**
 * @title SetherCappedCrowdsale
 * @dev Extension of SetherBaseCrowdsale with a max amount of funds raised
 */
contract SetherCappedCrowdsale is SetherMultiStepCrowdsale {
    .....
}

/**
 * @title SetherStartableCrowdsale
 * @dev Extension of SetherBaseCrowdsale where an owner can start the crowdsale
 */
contract SetherStartableCrowdsale is SetherBaseCrowdsale, Ownable {
  .....
}

/**
 * @title SetherFinalizableCrowdsale
 * @dev Extension of SetherBaseCrowdsale where an owner can do extra work
 * after finishing.
 */
contract SetherFinalizableCrowdsale is SetherBaseCrowdsale, Ownable {
  .....
}

/**
 * @title SetherCrowdsale
 * @dev This is Sether's crowdsale contract.
 */
contract SetherCrowdsale is SetherCappedCrowdsale, SetherStartableCrowdsale, SetherFinalizableCrowdsale {
    .....
}

合約2的代碼摘抄如下贡未,合約2的代碼就是合約1代碼的上半部分
合約2<SetherToken>

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  ....
}

library SafeMath {
  ....
}

contract ERC20Basic {
  ....
}

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20 is ERC20Basic {
  ....
}

contract BasicToken is ERC20Basic {
  ....
}

/**
 * @title Standard ERC20 token
 *
 * @dev Implementation of the basic standard token.
 * @dev https://github.com/ethereum/EIPs/issues/20
 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
 */
contract StandardToken is ERC20, BasicToken {
    ....
}

contract MintableToken is StandardToken, Ownable {
  ....
}

/**
 * @title SetherToken
 * @dev Sether ERC20 Token that can be minted.
 * It is meant to be used in sether crowdsale contract.
 */
contract SetherToken is MintableToken {
    ....
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末种樱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子俊卤,更是在濱河造成了極大的恐慌嫩挤,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件消恍,死亡現(xiàn)場(chǎng)離奇詭異岂昭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)狠怨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門约啊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人佣赖,你說我怎么就攤上這事恰矩。” “怎么了茵汰?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵枢里,是天一觀的道長。 經(jīng)常有香客問我蹂午,道長栏豺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任豆胸,我火速辦了婚禮奥洼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘晚胡。我一直安慰自己灵奖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布估盘。 她就那樣靜靜地躺著瓷患,像睡著了一般。 火紅的嫁衣襯著肌膚如雪遣妥。 梳的紋絲不亂的頭發(fā)上擅编,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音箫踩,去河邊找鬼爱态。 笑死,一個(gè)胖子當(dāng)著我的面吹牛境钟,可吹牛的內(nèi)容都是我干的锦担。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼慨削,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼洞渔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起缚态,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤磁椒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后猿规,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衷快,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年姨俩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蘸拔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡环葵,死狀恐怖调窍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情张遭,我是刑警寧澤邓萨,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響缔恳,放射性物質(zhì)發(fā)生泄漏宝剖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一歉甚、第九天 我趴在偏房一處隱蔽的房頂上張望万细。 院中可真熱鬧,春花似錦纸泄、人聲如沸赖钞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雪营。三九已至,卻和暖如春衡便,著一層夾襖步出監(jiān)牢的瞬間献起,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工砰诵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留征唬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓茁彭,卻偏偏與公主長得像总寒,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子理肺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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