Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
General proxy for calling external contract functions and returning their output. This is unsafe, work in progress.
pragma solidity ^0.4.24;
contract PipeProxy {
function proxy(
address _to,
bytes input_bytes,
uint256 gas_value
)
payable
public
returns (bytes)
{
uint256 value = msg.value;
bytes memory output;
uint256 output_len;
assembly {
let zero_mem_pointer := 0x80
let input_size := mload(input_bytes)
let input_ptr := add(zero_mem_pointer, 32)
let result := call(
gas_value, // gas limit
_to, // contract address to call
value, // value of transferred ETH
input_ptr, // inputs are stored at location input_ptr
input_size, // input size
0, // store output at pointer 0x0
0 // expected output size set to 0, because we will use returndatasize
)
output_len := returndatasize
}
output = new bytes(output_len);
assembly {
// copy return data content after output length (first 32 bytes)
returndatacopy(add(output, 32), 0, output_len)
}
return output;
}
}
contract TestPipeProxy {
PipeProxy pipe_proxy;
address test_contract;
constructor (address _pipe_proxy, address _test_contract) public {
pipe_proxy = PipeProxy(_pipe_proxy);
test_contract = _test_contract;
}
function m_addr() view public returns(bytes32 addr) {
bytes4 signature = bytes4(keccak256("m_addr()"));
bytes memory input = abi.encodePacked(signature);
bytes memory answer = pipe_proxy.proxy(test_contract, input, 70000);
assembly {
addr := mload(add(answer, 32))
}
}
function s_addr() view public returns(bytes32 addr) {
bytes4 signature = bytes4(keccak256("s_addr()"));
bytes memory input = abi.encodePacked(signature);
bytes memory answer = pipe_proxy.proxy(test_contract, input, 70000);
assembly {
addr := mload(add(answer, 32))
}
}
function addr_addr() view public returns(bytes32 addr1, bytes32 addr2) {
bytes4 signature = bytes4(keccak256("addr_addr()"));
bytes memory input = abi.encodePacked(signature);
bytes memory answer = pipe_proxy.proxy(test_contract, input, 70000);
assembly {
addr1 := mload(add(answer, 32))
addr2 := mload(add(answer, 64))
}
}
function m_uint(uint256 value) view public returns(bytes32 val) {
bytes4 signature = bytes4(keccak256("m_uint(uint256)"));
bytes memory input = abi.encodeWithSelector(signature, value);
bytes memory answer = pipe_proxy.proxy(test_contract, input, 70000);
assembly {
val := mload(add(answer, 32))
}
}
function s_uint() view public returns(bytes32 val) {
bytes4 signature = bytes4(keccak256("s_uint()"));
bytes memory input = abi.encodeWithSelector(signature);
bytes memory answer = pipe_proxy.proxy(test_contract, input, 70000);
assembly {
val := mload(add(answer, 32))
}
}
function addr_uint() view public returns(bytes32 addr, bytes32 val) {
bytes4 signature = bytes4(keccak256("addr_uint()"));
bytes memory input = abi.encodeWithSelector(signature);
bytes memory answer = pipe_proxy.proxy(test_contract, input, 70000);
assembly {
addr := mload(add(answer, 32))
val := mload(add(answer, 64))
}
}
function m_uint_arr(uint256[4] uint_arr) view public returns(bytes32[4] arr_val) {
bytes4 signature = bytes4(keccak256("m_uint_arr(uint256[4])"));
bytes memory input = abi.encodeWithSelector(signature, uint_arr);
bytes memory answer = pipe_proxy.proxy(test_contract, input, 70000);
bytes32 val;
for (uint256 i = 1; i <= uint_arr.length; i++) {
assembly {
val := mload(add(answer, mul(32, i)))
}
arr_val[i - 1] = val;
}
}
function dynamic_uint_arr(uint256 value) public returns(uint256[] arr_val) {
bytes4 signature = bytes4(keccak256("dynamic_uint_arr(uint256)"));
bytes memory input = abi.encodeWithSelector(signature, value);
bytes memory answer = pipe_proxy.proxy(test_contract, input, 70000);
uint256 array_length;
uint256 val;
uint256 offset;
assembly {
// first 32 bytes are answer length
// next 32 bytes are offset
// then we have the array length
array_length := mload(add(answer, 64))
}
arr_val = new uint256[](array_length);
for (uint256 i = 0; i < array_length; i++) {
offset = 96 + 32*i;
assembly {
val := mload(add(answer, offset))
}
arr_val[i] = val;
}
return arr_val;
}
}
contract TestFunctions {
address public addr;
uint256 public tvar = 10;
uint256[] public arr = [1, 2, 3];
struct TStruct {
uint256 tvar1;
address addr1;
}
constructor() {
addr = msg.sender;
}
function m_addr() view public returns(address) {
return msg.sender;
}
function s_addr() view public returns(address) {
return addr;
}
function addr_addr() view public returns(address, address) {
return (msg.sender, addr);
}
function m_uint(uint256 value) view public returns(uint256) {
return value;
}
function s_uint() view public returns(uint256) {
return tvar;
}
function addr_uint() view public returns(address, uint256) {
return (addr, tvar);
}
function m_uint_arr(uint256[4] uint_arr) view public returns(uint256[4]) {
return uint_arr;
}
function dynamic_uint_arr(uint256 value) public returns(uint256[]) {
arr.push(value);
return arr;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.