Certifying functional correctness of Ethereum smart contracts Dr. Petar Tsankov Co-founder and Chief scientist, ChainSecurity Senior researcher, ICE center, ETH Zurich @ptsankov
Inter-disciplinary research center at Next-generation blockchain security the #1 CS department in Europe using automated reasoning https://chainsecurity.com @chain_security Blockchain Safety of AI Security security and privacy
What do these have in common? contract Token { mapping(addr=>uint) balances; function balanceOf(address a){ return balances[a]; Must not fail! } function transfer(address to, uint n){ balances[msg.sender] -= n; balances[to] += n; }
What sets them apart ? contract Token { mapping(addr=>uint) balances; function balanceOf(address a){ return balances[a]; } Certified using formal verification Ce Be Best-ef effor ort function transfer(address to, uint n){ balances[msg.sender] -= n; balances[to] += n; }
What sets them apart ? contract Token { mapping(addr=>uint) balances; function balanceOf(address a){ return balances[a]; } Certified using formal verification Ce Be Best-ef effor ort function transfer(address to, uint n){ balances[msg.sender] -= n; balances[to] += n; }
Our mission Bring formal security guarantees to contracts - Mathematically model all behaviors of smart contracts - Prove that no bugs can occur - Scale via automation and state-of-the-art research
Our mission Bring formal security guarantees to contracts VerX Formal verifier for certifying custom functional - Mathematically model all behaviors of smart contracts specifications of Ethereum contracts - Prove that no bugs can occur - Scale via automation and state-of-the-art research
Why is it hard to ce certify the custom behavior of smart contracts? Note: Find generic vulnerabilities Certify cu custom m behavior
Functional correctness Crowdsale Escrow uint raised; mapping(address => uint) deposits; uint goal; uint closeTime; function deposit() { .. } function withdraw() { .. } function invest() { .. } function claimRefund() { .. } function close(){ .. } Requirements Sum of all deposits equals the escrow’s ether balance - Investors cannot claim refunds after the goal is reached -
Step 1: Fo Formalize requirements (Informal) requirement: ”Sum of all deposits equals the escrow’s ether balance” Formal property always sum(Escrow.deposits) == Escrow.balance)
Step 2: Ch Check formal property Initial state invest(0) invest(9999) claimRefund() ... ... claimRefund() invest (0) invest(9999) Unbounded depth Infeasible to brute-force width
Methods and guarantees RELIABILITY Time consuming - Manual review Ca Can miss errors -
Methods and guarantees RELIABILITY Fuzzing - Automated testing Symbolic execution - Ca Can mi miss er errors - Time consuming - Manual review Ca Can miss errors -
Checked states Fuzzing Missed states Initial state invest(9999) invest(0) claimRefund() ... ... claimRefund() invest (0) invest(9999) Tools: ChainFuzz, Echidna, ContractFuzzer, Harvey, … To
Checked states Symbolic execution Missed states Initial state invest(9999) invest(0) claimRefund() ... ... invest (0) invest(9999) claimRefund() Tools: Oyente, Manticore, Mythril, MAIAN, … To
Methods and guarantees Automated program - Formal verification RELIABILITY verification Prove Pr ves absence of errors - Fuzzing - Automated testing Symbolic execution - Ca Can mi miss er errors - Time consuming - Manual review Ca Can miss errors -
Checked states Formal verification invest(0) invest(0) invest(9999) invest(9999) claimRefund() claimRefund() ... ... ... ... VerX claimRefund() claimRefund() invest (0) invest (0) invest(9999) invest(9999)
Automated formal verification with VerX “Investors can claim refunds only if the sum of deposits never exceeded 10,000 ether “ Smart contract Formal property mapping(address => uint) deposits; (always Escrow.claimRefund function claimRefund(){..} ==> !before(sum(deposits) >= 10000) Ve Verified Ma May not t hold
Expressive and intuitive specifications always Escrow.deposit(address) Access control ==> (msg.sender == Escrow.owner)
Expressive and intuitive specifications always Escrow.deposit(address) Access control ==> (msg.sender == Escrow.owner) State-based always (now > Vault.refundTime + 1 week) properties ==> ! Vault.refund(uint256)
Expressive and intuitive specifications always Escrow.deposit(address) Access control ==> (msg.sender == Escrow.owner) State-based always (now > Vault.refundTime + 1 week) properties ==> ! Vault.refund(uint256) State machine always !(once(state == REFUND) properties && once(state == FINALIZED)
Expressive and intuitive specifications always Escrow.deposit(address) Access control ==> (msg.sender == Escrow.owner) State-based always (now > Vault.refundTime + 1 week) properties ==> ! Vault.refund(uint256) State machine always !(once(state == REFUND) properties && once(state == FINALIZED) Invariants over always totalSupply == sum(balances) aggregates
Expressive and intuitive specifications always Escrow.deposit(address) Access control ==> (msg.sender == Escrow.owner) State-based always (now > Vault.refundTime + 1 week) properties ==> ! Vault.refund(uint256) State machine always !(once(state == REFUND) properties && once(state == FINALIZED) Invariants over always totalSupply == sum(balances) aggregates Multi-contract always Token.totalSupply >= Sale.issuance invariants
Expressive and intuitive specifications always Escrow.deposit(address) Access control ==> (msg.sender == Escrow.owner) State-based always (now > Vault.refundTime + 1 week) properties ==> ! Vault.refund(uint256) Solid formal foundation State machine always (! once(state == REFUND) (Temporal logic) properties && once(state == FINALIZED) Invariants over always totalSupply == sum(balances) aggregates Multi-contract always Token.totalSupply >= Sale.issuance invariants
Dealing with unbo unded state spaces unbounde Use symbolic (not concrete) Initial state values invest(X) claimRefund(Y) Bounded depth Use program invest(X) claimRefund(Y) abstraction Feasible width
Sound symbolic reasoning - Hash-based storage allocation - Gas mechanics - Calls to untrusted contracts - Dynamically constructed contracts
Impact and experience Fast and sc scalable formal verification of Ethereum contracts Fa (157+ contracts, 100+ properties, ~1 min / property) Benefits: - Certif Ce tify what works (go beyond bug finding) - Re Re-us use libraries of common specifications - cation is cheap Re Re-ce certi rtificati
How to get access to VerX? Demo: http://verx.ch VerX as a service: contact@chainsecurity.com
One more announcement…
First automated framework for testing Solidity compilers
First automated framework for testing Solidity compilers
First automated framework for testing Solidity compilers https://github.com/eth-sri/soltix https://discord.gg/XKSVavS
Safety certification of contracts VerX: Automated formal verification “Investors can claim refunds only if the sum of deposits never exceeded 10,000 ether “ Formal property Smart contract contract Token { mapping(addr=>uint) balances; mapping(address => uint) deposits; function balanceOf(address a){ (always Escrow.claimRefund return balances[a]; } Must not fail! function claimRefund(){..} function transfer(address to, ==> !before(sum(deposits) >= 10000) uint n){ balances[msg.sender] -= n; balances[to] += n; } Ve Verified May not hold Ma Methods and techniques Symbolic reasoning + abstraction Initial state invest(X) claimRefund(Y) - Automated program Formal verification - RELIABILITY verification Proves absence of errors Pr invest(X) claimRefund(Y) - Fuzzing - Symbolic execution Automated testing - Ca Can mis miss er errors - Time consuming Bounded depth - Manual review Can miss errors Ca Feasible width
Recommend
More recommend