diff --git a/script/universal/MultisigBase.sol b/script/universal/MultisigBase.sol index b312b19..bcad696 100644 --- a/script/universal/MultisigBase.sol +++ b/script/universal/MultisigBase.sol @@ -13,9 +13,22 @@ import {Simulation} from "./Simulation.sol"; abstract contract MultisigBase is CommonBase { bytes32 internal constant SAFE_NONCE_SLOT = bytes32(uint256(5)); + address internal constant MULTI_DELEGATECALL_ADDRESS = 0x95b259eae68ba96edB128eF853fFbDffe47D2Db0; event DataToSign(bytes); + function _ownerSafe() internal view virtual returns (address); + + function _target(address _safe) internal view returns (address) { + // Always parse the env var as a string to avoid issues with boolean values. This lets + // us use "true" or "1" as the value to enable the multi-delegatecall. + bool useMultiDelegatecall = (vm.envOr("USE_MULTI_DELEGATECALL", false) || vm.envOr("USE_MULTI_DELEGATECALL", uint256(0)) == 1); + if (_safe == _ownerSafe() && useMultiDelegatecall) { + return MULTI_DELEGATECALL_ADDRESS; + } + return MULTICALL3_ADDRESS; + } + // Subclasses that use nested safes should return `false` to force use of the // explicit SAFE_NONCE_{UPPERCASE_SAFE_ADDRESS} env var. function _readFrom_SAFE_NONCE() internal pure virtual returns (bool); @@ -134,7 +147,7 @@ abstract contract MultisigBase is CommonBase { function _encodeTransactionData(address _safe, bytes memory _data) internal view returns (bytes memory) { return IGnosisSafe(_safe).encodeTransactionData({ - to: MULTICALL3_ADDRESS, + to: _target(_safe), value: 0, data: _data, operation: Enum.Operation.DelegateCall, @@ -149,23 +162,12 @@ abstract contract MultisigBase is CommonBase { function _execTransationCalldata(address _safe, bytes memory _data, bytes memory _signatures) internal - pure + view returns (bytes memory) { return abi.encodeCall( IGnosisSafe(_safe).execTransaction, - ( - MULTICALL3_ADDRESS, - 0, - _data, - Enum.Operation.DelegateCall, - 0, - 0, - 0, - address(0), - payable(address(0)), - _signatures - ) + (_target(_safe), 0, _data, Enum.Operation.DelegateCall, 0, 0, 0, address(0), payable(address(0)), _signatures) ); } @@ -173,11 +175,12 @@ abstract contract MultisigBase is CommonBase { internal returns (bool) { + address target = _target(_safe); if (_broadcast) { vm.broadcast(); } return IGnosisSafe(_safe).execTransaction({ - to: MULTICALL3_ADDRESS, + to: target, value: 0, data: _data, operation: Enum.Operation.DelegateCall, diff --git a/script/universal/MultisigBuilder.sol b/script/universal/MultisigBuilder.sol index 375ad4a..02686c1 100644 --- a/script/universal/MultisigBuilder.sol +++ b/script/universal/MultisigBuilder.sol @@ -22,11 +22,6 @@ abstract contract MultisigBuilder is MultisigBase { * ----------------------------------------------------------- */ - /** - * @notice Returns the safe address to execute the transaction from - */ - function _ownerSafe() internal view virtual returns (address); - /** * @notice Creates the calldata for both signatures (`sign`) and execution (`run`) */ diff --git a/script/universal/NestedMultisigBase.sol b/script/universal/NestedMultisigBase.sol index ee5064c..81017e5 100644 --- a/script/universal/NestedMultisigBase.sol +++ b/script/universal/NestedMultisigBase.sol @@ -18,11 +18,6 @@ abstract contract NestedMultisigBase is MultisigBase { * ----------------------------------------------------------- */ - /** - * @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`) */ diff --git a/script/universal/Simulation.sol b/script/universal/Simulation.sol index c39fa0f..7fe3f07 100644 --- a/script/universal/Simulation.sol +++ b/script/universal/Simulation.sol @@ -191,6 +191,9 @@ library Simulation { "&stateOverrides=", stateOverrides ); + if (vm.envOr("TENDERLY_GAS", uint256(0)) > 0) { + str = string.concat(str, "&gas=", vm.toString(vm.envOr("TENDERLY_GAS", uint256(0)))); + } if (bytes(str).length + _data.length * 2 > 7980) { // tenderly's nginx has issues with long URLs, so print the raw input data separately str = string.concat(str, "\nInsert the following hex into the 'Raw input data' field:");