Skip to content
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

Audit Draft PR for Code Review #3

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c73b5bc
apply a patch to the harness so the rule about hash collisions passes
Dec 16, 2024
7b7fab2
a new specification for guards, including transaction guards and modu…
Dec 16, 2024
4f7e6c6
a specification for execute, executionTxn, executeTxnFromModule, etc.…
Dec 16, 2024
5730c06
fix execTxnModulePermissions so that it checks whether the caller was…
Dec 16, 2024
658bdae
clean up two rule statements from bool == true to just bool
Dec 16, 2024
654d3fe
duplicate new rules for execTransactionFromModule to identical rules …
Dec 16, 2024
f46fd96
adding a spec file for rules about the setup, which contains two rule…
Dec 16, 2024
f2ed3c9
first draft of a fallback spec, with some TODOs including resolving s…
Dec 17, 2024
8f011da
remove unnecessary args in conf files
Dec 18, 2024
a8561df
small style adjustment
Dec 18, 2024
c97107a
combine the two setup rules into one more concise rules
Dec 18, 2024
019aef5
reintroduce prover args to guards conf because moduleGuardCalledRetur…
Dec 18, 2024
206a82b
extend some rules, deprecate/remove fixes used because I couldn't res…
Dec 18, 2024
e15d1a2
add rules on hashing
Dec 19, 2024
43f4cb1
change Safe spec to Hash spec for more accurate naming
Dec 19, 2024
9743c13
committing the hash spec, there was some confusion with renaming this…
Dec 19, 2024
00349d6
update fallback to most current version. all but one passes (annotate…
Dec 19, 2024
f2f39c5
execute_summary() improvement so it's more general
Dec 19, 2024
d8b3e02
debugging handlerCalledIfSet rule, included an invariant that handler…
Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions certora/applyHarness.patch
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
diff -druN Safe.sol Safe.sol
--- Safe.sol 2024-10-23 15:00:06
+++ Safe.sol 2024-10-23 15:04:05
--- Safe.sol 2024-12-11 12:09:10
+++ Safe.sol 2024-12-12 17:55:22
@@ -75,22 +75,24 @@
* so we create a Safe with 0 owners and threshold 1.
* This is an unusable Safe, perfect for the singleton
Expand Down Expand Up @@ -50,10 +50,21 @@ diff -druN Safe.sol Safe.sol
+
bytes32 domainHash = domainSeparator();

// We opted out for using assembly code here, because the way Solidity compiler we use (0.7.6)
// We opted for using assembly code here, because the way Solidity compiler we use (0.7.6) allocates memory is
@@ -450,7 +451,8 @@
// Store the domain separator
mstore(add(ptr, 32), domainHash)
// Calculate the hash
- txHash := keccak256(add(ptr, 30), 66)
+ //txHash := keccak256(add(ptr, 30), 66) // old
+ txHash := keccak256(add(ptr, 0), 128) // new
}
/* solhint-enable no-inline-assembly */
}

diff -druN base/Executor.sol base/Executor.sol
--- base/Executor.sol 2024-10-18 15:20:48
+++ base/Executor.sol 2024-10-23 15:03:22
--- base/Executor.sol 2024-12-11 12:09:10
+++ base/Executor.sol 2024-12-12 17:55:22
@@ -26,12 +26,8 @@
uint256 txGas
) internal returns (bool success) {
Expand All @@ -70,8 +81,8 @@ diff -druN base/Executor.sol base/Executor.sol
/* solhint-disable no-inline-assembly */
/// @solidity memory-safe-assembly
diff -druN interfaces/ISafe.sol interfaces/ISafe.sol
--- interfaces/ISafe.sol 2024-10-18 15:20:48
+++ interfaces/ISafe.sol 2024-10-23 15:03:22
--- interfaces/ISafe.sol 2024-12-11 12:09:10
+++ interfaces/ISafe.sol 2024-12-12 17:55:22
@@ -110,7 +110,7 @@
*/
function domainSeparator() external view returns (bytes32);
Expand Down
27 changes: 27 additions & 0 deletions certora/conf/v1.5/execute.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"files": [
"certora/harnesses/SafeHarness.sol",
"certora/mocks/ModuleGuardMock.sol", // a module guard
"certora/mocks/TxnGuardMock.sol", // a (safe) guard
],
"link": [

],
"verify": "SafeHarness:certora/specs/v1.5/Execute.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,
}
27 changes: 27 additions & 0 deletions certora/conf/v1.5/fallback.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"files": [
"certora/harnesses/SafeHarness.sol",
"certora/harnesses/ExtensibleFallbackHandlerHarness.sol",
"certora/mocks/DummyHandler.sol"
],
"link": [

],
"verify": "SafeHarness:certora/specs/v1.5/Fallback.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,
}
33 changes: 33 additions & 0 deletions certora/conf/v1.5/guards.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// a conf file for safe module guards
{
"files": [
"certora/harnesses/SafeHarness.sol",
"certora/mocks/ModuleGuardMock.sol", // a module guard
"certora/mocks/TxnGuardMock.sol", // a (safe) guard
],
"link": [

],
"verify": "SafeHarness:certora/specs/v1.5/Guards.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,

"prover_args": [
" -verifyCache -verifyTACDumps -testMode -checkRuleDigest -callTraceHardFail on",
derek-certora marked this conversation as resolved.
Show resolved Hide resolved
"-enableSolidityBasedInlining true"
],
}
25 changes: 25 additions & 0 deletions certora/conf/v1.5/hash.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/Hash.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,
}
25 changes: 25 additions & 0 deletions certora/conf/v1.5/setup.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/Setup.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,
}
15 changes: 15 additions & 0 deletions certora/harnesses/ExtensibleFallbackHandlerHarness.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: LGPL-3.0-only
import "../munged/handler/ExtensibleFallbackHandler.sol";
import {ISafe} from "../munged/interfaces/ISafe.sol";

