0xf5e753d3da60db214f2261343c1e1bc46e674d2fa4b7a953eaf3c52123aeebd20xa26b6df27f520017a2f0a5b0c0aa9c97d05f1f26Arbitrum0x712e2b12d75fe092838a3d2ad14b6ff73d3fdbc9ArbitrumOn Arbitrum block 296699667, transaction 0xf5e753d3da60db214f2261343c1e1bc46e674d2fa4b7a953eaf3c52123aeebd2 exploited Paribus by using a flash-loaned USDT balance to mint a Camelot BAD58/USDT LP NFT, deposit that NFT into the Paribus Camelot PNFT market, and immediately borrow out the available ETH, ARB, WBTC, and USDT liquidity. The borrowed WBTC was swapped to USDT, the Aave flash loan was repaid, and the attacker retained positive ETH, ARB, and USDT profit.
The root cause is that Paribus treated a freshly minted Camelot LP NFT as borrowable collateral and valued it from same-transaction spot state. Because the valuation path trusted the pool's current Algebra price, an attacker could manufacture collateral value inside the borrow transaction and consume Paribus liquidity before any normalizing price movement mattered.
Paribus extends a Compound-style lending design with PNFT markets that accept specific ERC-721 assets as collateral. For Camelot LP positions, the relevant market was 0xa26b6df27f520017a2f0a5b0c0aa9c97d05f1f26, governed by the Paribus comptroller at 0x712e2b12d75fe092838a3d2ad14b6ff73d3fdbc9.
The victim-side gate for NFT collateral is permissive. PNFPDelegate.mint only checks whether the NFT resolves to a whitelisted pool before minting the PNFT position token:
function mint(uint tokenId) external returns (Error) {
if (whitelistedPools[this.getPool(tokenId)])
return mintInternal(msg.sender, tokenId);
else
return Error.NON_WHITE_LISTED_POOL;
}
For Camelot positions, PNFPCamelotDelegate resolves the pool by asking the Camelot NFP oracle for the pool behind the NFT:
function getPool(uint tokenId) external view returns(address) {
NFPOracle uniV3Oracle = IAggregatorOracle(comptroller.oracle()).camelotV2Oracle();
return uniV3Oracle.getPool(tokenId);
}
The pricing weakness is in the LP oracle itself. UniV3PriceOracle.getPositionPrice fetches the live pool price from the pool and converts the position's token amounts into USD value:
(uint160 sqrtRatioX96,,,,,,) =
IUniswapV3Pool(
IUniswapV3Factory(UniswapNFPManagerInterface(nfpManager).factory()).getPool(token0, token1, fee)
).slot0();
price = getPriceByPositionData(
PositionData(token0, token1, tickLower, tickUpper, liquidity, tokensOwed0, tokensOwed1),
sqrtRatioX96
);
For Camelot's Algebra implementation, the same live-pool-state pattern appears in the trace through AlgebraPool::globalState(). The key consequence is that Paribus does not wait for a time-weighted or delayed valuation; it trusts the LP NFT's current pool-derived value immediately.
The vulnerability is an attacker-controlled collateral valuation flaw. Paribus whitelisted the BAD58/USDT Camelot pool and allowed its LP NFT positions to enter the lending system as PNFT collateral, but the valuation path used current pool state rather than a manipulation-resistant price source. That made collateral value a function of attacker-controlled intra-transaction state.
The exploit did not require privileged roles, stolen credentials, or hidden infrastructure. The attacker used only public contracts: Aave flash loans, Camelot routing and LP minting, the Paribus comptroller and PNFT market, and public borrow markets. Once the freshly minted LP position was priced, that inflated value flowed directly into mintNFTAllowed, getAccountLiquidity, and borrowAllowed.
The violated invariant is straightforward: collateral used in account-liquidity and borrow authorization must represent realizable value after collateral factors, not value manufactured from same-transaction spot conditions created by the borrower. The code-level breakpoint is the oracle call chain that prices position 224023 from live pool state and immediately uses that valuation inside Paribus liquidity checks.
The exploit begins with Aave flash-loan funding. The exploit trace shows L2PoolInstance::flashLoan issuing 3093209807085 USDT and later emitting the flash-loan event with a 1546604904 USDT premium:
emit FlashLoan(
target: 0xbD4786F93CEEf3DD73600eBE0b0BdccCA2f7d37c,
initiator: 0xbD4786F93CEEf3DD73600eBE0b0BdccCA2f7d37c,
asset: 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9,
amount: 3093209807085,
premium: 1546604904
)
The attacker then shaped the BAD58/USDT pool and minted a new Camelot LP NFT. The trace records the mint of token 224023 with a highly asymmetric position:
emit Mint(
sender: 0x00c7f3082833e796A5b3e4Bd59f6642FF44DCD15,
owner: 0x00c7f3082833e796A5b3e4Bd59f6642FF44DCD15,
bottomTick: -870000,
topTick: 870000,
liquidityAmount: 261501642958000974,
amount0: 136766218539458444869127,
amount1: 500000000000
)
emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0xa8906930e951Cc657843bD8616baF2555336Fdd2, tokenId: 224023)
Next, the attacker approved the PNFT market, entered the NFT market through the comptroller, and deposited the NFT. The trace shows the exact control flow:
0x712E2B12D75fe092838A3D2ad14B6fF73d3fdbc9::enterNFTMarkets([0xa26B6Df27F520017a2F0A5b0C0aA9C97D05f1f26])
PNFTTokenDelegator::fallback(224023)
PNFPCamelotDelegate::mint(224023)
0x00c7f3082833e796A5b3e4Bd59f6642FF44DCD15::safeTransferFrom(
0xa8906930e951Cc657843bD8616baF2555336Fdd2,
0xa26B6Df27F520017a2F0A5b0C0aA9C97D05f1f26,
224023
)
emit Mint(minter: 0xa8906930e951Cc657843bD8616baF2555336Fdd2, tokenId: 224023)
At this point the vulnerable valuation path executed. The trace shows repeated calls to ArbitrumPriceOracle::getUnderlyingNFTPrice, then getPositionPrice(224023), then AlgebraPool::globalState(). The resulting NFT valuation returned into Paribus liquidity checks is the value cited by the auditor:
ArbitrumPriceOracle::getUnderlyingNFTPrice(..., 224023)
0x48288207b349CB1Aa9fDFcADa0cbbBd1B946fcbf::getPositionPrice(224023)
AlgebraPool::globalState()
...
85908965900533954310217
That inflated position value was immediately consumed by Paribus. The same trace shows getAccountLiquidity followed by four borrowAllowed checks and successful borrow events for every drainable market:
0x712E2B12D75fe092838A3D2ad14B6fF73d3fdbc9::getAccountLiquidity(0xa8906930e951Cc657843bD8616baF2555336Fdd2)
0x712E2B12D75fe092838A3D2ad14B6fF73d3fdbc9::borrowAllowed(ETH market, 0xa890..., 12599960598441767978)
emit Borrow(..., 12599960598441767978, ...)
0x712E2B12D75fe092838A3D2ad14B6fF73d3fdbc9::borrowAllowed(ARB market, 0xa890..., 6510273280264926258675)
emit Borrow(..., 6510273280264926258675, ...)
0x712E2B12D75fe092838A3D2ad14B6fF73d3fdbc9::borrowAllowed(WBTC market, 0xa890..., 36729789)
emit Borrow(..., 36729789, ...)
0x712E2B12D75fe092838A3D2ad14B6fF73d3fdbc9::borrowAllowed(USDT market, 0xa890..., 3924210566)
emit Borrow(..., 3924210566, ...)
The balance diff confirms that the borrowing drained the victim markets and left attacker-side profit. The ETH market moved from 12599960598441767978 wei to zero, the ARB market from 6510273280264926258675 to zero, the WBTC market from 36729789 to zero, and the USDT market from 3924210566 to zero. Attacker-controlled accounts retained the corresponding assets after repaying the flash loan.
The adversary cluster in the submitted analysis is defensible and matches the evidence:
0x5af00b07007cc1349794df5b2c15528237648035 is the EOA that sent the exploit transaction and received the native ETH profit.0xbd4786f93ceef3dd73600ebe0b0bdccca2f7d37c is the top-level exploit contract called by the EOA.0xa8906930e951cc657843bd8616baf2555336fdd2 is the immediate borrower and PNFT holder shown in the trace.The end-to-end flow is:
The trace also shows that the overall strategy is reproducible, not an artifact of one bespoke contract instance. A second seed transaction, 0x43aa42d2f11afe42832a9619bc8066dfb83a921798b91eaf9d0345dd27dcfb06, deploys materially similar exploit bytecode, reinforcing the ACT classification.
The measurable protocol loss in the exploit transaction is the drained borrow-market liquidity:
12599960598441767978 wei6510273280264926258675367297893924210566The attacker-side profit after flash-loan repayment is also visible in the evidence. The EOA 0x5af00b07007cc1349794df5b2c15528237648035 gained 12599745876829677978 wei, while the exploit contract 0xbd4786f93ceef3dd73600ebe0b0bdccca2f7d37c retained 10283193627 USDT. Those post-repayment balances are only possible because Paribus let the attacker borrow against collateral value that was not safely realizable.
0xf5e753d3da60db214f2261343c1e1bc46e674d2fa4b7a953eaf3c52123aeebd20x43aa42d2f11afe42832a9619bc8066dfb83a921798b91eaf9d0345dd27dcfb060xa26b6df27f520017a2f0a5b0c0aa9c97d05f1f260x712e2b12d75fe092838a3d2ad14b6ff73d3fdbc90x00c7f3082833e796a5b3e4bd59f6642ff44dcd15PNFPDelegate.solPNFPCamelotDelegate.solUniV3PriceOracle.sol