State-Publication Authority Failure / Accounting Canonicalization Abuse
- Name: state-publication authority failure / accounting canonicalization abuse
- Category: exploit pattern / accounting-publication failure / attacker-timed canonicalization / sync-harvest-cache-write abuse / protocol-authored accounting truth failure
- Summary: This exploit family appears when a protocol has some intermediate accounting state that is not yet supposed to be money truth — pending rewards, a fresh exchange rate, a harvested profit figure, a cached NAV, a reserve refresh, or a newly recognized wrapper balance — and then exposes a helper that can bless that state as canonical. The attacker does not always need to forge balances or falsify an external oracle. Often they only need to shape an intermediate condition, then choose the exact moment a function like
syncRewards(),harvest(),cacheAssetPrice(),_updateDebtAndCollateralIndex(),gulp(), or some equivalent publication helper turns that condition into official share value, debt relief, collateral value, or reserve truth. Once that write lands, downstream mint, withdraw, redeem, borrow, or debt-accounting logic stops seeingtentative stateand starts seeingthe protocol's own answer. - Fast routing: start with Alchemix alETH when wrong-vault harvest logic publishes false profit as borrower debt repayment; GoGoPool when donated
WAVAXonly becomes next-depositor pricing truth aftersyncRewards(); Zunami when a strategy-side donation plus thin-market mark only becomes token-balance truth aftercacheAssetPrice(); Raft when a donation only becomes borrowable collateral once_updateDebtAndCollateralIndex()republishes raw balance growth into canonical collateral-index truth; Balancer STA when stale reserve drift only becomes live drainable pricing aftergulp()collapses internal reserves to attacker-shaped dust reality; ResupplyFi when a fresh wrapper mark only becomes exploitable once reciprocal conversion logic crystallizes it into canonicalexchangeRatestate; and KiloEx when a weakly authenticated forwarder / keeper chain lets the attacker self-publish absurd internal mark prices as protocol-owned truth without moving any external market first. - What it is:
- The protocol has some candidate accounting state that is not yet supposed to be final economic truth.
- A helper function can publish that candidate state into canonical storage, canonical reserves, a canonical share price, or a canonical debt / collateral index.
- The system treats that helper as bookkeeping or liveness plumbing instead of as a solvency-boundary authority surface.
- The attacker first shapes or times the candidate state, then triggers the publication step at the most favorable moment.
- Downstream consumers immediately trust the published result as if it were fully settled, honest protocol truth.
- Typical preconditions:
- One or more public or weakly bounded helpers can convert observed or inferred state into canonical accounting state.
- The candidate state depends on something attacker-timable or protocol-misclassified: a donation, stale reserve drift, a thin-market mark, a wrong vault pointer, a fresh wrapper rate, or a module-local accounting disagreement.
- Publication can happen in the same block or same transaction as monetization.
- Downstream consumers do not distinguish
freshly publishedfromsettled and trustworthy; they immediately use the result for minting, redemption, collateral valuation, debt forgiveness, or pool pricing. - One publication step can move enough value that the attacker can cash out before human operators or slower controls react.
- Common vulnerable surfaces:
- vault and wrapper helpers such as
syncRewards(),harvest(),checkpoint(),cacheAssetPrice(),updateIndex(), and reserve-refresh paths - debt or collateral index publishers that treat freshly recognized balance growth as canonical solvency truth
- AMM helpers like
gulp()or related reserve-sync routines that turn latent reserve drift into live pricing truth - strategy, AUM, or share-price writers that can publish a manipulable unwind quote or transient mark into canonical exchange-rate state
- any path where the same actor can both shape candidate state and trigger the helper that canonizes it
- vault and wrapper helpers such as
- Exploit sequence:
- The attacker identifies a helper that writes accounting state other modules later trust as canonical.
- They find a way to shape the candidate input: donation, stale accounting drift, thin-market trade, wrong module selection, or some other transient but monetizable condition.
- They hold that manipulated or misclassified state live for one block, one transaction, or one accounting frame.
- They trigger the publication helper so the protocol itself stores or refreshes the attacker-shaped value.
- A mint, redeem, withdraw, borrow, liquidation, or debt-relief path immediately consumes the newly published value as if it were honest settled truth.
- The attacker exits against real assets, real borrow capacity, or real debt forgiveness before the state can be corrected.
- Variants:
- Harvest profit misclassification — modules disagree about which vault, deposit set, or denominator is canonical, and
harvest()publishes false profit that the system honors as debt repayment or share growth. Alchemix alETH is the clean exemplar. - Reward-sync publication — a donation or pending reward balance only becomes share-pricing truth after a sync helper recognizes it. GoGoPool is the clean bootstrap exemplar.
- Cached-NAV snapshot abuse — a transient strategy-side valuation gets frozen into a cached price, index, or exchange rate that remains live long enough to monetize. Zunami is the clean accounting-side exemplar.
- Collateral-index republication — raw contract-balance growth or a fresh wrapper mark only becomes borrowable because an index-update path republishes it into canonical collateral truth. Raft and ResupplyFi are strong exemplars on that seam.
- Reserve-refresh collapse — stale internal reserve accounting is already wrong, but a public refresh like
gulp()decides exactly when that wrongness becomes active pricing and redemption truth. Balancer STA is the clean exemplar. - Same-transaction accounting relay — a manipulable valuation or fresh wrapper mark becomes canonical accounting truth and reaches a money-moving consumer in the same transaction.
- Harvest profit misclassification — modules disagree about which vault, deposit set, or denominator is canonical, and
- Quick classifier:
- If the main question is
who was allowed to make this attacker-shaped intermediate accounting state canonical right now?, start here. - If the main question is
how was the exchange rate or share price inflated in the first place?, start with donation-share-price-manipulation or first-deposit-inflation and return here for the publication step. - If the main question is
what exact helper let a stale, donated, or wrong-vault value become official protocol truth?, stay here. - If the main question is
why did a protocol-authored local reserve or pool state behave like an oracle?, compare with protocol-authored-market-state-oracle-failure. Use that note when the pricing object itself is the analytical center; use this one when the sharper lesson is the sync / harvest / cache helper that made the object canonical. - If the main question is broader design hardening rather than exploit classification, move to sync-harvest-and-cache-write-authority-discipline.
- If the main question is
Three accounting-publication promotions reviewers should not collapse
-
Fragile candidate accounting state exists
- A donation, pending reward delta, stale reserve drift, wrong vault pointer, thin-market wrapper mark, or fresh balance change is visible somewhere in the system.
- This is only an observation fact. It still does not answer who may bless that state as canonical accounting truth or which downstream consumers deserve to trust it.
-
Canonical local accounting publication exists
- A helper such as
syncRewards(),harvest(),cacheAssetPrice(),updateIndex(),_updateDebtAndCollateralIndex(), orgulp()writes that candidate state into canonical storage, canonical reserve accounting, canonical debt relief, or canonical share / collateral / NAV state. - This is already a much stronger authority step than merely noticing the value. But it is still not automatically proof that every downstream mint, redeem, borrow, or debt-accounting consumer should honor the freshest possible publication right away.
- A helper such as
-
Economically active downstream accounting truth exists
- Mint, burn, redeem, withdraw, borrow, liquidate, forgive debt, or pool-pricing code is now allowed to spend against the freshly published accounting state.
- This deserves its own boundary too.
Published nowis often not yet the same thing assafe to honor everywhere right now.
The recurring reviewer task is to answer three separate questions cleanly: what fragile accounting state was visible?, what exact helper published it as canonical local truth?, and which consumers were actually entitled to trust that fresh publication immediately?
- Detection heuristics:
- Search for functions named
sync,harvest,checkpoint,cache,gulp,updateIndex,updateAum, or similar and ask what exact economic truth they are allowed to publish. - Ask whether the same actor can both move the candidate state and trigger the helper that records it.
- Look for same-block or same-transaction paths where published state is immediately consumed by mint, redeem, borrow, withdrawal, liquidation, or swap logic.
- Review whether the helper publishes state derived from donations, thin markets, stale reserves, wrong module pointers, or module-local bookkeeping that can still be wrong.
- Test whether normalizing the manipulated market state after publication still leaves the protocol exploitable because the cached or stored value survives long enough to matter.
- Treat
permissionless publicationas a real security decision. If public publication is safe, the code should show explicit bounds, delays, smoothing, or downstream distrust.
- Search for functions named
- Defenses:
- Model sync, harvest, cache-write, reserve-refresh, and index-update helpers as accounting-oracle publishers, not harmless housekeeping.
- Separate observation from publication and publication from activation; a newly written value should not automatically become same-block redemption, collateral, debt, or reserve truth.
- Bound per-call impact with deviation caps, monotonicity rules, cooldowns, and per-epoch movement limits.
- Make downstream consumers distrust freshly published values until a delay, amortization window, or independent check makes them safe to honor.
- Keep internal topology canonical before publication. Wrong vault pointers, stale denominators, and stale module relationships should never become publishable profit or collateral truth.
- Add adversarial tests that explicitly combine
shape state -> publish state -> monetize statein one transaction.
Failure-prevention checklist
- Inventory every function that can turn candidate state into canonical accounting truth:
sync,harvest,checkpoint,cache,gulp, reserve refresh, index updates, collateral-index writes, reward recognition, and cached-NAV publication. Treat that inventory as solvency-boundary code. - For each publisher, write down what candidate input it is allowed to crystallize and how an attacker could shape that input: donation, thin-market quote, stale reserve drift, wrong vault pointer, delayed reward, fresh wrapper mark, or module-local accounting disagreement.
- Split observation, publication, and activation into separate stages whenever possible. A value being writable to storage should not automatically make it same-block redemption, collateral, debt-forgiveness, or swap-pricing truth.
- Inventory downstream consumers for each publication helper, not just the helper itself. Review exactly which redemption paths, debt-relief flows, collateral engines, reserve-pricing rails, or vault-share mint / burn surfaces will trust the freshly published value.
- Put hard movement limits on one publication step: deviation caps, monotonicity guards, epoch limits, or capped amortization. If one call can move too much truth, the helper is over-authorized.
- Preserve an explicit gate from
canonical local accounting publicationtoeconomically active downstream accounting truth; one helper should not silently promote a fragile value through both steps unless the protocol can defend that full combined transition. - Prevent the same actor from both shaping candidate state and immediately publishing it into canonical storage unless the downstream effect is tightly bounded.
- Require downstream consumers to distinguish
freshly publishedfromsettled. Lending, liquidation, withdrawal, and reserve-paying paths should be able to quarantine, haircut, delay, or ignore just-written values. - Keep module topology canonical before publication. Vault pointers, strategy registries, reserve ledgers, denominator state, and collateral adapters should not be mutable enough that a later helper can publish fiction from the wrong object.
- Adversarially test one-transaction bundles that do
manipulate -> publish -> monetize -> normalize. If the exploit still pays after the market leg is unwound but the published state remains live, the publication boundary is too weak. - Monitor for publication-risk signals in production: outsized one-call rate jumps, unusual sync timing after donations, same-block cache updates followed by large redemptions or borrows, and debt or collateral indices moving much faster than plausible organic growth.
- Make rollback explicit. If a bad publication lands, the protocol should know which consumers can be paused, which caches can be invalidated, and how blast radius is capped before governance catches up.
Audit prompts
- Which exact functions are allowed to convert candidate accounting state into canonical state, and what downstream code immediately trusts their output?
- Can one actor both create the favorable state and choose the publication moment in the same transaction or block?
- What manipulative inputs feed the publisher: donations, stale reserves, thin-market valuations, reward deltas, wrong module selection, or fresh wrapper marks?
- Does publication itself have effect bounds, or is the real safety assumption merely
nobody will time this adversarially? - Which downstream consumers treat a freshly published value as live truth for minting, redeeming, borrowing, withdrawing, liquidating, debt relief, or pool pricing without an extra distrust boundary?
- If the manipulated state normalizes right after publication, does the protocol still lose because the cached or stored value survives long enough to be monetized?
- Are there helpers that look operational —
harvest,sync,gulp,cache,checkpoint,updateIndex— but in practice exercise authority over solvency or reserve truth? - Can stale or wrong module topology make honest-looking publication code write dishonest economic truth, as in wrong-vault harvest or bad denominator selection?
- What exactly prevents
observe bad state -> publish bad state -> spend against bad statefrom happening in one attacker-controlled bundle? - When a publication is later found unsafe, how is it contained: invalidation bit, cooldown, stale flag, pause, bounded per-asset loss cap, or nothing?
Lessons that should already be standard
-
It only updates a cacheis not a defense. If later code trusts the cache for money movement, the cache writer is an oracle publisher. -
Timing rights are economic rights. Public housekeeping is still authority when the caller chooses when fragile state becomes canonical.
-
A protocol’s own published answer is often more dangerous than the raw manipulation that preceded it, because every downstream module tends to trust protocol-authored storage more than a visibly noisy market state.
-
Fragile candidate accounting state, canonical local accounting publication, and economically active downstream accounting truth are different trust levels. The safest design often lets the system notice fresh state quickly, publish it narrowly, and force money-moving consumers to accept it only later or only in bounded form.
-
Same-block publication plus same-block monetization is the recurring catastrophe shape. If the protocol cannot defend that bundle, it should break the bundle.
-
Sync and harvest code deserve the same adversarial review as mint, burn, borrow, and liquidation code. In this family, the helper is the monetization boundary.
-
Wrong internal topology is as dangerous as wrong prices. A harvest against the wrong vault or an index update against the wrong object can publish fiction without any external market manipulation at all.
-
The durable question is not just
can this value be manipulated?butwho is allowed to bless it as real, with what effect, and how quickly do other modules believe them? -
High-signal incidents:
- harvest debt-erasure incident (2021-06-16) —
harvest()on the wrong vault object published false profit that the protocol immediately honored as real borrower debt relief. - GoGoPool ggAVAX first-depositor share-price inflation near miss (2023-01-03) — donated
WAVAXonly became harmful oncesyncRewards()recognized it quickly enough to poison the next depositor’s exchange rate. - zETH SDT-donation price-caching share-inflation drain (2023-08-13) — strategy-side donation plus thin-market pricing only became spendable because
cacheAssetPrice()froze the manipulated NAV into token-balance truth. - collateral-index manipulation unbacked-R mint (2023-11-10) — donation-sensitive collateral-index publication made freshly inflated wrapper value canonical borrow power.
- zero-exchange-rate exploit (2025-06-26) — a fresh wrapper mark only became borrowable truth once reciprocal conversion logic crystallized it into canonical
exchangeRatestate. - gulp pool drain (2020-06-28) — the reserve-accounting mismatch already existed, but
gulp()let the attacker choose exactly when Balancer’s false reserve state became live pricing truth.
- harvest debt-erasure incident (2021-06-16) —
-
Why this pattern matters:
- Security reviews often notice the bad candidate input but underweight the helper that makes it canonical. The publication helper is frequently the monetization multiplier.
- This pattern explains why incidents that initially look unrelated — donations, rollout mistakes, stale reserves, fresh wrapper marks, cached strategy prices — rhyme at the decisive moment where a helper blesses bad intermediate state into official accounting truth.
- It is the accounting-family reminder that a protocol’s own authored write can be more dangerous than the external manipulation that preceded it, because every downstream consumer is inclined to trust
storage written by usmore thanmarket state observed by us.
What sound design looks like
- One observation boundary should stay explicit: a protocol may notice donations, pending rewards, stale reserve deltas, wrong-vault output, thin-market wrapper marks, or fresh balance changes without yet treating them as money-good accounting truth.
- One publication boundary should be explicit: helpers that write reserves, NAV, rewards, debt relief, collateral indices, or share-value state should be treated as accounting-oracle publishers with narrowly defined authority, not as passive bookkeeping.
- One activation boundary should stay separate from publication: a freshly written accounting value should not automatically become immediate solvency, withdrawal, redemption, debt-forgiveness, or reserve-pricing truth without delay, smoothing, quarantine, or independent confirmation.
- One actor should not control the whole
shape -> publish -> monetizebundle. The cleaner design separates who can influence candidate accounting state, who can publish it, and who can spend against it. - One publication step should have bounded blast radius: deviation caps, epoch caps, monotonicity rules, or amortized updates should keep a single cache write or sync call from rewriting too much economic truth at once.
- One bad publication should be containable: caches should be invalidatable, downstream consumers pausable, and just-published values quarantineable before they cascade into systemwide loss.
Where this pattern stops
- Use donation-share-price-manipulation when the main analytical work is how the attacker printed or inflated the wrapper rate itself.
- Use first-deposit-inflation when the main lesson is zero-supply bootstrap capture rather than attacker-timed publication of already-shaped state.
- Use reward-index-initialization-failure when the decisive mistake is not publication timing but a flywheel’s own sentinel and initialization semantics.
- Use balance-delta-provenance-failure when the deeper failure is that a raw balance change was misread as the wrong economic event before any publication-helper question appears.
- Use state-publication authority failure when the sharper lesson lives in explicit price publication, market-state oracle behavior, or off-family oracle-writing surfaces rather than in accounting, issuance, reward, debt, or share-state canonicalization. KiloEx is the clean cross-family exemplar there: the decisive publication helper was an attacker-reachable oracle write path rather than an accounting sync or share-state canonicalization helper.
Internal linkages
- Positive-design companion: sync-harvest-and-cache-write-authority-discipline — this note classifies the failure family; that note is the design checklist for how publication authority should have been bounded.
- Adjacent pattern: donation-share-price-manipulation — use that note when the exchange-rate lie itself is the analytical center and this one when the sharper follow-up is who was allowed to crystallize that lie into canonical accounting truth.
- Adjacent pattern: first-deposit-inflation — GoGoPool sits on the seam where first-depositor capture becomes much worse because reward publication is attacker-timed.
- Adjacent pattern: balance-delta-provenance-failure — some incidents combine
what balance growth meantconfusion withwho could publish itconfusion. - Adjacent pattern: reward-index-initialization-failure — useful contrast when the exploit comes from inconsistent initialization semantics rather than attacker-timed publication of otherwise-valid candidate state.
- Adjacent oracle cousin: state-publication-authority-failure — same structural control surface, but the oracle-market-abuse note is the better home when the pricing object or oracle-writer boundary itself is the main preserved lesson. KiloEx is the sharp current cross-family exemplar for that branch.
- Best concrete routing cluster so far: Alchemix alETH for harvest profit misclassification, GoGoPool for reward-sync publication, Zunami for cached-NAV snapshot abuse, Raft Finance and ResupplyFi for collateral-index / exchange-rate publication, and Balancer STA for reserve-refresh collapse.
Control surface
-
The leverage sits in the authority to publish protocol-authored accounting state, not just in the ability to move external prices or balances.
-
The key ladder is
fragile candidate accounting state exists,candidate state becomes canonical local accounting publication, andthat publication becomes economically active downstream accounting truth. -
The key question is always: who can decide when a tentative, manipulable, stale, or misclassified value climbs each rung of that ladder?
-
Once downstream modules trust that published answer for minting, redemption, borrowing, debt reduction, or reserve pricing, the helper that wrote it is part of the solvency boundary.
-
Sources:
- https://forum.alchemix.fi/public/d/137-incident-report-06162021
- https://rekt.news/alchemix-rekt
- https://code4rena.com/reports/2022-12-gogopool
- https://ackee.xyz/blog/zunami-hack-post-mortem/
- https://www.euler.finance/blog/exchange-rate-manipulation-in-erc4626-vaults
- https://www.openzeppelin.com/news/erc-4626-tokens-in-defi-exchange-rate-manipulation-risks
- https://medium.com/balancer-protocol/incident-with-non-standard-erc20-deflationary-tokens-95a0f6d46dea
-
Last reviewed: 2026-07-31 UTC