contract ExtensibleFallbackHandlerHarness is ExtensibleFallbackHandler {

function getSafeMethod(ISafe safe, bytes4 selector) public view returns (bytes32) {
return safeMethods[safe][selector];
}

function getContextAndHandler() external view returns (ISafe safe, address sender, bool isStatic, address handler) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that getContext() returns the msg.sender and the last part of the calldata, so it doesn't make sense to call it from CVL. Are you using this only to get the isStatic and handler?

_getContextAndHandler();
}

}
32 changes: 32 additions & 0 deletions certora/harnesses/SafeHarness.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// SPDX-License-Identifier: LGPL-3.0-only
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 @@ -31,6 +35,10 @@ contract SafeHarness is Safe {
}
}

function numSigsSufficient(bytes memory signatures,uint256 requiredSignatures) public pure returns (bool) {
return (signatures.length >= SafeMath.mul(requiredSignatures,65));
}

// harnessed getters
function getModule(address module) public view returns (address) {
return modules[module];
Expand All @@ -40,6 +48,10 @@ contract SafeHarness is Safe {
return getGuard();
}

function getModuleGuardExternal() public view returns (address) {
return getModuleGuard();
}

function getNativeTokenBalance() public view returns (uint256) {
return address(this).balance;
}
Expand All @@ -56,6 +68,26 @@ 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{
handler := sload(FALLBACK_HANDLER_STORAGE_SLOT)
}
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
24 changes: 24 additions & 0 deletions certora/mocks/DummyHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// a dummy handler contract
import {ISafe, IStaticFallbackMethod, IFallbackMethod, ExtensibleBase} from "../munged/handler/extensible/ExtensibleBase.sol";

contract DummyHandler is IFallbackMethod {
constructor(){
methodCalled = false ;
}

bool public methodCalled ;
function resetMethodCalled() public {
methodCalled = false;
}

// the DUMMY method
function handle(ISafe safe, address sender, uint256 value, bytes calldata data) external override returns (bytes memory result) {
methodCalled = true ;

return "Hello, world!";
}

function dummyMethod() public {
methodCalled = true ;
}
}
71 changes: 71 additions & 0 deletions certora/mocks/ModuleGuardMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// SPDX-License-Identifier: LGPL-3.0-only
/* solhint-disable one-contract-per-file */
pragma solidity >=0.7.0 <0.9.0;
import {IModuleGuard} from "../munged/base/ModuleManager.sol";
import {IERC165} from "../munged/interfaces/IERC165.sol";
import "../munged/libraries/Enum.sol";

contract ModuleGuardMock is IModuleGuard {

constructor(){
preCheckedTransactions = false ;
postCheckedTransactions = false ;
}

// some mock variables
bool public preCheckedTransactions ;
bool public postCheckedTransactions ;

function resetChecks() external {
preCheckedTransactions = false ;
postCheckedTransactions = false ;
}

/**
* @notice Checks the module transaction details.
* @dev The function needs to implement module transaction validation logic.
* @param to The address to which the transaction is intended.
* @param value The value of the transaction in Wei.
* @param data The transaction data.
* @param operation The type of operation of the module transaction.
* @param module The module involved in the transaction.
* @return moduleTxHash The hash of the module transaction.
*/
function checkModuleTransaction(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
address module
) external override returns (bytes32 moduleTxHash) {
// updates transaction checked
preCheckedTransactions = true ;
// if it passes, it returns a string of bytes
return bytes32(0);
}

/**
* @notice Checks after execution of module transaction.
* @dev The function needs to implement a check after the execution of the module transaction.
* @param txHash The hash of the module transaction.
* @param success The status of the module transaction execution.
*/
function checkAfterModuleExecution(bytes32 txHash, bool success) external override {
postCheckedTransactions = true;
}

/**
* @dev Returns true if this contract implements the interface defined by `interfaceId`.
* See the corresponding EIP section
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {
return
interfaceId == type(IModuleGuard).interfaceId || // 0x58401ed8
interfaceId == type(IERC165).interfaceId; // 0x01ffc9a7
}

}
Loading
Loading