Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning more than 4 variables from an external function causes an OOG error #1083

Closed
Georgi87 opened this issue Sep 10, 2016 · 11 comments
Closed
Assignees
Labels

Comments

@Georgi87
Copy link

Calling foo with the address of Events (test_contract.foo(events_contract.address) will fail at runtime with OOG if I return a, b, c, d, e:

contract Events {
    function getEvent(bytes32 eventHash) returns (int a, int b, int c, int d, int e) {}
}
contract Events {
    function getEvent(bytes32 eventHash)
        returns (int a, int b, int c, int d, int e);
}

contract test {
  function foo(address addr) {
    Events events = Events(addr);
    var (,,,,) = events.getEvent(0);
  }
}

However, if I remove e from contracts and do the same transaction it works:

contract Events {
    function getEvent(bytes32 eventHash) returns (int a, int b, int c, int d) {}
}
contract Events {
    function getEvent(bytes32 eventHash)
        returns (int a, int b, int c, int d);
}

contract test {
  function foo(address addr) {
    Events events = Events(addr);
    var (,,,) = events.getEvent(0);
  }
}

I added the two sources to this gist for testing:
https://ethereum.github.io/browser-solidity/#version=soljson-latest.js&optimize=true&gist=a7010392fd44542a8ff1e2ab3fd405d5

Tested with:
Version: 0.4.0+commit.acd334c.Linux.g++
Version: 0.4.1-develop.2016.09.09+commit.79867f4.Linux.g++

@axic
Copy link
Member

axic commented Sep 10, 2016

Since 0.4.0 there's a check to see if code exists at the specified address. If not, there's an invalid jump ("oog").

Practically that means you cannot use test with a random address in browser-solidity, you do need to deploy Events and supply the appropriate address.

@Georgi87
Copy link
Author

True, but you can deploy code with browser-solidity and pass the address. The issue also appears when executing the code in a pyetheruem test environment.

@axic
Copy link
Member

axic commented Sep 10, 2016

Your above example can be deployed, because Events is abstract.

I don't have the issue you're reporting (neither 4 or 5 arguments work, because of the invalid address). If I deploy a non-abstract Events, it works.

@Georgi87
Copy link
Author

Try to deploy the first two contracts:

// This is not abstract {}!
contract Events {
    function getEvent(bytes32 eventHash) returns (int a, int b, int c, int d, int e) {}
}
contract Events {
    function getEvent(bytes32 eventHash)
        returns (int a, int b, int c, int d, int e);
}

contract test {
  function foo(address addr) {
    Events events = Events(addr);
    var (,,,,) = events.getEvent(0);
  }
}

And you will see that calling foo in the 2nd contract will cause OOG if you pass the address from the first contract.

@pirapira
Copy link
Member

On solc from ethereum/develop and geth 1.5.0-unstable, I could not reproduce this. The link contains the commands I typed into RPC.

@Georgi87
Copy link
Author

Georgi87 commented Sep 15, 2016

Thanks for checking @pirapira. I haven't tested it against geth, but it fails in browser-solc and with pyethereum.

In browser foo returns OOG for the int a, int b, int c, int d, int e version and "0x" for the int a, int b, int c, int d.

@axic
Copy link
Member

axic commented Sep 15, 2016

@Georgi87 are you sure that a valid Events contract is deployed and passed to test()? The Events contract you have is abstract and therefore won't compile and cannot be deployed.

@Georgi87
Copy link
Author

Yes, I am sure. The abstract Events contract in the 2nd contract is just added to allow interfacing the actually deployed Events contract.

This deployed Events contract is not abstract:

// This is not abstract because it has a body {}!
contract Events {
    function getEvent(bytes32 eventHash) returns (int a, int b, int c, int d, int e) {}
}

If there are issues reproducing this issue with browser-solc or pyetheruem I am ready to help. Ping me on gitter.

@axic
Copy link
Member

axic commented Sep 15, 2016

I was able to reproduce this with 0.4.1+commit.4fc6fc2c.Emscripten.clang. I can't do much more now, maybe next week.

@axic axic added the bug 🐛 label Sep 15, 2016
@Georgi87
Copy link
Author

Thanks for checking @axic

@chriseth
Copy link
Contributor

The root cause here is that the memory resize costs are not properly taken into account for the return value. Before 0.4.0 we retained more gas with a call (not because of potential memory resize but because of potential account creation).

Probably the best solution here would be to touch the memory before the call, though ethereum/EIPs#90 would be a better solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants