Skip to content

Instantly share code, notes, and snippets.

@loredanacirstea
Last active July 29, 2018 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loredanacirstea/3de1c348c810221cc0384d3f9da6add3 to your computer and use it in GitHub Desktop.
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.
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