Technical Deep Dive

Root Cause Analysis

The Vulnerability

The exploit was a multi-stage attack where the attacker leveraged excessive permissions within the Arcadia Asset Management architecture.

Initial Attack Base

The attacker created multiple Arcadia Accounts to act as the base for the exploit.

View Transaction on Basescan

The Attack Sequence:

  • Taken three Morpho flashloans of approximately $1.5 billion.
  • Linked the Asset Manager to their account, setting themselves as the initiator.
  • Created a small Liquidity Provider (LP) position.
  • Repaid all debt of the victim account using the flashloaned funds.
  • Triggered a rebalance for their own LP position, injecting malicious custom calldata.
  • Abused missing validation to call the victim's Arcadia Account from within the context of the Asset Manager.
  • Withdrew the position, decomposed it, and stole the owner's funds.
  • Since the target account had its debt cleared, it ended in a 'healthy' state, bypassing failsafes.

Detailed Transaction Analysis

Explore Tenderly Trace
Exploit Flow

Technical Execution

Attack Logic

The root cause of the exploit is that the attacker could hijack the msg.sender context of the Asset Manager. Since the victim account trusted the Asset Manager, the attacker's injected call was executed with full privileges.

Mitigation Strategy

A critical check should have been performed to ensure the router is not a protocol account. Ideally, the swap logic should be handled by an isolated, non-permissioned intermediate contract.

Detailed Sequence

Relevant Contracts

Vulnerable Code Snippet

function _swapViaRouter(
    address positionManager,
    RebalancerPositionState memory position,
    bool zeroToOne,
    bytes memory swapData
) internal returns (uint256 balance0, uint256 balance1) {
    // Decode the swap data.
    (address router, uint256 amountIn, bytes memory data) = abi.decode(swapData, (address, uint256, bytes));

    // Approve token to swap.
    address tokenToSwap = zeroToOne ? position.token0 : position.token1;
    ERC20(tokenToSwap).safeApproveWithRetry(router, amountIn);

    // Execute arbitrary swap.
    (bool success, bytes memory result) = router.call(data);
    require(success, string(result));
}
Swap Logic Vulnerability

Prerequisites

Required knowledge to understand this exploit.

Flash Loans

Borrowing assets without collateral for one transaction.

Msg.Sender Context

How context changes (or doesn't) between calls.

Arbitrary Calls

Dangers of .call() with user data.

State Management

Checks-Effects-Interactions pattern.

Jump into the Code and Fix It