All incidents

Lodestar cplvGLP Inflation

Share
Dec 10, 2022 16:43 UTCAttackLoss: 3,814,441.16 plvGLP, 27.21 WETH +1 morePending manual check1 exploit txWindow: Atomic
Estimated Impact
3,814,441.16 plvGLP, 27.21 WETH +1 more
Label
Attack
Exploit Tx
1
Addresses
2
Attack Window
Atomic
Dec 10, 2022 16:43 UTC → Dec 10, 2022 16:43 UTC

Exploit Transactions

TX 1Arbitrum
0xc523c6307b025ebd9aef155ba792d1ba18d5d83f97c7a846f267d3d9a3004e8c
Dec 10, 2022 16:43 UTCExplorer

Victim Addresses

0xCC25daC54A1a62061b596fD3Baf7D454f34c56fFArbitrum
0x8f2354f9464514efdae441314b8325e97bf96cdcArbitrum

Loss Breakdown

3,814,441.16plvGLP
27.21WETH
100USDC

Similar Incidents

Root Cause Analysis

Lodestar cplvGLP Inflation

1. Incident Overview TL;DR

On Arbitrum block 45121904, transaction 0xc523c6307b025ebd9aef155ba792d1ba18d5d83f97c7a846f267d3d9a3004e8c exploited Lodestar's cplvGLP collateral pricing. The attacker used public GMX and Plutus flows to mint plsGLP directly into the plvGLP vault through GlpDepositor.donate(uint256) without minting matching plvGLP shares. Lodestar priced cplvGLP from plvGLP.totalAssets() / totalSupply(), so the vault-balance increase inflated the collateral price inside the same transaction and unlocked additional borrowing capacity. The balance diff shows protocol losses in plvGLP, WETH, and USDC, with corresponding attacker-side gains.

2. Key Background

Lodestar treats cplvGLP as a special collateral market. In Comptroller.getHypotheticalAccountLiquidityInternal, each collateral position contributes collateralFactor * exchangeRate * oraclePrice to account liquidity, so any manipulable input to oracle.getUnderlyingPrice(asset) directly affects borrow power.

For cplvGLP, the oracle path routes through Lodestar's GLP pricing logic rather than a plain Chainlink spot price. The root cause relies on plvGLP being an ERC4626 vault over plsGLP, because ERC4626 totalAssets() reflects the vault's raw asset balance:

function totalAssets() public view virtual override returns (uint256) {
    return _asset.balanceOf(address(this));
}

That accounting is safe only if asset balance changes correspond to share minting or burning. Here, an external public function could increase the vault's plsGLP balance without minting plvGLP shares.

3. Vulnerability Analysis & Root Cause Summary

The vulnerability is an attack-driven collateral-price manipulation. Lodestar trusted a per-share plvGLP exchange rate that was derived from plvGLP.totalAssets() / totalSupply(). Because plvGLP.totalAssets() is just the vault's raw plsGLP balance, any path that can donate assets into the vault without minting shares raises the apparent value of every existing share. The public Plutus GlpDepositor.donate(uint256) function provided exactly that path. Once the attacker increased the vault asset balance, Lodestar's PriceOracleProxyETH and GLPOracle returned a higher cplvGLP underlying price during borrow checks. The attacker then borrowed additional Lodestar assets against unchanged cplvGLP shares whose value had been overstated. This violates the core invariant that collateral value must only increase when economically backed collateral shares are minted or when trusted pricing inputs move.

4. Detailed Root Cause Analysis

Lodestar's borrow control path is visible in the verified Comptroller source:

vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);
if (vars.oraclePriceMantissa == 0) {
    return (Error.PRICE_ERROR, 0, 0);
}
vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});
vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), vars.oraclePrice);
vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.cTokenBalance, vars.sumCollateral);

For cplvGLP, the auditor-established pricing path routes getUnderlyingPrice into Lodestar's GLPOracle.getPlvGLPPrice(), which depends on the plvGLP exchange rate derived from totalAssets() and totalSupply(). Because totalAssets() is the raw plsGLP balance, direct asset inflows reprice the vault even when no new plvGLP shares are minted.

