Last active
July 24, 2022 18:40
-
-
Save Vectorized/b503cbcab367cc5c00eb4f994f328e5c to your computer and use it in GitHub Desktop.
Multicallable
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
// Author: vectorized.eth | |
pragma solidity ^0.8.4; | |
// Normal Solidity: 45845 | |
// Yul: 45350 | |
abstract contract Multicallable { | |
function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) { | |
assembly { | |
results := mload(0x40) | |
mstore(results, data.length) | |
let resultsOffsets := add(results, 0x20) | |
let memPtr := add(resultsOffsets, shl(5, data.length)) | |
let dataLengthsEnd := add(data.offset, shl(5, data.length)) | |
for { let i := data.offset } iszero(eq(i, dataLengthsEnd)) { i := add(i, 0x20) } { | |
// The offset of the current bytes in the calldata. | |
let o := add(data.offset, calldataload(i)) | |
// Copy the current bytes from calldata to the memory. | |
calldatacopy( | |
memPtr, | |
add(o, 0x20), // The offset of the current bytes' bytes. | |
calldataload(o) // The length of the current bytes. | |
) | |
if iszero(delegatecall( | |
gas(), | |
address(), | |
memPtr, | |
calldataload(o), | |
0x00, | |
0x00 | |
)) { | |
// Bubble up the revert if the delegatecall reverts. | |
returndatacopy(0x00, 0x00, returndatasize()) | |
revert(0x00, returndatasize()) | |
} | |
// Append the current `memPtr` into `resultsOffsets`. | |
mstore(resultsOffsets, memPtr) | |
resultsOffsets := add(resultsOffsets, 0x20) | |
// Append the `returndatasize()`, and the return data. | |
mstore(memPtr, returndatasize()) | |
returndatacopy(add(memPtr, 0x20), 0x00, returndatasize()) | |
// Advance the `memPtr` by `returndatasize() + 0x20`, | |
// rounded up to the next multiple of 32. | |
memPtr := and(add(add(memPtr, returndatasize()), 0x3f), 0xffffffffffffffe0) | |
} | |
mstore(0x40, memPtr) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment