From a2a81103bf6cbfb9ffad24898ca851b6e3081a30 Mon Sep 17 00:00:00 2001 From: artyukh Date: Sun, 29 May 2022 14:12:39 +0300 Subject: [PATCH] CallProxy version 423 --- contracts/libraries/MultiSendCallOnly.sol | 2 +- contracts/periphery/CallProxy.sol | 24 ++++++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/contracts/libraries/MultiSendCallOnly.sol b/contracts/libraries/MultiSendCallOnly.sol index 72637959..9213462e 100644 --- a/contracts/libraries/MultiSendCallOnly.sol +++ b/contracts/libraries/MultiSendCallOnly.sol @@ -18,7 +18,7 @@ contract MultiSendCallOnly { /// but reverts if a transaction tries to use a delegatecall. /// @notice This method is payable as delegatecalls keep the msg.value from the previous call /// If the calling method (e.g. execTransaction) received ETH this would revert otherwise - function multiSend(bytes memory transactions) public payable { + function _multiSend(bytes memory transactions) internal { // solhint-disable-next-line no-inline-assembly assembly { let length := mload(transactions) diff --git a/contracts/periphery/CallProxy.sol b/contracts/periphery/CallProxy.sol index 4b5e8968..8520200b 100644 --- a/contracts/periphery/CallProxy.sol +++ b/contracts/periphery/CallProxy.sol @@ -37,6 +37,7 @@ contract CallProxy is Initializable, AccessControlUpgradeable, MultiSendCallOnly /* ========== ERRORS ========== */ error DeBridgeGateBadRole(); + error CallProxyBadRole(); error ExternalCallFailed(); error NotEnoughSafeTxGas(); error CallFailed(); @@ -132,6 +133,23 @@ contract CallProxy is Initializable, AccessControlUpgradeable, MultiSendCallOnly } } + /// @dev Sends multiple transactions and reverts all if one fails. + /// @param transactions Encoded transactions. Each transaction is encoded as a packed bytes of + /// operation has to be uint8(0) in this version (=> 1 byte), + /// to as a address (=> 20 bytes), + /// value as a uint256 (=> 32 bytes), + /// data length as a uint256 (=> 32 bytes), + /// data as bytes. + /// see abi.encodePacked for more information on packed encoding + /// @notice The code is for most part the same as the normal MultiSend (to keep compatibility), + /// but reverts if a transaction tries to use a delegatecall. + /// @notice This method is payable as delegatecalls keep the msg.value from the previous call + /// If the calling method (e.g. execTransaction) received ETH this would revert otherwise + function multiSend(bytes memory transactions) external payable { + if (address(this) != msg.sender) revert CallProxyBadRole(); + _multiSend(transactions); + } + // we need to accept ETH from deBridgeGate receive() external payable { } @@ -148,7 +166,7 @@ contract CallProxy is Initializable, AccessControlUpgradeable, MultiSendCallOnly ) internal returns (bool result) { bool storeSender = _flags.getFlag(Flags.PROXY_WITH_SENDER); bool checkGasLimit = _flags.getFlag(Flags.SEND_EXTERNAL_CALL_GAS_LIMIT); - bool multisend = _flags.getFlag(Flags.MULTI_SEND); + bool multisendFlag = _flags.getFlag(Flags.MULTI_SEND); // Temporary write to a storage nativeSender and chainIdFrom variables. // External contract can read them during a call if needed if (storeSender) { @@ -170,7 +188,7 @@ contract CallProxy is Initializable, AccessControlUpgradeable, MultiSendCallOnly // if safeTxGas is zero set gasleft safeTxGas = safeTxGas == 0 ? gasleft() : uint256(safeTxGas); - if (multisend) { + if (multisendFlag) { _destination = address(this); assembly { result := call(safeTxGas, _destination, _value, add(_data, 0x20), mload(_data), 0, 0) @@ -203,6 +221,6 @@ contract CallProxy is Initializable, AccessControlUpgradeable, MultiSendCallOnly /// @dev Get this contract's version function version() external pure returns (uint256) { - return 422; // 4.2.2 + return 423; // 4.2.3 } } \ No newline at end of file