From 678e320a52fbcbfdc546d75610c2004239875541 Mon Sep 17 00:00:00 2001 From: Alan Lu Date: Mon, 28 Dec 2020 14:12:50 -0600 Subject: [PATCH] Generalize proxy setup and move version-specific calldata into facade --- contracts/solc-0.8/CPKFactory.sol | 28 ++++++++++++++------ contracts/solc-0.8/CPKFactoryFacade.sol | 24 +++++++++++++++-- contracts/solc-0.8/dep-ports/IGnosisSafe.sol | 17 ------------ 3 files changed, 42 insertions(+), 27 deletions(-) delete mode 100644 contracts/solc-0.8/dep-ports/IGnosisSafe.sol diff --git a/contracts/solc-0.8/CPKFactory.sol b/contracts/solc-0.8/CPKFactory.sol index e4542f9e..63692bb6 100644 --- a/contracts/solc-0.8/CPKFactory.sol +++ b/contracts/solc-0.8/CPKFactory.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only pragma solidity >=0.8.0; -import { IGnosisSafe } from "./dep-ports/IGnosisSafe.sol"; import { IGnosisSafeProxyFactory } from "./dep-ports/IGnosisSafeProxyFactory.sol"; import { ProxyImplSetter } from "./ProxyImplSetter.sol"; @@ -39,8 +38,7 @@ contract CPKFactory { address owner, address safeVersion, uint256 salt, - address fallbackHandler, - bytes calldata execTxCalldata + bytes[] calldata txsCalldata ) external payable @@ -56,13 +54,27 @@ contract CPKFactory { ProxyImplSetter(proxy).setImplementation(safeVersion); - { - address[] memory tmp = new address[](1); - tmp[0] = address(owner); - IGnosisSafe(proxy).setup(tmp, 1, address(0), "", fallbackHandler, address(0), 0, payable(0)); + bytes memory lastReturnData; + + for (uint i = 0; i < txsCalldata.length; i++) { + bool txSuccess; + (txSuccess, lastReturnData) = proxy.call{value: msg.value}(txsCalldata[i]); + assembly { + // txSuccess == 0 means the call failed + if iszero(txSuccess) { + // The revert data begins one word after the lastReturnData pointer. + // At the location lastReturnData in memory, the length of the bytes is stored. + // This differs from the high-level revert(string(lastReturnData)) + // as the high-level version encodes the lastReturnData in a Error(string) object. + // We want to avoid that because the underlying call should have already + // formatted the data in an Error(string) object + revert(add(0x20, lastReturnData), mload(lastReturnData)) + } + } } - proxy.call{value: msg.value}(execTxCalldata); + // final call in txsCalldata is assumed to be execTransaction + execTransactionSuccess = abi.decode(lastReturnData, (bool)); emit CPKCreation(proxy, safeVersion, owner, salt); } diff --git a/contracts/solc-0.8/CPKFactoryFacade.sol b/contracts/solc-0.8/CPKFactoryFacade.sol index 6757647c..05ac59f1 100644 --- a/contracts/solc-0.8/CPKFactoryFacade.sol +++ b/contracts/solc-0.8/CPKFactoryFacade.sol @@ -56,12 +56,32 @@ contract CPKFactoryFacade { ) } + bytes[] memory txsCalldata = new bytes[](2); + { + address[] memory owners = new address[](1); + owners[0] = address(owner); + txsCalldata[0] = abi.encodeWithSignature("setup(" + "address[]," // owners + "uint256," // threshold + "address," // to + "bytes," // data + "address," // fallbackHandler + "address," // paymentToken + "uint256," // payment + "address" // paymentReceiver + ")", owners, uint256(1), address(0), "", fallbackHandler, address(0), uint256(0), payable(0)); + } + + // msg.data works here as a substitute for encoding because this function's signature + // exactly matches the execTransaction signature from the Gnosis Safe, so the calldata + // encoding will be the same. + txsCalldata[1] = msg.data; + return cpkFactory.createProxyAndExecTransaction{value: msg.value}( owner, safeVersion, salt, - fallbackHandler, - msg.data + txsCalldata ); } } \ No newline at end of file diff --git a/contracts/solc-0.8/dep-ports/IGnosisSafe.sol b/contracts/solc-0.8/dep-ports/IGnosisSafe.sol deleted file mode 100644 index 9b0896a5..00000000 --- a/contracts/solc-0.8/dep-ports/IGnosisSafe.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -pragma solidity >=0.8.0; - -import { Enum } from "./Enum.sol"; - -interface IGnosisSafe { - function setup( - address[] calldata _owners, - uint256 _threshold, - address to, - bytes calldata data, - address fallbackHandler, - address paymentToken, - uint256 payment, - address payable paymentReceiver - ) external; -}