Hydrex
Senior Smart Contract Engineer
November 2025 – present
Hydrex is a concentrated-liquidity DEX on Base. I joined in November 2025 as a senior smart contract engineer, and I own its liquidity-mining reward system outright.
The reward system
Liquidity mining sounds simple until you try to make it exact. A campaign says: pay this budget, to whoever provides liquidity in this pool, over this window, in proportion to how much and for how long. Doing that honestly means measuring every position continuously, and settling on-chain cheaply enough that the gas does not eat the reward.
I designed and built the whole thing — a TypeScript and NestJS service that continuously snapshots every position in incentivised pools, converts those observations into time-weighted score-seconds, allocates against a fixed budget, publishes Merkle roots on-chain, and serves claim proofs through a public API. PostgreSQL with TimescaleDB underneath, Redis for caching.
To date it has distributed 25.1 million tokens to 1,669 liquidity providers, across 2,469 campaigns and 163 pools, through 777,470 on-chain root updates.
The constraint that shaped the design
Merkle roots here are cumulative and irreversible. Once a root is published, an allocation can only ever go up — you cannot claw back a number you have already committed to. Every other design decision follows from that.
So rather than recomputing totals and asserting afterwards that they never decreased, I built the allocator around incremental deltas, which makes the monotonic floor hold by construction. The pipeline snapshots first and aggregates second, which keeps every reward calculation replayable from raw observations — if a number is ever disputed, it can be rebuilt from what was actually observed on-chain rather than from a cached total.
Settlement is batched: one transaction per cycle carrying every campaign's root. Gas stays roughly flat as campaigns multiply — about 18k gas per root, 0.096 ETH in total across the system's life. It has absorbed an elevenfold increase in concurrent campaigns without a change in throughput, and sustained 99.97% transaction success across 154 consecutive days of unattended operation.
Invariants, and the bugs they did not catch
I specified seven financial invariants — budget conservation, the monotonic floor, duplicate-free trees, leaf encoding matched byte-for-byte to the on-chain verifier — enforced by 488 tests and by standalone audit scripts that run against production data as a deployment gate.
Two defects still got through, and both are the interesting kind: neither raised an error.
The first divided an incremental reward delta by a cumulative score-seconds denominator. Newly joined providers were underpaid by up to a third; providers who had left kept accruing. Every batch balanced. The budget held. Somebody's yield was simply quietly wrong.
The second was a cache key. The snapshot downsampler keyed its cache on the position, while the row it guarded was per-campaign. Wherever two campaigns ran on the same pool, the second silently wrote zero snapshots — and because processing order reshuffled each cycle, each campaign lost roughly half its data, nondeterministically. I found it by auditing the pipeline ahead of a change in campaign-creation permissions, and confirmed it was already affecting live pools.
I think about those two more than anything else I have shipped. Failure modes that do not look like failures are the ones worth building your process around.
Contracts and security
Alongside the distributor I work on the protocol's Solidity — roughly 6,370 lines of production contract code to date.
I delivered the protocol's decentralisation workstream, moving privileged functions behind a timelock and tightening who can do what on-chain. Fifteen contracts, audited, zero high-severity findings, no failed remediations. I have been the sole counterpart to our external auditors across four engagements: scoping, findings response, remediation.
I also split the distributor from one process into separate web and worker processes. The driver was operational — a shared connection pool let aggregation starve user requests, and memory and hosting costs were unpredictable — but the security consequence is the better half: the public API process now cannot hold the signing key at all. The operator key is restricted to a single on-chain role, verified to hold no administrative privileges.