provable-things / ethereum-api

Provable API for Ethereum smart contracts
https://docs.provable.xyz/#ethereum
MIT License
800 stars 428 forks source link

Error: The contract code couldn't be stored, please check your gas amount. #66

Closed rrubo closed 6 years ago

rrubo commented 6 years ago

Greetings,

I have an error deploying contracts using Oraclize through Truffle, getting the following error:

Running migration: 2_deploy_contracts.js
  Deploying PowerEther...
  ... 0x141b74b6b86b31949524624e08c07e77cdecbadcb4771a6f0420af73e4cab8b5
Error encountered, bailing. Network state unknown. Review successful transactions manually.
Error: The contract code couldn't be stored, please check your gas amount.
    at Object.callback (C:\Users\ruham\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3\lib\web3\contract.js:147:1)
    at C:\Users\ruham\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3\lib\web3\method.js:142:1
    at C:\Users\ruham\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3\lib\web3\requestmanager.js:89:1
    at C:\Users\ruham\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-migrate\index.js:225:1
    at C:\Users\ruham\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\truffle-provider\wrapper.js:134:1
    at XMLHttpRequest.request.onreadystatechange (C:\Users\ruham\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3\lib\web3\httpprovider.js:128:1)
    at XMLHttpRequestEventTarget.dispatchEvent (C:\Users\ruham\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2\lib\xhr2.js:64:1)
    at XMLHttpRequest._setReadyState (C:\Users\ruham\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2\lib\xhr2.js:354:1)
    at XMLHttpRequest._onHttpResponseEnd (C:\Users\ruham\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2\lib\xhr2.js:509:1)
    at IncomingMessage.<anonymous> (C:\Users\ruham\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2\lib\xhr2.js:469:1)
    at IncomingMessage.emit (events.js:165:20)
    at endReadableNT (_stream_readable.js:1101:12)
    at process._tickCallback (internal/process/next_tick.js:152:19)

I opened the issue here, since this error is most probably dealing with abstract functions that Oraclize contract uses. When removing Oraclize from the contract, the migration proceeded without errors. Note, that this issue is with Truffle, since things work when deploying through Remix IDE. Is there a way to somehow fix/change the abstractions?

D-Nice commented 6 years ago

Please let us know the version of Truffle that was used, and solidity compiler for versions of Truffle that allow you to choose it. Additionally, does your migration script reserve sufficient gas for the deployment and was this on a local testnet or some public network?

rrubo commented 6 years ago

The contract was run on a local Ganache node via Truffle. The versions:

Truffle v4.1.14 (core: 4.1.14)
Solidity v0.4.24 (solc-js)

There is no problem with the gas amount, since I tried values up to 50 million. I suspect the issue is within the Oraclize contract, since it uses abstract functions.

Everything works fine, though, when running the contract from Remix IDE to Ganache.

UPD: When commenting the __callback() function, Truffle migrates the contract without any errors.

D-Nice commented 6 years ago

Have you run the ethereum-bridge on the Ganache node before trying to deploy the contracts? If yes, is your contract code available publicly for us to test, as this is normally not an issue with Oraclize itself, as we use it with Truffle without issue in our own projects, with Ganache/Truffle develop, but of course worth checking.

This repo is normally what we recommend using as the base for contracts to be developed in Truffle and that will utilize Oraclize, allows you to start the bridge with a simple npm command: https://github.com/oraclize/truffle-starter/tree/78cee3bc560eb69f0ad30c1c0aa27af761057074

rrubo commented 6 years ago

Ethereum-bridge is up and running before trying to deploy the contracts. I will try the repo you've mentioned, and if no success, will figure how to share the code.

D-Nice commented 6 years ago

if you don't wish to release publicly but still share the code, you can leave a message in our gitter, and one of us can contact you on there, if you wish to pm it instead.

EDIT: Link https://gitter.im/oraclize/ethereum-api

rrubo commented 6 years ago

Thanks, just wrote in Gitter.

rrubo commented 6 years ago

Btw, in Remix thhe execution cost is 5866002 gas, and the transaction cost is 4469926 gas. In Truffle, I am setting 15000000 in truffle.js, and it still gives me the same error. Thus, I think this is not an issue of gas.

D-Nice commented 6 years ago

After the user shared his contract with us, we were able to pin the above issue actually arising from EIP170 enforcement which limits the allowable byte length of contracts to 0x6000 or 24576 bytes.

The user's contract would be about 32.5k bytes as is, unoptimized. When removing the __callback function, which would cause less parts of the Oraclize api to be imported, it would lower it down to 23k, which would be below the EIP170 limit.

The user was given a few solutions, from easiest they are:

  1. Enable optimization. Optimization was able to bring the contract down from 32.5k to about 20k, which rendered it deployable in its current state without the need for refactoring or a major rewrite.

  2. Use the Oraclize library. We still keep the experimental marker, as we have not had it audited yet, however, we have used it in our own mainnet projects without fault up to this point, which dealt in real funds. A small amount of oraclize method refactoring is needed: https://github.com/oraclize/ethereum-api/tree/master/lib-experimental

  3. Make your contract architecture more modular, basically a multi contract deployment, where storage is in one contract, logic in another, and another contract solely for tracking, sending and receiving Oraclize queries. This has other advantages as well, such as allowing certain parts to be updated, more critical ones set in stone, while allowing for persistence, but of course, that's not necessarily the design goal of every smart contract system.

Basically, if you run into this issue, check your contract's size, and if it exceeds 0x6000. If it does, you can still use it on older pre-suprious dragon EVMs, such as our old browser solidity IDE.