Cork Protocol — disclosed vulnerability reports and payouts
Every publicly disclosed and closed bug bounty report we hold for Cork Protocol, with our own summary of each finding and a link to the original disclosure.
- Reports indexed
- 14
- Total paid
- $0
- Critical
- 0
- Largest payout
- $0
This page collects the 14 closed, publicly disclosed Cork Protocol reports indexed on Coin Buggie. Nothing here is active or unpatched — every entry was published by the programme or the researcher after remediation.
The findings concentrate in Logic error, across EVM-Solidity. Reading a single protocol end to end is the fastest way to see which assumptions its codebase repeatedly gets wrong, which is usually a better predictor of where the next finding lives than the category alone.
Use the vulnerability class links below to compare these findings against the same bug class in other protocols.
What reviewers look for
- Logic error findings disclosed against Cork Protocol
Curated highlights
The largest disclosed payouts in this group, with our own summary of each. Every report links back to the original disclosure.
Cork Protocol: Wrong accounting of locked RA when repurchasing DS+PA with RA
Cork Protocol's PSM repurchase flow allows users to deposit RA to redeem DS+PA, with a fee taken from the deposit used to mint CT+DS for AMM liquidity. The locked-RA accounting double-counts this fee: PsmLib.repurchase locks the full user-provided RA via lockUnchecked(), then the fee portion is locked again when unsafeIssueToLv() increments the locked total by the minted CT amount. The inflated tracked locked-RA drives reward over-distribution, so early users can absorb value that later redeemers are owed, potentially leaving insufficient RA in the contract for last-in users. The finding was sponsor-confirmed and adjudicated as High with duplicates.
Cork Protocol: Attackers will steal the reserve from the `Vault` by receiving `ra` in `FlashSwapRouter::__swapDsforRa()`
Cork Protocol's FlashSwapRouter misroutes reserve assets during the DS-for-RA flash-swap sell path. When a user calls swapRaforDs() and the reserve is sold, the internal __swapDsforRa() helper runs a UniswapV2-style flash swap whose uniswapV2Call callback decodes the original caller from the swap data and ultimately safeTransfer's the reserve asset (Ra) to that arbitrary caller. In parallel the Vault records the liquidity provision and funds it from Ra already held in the contract, so the fee Ra that should have settled against the Vault is instead pocketed by the user. Because preconditions are essentially none and the path is single-call, an attacker can drain the entire Vault reserve by repeating the swap. Sherlock adjudicated this as High, rejected an escalation to downgrade it to Low, and the sponsor confirmed a pre-existing fix in PR #63.
Cork Protocol: Admin will not be able to upgrade the smart contracts, breaking core functionality and rendering the upgradeable contracts useless
Cork Protocol's AssetFactory and FlashSwapRouter inherit OpenZeppelin's UUPSUpgradeable pattern to support upgrades, but their initialize() and _authorizeUpgrade() functions were decorated with the notDelegated modifier. Because UUPS upgrade calls execute _authorizeUpgrade through a delegatecall (proxy) context, the modifier forces every upgrade attempt to revert, permanently bricking upgradability for both contracts while also preventing first initialization if they had been proxied. The inability to patch a live depeg-swap DEX economically matters because any discovered bug or required change cannot be deployed, leaving users exposed to permanently stuck or un-recoverable funds. The finding was confirmed by the protocol team, which had already removed the modifiers, and the fix landed in a merged pull request.
Cork Protocol: Incoming Redemption Assets not being tracked when repurchase is called
Cork Protocol's PsmLib.repurchase() accepts redemption asset (RA) and returns a DepegSwap + pegged asset, but credits the incoming RA through lockUnchecked() instead of recording it in the PsmRedemptionAssetManager.locked counter. Because that internal counter is the sole basis for measuring RA circulation in the system, repurchase payments never increment it. When the DepegSwap expires and redeemWithCt() calls _separateLiquidity(), the tracked balance is snapshotted into a pool archive and reset, and the unrecorded repurchase RA exceeds the tracked amount — stranding the untracked difference permanently in the contract and causing a direct loss of user funds. The protocol team confirmed the finding as valid and merged a fix (PR #77) that tracks the incoming RA via lockFrom().
Cork Protocol: Lack of slippage protection leads to loss of protocol funds
Cork Protocol's vault performs two unguarded AMM operations: redeeming CT tokens for RA tokens via a swap executed with a zero minimum-out amount and a `block.timestamp` deadline, and removing liquidity from the RA-CT pair with zero minimum amounts. Because these transactions are visible in the mempool, an attacker can front-run a pending redemption, move the pool price, and force the protocol to accept a heavily unfavorable fill. A `block.timestamp` deadline also lets a malicious block producer defer execution into a high-slippage state. The sponsor confirmed the slippage facet as valid and fixed both gaps, with the full fix merged in pull request #76.
Cork Protocol: Users will steal excess funds from the Vault due to `VaultPoolLib::redeem()` not always decreasing `self.withdrawalPool.raBalance` and `self.withdrawalPool.paBalance`
Cork Protocol's Vault redemption path has a state-accounting bug. In the partial-redemption branch of `VaultPoolLib::redeem()`, funds pulled from the AMM pool are transferred out but the internal `withdrawalPool.raBalance` and `paBalance` counters are never decremented. On the next issuance, `VaultPoolLib::reserve()` recomputes balances from those stale counters and double-counts the already-paid funds, inflating the withdrawal exchange rates. Users can then redeem the same funds twice, draining the vault and leaving unaware users unable to withdraw. The maintainer acknowledged the finding as valid, though the expiry-redemption feature that triggers it was removed in the updated protocol.
All reports in this group
- Cork Protocol: FlashSwapRouter::emptyReserve() and FlashSwapROuter::emptyReservePartial() functions return incorrect valuesLogic error$0
- Cork Protocol: The UUPS proxie standard is implemented incorrectly, making the protocol not upgradeableLogic error$0
- Cork Protocol: Providing liquidity to the AMM does not check the return value of actually provided tokens leading to locked funds.Logic error$0
- Cork Protocol: Admin new issuance or user calling `Vault::redeemExpiredLv()` after `Psm::redeemWithCt()` will lead to stuck funds when trying to withdrawLogic error$0
- Cork Protocol: Withdrawing all `lv` before expiry will lead to lost funds in the VaultLogic error$0
- Cork Protocol: `VaultPoolLib::reserve()` will store the `Pa` not attributed to user withdrawals incorrectly and leave in untracked once it expires againLogic error$0
- Cork Protocol: Users redeeming early will withdraw `Ra` without decreasing the amount locked, which will lead to stolen funds when withdrawing after expiryLogic error$0
- Cork Protocol: Admin will not be able to only pause deposits in the `Vault` due to incorrect check leading to DoSed withdrawalsLogic error$0