I'm developing a Dapp with a function (let's just call functionA) that has potentially significantly different gas cost between invocations. This is due to the need for costly extra computation when certain conditions are met. It is expected that for most invocations of functionA the conditions won't be met. However the extra computation is vital for properly functioning of functionA, so it needs to be performed from time to time, just not often.

The problem is the extra computation is very costly, so much so that it might double the gas cost for functionA. functionA is intended to be used by end users, and I'm worried that, when multiple users call functionA at roughly the same time, around the time that the condition for extra computation are met, gas estimate for some of those transactions might be too low and leads to failure due to out of gas exception, wasting user money and time and causing frustration and bad user experience in general.

My question(s) are, what is the best practices to deal with such cases? Should I redesign the function / contract to avoid that and how do I do that? Or how can I improve the user experience?

(Below are more explanation for the context of the question and can be skipped.)

Consider a function

function functionA() external {
    if (condition) {

functionA is to be called by end users. Most of the time, condition is false and functionA will just do regular stuff, costing regular gas. However, once in a while condition will be true and functionA will do more and cost a lot more gas than normal, after that condition will be false again.

The problem arises when multiple users attempt to call functionA at roughly the same time. I expect the gas cost estimate provided most JSON-RPC providers will return only the regular gas cost (as they are simulated when condition is false). If this happens around the time condition turns from false to true, the transactions that are estimated before condition changes but included after condition changes will be under-estimated and fail (because condition won't change to false again unless the extra computation are performed). This is even more likely when the time between gas estimation and actual transaction execution is long (for example on "slow" networks like Ethereum or network congestion), and with more transaction submitted together more will likely fail, wasting more user's money. It's even worse considering that as users resubmitted transactions, usually only 1 of them needs to perform the extra computation and the rest will just do regular stuff anyway, essentially wasting money and time for nothing. It's also hard to predict when condition will change to true with multiple concurrent transactions and undetermined time until actual execution.

A few alternatives I'm considering:

  • Extract the extra computation to another function that can be called separately, probably from an external system. But I'd rather not having to maintain another system to call that function regularly.
  • Set gas limit in front-end high enough so it can cover even cases with extra computation. However how high is high enough might be not easily pre-calculated, and the high gas limit is displayed in some wallet as high fee (even though it won't actually costs that much most of the time), which might be a turn-off for users.
  • I'd try splitting the computation into smaller steps so it can be executed independently.
    – Ismael
    Sep 20 at 4:52

Your Answer

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

Browse other questions tagged or ask your own question.