The seed transaction trace records the exact exploit breakpoint. The attack calls GlpDepositor.donate(5620813918834889782579953), after which the trace shows the Plutus flow moving sGLP into the staker and minting plsGLP directly to the plvGLP vault. No corresponding plvGLP share mint is required at that step. Later in the same transaction, repeated Lodestar borrow checks call GLPOracle::getPlvGLPPrice() and then PlvGlpToken::totalAssets() before allowing borrows.

That sequence creates a deterministic exploit chain:

public donate() call
-> plsGLP minted to plvGLP vault
-> plvGLP totalAssets increases while totalSupply stays flat
-> Lodestar reads higher cplvGLP price
-> borrowAllowed sees higher liquidity
-> attacker borrows more assets than legitimate collateral supports

The balance diff corroborates the effect. It records 100000000 USDC credited to 0xb50f58d50e30dfdaad01b1c6bcc4ccb0db55db13, 27209331048469514630 WETH and 3814441161509835687601554 plvGLP losses on victim-side markets, and corresponding attacker-side gains in the exploit flow.

5. Adversary Flow Analysis

The adversary cluster is anchored by EOA 0xc29d94386ff784006ff8461c170d1953cc9e2b5c, which the collection metadata identifies as the creator of helper contracts 0x7596acadf6c93f01b877f5a44b49407fffc53508 and 0xe1ba6511f95d8e6bca786ecbc4472de4c4137bff. The seed transaction uses those helpers to assemble collateral, manipulate the vault balance, and then borrow additional assets.

The exploit flow is:

1. Take flash liquidity and build a cplvGLP-backed position.
2. Call public Plutus staking flows to obtain sGLP.
3. Call GlpDepositor.donate(...) so plsGLP is minted to the plvGLP vault without minting new plvGLP shares.
4. Re-enter Lodestar borrow checks after oracle repricing.
5. Borrow additional Lodestar market assets and settle proceeds to the attacker cluster.

The seed trace shows repeated calls such as Comptroller::borrowAllowed(...), GLPOracle::getPlvGLPPrice(), PlvGlpToken::totalAssets(), and downstream Borrow(...) events across Lodestar markets after the donation step. The downstream borrower helper 0xe1ba6511f95d8e6bca786ecbc4472de4c4137bff then borrows assets including USDC and DAI against the inflated cplvGLP collateral valuation.

6. Impact & Losses

The exploit caused cross-market loss to Lodestar by inflating one collateral market and borrowing against the false liquidity. The quantified losses recorded in the submitted root cause are:

  • plvGLP: 3814441161509835687601554 raw units, 18 decimals
  • WETH: 27209331048469514630 raw units, 18 decimals
  • USDC: 100000000 raw units, 6 decimals

The impact is broader than a single token transfer because the flaw corrupts the protocol's solvency checks. Once cplvGLP is overstated, any borrow market using Lodestar's shared Comptroller liquidity engine is exposed.

7. References

  • Seed exploit transaction: 0xc523c6307b025ebd9aef155ba792d1ba18d5d83f97c7a846f267d3d9a3004e8c
  • Lodestar Comptroller proxy: 0x8f2354f9464514efdae441314b8325e97bf96cdc
  • Lodestar Comptroller implementation: 0x50ddd0eae0a0896f648f9e982ec65c5b8a73d02d
  • Lodestar cplvGLP market: 0xCC25daC54A1a62061b596fD3Baf7D454f34c56fF
  • Lodestar PriceOracleProxyETH: 0x5947189d2D7765e4f629C803581FfD06bc57dE9B
  • Lodestar GLPOracle: 0xBa46F854A5B099fceA178C6e7ed047BaffECe5Ac
  • Plutus GlpDepositor: 0x13F0D29b5B83654A200E4540066713d50547606E
  • Plutus plvGLP vault: 0x5326E71Ff593Ecc2CF7AcaE5Fe57582D6e74CFF1
  • Trace evidence: /workspace/session/artifacts/collector/seed/42161/0xc523c6307b025ebd9aef155ba792d1ba18d5d83f97c7a846f267d3d9a3004e8c/trace.cast.log
  • Balance diff evidence: /workspace/session/artifacts/collector/seed/42161/0xc523c6307b025ebd9aef155ba792d1ba18d5d83f97c7a846f267d3d9a3004e8c/balance_diff.json
  • Verified victim source and creation metadata in /workspace/session/artifacts/collector/iter_1/contract/42161/