Skip to content

Commit bdcbd04

Browse files
committed
chore: initial Certora specs setup
1 parent 7ad2668 commit bdcbd04

File tree

13 files changed

+166
-6
lines changed

13 files changed

+166
-6
lines changed

.github/workflows/ci.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,46 @@ jobs:
2626
path: fuzzing/corpus
2727
key: fuzzing
2828
- run: npm run fuzz
29+
30+
verify:
31+
runs-on: ubuntu-latest
32+
33+
steps:
34+
- uses: actions/checkout@v4
35+
with:
36+
submodules: recursive
37+
38+
- name: Install Python
39+
uses: actions/setup-python@v2
40+
with: { python-version: 3.9 }
41+
42+
- name: Install Java
43+
uses: actions/setup-java@v1
44+
with: { java-version: "11", java-package: jre }
45+
46+
- name: Install Certora CLI
47+
run: pip3 install certora-cli==7.6.3
48+
49+
- name: Install Solidity
50+
run: |
51+
wget https://github.com/ethereum/solidity/releases/download/v0.8.23/solc-static-linux
52+
chmod +x solc-static-linux
53+
sudo mv solc-static-linux /usr/local/bin/solc
54+
55+
- name: "Install Node.js"
56+
uses: "actions/setup-node@v3"
57+
with:
58+
cache: "npm"
59+
node-version: "lts/*"
60+
61+
- name: "Install the Node.js dependencies"
62+
run: "npm install"
63+
64+
- name: Verify rules
65+
run: "npm run verify"
66+
env:
67+
CERTORAKEY: ${{ secrets.CERTORAKEY }}
68+
69+
strategy:
70+
fail-fast: false
71+
max-parallel: 16

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ cache
33
artifacts
44
deployment-localhost.json
55
crytic-export
6+
.certora_internal

Readme.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ To start a local Ethereum node with the contracts deployed, execute:
2222

2323
npm start
2424

25+
You can run Certora's specs with:
26+
27+
npm run verify
28+
2529
This will create a `deployment-localhost.json` file containing the addresses of
2630
the deployed contracts.
2731

certora/confs/Marketplace.conf

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"files": [
3+
"contracts/Marketplace.sol",
4+
"contracts/Groth16Verifier.sol",
5+
"certora/helpers/ERC20A.sol",
6+
],
7+
"parametric_contracts": ["Marketplace"],
8+
"link" : [
9+
"Marketplace:_token=ERC20A",
10+
"Marketplace:_verifier=Groth16Verifier"
11+
],
12+
"msg": "Verifying Marketplace",
13+
"rule_sanity": "basic",
14+
"verify": "Marketplace:certora/specs/Marketplace.spec",
15+
"optimistic_loop": true,
16+
"loop_iter": "3",
17+
"optimistic_hashing": true,
18+
"hashing_length_bound": "512",
19+
}
20+
21+

certora/helpers/ERC20A.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.23;
4+
5+
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6+
7+
contract ERC20A is ERC20 {
8+
constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {}
9+
}

certora/scripts/verify-marketplace.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
if [[ "$1" ]]
2+
then
3+
RULE="--rule $1"
4+
fi
5+
6+
if [[ "$2" ]]
7+
then
8+
MSG="- $2"
9+
fi
10+
11+
certoraRun \
12+
contracts/Marketplace.sol \
13+
certora/helpers/ERC20A.sol \
14+
certora/harness/MarketplaceHarness.sol \
15+
--verify MarketplaceHarness:certora/specs/Marketplace.spec \
16+
--optimistic_loop \
17+
--loop_iter 3 \
18+
--rule_sanity "basic" \
19+
--link Marketplace:_token=ERC20A \
20+
--parametric_contracts MarketplaceHarness \
21+
$RULE \
22+
--msg "Verifying Marketplace.sol $RULE $MSG"

certora/specs/Marketplace.spec

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using ERC20A as Token;
2+
3+
/*--------------------------------------------
4+
| Ghosts and hooks |
5+
--------------------------------------------*/
6+
7+
ghost mathint totalReceived;
8+
9+
hook Sload uint256 defaultValue currentContract._marketplaceTotals.received {
10+
require totalReceived >= to_mathint(defaultValue);
11+
}
12+
13+
hook Sstore currentContract._marketplaceTotals.received uint256 defaultValue (uint256 defaultValue_old) {
14+
totalReceived = totalReceived + defaultValue - defaultValue_old;
15+
}
16+
17+
ghost mathint totalSent;
18+
19+
hook Sload uint256 defaultValue currentContract._marketplaceTotals.sent {
20+
require totalSent >= to_mathint(defaultValue);
21+
}
22+
23+
hook Sstore currentContract._marketplaceTotals.sent uint256 defaultValue (uint256 defaultValue_old) {
24+
totalSent = totalSent + defaultValue - defaultValue_old;
25+
}
26+
27+
/*--------------------------------------------
28+
| Properties |
29+
--------------------------------------------*/
30+
31+
rule sanity(env e, method f) {
32+
calldataarg args;
33+
f(e, args);
34+
assert true;
35+
satisfy true;
36+
}
37+
38+
rule totalReceivedCannotDecrease(env e, method f) {
39+
mathint total_before = totalReceived;
40+
41+
calldataarg args;
42+
f(e, args);
43+
44+
mathint total_after = totalReceived;
45+
46+
assert total_after >= total_before;
47+
}
48+
49+
rule totalSentCannotDecrease(env e, method f) {
50+
mathint total_before = totalSent;
51+
52+
calldataarg args;
53+
f(e, args);
54+
55+
mathint total_after = totalSent;
56+
57+
assert total_after >= total_before;
58+
}

contracts/FuzzMarketplace.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity ^0.8.0;
2+
pragma solidity ^0.8.23;
33

44
import "./TestToken.sol";
55
import "./Marketplace.sol";

contracts/TestEndian.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity ^0.8.0;
2+
pragma solidity ^0.8.23;
33

44
import "./Endian.sol";
55

contracts/TestMarketplace.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity ^0.8.0;
2+
pragma solidity ^0.8.23;
33

44
import "./Marketplace.sol";
55

contracts/TestProofs.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity ^0.8.0;
2+
pragma solidity ^0.8.23;
33

44
import "./Proofs.sol";
55

contracts/TestToken.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity ^0.8.0;
2+
pragma solidity ^0.8.23;
33

44
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
55

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
"format": "prettier --write contracts/**/*.sol test/**/*.js",
1010
"format:check": "prettier --check contracts/**/*.sol test/**/*.js",
1111
"lint": "solhint contracts/**.sol",
12-
"deploy": "hardhat deploy"
12+
"deploy": "hardhat deploy",
13+
"verify": "npm run verify:marketplace",
14+
"verify:marketplace": "certoraRun certora/confs/Marketplace.conf"
1315
},
1416
"devDependencies": {
1517
"@nomiclabs/hardhat-ethers": "^2.2.1",

0 commit comments

Comments
 (0)