-
-
Save benjiqq/f39009544bbcbbae7ce939bab9a5d14c to your computer and use it in GitHub Desktop.
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
/* | |
* STATICCALL Proxy | |
* | |
* It expects the input: | |
* 256 bit - address | |
* 256 bit - gas | |
* 256 bit - value | |
* n bit - calldata to be proxied | |
* | |
* And returns the output: | |
* 8 bit - original CALL result | |
* n bit - result data | |
* | |
*/ | |
contract StaticCallProxy { | |
function() payable external { | |
assembly { | |
let _dst := calldataload(0) | |
let _gas := calldataload(32) | |
let _value := calldataload(64) | |
let _len : = sub(calldatasize, 96) | |
calldatacopy(0, 96, _len) | |
let ret := call(_gas, _dst, _value, 0, _len, 0, 0) | |
let result_len := returndatasize() | |
mstore8(0, ret) | |
returndatacopy(1, 0, result_len) | |
revert(0, add(result_len, 1)) | |
} | |
} | |
} |
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
contract StaticCallViaRevert { | |
/* | |
* This is the envelope which calls the recipient and uses revret to roll back state. | |
* | |
* The return value is organised as: | |
* 8 bit - original CALL return value | |
* n bit - the original call result | |
*/ | |
function staticWrapInternal(address destination, uint gas, bytes calldata) external { | |
assembly { | |
let offset := 0 | |
let len := 0 | |
// load calldata position of the 'calldata' parameter | |
calldata | |
=: len | |
=: offset | |
// load calldata to memory | |
calldatacopy(0, offset, len) | |
let ret := call(gas, destination, 0, offset, len, 0, 0) | |
let result_len := returndatasize() | |
mstore8(0, ret) | |
returndatacopy(1, 0, result_len) | |
revert(0, add(result_len, 1)) | |
} | |
} | |
/* | |
* This is the interface implemented in Solidity for each static-call-via-revert invocation. | |
*/ | |
function staticWrap(address destination, uint gas, bytes calldata) internal returns (bool success, bytes result) { | |
address self = this; | |
uint calldata_len = calldata.length; | |
uint result_len; | |
assembly { | |
// Use end-of-memory pointer to build calldata | |
let freeMemory := mload(64) | |
// Assume the signature of 'staticWrapInternal(address destination, uint gas, bytes calldata)' is 11223344 | |
mstore8(freeMemory, 0x11) | |
mstore8(add(freeMemory, 1), 0x22) | |
mstore8(add(freeMemory, 2), 0x33) | |
mstore8(add(freeMemory, 3), 0x44) | |
// FIXME: memcpy here calldata + 32 to freeMemory + 4 | |
// Ignore result, as it will be a failure in every case | |
pop(call(gas, self, 0, freeMemory, add(calldata_len, 4), 0, 0)) | |
result_len := returndatasize() | |
} | |
result = new bytes(result_len); | |
if (result_len > 1) { | |
assembly { | |
returndatacopy(success, 0, 1) | |
returndatacopy(result, 1, sub(result_len, 1)) | |
} | |
} | |
} | |
function test() { | |
staticWrap(0x1234, 100000, hex"112233440000"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment