Skip to content

Instantly share code, notes, and snippets.

View marz-hunter's full-sized avatar
πŸ•·οΈ
bug

Jack marz-hunter

πŸ•·οΈ
bug
View GitHub Profile

Summary

The _processFeedResponses() function in PriceFeed.sol (lines 171-173) decodes and uses the share price from LST tokens without any bounds validation. A malicious or compromised LST token returning zero share price causes all collateral to appear worthless (triggering mass liquidations), while an inflated share price allows attackers to borrow unlimited USBD against minimal collateral. This vulnerability can result in complete protocol insolvency.

Finding Description

The Bima Protocol supports LST (Liquid Staking Token) collaterals that have exchange rates with their underlying assets. The PriceFeed fetches these exchange rates via sharePriceSignature calls.

The vulnerability exists at lines 171-173:

Summary

The _calcEthPrice() function in PriceFeed.sol (line 194-197) recursively calls fetchPrice(address(0)) to get the ETH/USD price for ETH-indexed tokens. If the ETH oracle (address(0)) is misconfigured as ETH-indexed, this creates infinite recursion and complete DoS. Additionally, ETH oracle downtime causes cascading failures for ALL ETH-indexed collateral types, creating a single point of failure that can freeze the entire protocol.

Finding Description

The Bima Protocol supports ETH-indexed collateral tokens where the base price is denominated in ETH rather than USD. To convert these prices, _calcEthPrice() fetches the ETH/USD price by calling fetchPrice(address(0)).

The vulnerability exists at lines 194-197:

Summary

The _processFeedResponses() function in PriceFeed.sol uses abi.encode() instead of abi.encodeWithSelector() when making external calls to fetch share prices from LST tokens (line 171). This produces 32 bytes of malformed calldata instead of the required 4-byte function selector, causing all share price lookups to fail. As a result, the Bima Protocol cannot support yield-bearing Bitcoin LST tokens like wrapped staked BTC derivatives, completely blocking core protocol functionality.

Finding Description

The Bima Protocol is a Liquity-fork CDP lending protocol that allows users to deposit Bitcoin LSTs as collateral to mint USBD stablecoin. To support derivative tokens with exchange rates (like wstETH, rETH, etc.), the PriceFeed contract has a sharePriceSignature mechanism to fetch the share price from the token contract.

The vulnerability exists at line 171 in PriceFeed.sol:

Summary

The _sharesByQuote() function in UFarmPool.sol at lines 809-811 contains the classic ERC4626 vault inflation vulnerability. When a pool has zero total supply, the first depositor can deposit 1 wei to receive 1 share, then donate a large amount directly to the contract to inflate the share price. Subsequent depositors receive 0 shares due to integer division rounding down, and the attacker withdraws all funds. An attacker can steal 100% of any victim's deposit with minimal capital at risk.

Finding Description

The UFarm Digital protocol implements share-based accounting for pool deposits through the _sharesByQuote() function. The vulnerability exists because:

  1. The share calculation has no virtual shares offset:

Summary

The frxETHMinter contract contains multiple centralization risks that allow the contract owner to unilaterally extract all user-deposited ETH. The owner can: (1) set withholdRatio to 100%, preventing ETH from reaching validators, (2) withdraw all withheld ETH via moveWithheldETH(), and (3) withdraw all contract ETH via recoverEther(). These functions have no timelock, multisig requirement, or governance oversight, creating a single point of failure where a compromised owner key leads to total fund loss.

Finding Description

Vulnerability 1: withholdRatio Can Be Set to 100%

Location: frxETHMinter.sol:165

Summary

The sfrxETH vault is vulnerable to read-only reentrancy attacks that can affect external protocols using pricePerShare() or convertToAssets() as price oracles. During withdraw() or redeem() operations, if the underlying token (frxETH) triggers callbacks, external protocols querying the vault's price functions will see stale/incorrect values. This can lead to unfair liquidations, arbitrage opportunities, or price manipulation in integrated protocols.

Finding Description

The vulnerability exists because state updates and external calls are not atomic, and view functions can be called during callbacks:

In sfrxETH.sol:

Summary

The xERC4626 vault uses block.timestamp to calculate the linear unlock of staking rewards over the reward cycle. Since miners can manipulate block.timestamp by approximately +/-15 seconds, and the reward unlock is time-proportional, this creates opportunities for MEV extraction. Attackers can sandwich transactions around cycle boundaries to profit from reward distribution timing, particularly affecting large depositors and withdrawers.

Finding Description

The vulnerability exists in the time-based reward calculation in totalAssets() at xERC4626.sol:45-53:

function totalAssets() public view override returns (uint256) {

Summary

The syncRewards() function in xERC4626.sol performs an unchecked subtraction at line 85 that will underflow and revert if the vault's token balance drops below storedTotalAssets + lastRewardAmount. This can occur due to slashing events, external bugs, or accounting errors. Once triggered, all vault operations become permanently blocked since the andSync modifier calls syncRewards() before every transaction.

Finding Description

The vulnerability exists in the reward calculation at xERC4626.sol:85:

function syncRewards() public virtual {

Summary

The syncRewards() function in xERC4626.sol casts nextRewards to uint192 without overflow protection. If rewards exceed type(uint192).max (6.27e57), the cast causes a revert that permanently bricks the vault. Since all deposit/withdraw/redeem operations call syncRewards() via the andSync modifier, this creates a complete denial of service - all user funds become permanently locked.

Finding Description

The vulnerability exists in the syncRewards() function at xERC4626.sol:78-96:

function syncRewards() public virtual {