Skip to content
This repository has been archived by the owner on Oct 26, 2022. It is now read-only.

Commit

Permalink
Merge cdefa33 into b6ee39d
Browse files Browse the repository at this point in the history
  • Loading branch information
z0r0z committed Aug 2, 2022
2 parents b6ee39d + cdefa33 commit 42cf1bb
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
61 changes: 61 additions & 0 deletions contracts/taskers/MultiTasker.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.15;

/// @title Multi Tasker - Allows to batch multiple Furo transactions into one.
/// @author Modified from Gnosis Safe MultiSendCallOnly
/// (https://github.com/safe-global/safe-contracts/blob/main/contracts/libraries/MultiSendCallOnly.sol)
contract MultiTasker {
/// @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 onTaskReceived(bytes memory transactions) public payable {
// solhint-disable-next-line no-inline-assembly
assembly {
let length := mload(transactions)
let i := 0x20
for {
// Pre block is not used in "while mode"
} lt(i, length) {
// Post block is not used in "while mode"
} {
// First byte of the data is the operation.
// We shift by 248 bits (256 - 8 [operation byte]) it right since mload will always load 32 bytes (a word).
// This will also zero out unused data.
let operation := shr(0xf8, mload(add(transactions, i)))
// We offset the load address by 1 byte (operation byte)
// We shift it right by 96 bits (256 - 160 [20 address bytes]) to right-align the data and zero out unused data.
let to := shr(0x60, mload(add(transactions, add(i, 0x01))))
// We offset the load address by 21 byte (operation byte + 20 address bytes)
let value := mload(add(transactions, add(i, 0x15)))
// We offset the load address by 53 byte (operation byte + 20 address bytes + 32 value bytes)
let dataLength := mload(add(transactions, add(i, 0x35)))
// We offset the load address by 85 byte (operation byte + 20 address bytes + 32 value bytes + 32 data length bytes)
let data := add(transactions, add(i, 0x55))
let success := 0
switch operation
case 0 {
success := call(gas(), to, value, data, dataLength, 0, 0)
}
// This version does not allow delegatecalls
case 1 {
revert(0, 0)
}
if eq(success, 0) {
revert(0, 0)
}
// Next entry starts at 85 byte + data length
i := add(i, add(0x55, dataLength))
}
}
}
}
9 changes: 9 additions & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,15 @@ const config: HardhatUserConfig = {
},
},
},
{
version: "0.8.15",
settings: {
optimizer: {
enabled: true,
runs: 99999,
},
},
},
{
version: "0.6.12",
settings: {
Expand Down

0 comments on commit 42cf1bb

Please sign in to comment.