Documentation · Reference
GeneLens
The optional, stateless read contract that decodes GeneHook storage into typed records, function by function.
GeneLens is read-only reporting for GENE. It holds no state, no funds and no permissions, and GeneHook never calls it. It reads GeneHook's storage through GeneHook.extsload() and decodes the fixed layout into GeneHook's own record types. Anyone can deploy their own copy or decode the same slots off-chain with eth_getStorageAt (GeneLens.sol:12-16; GeneHook.sol:46). The hook makes external calls only to the PoolManager and GeneToken (invariant CALL).
GeneLens has no constructor arguments, no storage, no events and no custom errors. Every function except genome() takes the hook address as its first argument. Its only revert is the string "index" in positionAt (GeneLens.sol:94).
Layout check. test/unit/LensLayout.t.sol compares every decoder with typed views over the same storage, using a reference hook generated from the production source (LensLayout.t.sol:11-16; invariant LENS). The slot map is on Storage layout.
Epoch timing. Epoch-dependent views (blockState, caps, ethBudgets, flowBudgets(e-1), epochRecord(e-1)) describe the last touched epoch until the new epoch's first touch. currentEpoch itself is computed from block.number and is always current.
#Typed records
| Function | Mutability | Returns | Behaviour | Source |
|---|---|---|---|---|
geneStatus(GeneHook hook, uint8 g) |
view | GeneHook.GeneStatus |
Decodes slots 10 + 2g and 11 + 2g: state, history, count, firstEvidenceEpoch, expressedEpoch, evidenceHash |
GeneLens.sol:46-56 |
epochRecord(GeneHook hook, uint32 e) |
view | GeneHook.EpochRecord |
Decodes _records[e]: revenue, activeBlocks, pathTicks, ethCommitted, closed. An epoch never written reads as all zero |
GeneLens.sol:58-60, GeneLens.sol:266-273 |
blockState(GeneHook hook) |
view | (GeneHook.BlockState, GeneHook.EpochAcc) |
Decodes slots 0 and 1 | GeneLens.sol:62-76, GeneLens.sol:275-282 |
caps(GeneHook hook) |
view | (GeneHook.Caps, GeneHook.Caps2) |
Decodes slots 7 and 8 as stored, without checking Caps.epoch against the current epoch |
GeneLens.sol:78-87 |
positionCount(GeneHook hook) |
view | uint256 |
Length of the position registry (slot 18) | GeneLens.sol:89-91 |
positionAt(GeneHook hook, uint256 i) |
view | GeneHook.Position |
(lower, upper) of registry entry i; index 0 is the genesis band. Reverts "index" if i >= positionCount |
GeneLens.sol:93-98 |
flowBudgets(GeneHook hook, uint32 e) |
view | GeneHook.Budgets |
Net-flow budgets created when epoch e closed (spent in e + 1): bid, imm, pLow |
GeneLens.sol:158-165 |
cumulativeFlow(GeneHook hook) |
view | GeneHook.CumFlow |
Cumulative net curve GENE since launch (nc, 1e12-wei units), its all-time high (hwm) and the lowest level since that high (lwm) |
GeneLens.sol:193-200 |
#Bookkeeping scalars
| Function | Mutability | Returns | Behaviour | Source |
|---|---|---|---|---|
currentEpoch(GeneHook hook) |
view | uint32 |
(block.number - launchBlock) / EPOCH_BLOCKS once launched, else 0 |
GeneLens.sol:100-105 |
launchBlock(GeneHook hook) |
view | uint40 |
Slot 2, bits 0-39 | GeneLens.sol:109-111 |
evolveCursor(GeneHook hook) |
view | uint32 |
Slot 2, bits 48-79: the next closed epoch to process | GeneLens.sol:113-115 |
immuneStressBits(GeneHook hook) |
view | uint8 |
Slot 2, bits 80-87: IMMUNITY deployment-stress register | GeneLens.sol:117-119 |
lastMetabolizeBlock(GeneHook hook) |
view | uint40 |
Slot 2, bits 88-127 | GeneLens.sol:121-123 |
lastRegenerateBlock(GeneHook hook) |
view | uint40 |
Slot 2, bits 128-167 | GeneLens.sol:125-127 |
harvestCursor(GeneHook hook) |
view | uint256 |
Slot 20: the round-robin harvest cursor | GeneLens.sol:129-131 |
#Derived views
| Function | Mutability | Returns | Behaviour | Source |
|---|---|---|---|---|
evidenceHashFor(GeneHook hook, uint8 g, uint32 first, uint32 last) |
view | bytes32 |
Recomputes keccak256(abi.encode(g, first, last, EpochRecord[first..last])) from stored records only. Equals geneStatus(g).evidenceHash for the range [firstEvidenceEpoch, expressedEpoch] |
GeneLens.sol:133-147; GeneHook.sol:975-982 |
anchors(GeneHook hook) |
view | (int24 atlTick, int24 athTick) |
The two placement anchors from slot 0 | GeneLens.sol:149-156 |
ethBudgets(GeneHook hook) |
view | (uint256 bidLeft, uint256 immunityLeft, uint256 churnLeft) |
The current epoch's three ETH budgets net of what was placed. Counters are treated as zero when their stored epoch differs from the current one. bidLeft uses hook.ethBudget(); churnLeft is revenue(e-1) - bid(e-1) less churn placed. All zero in epoch 0 |
GeneLens.sol:167-191 |
genome() |
pure | bytes |
The exact Genome.encode() byte string; keccak256(genome()) == hook.genomeHash() |
GeneLens.sol:202-206 |
report(GeneHook hook) |
view | GeneLens.MassReport |
See below | GeneLens.sol:209-227 |
#report()
report returns a MassReport (GeneLens.sol:36-43):
| Field | Meaning | Source |
|---|---|---|
permanentMassLiquidity |
hook.massLiquidity(): liquidity units ever added |
GeneLens.sol:37, GeneLens.sol:223 |
reachableEthDown[3] |
ETH a seller would receive from protocol positions moving the price down 5%, 10% and 25% from spot | GeneLens.sol:38, GeneLens.sol:213, GeneLens.sol:246-259 |
reachableGeneUp[3] |
GENE a buyer would receive from protocol positions moving the price up 5%, 10% and 25% | GeneLens.sol:39, GeneLens.sol:214, GeneLens.sol:246-259 |
cumulativeEthCommitted |
hook.ethCommitted() |
GeneLens.sol:40, GeneLens.sol:224 |
cumulativeGeneCommitted |
hook.geneCommitted() |
GeneLens.sol:41, GeneLens.sol:225 |
positions |
positionCount(hook) |
GeneLens.sol:42, GeneLens.sol:226 |
The tick offsets are [513, 1054, 2877] down (from ln(1/(1-x)) / ln(1.0001)) and [488, 953, 2232] up (from ln(1+x) / ln(1.0001)) (GeneLens.sol:213-214). Liquidity per position is read from the PoolManager with getPositionInfo(poolId, hook, lower, upper, bytes32(0)) (GeneLens.sol:239). Reachable depth is computed from current positions at the current price, and reads zero for a move that reaches no protocol position; see anchors.
Sources (10)
- src/GeneLens.sol:12-43
- src/GeneLens.sol:46-206
- src/GeneLens.sol:209-259
- src/GeneLens.sol:262-301
- src/GeneHook.sol:46
- src/GeneHook.sol:72-128
- src/GeneHook.sol:199-221
- src/GeneHook.sol:950-963
- src/GeneHook.sol:975-982
- test/unit/LensLayout.t.sol:11-16
Paths are relative to the GENE repository at tag rc4-audit-candidate (aca5fcd).