Liquidity Mining Contract Development: Audit and Gas Optimization

At peak load, liquidity mining contracts drop transactions, and with them — rewards and reputation. We develop and optimize such contracts turnkey: we audit the logic, reduce execution cost, and deliver the solution with a report and a maintenance procedure. The share of failed operations is reduced severalfold, while system behavior remains predictable.

Blockchain Development Services

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1375
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1349
  • B2B Advance company logo design
    B2B Advance company logo design
    794
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1087
  • AIDER company logo development
    AIDER company logo development
    1032
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1129

Why liquidity mining contracts fail under peak load

Liquidation of collateral positions is a race with a short window. As soon as the collateral price drops below the threshold, liquidity mining contracts must assemble and send a call before competitors.

During peak network activity, the window shrinks to a few blocks, and some calls do not make it into a block at all.

The failure mechanics are predictable. Several participants simultaneously compete for the same position, bids for a place in the block grow by multiples, and the one who offered more wins.

A transaction with an insufficient bid hangs in the queue or executes after a competitor has already closed the position. These are failed transactions: the network charges for computation even when the call returns an error.

The cost of such an error is higher than the lost fee. The protocol undercollects the liquidation bonus, some positions turn into bad debt, and operating on stale state opens arbitrage against the protocol itself.

In networks like Ethereum, both execution order and operation cost are determined by contract logic — meaning that is where they are managed as well.

We break down how this is addressed: where an audit finds unnecessary costly calls in the liquidation pass, how optimization lowers the cost of an operation, and why the rule "one position — one winner" removes the race during peak network activity.

What an optimized contract provides: speed and resilience

A liquidity mining contract is a cycle: a participant deposits liquidity, the contract accrues rewards, periodically distributes them, and cleans up state.

While the logic is written in a straightforward way, the contract itself becomes the bottleneck: storage accesses on every iteration, recalculation across the entire participant array, duplicate checks.

Operation cost optimization starts with state layout: fields that are read together are packed into one slot, intermediate values are kept in memory, and accrued rewards are calculated in batches.

The call stops hitting the block limit, and the share of executed operations grows — distribution completes in full rather than in parts after repeated attempts.

We test load resilience during spikes: when the number of participants grows by multiples, the operation cost must not grow linearly; otherwise some calls drop out due to insufficient gas precisely at the peak.

After rework, distribution proceeds in a fixed number of steps, mass actions are batched, and response time stays within a predictable range.

Predictable behavior means there are no hidden execution paths. The audit records all branches: checks before transfers, order of calculations, boundary and zero values.

Together with logic rework, this eliminates an entire class of failures where a call formally succeeds but the reward is not accrued or is accrued twice. We perform calculations on the current Solidity branch and profile scenarios on a test network state.

We compare the result before and after: share of successful operations, confirmation time under load, operation cost in gas, number of repeated calls per accrual.

Work modes: audit of existing logic, optimization, development

The choice of work mode depends on what you already have — deployed bytecode with no upgrade capability, upgradeable logic behind a proxy, or so far only a strategy description.

The difference is fundamental: either fix hot paths in place or move improvements into a new deployment with migration of positions and permissions.

When each mode is appropriate

Mode When it is appropriate Limitations
Logic audit The contract is already in production, upgrade is impossible or undesirable; risk assessment and confirmation of calculation correctness are needed Code does not change: identified bottlenecks are addressed only by a new deployment; if source code is unavailable, some conclusions remain hypotheses
Logic rework The logic works, but rebalancing execution or failure handling is unsatisfactory; the external interface cannot be changed Freedom of action is limited by preserving signatures and addresses; modified areas require re-checking and storage review before upgrade
Development from scratch The strategy is your own, the old architecture cannot handle front-running protection or permission separation; a new address is acceptable Takes longer: design, tests, audit; positions and permissions are migrated manually, and the old contract remains in history

