Skip to content

Commit 2848cfb

Browse files
authored
Merge pull request #61 from Certora/liav/CERT-5336-V7-Examples
Liav/cert 5336 v7 examples
2 parents 345eef2 + 4a6a349 commit 2848cfb

File tree

23 files changed

+236
-31
lines changed

23 files changed

+236
-31
lines changed

CLIFlags/Helpers/Fibonacci.sol

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: AGPL-3.0-only
2+
3+
pragma solidity >=0.8.0;
4+
5+
6+
contract Fibonacci {
7+
function fibonacci(uint32 i) external returns (uint32) {
8+
if(i == 1 || i == 2) {
9+
return 1;
10+
}
11+
return this.fibonacci(i- 1) + this.fibonacci(i - 2);
12+
}
13+
}

CLIFlags/Helpers/Fibonacci.spec

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
methods {
2+
function fibonacci(uint32) external returns (uint32) envfree;
3+
}
4+
5+
rule fibonacciMonotonicallyIncreasing {
6+
uint32 i1;
7+
uint32 i2;
8+
9+
assert i2 > i1 => fibonacci(i2) >= fibonacci(i1);
10+
}
11+
12+
rule fifthFibonacciElementIsFive {
13+
assert fibonacci(5) == 5;
14+
}

CLIFlags/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@ For more information about available CLI options go to: https://docs.certora.com
1515
| [--independent_satisfy](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#independent-satisfy) | |
1616
| [--rule_sanity](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#rule-sanity) | [none](https://prover.certora.com/output/15800/16fdf7aa282243e591889d9ec27a71ef?anonymousKey=6bdd16c5780e0127246ddc3eea3ee8a22c9729b8) / [basic](https://prover.certora.com/output/15800/2c5aa93c4bc54a939dea395202c0e47c?anonymousKey=bf07b5bdc3a7c7b28fda762942b02456731d2371) / [advanced](https://prover.certora.com/output/15800/e44ef408e1794a8fa32178f63fbe83da?anonymousKey=4afd4e7f98fc3d11d03b0a8522d417a2671f70fe) |
1717
| [--solc](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#solc) | [ERC20 compiled with solc8.0](https://prover.certora.com/output/15800/aa8e3c59b7434058a1f0927f6cd1da77?anonymousKey=099deb423f4cb86913f8a536309ea8a64511ca46) / [compiled with solc8.10](https://prover.certora.com/output/15800/c67c4072730d40f7b081556ddf78334e?anonymousKey=e9d7ffddc9f338e3a865505fbbe18f095823ae43) |
18-
| [--solc_map](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#solc-map) | |
19-
| [--solc_optimize](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#solc-optimize) | |
2018
| [--solc_via_ir](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#solc-via-ir) | [false](https://prover.certora.com/output/15800/83116717cc7a48f5b53172666a83817e?anonymousKey=0a5ee559275dcb173b18a69caeda4f33a2b8f014) / [true](https://prover.certora.com/output/15800/4a29b3f21b884b8d8fc5550f61fa45b7?anonymousKey=f1909b5b181ae4534377501a3c06c896bfff2d67) |
2119
| [--solc_evm_version](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#solc-evm-version) | [ERC20 with Berlin](https://prover.certora.com/output/15800/1d55dc0613b444f2a690fce8f645d9d1?anonymousKey=9efa9f0b59bfc8c37aa7c9d0d8573c9d99f1c2cf) / [ERC20 with London](https://prover.certora.com/output/15800/115e1f215f344fefb7dd389cb4db9d9f?anonymousKey=75c515fd97ff0ae21b887b5915db180d807dc9d2) |
2220
| [--solc_allow_path](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#solc-allow-path) | Every conf example in this folder has it. |
2321
| [--packages_path](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#packages-path) | |
2422
| [--packages](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#packages) | |
23+
| --optimistic_fallback | [false](https://prover.certora.com/output/15800/5f15bade773a4d5c9494408d3751156c?anonymousKey=c28bae503fe3444c21adc2971bda5a2f74e685cc) / [true](https://prover.certora.com/output/15800/a23a21a8ef9642ba83d97547fc361b70?anonymousKey=596e02bc0b6976504873489348d118bdbb2abb7f) notice rule storageAfterTwoWithdrawalsFromInitDoesNotChange |
2524
| [--optimistic_loop](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#optimistic-loop) | [false](https://prover.certora.com/output/15800/8db8b5eaeb244ba490394e05edac0fe1?anonymousKey=5067d0c0908cc2f1cb348e8b163bfec327884cee) / [true](https://prover.certora.com/output/15800/89e59b62f44f439c9502363cef4e7b49?anonymousKey=bac549ca44168b6e0b282a980240c247b34d77ee) |
2625
| [--loop_iter](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#loop-iter) | [A run with 1 loop unrolling](https://prover.certora.com/output/15800/9b085d85bcc345d5bd2612f8bea5da98?anonymousKey=a6c544d73525dcb582eba2b971d85d97c16b35db) / [Same run with 3 loop unrolling](https://prover.certora.com/output/15800/0b152fe8cfcc41168429a287fa2ba7f8?anonymousKey=38fd94f0ac9bd36f3cecb23d8275b23b864e2d77) |
26+
| --optimistic_contract_recursion | [false](https://prover.certora.com/output/15800/908365f5dfb04e2b9a6d0dfef3a7c006?anonymousKey=2db3842d23c9fb7a6065551ed56fc9bdfa815595) / [true](https://prover.certora.com/output/15800/65a836c4a9f542f79ad7e2fd563a8a18?anonymousKey=2bb9bcbad7f489038331183b3e6573fec4235c73) |
27+
| --contract_recursion_limit | [A run with limit of 1 recursion calls](https://prover.certora.com/output/15800/e2b6169b29af4a1a984a12cfb7192754?anonymousKey=8377c4f7bc0388ede45cef5aac6bfe6746471bec) / [Same run but with limit of 5](https://prover.certora.com/output/15800/e30361434d7d4f90835977a131226ea3?anonymousKey=6a06425fa5a78281927156369530d28fca0578a6) |
2728
| [--optimistic_summary_recursion](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#optimistic-summary-recursion) | |
2829
| [--summary_recursion_limit](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#summary-recursion-limit) | |
2930
| [--optimistic_hashing](https://docs.certora.com/en/latest/docs/prover/cli/options.html?highlight=bank#optimistic-hashing) | |
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"files": [
3+
"Helpers/Fibonacci.sol"
4+
],
5+
"verify": "Fibonacci:Helpers/Fibonacci.spec",
6+
// Specify the allowed number of recursion calls.
7+
"contract_recursion_limit": "5",
8+
9+
"rule": ["fifthFibonacciElementIsFive"]
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"files": [
3+
"Helpers/Fibonacci.sol"
4+
],
5+
"verify": "Fibonacci:Helpers/Fibonacci.spec",
6+
// Turn on optimistic contract recursion.
7+
"optimistic_contract_recursion": true,
8+
9+
"contract_recursion_limit": "1",
10+
"rule": ["fibonacciMonotonicallyIncreasing"]
11+
}

CLIFlags/optimistic_fallback.conf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"files": [
3+
"../CVLByExample/Structs/BankAccounts/Bank.sol"
4+
],
5+
"verify": "Bank:../CVLByExample/Storage/certora/specs/storage.spec",
6+
//Allow going to contract fallback function on unresolved.
7+
"optimistic_fallback": true,
8+
9+
"optimistic_loop": true,
10+
"loop_iter": "3",
11+
"multi_assert_check": true,
12+
"rule_sanity": "basic",
13+
"solc_allow_path": "../"
14+
}

CVLByExample/QuantifierExamples/EnumerableSet/certora/spec/set.spec

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@ ghost mapping(bytes32 => uint256) ghostIndexes {
2323
// ghost field for the length of the values array (stored in offset 0)
2424
ghost uint256 ghostLength {
2525
// assumption: it's infeasible to grow the list to these many elements.
26-
axiom ghostLength < 0xffffffffffffffffffffffffffffffff;
26+
axiom ghostLength < max_uint256;
2727
}
2828

2929
// HOOKS
3030
// Store hook to synchronize ghostLength with the length of the set._inner._values array.
31-
// We need to use (offset 0) here, as there is no keyword yet to access the length.
32-
hook Sstore currentContract.set.(offset 0) uint256 newLength {
31+
hook Sstore currentContract.set._inner._values.length uint256 newLength {
3332
ghostLength = newLength;
3433
}
3534
// Store hook to synchronize ghostValues array with set._inner._values.
@@ -50,8 +49,7 @@ hook Sstore currentContract.set._inner._indexes[KEY bytes32 value] uint256 newIn
5049
// and that the solver can use this knowledge in the proofs.
5150

5251
// Load hook to synchronize ghostLength with the length of the set._inner._values array.
53-
// Again we use (offset 0) here, as there is no keyword yet to access the length.
54-
hook Sload uint256 length currentContract.set.(offset 0) {
52+
hook Sload uint256 length currentContract.set._inner._values.length {
5553
require ghostLength == length;
5654
}
5755
hook Sload bytes32 value currentContract.set._inner._values[INDEX uint256 index] {

CVLByExample/Storage/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ Run this configuration via:
1818

1919
```certoraRun runStorage.conf```
2020

21-
[Report of this run](https://prover.certora.com/output/15800/99b53a463b524e35ae8f0d31534785cd?anonymousKey=11428309d8ae62ecb8ae41811146878f1207e4ce)
21+
[Report of this run](https://prover.certora.com/output/15800/915c17159838441a9ecf6fd5672b033d?anonymousKey=176943c3b4df8b5b92bc346545be02f072516013)
2222

CVLByExample/Storage/certora/specs/storage.spec

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ rule storageDoesNotChangeByWithdrawWhenRevert() {
4949
/// This rule demonstrates how to verify changes in the full storage when changing data structures of the current contract.
5050
/// The storage changes after each customer addition.
5151
/// The rule Should pass.
52-
rule addingCustomersChangesStorageShouldPass(BankAccountRecord.Customer c1, BankAccountRecord.Customer c2) {
52+
rule addingCustomersChangesStorage(BankAccountRecord.Customer c1, BankAccountRecord.Customer c2) {
5353
require c1.id != c2.id;
5454
addCustomer(c1);
5555
storage afterC1 = lastStorage;
@@ -72,7 +72,7 @@ rule witnessForStorageChangeAfterEachCustomerAddition(BankAccountRecord.Customer
7272
/// This rule demonstrates how to compare the storage of a specific contract and nativeBalances in several
7373
/// points of the run using several variables and indices.
7474
/// Different storage after each customer addition.
75-
rule integrityOfStoragePerCustomerShouldPass(BankAccountRecord.Customer c1, BankAccountRecord.Customer c2) {
75+
rule integrityOfStoragePerCustomer(BankAccountRecord.Customer c1, BankAccountRecord.Customer c2) {
7676
require c1.id != c2.id;
7777
require !isCustomer(c1.id);
7878
require !isCustomer(c2.id);
@@ -94,23 +94,42 @@ rule integrityOfStoragePerCustomerShouldPass(BankAccountRecord.Customer c1, Bank
9494

9595
/// This rule demonstrates how to call `deposit` (can be any transaction) twice from the same state by restoring the storage to
9696
/// its initial state before the second call.
97+
rule storageAfterTwoDepositFromInitDoesNotChange() {
98+
uint256 bankAccount;
99+
env e;
100+
require e.msg.sender < max_address;
101+
// uint256 initBalance = nativeBalances[bank];
102+
storage initStorage = lastStorage;
103+
deposit(e, bankAccount);
104+
// Only full storage can be assigned to a variable.
105+
storage afterCallStorage = lastStorage;
106+
// nativeBalances is mapping(address => uint256. mapping is not yet supported as a CVL local variable type, so a variable
107+
// corresponds to a single entry is used instead.
108+
uint256 afterCallBalance = nativeBalances[bank];
109+
deposit(e, bankAccount) at initStorage;
110+
assert (nativeBalances[bank] == afterCallBalance, "Different native balances from same initial storage");
111+
assert(lastStorage[bank] == afterCallStorage[bank], "Different native storage from same initial storage");
112+
assert(lastStorage[nativeBalances] == afterCallStorage[nativeBalances],
113+
"Different storage of native balances after call from same initial storage");
114+
}
115+
97116
/// Two withdrawals are sequentially called where both start from the initial state. Therefore, the storage after each of the
98117
/// withdrawals are the same.
99118
/// This fails in the default configuration because of the call to an unresolved function in withdraw.
100-
/// It passes with -optimistic_fallback.
101-
rule storageAfterTwoDepositFromInitDoesNotChangeShouldPass() {
119+
/// It passes with --optimistic_fallback.
120+
rule storageAfterTwoWithdrawalsFromInitDoesNotChange() {
102121
uint256 bankAccount;
103122
env e;
104123
require e.msg.sender < max_address;
105124
// uint256 initBalance = nativeBalances[bank];
106125
storage initStorage = lastStorage;
107-
deposit(e, bankAccount);
126+
withdraw(e, bankAccount);
108127
// Only full storage can be assigned to a variable.
109128
storage afterCallStorage = lastStorage;
110129
// nativeBalances is mapping(address => uint256. mapping is not yet supported as a CVL local variable type, so a variable
111130
// corresponds to a single entry is used instead.
112131
uint256 afterCallBalance = nativeBalances[bank];
113-
deposit(e, bankAccount) at initStorage;
132+
withdraw(e, bankAccount) at initStorage;
114133
assert (nativeBalances[bank] == afterCallBalance, "Different native balances from same initial storage");
115134
assert(lastStorage[bank] == afterCallStorage[bank], "Different native storage from same initial storage");
116135
assert(lastStorage[nativeBalances] == afterCallStorage[nativeBalances],

CVLByExample/Structs/BankAccounts/certora/specs/structs.spec

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,7 @@ ghost mapping(address => uint256) numOfAccounts {
122122
}
123123

124124
/// Store hook to synchronize numOfAccounts with the length of the customers[KEY address a].accounts array.
125-
/// We need to use (offset 32) here, as there is no keyword yet to access the length.
126-
hook Sstore _customers[KEY address user].(offset 32) uint256 newLength {
125+
hook Sstore _customers[KEY address user].accounts.length uint256 newLength {
127126
if (newLength > numOfAccounts[user])
128127
require accountBalanceMirror[user][require_uint256(newLength-1)] == 0 ;
129128
numOfAccounts[user] = newLength;
@@ -137,8 +136,7 @@ invariant checkNumOfAccounts(address user)
137136
numOfAccounts[user] == bank.getNumberOfAccounts(user);
138137

139138
/// This Sload is required in order to eliminate adding unintializaed account balance to sumBalances.
140-
/// (offset 32) is the location of the size of the mapping. It is used because the field `size` is not yet supported in cvl.
141-
hook Sload uint256 length _customers[KEY address user].(offset 32) {
139+
hook Sload uint256 length _customers[KEY address user].accounts.length {
142140
require numOfAccounts[user] == length;
143141
}
144142

0 commit comments

Comments
 (0)