Skip to content

Commit

Permalink
refactor NestedMultisigBuilder to use NestedMultisigBase
Browse files Browse the repository at this point in the history
  • Loading branch information
jackchuma committed Jan 22, 2025
1 parent 07afeac commit 83d457c
Showing 1 changed file with 2 additions and 122 deletions.
124 changes: 2 additions & 122 deletions script/universal/NestedMultisigBuilder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,26 @@ import {IMulticall3} from "forge-std/interfaces/IMulticall3.sol";
import {Vm} from "forge-std/Vm.sol";

import {IGnosisSafe} from "./IGnosisSafe.sol";
import {MultisigBase} from "./MultisigBase.sol";
import {NestedMultisigBase} from "./NestedMultisigBase.sol";
import {Signatures} from "./Signatures.sol";
import {Simulation} from "./Simulation.sol";

/**
* @title NestedMultisigBuilder
* @notice Modeled from Optimism's SafeBuilder, but built for nested safes (Safes where the signers are other Safes).
*/
abstract contract NestedMultisigBuilder is MultisigBase {
abstract contract NestedMultisigBuilder is NestedMultisigBase {
/**
* -----------------------------------------------------------
* Virtual Functions
* -----------------------------------------------------------
*/

/**
* @notice Returns the nested safe address to execute the final transaction from
*/
function _ownerSafe() internal view virtual returns (address);

/**
* @notice Creates the calldata for both signatures (`sign`) and execution (`run`)
*/
function _buildCalls() internal view virtual returns (IMulticall3.Call3[] memory);

/**
* @notice Follow up assertions to ensure that the script ran to completion.
* @dev Called after `sign` and `run`, but not `approve`.
*/
function _postCheck(Vm.AccountAccess[] memory accesses, Simulation.Payload memory simPayload) internal virtual;

/**
* @notice Follow up assertions on state and simulation after a `sign` call.
*/
function _postSign(Vm.AccountAccess[] memory accesses, Simulation.Payload memory simPayload) internal virtual {}

/**
* @notice Follow up assertions on state and simulation after a `approve` call.
*/
function _postApprove(Vm.AccountAccess[] memory accesses, Simulation.Payload memory simPayload) internal virtual {}

/**
* @notice Follow up assertions on state and simulation after a `run` call.
*/
function _postRun(Vm.AccountAccess[] memory accesses, Simulation.Payload memory simPayload) internal virtual {}

/**
* -----------------------------------------------------------
* Implemented Functions
Expand Down Expand Up @@ -138,98 +112,4 @@ abstract contract NestedMultisigBuilder is MultisigBase {
_postRun(accesses, simPayload);
_postCheck(accesses, simPayload);
}

function _readFrom_SAFE_NONCE() internal pure override returns (bool) {
return false;
}

function _generateApproveCall(address _safe, IMulticall3.Call3[] memory _calls)
internal
view
returns (IMulticall3.Call3 memory)
{
bytes32 hash = _getTransactionHash(_safe, _calls);

console.log("---\nNested hash:");
console.logBytes32(hash);

return IMulticall3.Call3({
target: _safe,
allowFailure: false,
callData: abi.encodeCall(IGnosisSafe(_safe).approveHash, (hash))
});
}

function _simulateForSigner(address _signerSafe, address _safe, IMulticall3.Call3[] memory _calls)
internal
returns (Vm.AccountAccess[] memory, Simulation.Payload memory)
{
bytes memory data = abi.encodeCall(IMulticall3.aggregate3, (_calls));
IMulticall3.Call3[] memory calls = _simulateForSignerCalls(_signerSafe, _safe, data);

// Now define the state overrides for the simulation.
Simulation.StateOverride[] memory overrides = _overrides(_signerSafe, _safe);

bytes memory txData = abi.encodeCall(IMulticall3.aggregate3, (calls));
console.log("---\nSimulation link:");
// solhint-disable max-line-length
Simulation.logSimulationLink({_to: MULTICALL3_ADDRESS, _data: txData, _from: msg.sender, _overrides: overrides});

// Forge simulation of the data logged in the link. If the simulation fails
// we revert to make it explicit that the simulation failed.
Simulation.Payload memory simPayload =
Simulation.Payload({to: MULTICALL3_ADDRESS, data: txData, from: msg.sender, stateOverrides: overrides});
Vm.AccountAccess[] memory accesses = Simulation.simulateFromSimPayload(simPayload);
return (accesses, simPayload);
}

function _simulateForSignerCalls(address _signerSafe, address _safe, bytes memory _data)
internal
view
returns (IMulticall3.Call3[] memory)
{
IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](2);
bytes32 hash = _getTransactionHash(_safe, _data);

// simulate an approveHash, so that signer can verify the data they are signing
bytes memory approveHashData = abi.encodeCall(
IMulticall3.aggregate3,
(
_toArray(
IMulticall3.Call3({
target: _safe,
allowFailure: false,
callData: abi.encodeCall(IGnosisSafe(_safe).approveHash, (hash))
})
)
)
);
bytes memory approveHashExec = _execTransationCalldata(
_signerSafe, approveHashData, Signatures.genPrevalidatedSignature(MULTICALL3_ADDRESS)
);
calls[0] = IMulticall3.Call3({target: _signerSafe, allowFailure: false, callData: approveHashExec});

// simulate the final state changes tx, so that signer can verify the final results
bytes memory finalExec = _execTransationCalldata(_safe, _data, Signatures.genPrevalidatedSignature(_signerSafe));
calls[1] = IMulticall3.Call3({target: _safe, allowFailure: false, callData: finalExec});

return calls;
}

function _overrides(address _signerSafe, address _safe) internal view returns (Simulation.StateOverride[] memory) {
Simulation.StateOverride[] memory simOverrides = _simulationOverrides();
Simulation.StateOverride[] memory overrides = new Simulation.StateOverride[](2 + simOverrides.length);
overrides[0] = _safeOverrides(_signerSafe, MULTICALL3_ADDRESS);
overrides[1] = _safeOverrides(_safe, address(0));
for (uint256 i = 0; i < simOverrides.length; i++) {
overrides[i + 2] = simOverrides[i];
}
return overrides;
}

function _toArray(IMulticall3.Call3 memory call) internal pure returns (IMulticall3.Call3[] memory) {
IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](1);
calls[0] = call;
return calls;
}
}

0 comments on commit 83d457c

Please sign in to comment.