Last active
July 29, 2018 14:04
-
-
Save loredanacirstea/3de1c348c810221cc0384d3f9da6add3 to your computer and use it in GitHub Desktop.
General proxy for calling external contract functions and returning their output. This is unsafe, work in progress.
This file contains 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
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