EIP-1283の脆弱性の解決方法


#1

Constantinopleへのupdateを延期する原因となったRe-Entrancy攻撃につながるSSTOREガスコストの見直しにおける脆弱性を解決する方法を議論したい。

関連記事:
https://blog.ethereum.org/2019/01/15/security-alert-ethereum-constantinople-postponement/
https://medium.com/chainsecurity/constantinople-enables-new-reentrancy-attack-ace4088297d9
https://www.coindesk.com/ethereums-constantinople-upgrade-faces-delay-due-to-security-vulnerability

なんで延期になったの?:
re-entrancyが可能だから延期になったわけではなく、transferをトリガーにしてcallされたfallback関数からContractのstateを変更できたことが問題の本質と思われます。仕様として定義されている安全に送金が行えるためのgas limitとしてcallstipendというcostが定義されています。具体的な数字は2300です。この範囲内ではConstantinople以前ではContractのstorageの書き換えは不可能でした。なぜならば、storageの書き換えには5000gasが必ずかかるためです。(0クリアだとしても2500かかります。5000がcost計上され、その後15000がrefundとして計上されますが、実際にrefundされるのはcostの50%までのためです。)
今回はEIP-1823によってdirty storageに対しての書き換えコストが最低200に低減されたため、安全とみなされていたstipendのgas量の範囲内でcontractのstorageを書き換えられてしまうという、仕様を満たさない状況が発生したため、updateを延期したと思われます。
なお、以上の情報は裏付けされるソースがないので多分に僕の想像が含まれていることはご了承ください。

で、ここで議論したいのはEIP-1283のシンプルさを保ちつつ、この問題をどのようにしたら解決できるのか?を議論したいです。
クリアしたい条件を箇条書きにすると以下の通りです。

  1. transferでの送金に対しては、それ以降のContractのstate変更は抑制したい。(今回の問題の本質部分の解決)
  2. dirty storageの判定をできるだけシンプルにしたい。EIP-1283とイコールであることが理想。
  3. sstoreのコスト低減はできるだけ多くの状況で教授したい。一度でもtransferを呼び出したらdirty mapをクリアする。とかにすると何となく、EIP-1283の恩恵はほとんど生かせなくなると思う。

#2

その他のdiscusion forum:
https://ethereum-magicians.org/t/remediations-for-eip-1283-reentrancy-bug/2434/2
https://ethresear.ch/t/constantinople-sstore-vulnerability/4824/2


#3

trail of bitsによるEIP-1283のreviewと新しい解決提案