
Autonomint audit contest
A public audit contest on Sherlock (hedged stablecoin), completed on 4th December 2024. 0xSimao placed #1. 38 of his findings are published: 26 high severity and 12 medium.
What Autonomint is
Autonomint issues a hedged stablecoin: depositors post collateral and receive downside protection priced as an option, while a counterparty side (dCDS) takes the other half of that trade and earns the option fees, liquidations settling between them.
Scope
The Sherlock competition covered the borrowing and dCDS flows: deposit and withdrawal pricing as collateral recovers, strike-price redemption, fee application between depositor and counterparty, and the two liquidation types.
High severity findings
- Borrower withdrawing at a loss will cause losses for cds depositors that only withdraw after the price recovers
- Total cds deposited amount is incorrectly modified when cds depositor is at a loss, leading to stuck USDa
- Cds depositors profit up to the strike price is not redeemable as the total cds deposited amount is not increased
- Cds depositor profit is never taxed as the tax is only applied on the option fees
- Type 1 borrower liquidation will incorrectly add cds profit directly to
totalCdsDepositedAmount - Liquidation profit is never given to cds depositors who will take these losses
borrowing::withdraw()at a loss will increase downside protected and misscalculate option fees- Some liquidated collateral will be locked
- Cds amounts to reduce from each chain are incorrect and will lead to the inability to withdraw cds in one of the chains
- Potential Underflow in
withdrawInterest borrowing::liquidate()sends the wrong liquidation index to the destination chain, overwritting liquidation information and getting collateral stuck- Malicious user can call
borrowing::calculateCumulativeRate()any number of times to inflate debt rate aslastEventTimeis not updated - Late abond holders steal USDa amount from liquidations from earlier abond holders
CDSLib::withdrawUserWhoNotOptedForLiq()tax is not stored in the treasury- Using LayerZero for synchronizing global states between two chains may lead to overwriting of global states.
- Borrower deposit, withdraw, deposit will reinit
omniChainData.cdsPoolValue, getting profit stuck for cds depositors - Missing Update to
omnichain.totalAvailableLiquidationAmountinwithdrawUser - Liquidation will reduce total cds deposited amount, leading to incorrect option fees
Borrowing::redeemYieldsdebitsABONDfrommsg.senderbut redeems touserusingABOND.Statedata fromuser- The user overpays the USDA amount for downside protection while withdrawing
totalCdsDepositedAmountWithOptionFeesis incorrectly reduced inCDSLib::withdrawUser(), leading to stuck option fees- Strike Price Not Validated Against Strike Percent, Leading to Exploitation Risk
treasury.updateYieldsFromLiquidatedLrts()updates the yield in the current chain, but collateral may be in the other chain- odosAssembledData can be manipulated
- cds owners can withdraw more than expected via manipulating excessProfitCumulativeValue
- Malicious users can DOS the protocol by setting downsideProtected to a large value
Medium severity findings
- Accumulated profit/losses by the cumulative value is not dealt with in
borrowingLiquidation::liquidationType1(), leading to losses - Interest generated by last bond will not go to anyone when liquidating as there is no bond amount to collect it
GlobalVariables::oftOrCollateralReceiveFromOtherChains()calculates the fee as if it was the same in both chains, which is falseGlobalVariables::oftOrCollateralReceiveFromOtherChains()always charges twice the collateral onCOLLATERAL_TRANSFER, which is not needed- Yield form LRTs are forever stuck in the protocol and cannot be withdrawn
- DOS on liquidation type 1 due to underflow in cds profits computation
- Protected downside is not updated when
cds.getTotalCdsDepositedAmount() < downsideProtected Treasury.noOfBorrowerscan be set to 0 by looping wei deposit<->withdrawals and DoS withdrawals and reset borrower debtCDSLib::calculateCumulativeRate()incorrectly only increment the local option fees when there are cds deposits- Inconsistent Use of
lastCumulativeRateindepositTokens()andwithdraw()Functions inBorrowingsContract - Withdrawing ionic during liquidation has a flaw
- An attacker can manipulate
omniChainData.cdsPoolValueby breaking protocol.
The contest