Skip to content

Commit

Permalink
add rules on hashing
Browse files Browse the repository at this point in the history
  • Loading branch information
Derek Sorensen authored and Derek Sorensen committed Dec 19, 2024
1 parent 206a82b commit e15d1a2
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
25 changes: 25 additions & 0 deletions certora/conf/v1.5/safe.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"files": [
"certora/harnesses/SafeHarness.sol"
],
"link": [

],
"verify": "SafeHarness:certora/specs/v1.5/Safe.spec",

"assert_autofinder_success": true,
"optimistic_summary_recursion": true,
"optimistic_contract_recursion": true,

"summary_recursion_limit": "2",
"contract_recursion_limit": "2",
"loop_iter": "3",
"optimistic_loop": true,
"optimistic_hashing": true,
"optimistic_fallback": true,

"rule_sanity": "basic",

"solc": "solc7.6",
"solc_via_ir": false,
}
14 changes: 14 additions & 0 deletions certora/harnesses/SafeHarness.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import "../munged/Safe.sol";
import {SafeMath} from "../munged/external/SafeMath.sol";
import {ISafe, IStaticFallbackMethod, IFallbackMethod, ExtensibleBase} from "../munged/handler/extensible/ExtensibleBase.sol";
import {IFallbackHandler, FallbackHandler} from "../munged/handler/extensible/FallbackHandler.sol";


contract SafeHarness is Safe {
constructor(
Expand Down Expand Up @@ -66,6 +68,10 @@ contract SafeHarness is Safe {
return getOwners().length;
}

function approvedHashVal(address a, bytes32 hashInQuestion) public view returns (uint256) {
return approvedHashes[a][hashInQuestion];
}

function getFallbackHandler() public view returns (address) {
address handler;
assembly{
Expand All @@ -74,6 +80,14 @@ contract SafeHarness is Safe {
return handler ;
}

function callSetSafeMethod(bytes4 selector, bytes32 newMethod) public {
IFallbackHandler(address(this)).setSafeMethod(selector,newMethod);
}

function callDummyHandler(bytes4 selector) public {
address(this).call(abi.encodeWithSelector(selector));
}

function getTransactionHashPublic(
address to,
uint256 value,
Expand Down
47 changes: 47 additions & 0 deletions certora/specs/v1.5/Safe.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* A specification for the Safe setup function */


// ---- Methods block ----------------------------------------------------------
methods {
function getThreshold() external returns (uint256) envfree;

function SecuredTokenTransfer.transferToken(address token, address receiver, uint256 amount) internal returns (bool) => NONDET ;
}

// ---- Functions and ghosts ---------------------------------------------------


// ---- Invariants -------------------------------------------------------------


// ---- Rules ------------------------------------------------------------------

/// @dev approvedHashes[user][hash] can only be changed by msg.sender==user
/// @status Done: https://prover.certora.com/output/39601/bb515eafa67e4edd99bb5aa51a63877b?anonymousKey=9c42e3105c1c3a3fbc95c8a24fa43b3dd43a05d6

rule approvedHashesUpdate(method f,bytes32 userHash,address user) filtered {
f -> f.selector != sig:simulateAndRevert(address,bytes).selector
} {
env e;

uint256 hashBefore = approvedHashVal(e,user,userHash);

calldataarg args;
f(e,args);

uint256 hashAfter = approvedHashVal(e,user,userHash);

assert (hashBefore != hashAfter =>
(e.msg.sender == user)
);
}


/// @dev approvedHashes is set when calling approveHash
/// @status Done: https://prover.certora.com/output/39601/bb515eafa67e4edd99bb5aa51a63877b?anonymousKey=9c42e3105c1c3a3fbc95c8a24fa43b3dd43a05d6

rule approvedHashesSet(bytes32 hashToApprove) {
env e;
approveHash(e,hashToApprove);
assert(approvedHashVal(e,e.msg.sender,hashToApprove) == 1);
}

0 comments on commit e15d1a2

Please sign in to comment.