A logic audit does not change bytecode: we analyze the path from liquidity provision to fee collection, check who withdraws funds and under what conditions, how uncollected amounts are calculated, reproduce price leaving the range, and external router failure.

Rework is the next step: we rewrite hot sections, remove repeated storage accesses inside the rebalancing loop, replace long error strings with compact ones, preserving selectors and addresses so bots and calling contracts do not notice a difference.

Development from scratch is undertaken when you need your own range calculation model, front-running protection, or roles with limited permissions.

Then the storage scheme is designed for batch operations, invariants are enforced by tests, and migration of open positions is planned before the switchover.

How the work is structured: from audit to solution handover

The stages proceed sequentially, and each is closed with a verifiable result: a report, gas usage measurement before and after changes, and running scenarios on a test network.

Between the steps are checkpoints where the client sees the result and adjusts priorities before deployment to the mainnet.

  1. Audit of the current implementation. We analyze how a participant's share is calculated, at what point income is accrued, and who can change rates and pool parameters. The output is a report with severity levels, gas usage bottlenecks, and an estimate of the scope of changes.
  2. Design of the target logic. We fix the accrual and distribution rules, access roles, withdrawal limits, and behavior on external call failure. The agreed scheme becomes the basis of the code rather than being clarified along the way.
  3. Optimization of hot paths. We remove unnecessary state accesses, rewrite loops over participants and storage structures so that the cost of mass accrual does not grow linearly. We confirm the effect with before-and-after measurements.
  4. Tests and testnet validation. We cover mass accrual, partial withdrawal, calls without permissions, and external contract failure, then run everything on a test network against a copy of the real state.
  5. Re-audit. An independent review before deployment: we check that the fixes have not opened new bypass paths.
  6. Solution handover. We deliver the code, configurations, role scheme, and upgrade and rollback instructions, walk through everything with your team, and support the first accrual cycle.

Audit report, logic diagram, and support regulations

Work is finished not at the moment of successful deployment, but when the client can change the contracts independently — without us and without the risk of breaking the pool's economics.

That is why documentation is written based on the actual code, not "later": each artifact describes what is actually on-chain, including the accepted trade-offs between gas usage and attack protection. The package remains in your repository together with the source code.

  • Audit report — discovered vulnerability classes with priority, exploitation scenario, and a mark of "fixed/accepted consciously". For each disputed point, it states why it was left as is.
  • Contract logic diagram — reward flow from distribution to withdrawal: who accrues, by what formula, where the share is calculated and at what point it is fixed. With a map of external calls and dependencies between contracts.
  • Permissions and roles model — which functions are available to the admin, operator, and position holder, what cannot be done without multisig, and where a delay for executing critical changes is built in.
  • Gas optimization guide — a before/after table for hot operations explaining what produced the gain and what limitations it imposes on future changes.
  • Support regulations — frequency of checks, procedure for updating pool parameters, response to anomalies, and actions when external interference is detected.
  • Deployment and rollback instructions — step-by-step deployment procedure, post-deployment checks, and return to the previous working configuration if something goes wrong.
  • Change acceptance checklist — the minimum set of checks run before each contract upgrade so that changing one formula does not nullify the operation of the entire system.

The package is designed for use by another team: descriptions are tied to functions and files, not to people. If needed, we will walk through the documentation with your engineers and hand over the repository with explanations.

Case study: how we cut the share of failed transactions threefold

A working liquidity mining protocol on Ethereum came to us: pools were being filled, but every fifth call ended in a revert. The user lost gas and could not see the reason — the interface returned one generic error for all cases.

The task was framed as an audit and gas optimization, but in practice it required eliminating an entire class of failed transactions.

What the measurements showed

We broke down the reverts by cause. Two-thirds came from two scenarios: gas exhaustion inside the reward accrual loop, when the participant list no longer fit within the limit, and triggering of the minimum output with a stale pool quote. The remainder were repeated calls after the state had already changed.

What we changed and what we got

