10

I need some advice about handling a large contract. At a certain size it causes an out-of-gas error when I deploy to a local testrpc node. I experience this when the bytecode reaches approximately 45K. I have temporarily solved the issue by factoring out as much logic as possible into a library that is deployed separately. However, I'm running out of things that I can take out. The main contract has about 30 functions, many of which are now just forwarding to the library functions. Soon I will be unable to add even small features or improvements to the codebase, not to mention the undesirable effect of inducing refactoring for optimization reasons not architectural reasons.

How do you avoid the out-of-gas error for large contracts?

  • 1
    you have one contract and one library? why you don't want use multiple contracts, that you can deploy more granular, given that from a software design perspective modularity is always encouraged...? – Roland Kofler Jul 25 '16 at 17:58
  • Yes, I agree. One challenge with that is being able to modify contract variables. Most of my functions modify state, which can only be done within the contract. There is not a clear separation of concern between different state variables in order to modularize them, although I recognize that it would not be impossible if I did a complete rewrite. – Raine Revere Jul 26 '16 at 14:13
9

I am also running into this issue as I have started to test my new contract which is using 79k in byte code so the Ethereum test-net will not allow the contract to be deployed.

My contract gas usage to be deployed is 7058868, which is much higher then the network block size limits.

I can recommend the following tips:

  • Continue to refactor into libraries. This is the #1 way to reduce the bytecode size of the main contract.

  • Use shorter types for struct elements and sort them such that short types are grouped together. Started doing this and it makes a massive difference even if the code is not as readable or clean looking.

  • Move duplicate functionality into generic functions or function modifiers (even if it means more function parameters).

  • Instead of creating multiple getters (or multiple public members), create bundled getters that return multiple values at once.

  • Use local variables to reference storage array elements.

  • Remove some constant functions that are not critical to the contract.

I am using the Metamask chrome plugin for test deployment which gives more information on deployment failure—such as contract gas usage.

The official Ethereum wallet software just displays a window after deployment failure that says - 'Intrinsic gas is too low'.

  • Hi! These are great suggestions and I believe can form the basis of an accepted answer. I made a suggested edit (needs to be approved) that adds a couple other points to your list. I consulted with another experienced Ethereum developer about this last week and got some more clarity about the issue. Indeed, it is a common problem for large-ish contracts, and the main solution is to use libraries. Other small optimizations can help. – Raine Revere Aug 5 '16 at 16:11
  • The one thing from your answer that was not entirely clear was this statement: "Remove local variables and instead use the full array path (this will make the code less readable)." Could you edit to clarify what you mean with this? Thanks! – Raine Revere Aug 5 '16 at 16:11
  • I don't yet understand. Solidity may involve reference types and memory, but I don't think you can have explicit pointers. It may be helpful if you can find a way to explain that point such that a broader audience can understand. – Raine Revere Aug 5 '16 at 17:53
  • I have updated the answer with 'use local variables to reference storage array elements.' And deleted my comments as they will just confused people. – Alex Darby Aug 11 '16 at 23:02
2

The contract currently fits the maximum size (~89 KB) of a block.

Are you running "expensive" code (with nested loops, with a high number of iterations or a large number of floating point operations)?

You may want to write test cases for methods used in the contract and run them using the solidity browser which allows for manually setting the gasLimit and gasPrice, as well as including one contract into another.

You cannot avoid the out-of-gas error since it's one of the base principles of Ethereum (used a means of preventing resource exhaustion). You have to pay for every action you perform on the block chain.

  • Thanks, that second link was very helpful. I am not sure if your comment about expensive code is relevant; the vast majority of the code in my contract is not run in my constructor. The out-of-gas error occurs when the contract is deployed, so the only code being executed is the constructor code. When I remove (any) non-constructor code, the out-of-gas limit goes away, indicating that it is caused simply by the size of the bytecode and not contract function execution. Including one contract in another will not help, as it still must deploy the same total bytecode. – Raine Revere Jul 26 '16 at 14:31
  • The comment on expensive code is relevant in that the price of execution is dependent on the number of executed instructions; the higher the number of instructions, the higher the price. When execution runs out of gas, it is aborted and the caller NOT refunded. – Sebi Jul 26 '16 at 14:45
  • The contract is not failing on execution, it is failing on deployment. – Raine Revere Jul 26 '16 at 14:56
  • So, the bulk of the data/computation is in constructors? "When I remove (any) non-constructor code, the out-of-gas limit goes away" Can you give a bit more details? Does the error occur regardless of the size of the code? – Sebi Jul 26 '16 at 15:09
  • No, actually. Please read the OP again if you need to. The out-of-gas error is occurring from CODE THAT IS NOT EXECUTED. I have proven this by decreasing the bytecode size of the contract to be deployed regardless of which code is removed. This is not your typical out-of-gas error due to execution cycles. Hope that helps to clarify. – Raine Revere Jul 26 '16 at 15:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.