Skip to content

Instantly share code, notes, and snippets.

@axic
Last active May 25, 2023 03:02
Show Gist options
  • Save axic/fc61daf7775c56da02d21368865a9416 to your computer and use it in GitHub Desktop.
Save axic/fc61daf7775c56da02d21368865a9416 to your computer and use it in GitHub Desktop.
/*
* 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))
}
}
}
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