-
Notifications
You must be signed in to change notification settings - Fork 48
Adding General Rules #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
60ab7a1
5a94ada
8b4830d
7384675
021e3fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "files": [ | ||
| "contracts/ERC20.sol:ERC20" | ||
| ], | ||
| "verify": "ERC20:certora/spec/general.spec", | ||
| "solc": "solc8.17", | ||
| "solc_args": [], | ||
|
||
| "msg": "genral Rules on ERC20 contract" | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "files": [ | ||
| "contracts/Vault.sol:Vault" | ||
|
||
| ], | ||
| "verify": "Vault:certora/spec/general.spec", | ||
| "solc": "solc8.17", | ||
| "solc_args": [], | ||
|
||
| "msg": "genral Rules on Vault contract" | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| using DummyERC20A as erc20; | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comment: /** General spec file that can used on any solidity contract, helps highlight the behavior or the contract **/ |
||
| methods { | ||
| function _.name() external => DISPATCHER(true); | ||
| function _.symbol() external => DISPATCHER(true); | ||
| function _.decimals() external => DISPATCHER(true); | ||
| function _.totalSupply() external => DISPATCHER(true); | ||
| function _.balanceOf(address) external => DISPATCHER(true); | ||
| function _.allowance(address,address) external => DISPATCHER(true); | ||
| function _.approve(address,uint256) external => DISPATCHER(true); | ||
| function _.transfer(address,uint256) external => DISPATCHER(true); | ||
| function _.transferFrom(address,address,uint256) external => DISPATCHER(true); | ||
|
|
||
| function erc20.balanceOf(address) external returns (uint256) envfree; | ||
| } | ||
|
|
||
| /* | ||
| Property: Find and show a path for each method. | ||
| */ | ||
| rule reachability(method f) | ||
| { | ||
| env e; | ||
| calldataarg args; | ||
| f(e,args); | ||
| satisfy true; | ||
| } | ||
|
|
||
| /* | ||
| Property: Define and check functions that should never revert | ||
| Notice: use f.selector to state which functions should not revert,e.g.f.selector == sig:balanceOf(address).selector | ||
| */ | ||
| definition nonReveritngFunction(method f ) returns bool = true; | ||
|
|
||
| rule noRevert(method f) filtered {f -> nonReveritngFunction(f) } | ||
| { | ||
| env e; | ||
| calldataarg arg; | ||
| //consider auto filtering for non-payable functions | ||
| require e.msg.value == 0; | ||
| f@withrevert(e, arg); | ||
| assert !lastReverted, "method should not revert"; | ||
| } | ||
|
|
||
|
|
||
| /* | ||
| Property: Checks if a function can be frontrun | ||
| Notice: Can be enhanced to check more than one function as rules can be double-parameteric | ||
| */ | ||
| rule simpleFrontRunning(method f, method g) filtered { f-> !f.isView, g-> !g.isView } | ||
| { | ||
| env e1; | ||
| calldataarg arg; | ||
|
|
||
| storage initialStorage = lastStorage; | ||
| f(e1, arg); | ||
|
|
||
|
|
||
| env e2; | ||
| calldataarg arg2; | ||
| require e2.msg.sender != e1.msg.sender; | ||
| g(e2, arg2) at initialStorage; | ||
|
|
||
| f@withrevert(e1, arg); | ||
| bool succeeded = !lastReverted; | ||
|
|
||
| assert succeeded, "should be called also if frontrunned"; | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| @title - This rule find which functions are privileged. | ||
| @notice A function is privileged if there is only one address that can call it. | ||
| @dev The rules finds this by finding which functions can be called by two different users. | ||
| */ | ||
|
|
||
| rule privilegedOperation(method f, address privileged) | ||
| { | ||
| env e1; | ||
| calldataarg arg; | ||
| require e1.msg.sender == privileged; | ||
|
|
||
| storage initialStorage = lastStorage; | ||
| f@withrevert(e1, arg); // privileged succeeds executing candidate privileged operation. | ||
| bool firstSucceeded = !lastReverted; | ||
|
|
||
| env e2; | ||
| calldataarg arg2; | ||
| require e2.msg.sender != privileged; | ||
| f@withrevert(e2, arg2) at initialStorage; // unprivileged | ||
| bool secondSucceeded = !lastReverted; | ||
|
|
||
| assert !(firstSucceeded && secondSucceeded), "function is privileged"; | ||
| } | ||
|
|
||
|
|
||
| rule decreaseInSystemEth(method f) { | ||
|
|
||
| uint256 before = nativeBalances[currentContract]; | ||
|
|
||
| env e; | ||
| calldataarg arg; | ||
| f(e, arg); | ||
|
|
||
| uint256 after = nativeBalances[currentContract]; | ||
|
|
||
| assert after >= before || false ; /* fill in cases where eth can decrease */ | ||
| } | ||
|
|
||
|
|
||
| rule decreaseInERC20(method f) { | ||
|
|
||
| uint256 before = erc20.balanceOf(currentContract); | ||
|
||
|
|
||
| env e; | ||
| calldataarg arg; | ||
| f(e, arg); | ||
|
|
||
| uint256 after = erc20.balanceOf(currentContract); | ||
|
|
||
| assert after >= before || false ; /* fill in cases eth can decrease */ | ||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove solce, type in general