The accrual loop was split into bounded batches, and reward calculation was moved to an accumulator with lazy recalculation.

We calculate the minimum output from fresh state at the moment of sending, and before signing the transaction goes through simulation — on revert, the user sees the reason without spending gas.

Metric Before After
Share of failed transactions 21% 6%
Reverts due to gas in the accrual loop 42% of all reverts less than 4%
Gas usage for reward withdrawal baseline 1.8 times lower

The causes of reverts were moved to a separate dashboard: the next class of failures becomes visible on the graph before someone writes to support about it.

What to do if the solution is already deployed and cannot be stopped

A working solution cannot be stopped: the pool, participant shares, and accrual history live in state that cannot be reproduced by restarting from scratch.

On-chain code is immutable, so an upgrade is not a file edit but a migration of logic into a new contract that reads the same state.

The key to upgrading without downtime is the seam between storage and logic. When state resides in a separate layer and calculations reside in a replaceable module, an upgrade comes down to deploying a new version and switching a pointer.

If there is no seam, it should be built in advance; otherwise every logic change turns into a migration of all data with a risk window.

We perform logic migration step by step: state snapshot, invariant checks — participant sums, liquidity volume, period counters — deployment of the new version alongside the old one, and a run on a state copy under the same conditions. We switch only after reconciliation. External calls remain the same; the internal arithmetic changes, so participants see no disruption.

We change roles and access separately from logic; otherwise the switchover may expand permissions through oversight. The previous version remains operational: until the new one proves stable under load, rollback is a reverse switch, not restoration from an archive.

If reward calculation changed, we compare a sample before and after on the same inputs — with no missed payouts.

Describe what is deployed now and how access is organized — we will come back with a switchover plan, rollback procedure, and list of checks.

Common technical questions about integration and support

Before launching liquidity mining contracts, clients usually have the same technical concerns: will the accrual logic withstand real load, what will happen to already connected services after an upgrade, and who is responsible for the contract after handover. Below are substantive answers.

Logic validation, integration, and support determine whether the pool will survive to the end of the first week without manual intervention.

How do you verify that the accrual and reward distribution logic is correct?

We calculate a reference distribution model and run the contract on a mainnet fork: partial withdrawal, early exit, multiple pools, zero stake. Rewards are compared against the model at every block — a discrepancy in even one scenario becomes a blocker for deployment.

What will happen to integrations after a contract upgrade?

We upgrade logic through a proxy: the contract address and event scheme remain the same, so wallets, indexers, and analytics continue to read the same data without changes on their side. The public interface is extended in a backward-compatible way.

Who manages the contract after launch and how is access structured?

Roles are separated: parameter configuration, emergency stop, and read-only access. Admin keys are in a multisig, and every action leaves an event in the log. Support includes event monitoring and alerts for anomalous withdrawals from pools.

Let's discuss the task: what data is needed for an estimate

So that the estimate is based on facts rather than guesses, we need inputs about your system.

Liquidity mining contracts are almost always interconnected — pool, reward router, share storage — and the cost of work is determined not by the number of files, but by how many inconsistencies they contain and how expensive write operations are.

  • composition and connections of contracts: what roles each has, who calls whom and in what order;
  • distribution logic: how a participant's share is calculated, when the reward is accrued, how fees and refunds are handled;
  • on-chain addresses and source verification, if the system is already deployed — we will compare the code with what actually executes;
  • access to the repository and build artifacts, as well as a test environment with separate keys — production access is not needed at the estimate stage;
  • current metrics: how many transactions per day, which calls consume the most gas, where operation cost is growing;
  • limitations: immutable parameters, validation requirements, release procedure for upgrades;
  • what has already been done: reports from previous reviews, incidents, known bottlenecks.

Describe the task in free form — we will come back with an estimate and work plan: stages, scope of checks, gas optimization procedure, and points where your decisions are needed.

If you do not yet have answers to some points, we will start with what is available: usually that is enough to outline the scope of work and risks.