a formal verification tool for ethereum vm bytecode
play

A Formal Verification Tool for Ethereum VM Bytecode Daejun Park Yi - PowerPoint PPT Presentation

A Formal Verification Tool for Ethereum VM Bytecode Daejun Park Yi Zhang Manasvi Saxena Philip Daian Grigore Rosu Nov 7, 2018 @ FSE18 Smart contracts Programs that run on blockchain Usually written in a high-level


  1. A Formal Verification Tool for Ethereum VM Bytecode Daejun Park Yi Zhang Manasvi Saxena Philip Daian Grigore Rosu � Nov 7, 2018 @ FSE’18

  2. Smart contracts • Programs that run on blockchain • Usually written in a high-level language • Solidity (JavaScript-like), Vyper (Python-like), … • Compiled down to VM bytecode • EVM (Ethereum VM), IELE (LLVM-like VM), … our target • Runs on VM of blockchain nodes

  3. Smart contract example function transfer( address from, address to, uint256 value) returns ( bool ) { � if ( balances[from] >= value ) { balances[to] =+ value; balances[from] -= value; � return true; } else { return false; } }

  4. Smart contract example function transfer( address from, address to, uint256 value) returns ( bool ) { � if ( balances[from] >= value ) { ‘ =+ ’ vs ‘ += ’ balances[to] =+ value; balances[from] -= value; � return true; } else { return false; } } * ETHNews.com, “Ether.Camp’s HKG Token Has A Bug And Needs To Be Reissued”

  5. Smart contract example function transfer( address from, address to, uint256 value) returns ( bool ) { � if ( balances[from] >= value ) { balances[to] = (+ value ) ; balances[from] -= value; � return true; } else { return false; } } * ETHNews.com, “Ether.Camp’s HKG Token Has A Bug And Needs To Be Reissued”

  6. Smart contract example function transfer( address from, address to, uint256 value) returns ( bool ) { � if ( balances[from] >= value ) { balances[to] = value; balances[from] -= value; � return true; } else { return false; } } * ETHNews.com, “Ether.Camp’s HKG Token Has A Bug And Needs To Be Reissued”

  7. Smart contract example function transfer( address from, address to, uint256 value) returns ( bool ) { � if ( balances[from] >= value ) { balances[to] += value; balances[from] -= value; � return true; } else { return false; } }

  8. Smart contract example function transfer( address from, address to, uint256 value) returns ( bool ) { � if ( balances[from] >= value ) { balances[to] + = value; arithmetic overflow balances[from] -= value; � return true; } else { return false; } }

  9. Smart contract example function transfer( address from, address to, uint256 value) returns ( bool ) { � if ( balances[from] >= value ) { balances[to] = SafeMath.add (balances[to], value); balances[from] -= value; will throw if overflow � return true; } else { return false; } }

  10. Smart contract example function transfer( address from, address to, uint256 value) returns ( bool ) { � if ( balances[from] >= value ) { balances[to] = SafeMath.add (balances[to], value); balances[from] -= value; � return true; } else { return false; } }

  11. Smart contract example function transfer( address from , address to , uint256 value) returns ( bool ) { � if ( balances[from] >= value ) { balances[to] = SafeMath.add (balances[to], value); balances[from] -= value; self-transfer may fail � return true; } else { return false; } }

  12. Smart contract example function transfer( address from , address to , uint256 value) returns ( bool ) { � if ( balances[from] >= value ) { � balances[from] -= value; balances[to] = SafeMath.add (balances[to], value); return true; more robust } else { return false; } }

  13. Why bytecode? address: 0x01 interface Token { contract GoodToken { function transfer() returns ( bool ); function transfer() { } return true; � } contract Wallet { } function transfer( address token) { address: 0x02 return Token(token).transfer(); } contract BadToken { } function transfer() { } }

  14. Why bytecode? address: 0x01 interface Token { contract GoodToken { function transfer() returns ( bool ); function transfer() { } return true; � } contract Wallet { } function transfer( address token) { address: 0x02 return Token(token).transfer(); } contract BadToken { if token = 0x01 } function transfer() { } }

  15. Why bytecode? address: 0x01 interface Token { contract GoodToken { function transfer() returns ( bool ); function transfer() { } return true; � } contract Wallet { } function transfer( address token) { address: 0x02 return Token(token).transfer(); } contract BadToken { if token = 0x02 } function transfer() { } }

  16. Why bytecode? address: 0x01 interface Token { contract GoodToken { function transfer() returns ( bool ); function transfer() { } return true; � } contract Wallet { } function transfer( address token) { address: 0x02 return Token(token).transfer(); } contract BadToken { if token = 0x02 } function transfer() { } }

  17. Why bytecode? address: 0x01 interface Token { contract GoodToken { function transfer() returns ( bool ); function transfer() { } return true; � } contract Wallet { } function transfer( address token) { address: 0x02 return Token(token).transfer(); } contract BadToken { if token = 0x02 } function transfer() { } } • Return true in Solidity 0.4.21 or earlier • Revert in Solidity 0.4.22 or later (latest: 0.4.25) * Lukas Cremer, “Missing return value bug — At least 130 tokens affected”

  18. K EVM Verifier � � � � Smart contract � Bytecode � K EVM Verifier � Specification � (+ loop invariants) � � �

  19. K EVM Verifier Abstractions Lemmas Smart contract Bytecode Deductive Verifier [OOPSLA’16] Specification (+ loop invariants) EVM Semantics [CSF’18] K EVM Verifier

  20. Specification example [transfer-success] � callData : #abiCallData(“ transfer ", #address( FROM ), #address( TO ), #uint256( VALUE )) � storage : #( BALANCES[FROM] ) ⟼ (BAL_FROM ⟹ BAL_FROM - VALUE ) #( BALANCES[TO] ) ⟼ (BAL_TO ⟹ BAL_TO + VALUE ) � requires : FROM ≠ TO VALUE ≤ BAL_FROM BAL_TO + VALUE < (2 ^ 256) true � output : function transfer( address from , address to , _ ⟹ #asByteArray( 1 , 32) uint256 value) returns ( bool ) { ! � if ( balances[from] >= value ) { ! true statusCode : balances[from] -= value; balances[to] = SafeMath.add (balances[to], value); _ ⟹ EVMC_SUCCESS return true; } else { return false; } }

  21. Verified smart contracts* • High-profile ERC20 token contracts • Ethereum Casper FFG (Hybrid PoW/PoS) • Gnosis MultiSigWallet (ongoing) • DappHub MakerDAO (by DappHub) • Uniswap (decentralized exchange) • Bihu (KEY token operation) * https://github.com/runtimeverification/verified-smart-contracts

  22. Challenges for EVM bytecode verification • Byte-twiddling operations • Non-linear integer arithmetic 
 (e.g., modulo reduction) • Arithmetic overflow detection • Gas limit • Variable gas cost depending on contexts • Hash collision

  23. Byte-twiddling operations Given: x [ n ] def = ( x/ 256 n ) mod 256 merge ( x [ i..j ]) def = merge ( x [ i..j + 1]) * 256 + x [ j ] when i > j merge ( x [ i..i ]) def = x [ i ] Prove: ve “ x = merge ( x [31 .. 0]) ”. ple by omitting the modu

  24. Abstractions syntax Int ::= nthByte(Int, Int, Int) [function] � � � rule merge(nthByte(V, 0, N) ... nthByte(V, N-1, N)) ⟹ V requires 0 ≤ V < 2 ^ (N * 8) and 1 ≤ N ≤ 32

  25. Challenges for EVM bytecode verification • Byte-twiddling operations • Non-linear integer arithmetic 
 (e.g., modulo reduction) • Arithmetic overflow detection • Gas limit • Variable gas cost depending on contexts • Hash collision

  26. Smart contract example Why bytecode? address: 0x01 interface Token { contract GoodToken { function transfer() returns ( bool ); function transfer() { function transfer( address from , } return true; address to , ! } uint256 value) returns ( bool ) { contract Wallet { } function transfer( address token) { ! address: 0x02 return Token(token).transfer(); if ( balances[from] >= value ) { } contract BadToken { ! if token = 0x02 } function transfer() { } balances[from] -= value; } balances[to] = SafeMath.add (balances[to], value); return true; } else { • Return true in Solidity 0.4.21 or earlier return false; } } • Revert in Solidity 0.4.22 or later * Lukas Cremer, “Missing return value bug — At least 130 tokens affected” https://github.com/runtimeverification/verified-smart-contracts K EVM Verifier Specification example [transfer-success] ! callData : Abstractions #abiCallData(" transfer ", #address( TO ), #uint256( VALUE )) Lemmas ! storage : Smart contract YES #( BALANCES[FROM] ) ⟼ (BAL_FROM ⟹ BAL_FROM - VALUE ) Bytecode Deductive #( BALANCES[TO] ) ⟼ (BAL_TO ⟹ BAL_TO + VALUE ) Verifier ! [OOPSLA’16] requires : Specification FROM ≠ TO NO (+ loop invariants) VALUE ≤ BAL_FROM EVM BAL_TO + VALUE < (2 ^ 256) Semantics ! [CSF’18] statusCode : _ ⟹ EVMC_SUCCESS true ! K EVM Verifier output : _ ⟹ #asByteArray( 1 , 32)

  27. Backup

  28. Overflow bug exploit function batchTransfer( address [] receivers, uint256 value) public whenNotPaused returns ( bool ) { � overflow uint cnt = receivers.length; uint256 amount = uint256 (cnt) * value; require (cnt > 0 && cnt <= 20); require (value > 0 && balances[msg.sender] >= amount); � balances[msg.sender] = balances[msg.sender].sub(amount); � for ( uint i = 0; i < cnt; i++) { balances[receivers[i]] = balances[receivers[i]].add(value); Transfer(msg.sender, receivers[i], value); } � return true; missed by both Oyente and Securify at that time } * https://twitter.com/vietlq/status/989266840315727872 * https://twitter.com/vietlq/status/989348032046157824

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend