Fantastic Bugs - The Stanford Center for Blockchain Researchblowing bugs” “The Certora-Prover...

Preview:

Citation preview

& how to automatically find themusing reusable invariants

J A N U A R Y 2 0 2 0 2020

Mooly Sagiv

Fantastic Bugs

Keeping your code secure forever

Free demo & user-guide at demo.certora.com

The Certora Team

Shelly GrossmanChief Scientist

Dr. James WilcoxCTO

Dr. Nurit DorHead of Product

Dr. John TomanFormal Verification Expert

Lior OppenheimSecurity Researcher

Marcelo Taube Product Architect

Thomas BernardiSoftware Engineer

Or PistinerSoftware Engineer

Dr. Alexander NutzFormal Verification Expert

Anastasia Fedotov Software

Engineer

And also

Noam RinetzkyNeil ImmermanUMASS

Daniel Jackson MIT

“…Certora's technology is used daily to locate mind blowing bugs”

“The Certora-Prover has already surfaced significant problems missed by expensive and unscalable manual audits."

“Certora’s Prover tool has already uncovered a number of nuanced bugsand also mathematically proved interesting properties of linked lists.”

Top tier customers

Geoff Hayes, CTO Shamiq Islam, Head of Security Marek Olszweski, Founder

Prover (SaaS)

Code Invariants“what we should do”

Yes

No

Product: Continuous Code Verification

Proofs forguaranteedinvariants

Test cases with inputs showing actual invariantviolations

Customer Code“what we do”V1

V2

V3

MOVEFAST AND

BREAK NOTHING

S a: address balances[a]

transfer (from, to, amount) {require (balances[from] ³ amount);balancesFrom := balances[from] - amount;balancesTo := balances[to] + amount;balances[from] := balancesFrom;balances[to] := balancesTo;

}

Code:

balances@start[from] ³ amountbalancesFrom = balances@start[from] – amountbalancesTo = balances@start[to] + amountbalances[from] = balancesFrom balances[to] = balancesTobalances[from] + balances[to] ¹

balances@start[from] + balances@start[to]

Constraints:

Secret Sauce: Constraint Solving

from=“Alice”to=“Alice”amount = 18balances@start[Alice] = 20balances[Alice] = 38

Solution:Invariant:

The Bug

transfer (Alice, Alice, 18) {require (balances[from] ³ 18);balancesFrom := balances[from] - 18;balancesTo := balances[to] + 18;balances[from] := balancesFrom; balances[to] := balancesTo;

}

Balances [Alice] balances[from] balances[to]

20

The Bug

transfer (Alice, Alice, 18) {require (balances[from] ³ 18);balancesFrom := balances[from] - 18;balancesTo := balances[to] + 18;balances[from] := balancesFrom; balances[to] := balancesTo;

}

Balances [Alice] balances[from] balances[to]

20 2

The Bug

transfer (Alice, Alice, 18) {require (balances[from] ³ 18);balancesFrom := balances[from] - 18;balancesTo := balances[to] + 18;balances[from] := balancesFrom; balances[to] := balancesTo;

}

Balances [Alice] balances[from] balances[to]

20 2 38

The Bug

transfer (Alice, Alice, 18) {require (balances[from] ³ 18);balancesFrom := balances[from] - 18;balancesTo := balances[to] + 18;balances[from] := balancesFrom; balances[to] := balancesTo;

}

Balances [Alice] balances[from] balances[to]

2 2 38

The Bug

transfer (Alice, Alice, 18) {require (balances[from] ³ 18);balancesFrom := balances[from] - 18;balancesTo := balances[to] + 18;balances[from] := balancesFrom; balances[to] := balancesTo;

}

Balances [Alice] balances[from] balances[to]

38 2 38

S a: address balances[a]

Invariant:

S a: address balances[a]

from ¹ tobalances@start[from] ³ amountbalancesFrom = balances@start[from] – amountbalancesTo = balances@start[to] + amountbalances[from] = balancesFrom balances[to] = balancesTobalances[from] + balances[to] ¹

balances@start[from] + balances@start[to]

transfer (from, to, amount) {require(from != to);require (balances[from] ³ amount);balancesFrom := balances[from] - amount;balancesTo := balances[to] + amount;balances[from] := balancesFrom;balances[to] := balancesTo;

}

Code:Constraints:

Secret Sauce: Constraint Solving

Invariant:A mathematical proof that the invariant is maintained

Myths and Reality about Formal Verification

Myths: Reality:

FV can only prove absence of bugs Biggest value of FV is finding bugs

Hardest problem is computational Hardest problem is specification

FV has to be done at accurate machine level Abstraction is key to scalability:- Natural vs. bit-vector arithmetic- Memory abstraction- Loop abstraction- Ignore gas

Must consider all objects at once Modularity concept enable scalability

FV is one-time deal FV guarantees code upgrade safety

The Bounded Supply Invariant (ERC20 tokens)

“Nobody should be able to mint unbounded number of tokens”

Shamiq IslamHead of Security,

Minted tokens < predefined amount

MakerDao Test Version

Bid value

new()

Alice’s bid

Bob’s bid

close()

Max UINT

Total supply increases by Bob’s bid and transferred

to Bob

bid() bid()

Initial bid

Time

Total supply value

Auction end time

Charlie’s bid

bid()

MakerDao Test Version

Bidvalue

new() close()

Max UINT

bid()Time

Total supply value

Mallory’s bid

Total supply increases by Mallory’s bid and

transferred to MalloryBecomes Max UINT!

Bid expiry time

Checking the bounded supply invariant

Fixing the Code

function close(uint id) public {require(auctions[id].bid_expiry != 0

&& (auctions[id].bid_expiry < now || auctions[id].end_time < now));

require(auctions[id].prize.safeAdd(auctions[id].prize)+ getTotalSupply() >= getTotalSupply());

mint(auctions[id].winner, auctions[id].prize);delete auctions[id];}

Checking the bounded supply invariant

High Level Smart Contract Invariants

Immunity to reentrancy attack DAO, SpankChain, Constantinople fork

Robustness

Bounded Token Supply

Informal Property: Bugs Found:

Compound V1 Price Oracle

Maker MCD

Proportional token distribution Compound V2, Maker MCD

Any loan can be fully repaid

Sufficient reserves

Compound V2

Several tokens, Maker MCD

Shelly @ Certora Geoff Hayes @ Compound Shamiq Islam @ Coinbase Jared Flatow @ Compound

Correctness rules for Debt (Compound Finance)

function repayBehalfExplicit(address borrower, CEther cEther_) public payable {

uint received = msg.value;uint borrows = cEther_.borrowBalanceStored(borrower);if (received > borrows) {

cEther_.repayBorrowBehalf.value(borrows)(borrower);msg.sender.transfer(received - borrows);

} else {cEther_.repayBorrowBehalf.value(received)(borrower);

}}

Any debt can be paid off: repayAmount ≥ borrowed è newBorrowBalance = 0

Correctness rules for Debt (Compound Finance)

2530

5

6

0

5

10

15

20

25

30

35

40

… 8 9 10 …

Debt

Repay Ξ 40

Time

Refunded Ξ 10Accrued Ξ 6 interest in 9: > 0 outstanding borrow

6

1

Any debt can be paid off: repayAmount ≥ borrowed è newBorrowBalance = 0

Correctness rules for Debt (Compound Finance)

Any debt can be paid off: repayAmount ≥ borrowed è newBorrowBalance = 0

function repayBehalfExplicit(address borrower, CEther cEther_) public payable {

uint received = msg.value;uint borrows = cEther_.borrowBalanceStored(borrower);if (received > borrows) {

cEther_.repayBorrowBehalf.value(borrows)(borrower);msg.sender.transfer(received - borrows);

} else {cEther_.repayBorrowBehalf.value(received)(borrower);

}}

Correctness rules for Debt (Compound Finance)

Any debt can be paid off: repayAmount ≥ borrowed è newBorrowBalance = 0

function repayBehalfExplicit(address borrower, CEther cEther_) public payable {

uint received = msg.value;uint borrows = cEther_.borrowBalanceStored(borrower);if (received > borrows) {

cEther_.repayBorrowBehalf.value(borrows)(borrower);msg.sender.transfer(received - borrows);

} else {cEther_.repayBorrowBehalf.value(received)(borrower);

}}

cEther_.borrowBalanceCurrent(borrower);

Summary

Software specification is the holy grail of computer science

Reusable invariants provide a layer of security used for early bug detection

Community effort

Code is the law è Spec is the law

1

34

2

Thank you! Mooly Sagivmooly@certora.com

Twitter@SagivMooly

www.certora.com

+1-617-650-4612

+972-548-303-111

2020

Recommended