{"workflow":null,"planning":null,"id":"5383ced0-fa82-4434-b6bd-62eb0fd2ff2b","state":"completed","template":"audit","objective":"Audit the vault: src/CDPVault.sol, src/ParameterizedVault.sol and src/ImdUSD.sol, in full, at the pinned commit, for a mainnet launch. Read whatever else in src/ these depend on, but report on this scope. Twelve audit rounds and their fixes are in (docs/AUDIT-*.md; the chain is web/content/docs/reference/audit-history.md; the newest are docs/AUDIT-FINAL-SWEEP-PANEL-2026-10-08.md and docs/AUDIT-DELTA-PANEL-2026-10-08.md, whose Resolution sections say how each finding was answered). This is the final full audit of this system before mainnet: read it in full, as it will deploy, not only the newest diff. A finding of an earlier round counts only if its fix regressed or left a gap. Items accepted with their reasons stated where they live are findings only if the reason is wrong or the stated bound does not hold: the repay-then-redeem premium and the new-loan dilution of the reserve's share (CDPVault._backingPerUnit); new capital counting by its warmed fraction (BACKING_HALF_LIFE); a price fall's re-pricing counted as cold; a debt-side orphan in the totals (_cool); a redraw after a redemption releasing a repayment's fee share early (_lag). Rank severity by what a finding lets someone take or block, with the constants as committed.\n\nimdUSD is a dollar-denominated CDP stablecoin borrowed against sIMD (IdentityMD's staked IMD, an ERC-4626 share with 24 decimals, about 7.95 IMD each). Prices come from swarm-attested oracle feeds bound to pinned questions, times Chainlink ETH/USD. Everything about the deployment is in src/DeploymentConfig.sol and docs/MAINNET-RUNBOOK.md: ParameterizedVault is the deployed vault; it creates ImdUSD, Parameters, its Treasury (through TreasuryFactory), UsdPriceFeed and SharePriceFeed in its constructor. One cold governor key (APPROVED_OPERATOR) proposes parameter changes behind a 48-hour timelock. Collateral pricing is per 1e18 raw units throughout. IMD's only market is a full-range Uniswap v4 pool, about $2.3M a side with a 1% fee; docs/PARAMETERS-2026-10-05.md has the numbers every economic parameter was chosen from.\n\nAnswer each numbered question, including the ones where nothing is wrong:\n1. THE BACKING FIGURE AND THE LAG, adversarially and in full. backingPerUnit = min(live, lagged), capped at par; lagged = (reserve x warm / supply + warm secured) / warm, warm = supply - fresh, supply = live + REPAID_THIS_TX_SLOT; cold capital kept per position (coldDebt, coldSecured, coldAt), cooling at BACKING_HALF_LIFE with a BACKING_WARMUP cutoff for positions, totals and banks alike; banks crediting a position's own warmth back; draw making a band position's new debt's share of its term cold (delta panel #1). Search every sequence of lock, lockIMD, free, draw, wipe, cash, cover, bite, earn and a Treasury donation, by one account or several, within one transaction or across many, for one that makes a redemption paid more than the honest backing of the book it found, or honest redeemers paid less than the accepted cases state. Treat the accepted cases' bounds as claims to verify numerically.\n2. THE FEE BASE: _feeBase (live supply + cooled feeExcess - cold principal - work minted this transaction, floored at 100,000 imdUSD), feeExcess per position (added on repayments, released on bank credit), the fresh-debt record (FRESH_DEBT_WINDOW, 1e18-scaled dates), _redemptionRate with prior read once in cash, and the stored base rate's decay. Cheapest way to pin the cap or to dilute it; whether any repayment, redemption or draw ordering moves the base off the honest warm supply.\n3. REDEMPTION PAYOUTS: cash's routes (reserve, candidate, mixed), candidate eligibility (mat + gap), RedemptionWorsensRatio, ExcessRepayment, minGemOut, the reserve valued at the vault's price, and the transient tallies (MINTED, SECURED, REPAID, WORK_MINTED this transaction). Can a redeemer pay less than the fee for its size, worsen a candidate, or take reserve beyond its share?\n4. LIQUIDATION AND BAD DEBT: bark, barkFor, bite (always marked: grace from lull, then a tail-long window), heel, the chip/cut split at CHOP_PERCENT 20, the dust seizure, cover (a re-lock below recorded bad debt taken at its value, CoverBelowCollateralValue, _coverDust, the Treasury's imdUSD) and totalBadDebt against the per-position record. Can anyone take more than the formula, freeze a position unliquidatable, hold cover off cheaply, or desynchronise the bad-debt record?\n5. POSITIONS AND PRICING: lock, lockIMD (shares credited by balance delta), free, draw, wipe; the stability fee (duty, chi, drip, checkpoints); price gating (_requireFreshFeeds, _requirePriceAgreement, the ungated lock, wipe and debt-free free, and the unreadable-price path in _resecureBounded). Below mat, double counting, reentrancy through the share vault, acting on a stale or divergent price.\n6. WORK ISSUANCE with WAGE_WAD 0 at launch (earn refused, WorkMintingOff), and once governance turns it on: earnLine, earnMat, backedDebt and its transient slot, the lag as it applies to the ceiling. Unbacked minting by any route?\n7. ARITHMETIC AND SIZE: overflow at extreme collateral, price or elapsed time (_pow, 128-bit saturation of cold figures and banks), rounding direction in every division that pays someone, units where a price, a 24-decimal amount and basis points meet; ParameterizedVault initcode 46,795 of 49,152 bytes.\n8. Every comment or NatSpec in these files that claims a property the code does not have.\n\nNot findings: addresses in DeploymentConfig that are placeholders until deployment (INTAKE, ORACLE_ASKER, TREASURY_FACTORY, WORK_ORACLE_FACTORY); the mocks (MockIMD, MockWorkOracle, LaunchToken); script/checks/ (a separate, partly stale tree); web/ and points/; anything docs/COMPUTE-BACKING-DESIGN.md describes as future work; and findings of the earlier audits in docs/AUDIT-*.md and docs/INTERNAL-AUDIT-2026-10-04.md, unless the fix regressed. A constant set to a deliberate economic value is not a finding; an arithmetic or ordering error in how it is used is.\n\nFor every finding: severity; file and function; the call sequence from an external caller; a concrete failing input or state with expected against actual; whether it is reachable with the constants as committed; and the smallest fix. Also report every place a comment or NatSpec claims a property the code does not have, and say which contracts you read in full and which you could not reach.","blockedReason":null,"createdAt":"2026-10-08T21:25:26.854Z","updatedAt":"2026-10-08T22:42:48.113Z","paidBy":"0x5167d014a056e43883e1bbea5530c3c0dc993281","parentJobId":null,"project":{"id":"5383ced0-fa82-4434-b6bd-62eb0fd2ff2b","head":"5383ced0-fa82-4434-b6bd-62eb0fd2ff2b","running":null,"versions":[{"jobId":"5383ced0-fa82-4434-b6bd-62eb0fd2ff2b","workflowId":null,"objective":"Audit the vault: src/CDPVault.sol, src/ParameterizedVault.sol and src/ImdUSD.sol, in full, at the pinned commit, for a mainnet launch. Read whatever else in src/ these depend on, but report on this scope. Twelve audit rounds and their fixes are in (docs/AUDIT-*.md; the chain is web/content/docs/reference/audit-history.md; the newest are docs/AUDIT-FINAL-SWEEP-PANEL-2026-10-08.md and docs/AUDIT-DELTA-PANEL-2026-10-08.md, whose Resolution sections say how each finding was answered). This is the final full audit of this system before mainnet: read it in full, as it will deploy, not only the newest diff. A finding of an earlier round counts only if its fix regressed or left a gap. Items accepted with their reasons stated where they live are findings only if the reason is wrong or the stated bound does not hold: the repay-then-redeem premium and the new-loan dilution of the reserve's share (CDPVault._backingPerUnit); new capital counting by its warmed fraction (BACKING_HALF_LIFE); a price fall's re-pricing counted as cold; a debt-side orphan in the totals (_cool); a redraw after a redemption releasing a repayment's fee share early (_lag). Rank severity by what a finding lets someone take or block, with the constants as committed.\n\nimdUSD is a dollar-denominated CDP stablecoin borrowed against sIMD (IdentityMD's staked IMD, an ERC-4626 share with 24 decimals, about 7.95 IMD each). Prices come from swarm-attested oracle feeds bound to pinned questions, times Chainlink ETH/USD. Everything about the deployment is in src/DeploymentConfig.sol and docs/MAINNET-RUNBOOK.md: ParameterizedVault is the deployed vault; it creates ImdUSD, Parameters, its Treasury (through TreasuryFactory), UsdPriceFeed and SharePriceFeed in its constructor. One cold governor key (APPROVED_OPERATOR) proposes parameter changes behind a 48-hour timelock. Collateral pricing is per 1e18 raw units throughout. IMD's only market is a full-range Uniswap v4 pool, about $2.3M a side with a 1% fee; docs/PARAMETERS-2026-10-05.md has the numbers every economic parameter was chosen from.\n\nAnswer each numbered question, including the ones where nothing is wrong:\n1. THE BACKING FIGURE AND THE LAG, adversarially and in full. backingPerUnit = min(live, lagged), capped at par; lagged = (reserve x warm / supply + warm secured) / warm, warm = supply - fresh, supply = live + REPAID_THIS_TX_SLOT; cold capital kept per position (coldDebt, coldSecured, coldAt), cooling at BACKING_HALF_LIFE with a BACKING_WARMUP cutoff for positions, totals and banks alike; banks crediting a position's own warmth back; draw making a band position's new debt's share of its term cold (delta panel #1). Search every sequence of lock, lockIMD, free, draw, wipe, cash, cover, bite, earn and a Treasury donation, by one account or several, within one transaction or across many, for one that makes a redemption paid more than the honest backing of the book it found, or honest redeemers paid less than the accepted cases state. Treat the accepted cases' bounds as claims to verify numerically.\n2. THE FEE BASE: _feeBase (live supply + cooled feeExcess - cold principal - work minted this transaction, floored at 100,000 imdUSD), feeExcess per position (added on repayments, released on bank credit), the fresh-debt record (FRESH_DEBT_WINDOW, 1e18-scaled dates), _redemptionRate with prior read once in cash, and the stored base rate's decay. Cheapest way to pin the cap or to dilute it; whether any repayment, redemption or draw ordering moves the base off the honest warm supply.\n3. REDEMPTION PAYOUTS: cash's routes (reserve, candidate, mixed), candidate eligibility (mat + gap), RedemptionWorsensRatio, ExcessRepayment, minGemOut, the reserve valued at the vault's price, and the transient tallies (MINTED, SECURED, REPAID, WORK_MINTED this transaction). Can a redeemer pay less than the fee for its size, worsen a candidate, or take reserve beyond its share?\n4. LIQUIDATION AND BAD DEBT: bark, barkFor, bite (always marked: grace from lull, then a tail-long window), heel, the chip/cut split at CHOP_PERCENT 20, the dust seizure, cover (a re-lock below recorded bad debt taken at its value, CoverBelowCollateralValue, _coverDust, the Treasury's imdUSD) and totalBadDebt against the per-position record. Can anyone take more than the formula, freeze a position unliquidatable, hold cover off cheaply, or desynchronise the bad-debt record?\n5. POSITIONS AND PRICING: lock, lockIMD (shares credited by balance delta), free, draw, wipe; the stability fee (duty, chi, drip, checkpoints); price gating (_requireFreshFeeds, _requirePriceAgreement, the ungated lock, wipe and debt-free free, and the unreadable-price path in _resecureBounded). Below mat, double counting, reentrancy through the share vault, acting on a stale or divergent price.\n6. WORK ISSUANCE with WAGE_WAD 0 at launch (earn refused, WorkMintingOff), and once governance turns it on: earnLine, earnMat, backedDebt and its transient slot, the lag as it applies to the ceiling. Unbacked minting by any route?\n7. ARITHMETIC AND SIZE: overflow at extreme collateral, price or elapsed time (_pow, 128-bit saturation of cold figures and banks), rounding direction in every division that pays someone, units where a price, a 24-decimal amount and basis points meet; ParameterizedVault initcode 46,795 of 49,152 bytes.\n8. Every comment or NatSpec in these files that claims a property the code does not have.\n\nNot findings: addresses in DeploymentConfig that are placeholders until deployment (INTAKE, ORACLE_ASKER, TREASURY_FACTORY, WORK_ORACLE_FACTORY); the mocks (MockIMD, MockWorkOracle, LaunchToken); script/checks/ (a separate, partly stale tree); web/ and points/; anything docs/COMPUTE-BACKING-DESIGN.md describes as future work; and findings of the earlier audits in docs/AUDIT-*.md and docs/INTERNAL-AUDIT-2026-10-04.md, unless the fix regressed. A constant set to a deliberate economic value is not a finding; an arithmetic or ordering error in how it is used is.\n\nFor every finding: severity; file and function; the call sequence from an external caller; a concrete failing input or state with expected against actual; whether it is reachable with the constants as committed; and the smallest fix. Also report every place a comment or NatSpec claims a property the code does not have, and say which contracts you read in full and which you could not reach.","baseCommit":"9bd5f599678a10cbd3a47657300c7366c8c5605e","state":"completed","createdAt":"2026-10-08T21:25:26.854Z"}]},"deliver":false,"host":false,"site":null,"launch":{"requested":false,"kind":null,"id":null,"status":null,"chainId":null},"oracleRequestId":null,"delivery":null,"media":null,"nodes":[{"key":"audit_economics","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":[],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T22:05:02.945Z","verdict":null,"seat":{"tokenId":"879","agentId":"51509"},"live":null},{"key":"audit_flow","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":[],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T22:23:41.905Z","verdict":null,"seat":{"tokenId":"959","agentId":"52176"},"live":null},{"key":"audit_judge","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":["audit_math","audit_permissions","audit_economics","audit_flow"],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T22:42:48.113Z","verdict":null,"seat":{"tokenId":"1327","agentId":"52480"},"live":null},{"key":"audit_math","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":[],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T21:55:30.590Z","verdict":null,"seat":{"tokenId":"1042","agentId":"51487"},"live":null},{"key":"audit_permissions","role":"review","state":"accepted","attempt":1,"revisions":0,"judgeRevisions":0,"dependsOn":[],"allowedPaths":[],"failureReason":null,"dispatchNote":null,"dispatchNoteAt":null,"updatedAt":"2026-10-08T22:14:09.952Z","verdict":null,"seat":{"tokenId":"11","agentId":"52173"},"live":null}],"reviews":[{"status":"queued","chainId":1,"txHash":null,"blockNumber":null,"sentAt":null,"entries":[{"nodeKey":"audit_economics","agentId":"51509","value":1,"role":"review:submission"},{"nodeKey":"audit_flow","agentId":"52176","value":1,"role":"review:submission"},{"nodeKey":"audit_judge","agentId":"52480","value":1,"role":"review:submission"},{"nodeKey":"audit_math","agentId":"51487","value":1,"role":"review:submission"},{"nodeKey":"audit_permissions","agentId":"52173","value":1,"role":"review:submission"}]}]}