We do not have a reliable USD price for the recorded assets yet.
0x1ea0a2e88efceccb2dd93e6e5cb89e5421666caeefb1e6fc41b68168373da3420x82c063afefb226859abd427ae40167cb77174b68EthereumAn Ethereum mainnet attacker exploited Bullrun helper contract 0x82c063afefb226859abd427ae40167cb77174b68 in transaction 0x1ea0a2e88efceccb2dd93e6e5cb89e5421666caeefb1e6fc41b68168373da342 at block 19063677. The attacker used router 0xd129d8c12f0e7aa51157d9e6cc3f7ece2dc84ecd to call the helper's public redeem(uint256,address) entrypoint, causing the helper to redeem its own BUI inventory through Set Protocol and send the underlying basket to the attacker-controlled router. The transaction ended with sender 0xd215ffaf0f85fb6f93f11e49bd6175ad58af0dfd gaining 134.411643345413003066 ETH net of gas.
The root cause is straightforward access-control failure in the helper, not in Set Protocol itself. The helper exposed a public redemption path over helper-owned BUI and performed no caller authorization before forwarding into DebtIssuanceModuleV2.redeem(address,uint256,address).
Bullrun index token BUI at 0xb7470fd67e997b73f55f85a6af0deb2c96194885 is a Set Protocol SetToken. Redemptions are handled by DebtIssuanceModuleV2 at 0x69a592d2129415a4a1d1b1e309c17051b7f28d57, which burns SetToken balance from the caller and transfers the component basket to a chosen recipient. The collected source for the SetToken confirms the protocol-side component transfers are normal invoke calls from the SetToken to each component token, while the seed balance diff shows the helper was holding a large BUI balance immediately before the exploit.
The vulnerable component is a separate helper contract at 0x82c063afefb226859abd427ae40167cb77174b68. It is not verified in the collected artifacts, so the analysis relies on disassembly plus live trace evidence. That disassembly reconstructs a public helper selector 0x7bde82f2 as redeem(uint256,address) and shows that it forwards to Set Protocol selector 0x5c833bfd, redeem(address,uint256,address), using stored addresses from helper storage. This means the helper was effectively acting as a custodian of BUI while delegating redemption authority to any caller.
The vulnerability class is unauthorized asset outflow from a custody wrapper. The helper held BUI on its own balance sheet, but its public redemption entrypoint did not verify that the caller owned those BUI, was approved by a beneficiary, or was an authorized controller of the helper inventory. Instead, the helper forwarded the call directly into Set Protocol's redemption module using the helper itself as the token holder.
That design breaks the core safety invariant for a custody wrapper: only an authorized controller may consume custodied inventory. Set Protocol still behaved correctly. The module burned BUI from msg.sender, which in this call path was the helper contract, and then transferred the redeemed components to the caller-specified recipient. The exploit therefore required no bug in BUI or in DebtIssuanceModuleV2; it only required the helper to hold BUI and leave the public redeem path callable.
The code-level breakpoint is the helper dispatch for selector 0x7bde82f2. The disassembly excerpt shows storage loads for the module and SetToken addresses, construction of the downstream redeem calldata, and an external CALL with no authorization branch:
00000eb3: JUMPDEST
...
00000eec: PUSH4 0x5c833bfd
...
00000f4b: GAS
00000f4c: CALL
The same excerpt records the critical interpretation: selector 0x7bde82f2 maps to redeem(uint256,address), selector 0x5c833bfd maps to redeem(address,uint256,address), and there is no caller authorization check on the helper path before the external call.
The pre-state at block 19063676 is sufficient to realize the ACT opportunity. The helper held 2786531398478570664388 BUI, the Set Protocol issuance module was live, and the helper still exposed its public redeem path. The seed balance diff captures the exact starting BUI balance and the post-transaction dust balance, while the trace shows the live call chain from the attacker router into the helper and then into Set Protocol.
The exploit transaction was sent by EOA 0xd215ffaf0f85fb6f93f11e49bd6175ad58af0dfd to router 0xd129d8c12f0e7aa51157d9e6cc3f7ece2dc84ecd. Inside that router execution, the trace shows the router calling the helper twice through the same public selector, and in each case the helper immediately calls DebtIssuanceModuleV2:
SM Address: 0x82c063afefb226859abd427ae40167cb77174b68, caller:0xd129d8c12f0e7aa51157d9e6cc3f7ece2dc84ecd, input_size:68
SM Address: 0x69a592d2129415a4a1d1b1e309c17051b7f28d57, caller:0x82c063afefb226859abd427ae40167cb77174b68, input_size:100
That trace pattern is the operational proof of the bug. The attacker never needed to own BUI. The helper itself was the account whose BUI was burned, because the helper was the msg.sender seen by DebtIssuanceModuleV2. The recipient, however, was attacker-chosen, so the redeemed basket moved to the attacker's router rather than back to any legitimate helper beneficiary.
The economic effect is visible in both the trace and balance artifacts. The SetToken source uses invoke calls to send components out during redemption, and the seed trace shows repeated SetToken::invoke(...) transfers to router 0xd129... across the redeemed basket components. The seed balance diff independently confirms that the helper's BUI balance fell by exactly 2786528808593750000000, leaving only 2589884820664388 BUI dust, while manager fee recipient 0x62b00335cbE05cEB3B776165E724A647F9FC0891 gained 278652880859375000000 BUI, matching the configured 10% redeem fee.
{
"token": "0xb7470fd67e997b73f55f85a6af0deb2c96194885",
"holder": "0x82c063afefb226859abd427ae40167cb77174b68",
"before": "2786531398478570664388",
"after": "2589884820664388",
"delta": "-2786528808593750000000"
}
Once the basket reached the router, the attacker liquidated it within the same transaction. The seed metadata and trace show swaps and WETH unwraps after the redemption stage, and the final native balance delta proves the realization of profit by the sender EOA. This closes the end-to-end loop from missing authorization, to unauthorized redemption of helper-held BUI, to immediate extraction of market value.
The adversary flow is a single-transaction helper drain followed by basket liquidation. First, EOA 0xd215ff... initiated router 0xd129.... Second, the router called helper 0x82c063... through the public redeem(uint256,address) selector, with the router itself as recipient. Third, the helper forwarded to Set Protocol's DebtIssuanceModuleV2.redeem(address,uint256,address), which burned helper-held BUI and transferred the component basket to the router. Fourth, the router swapped the redeemed components into WETH and then unwrapped WETH into ETH returned to the sender.
The component extraction stage is directly evidenced by the trace lines showing the helper-to-module call chain and by repeated SetToken component transfers to the router. The transaction input also contains the helper selector 0x7bde82f2 embedded in the router calldata, consistent with the trace. This is not a privileged pathway: any unprivileged EOA able to submit a transaction could have invoked the same helper function while the helper held redeemable BUI.
The attacker-related accounts are defensibly identified. The sender EOA 0xd215ff... is the profit sink according to balance_diff.json, and router 0xd129... is the execution contract that receives redeemed components and performs the liquidation leg. The victim side is the helper contract that lost custody over its BUI inventory, with the BUI SetToken serving as the protocol asset consumed by the unauthorized helper-triggered redemption.
The direct measurable loss is the unauthorized consumption of 2786528808593750000000 BUI from the helper contract. In smallest on-chain units, that loss is:
{
"token_symbol": "BUI",
"amount": "2786528808593750000000",
"decimal": 18
}
The helper was left with only 2589884820664388 BUI dust. At the same time, the manager fee recipient correctly received 278652880859375000000 BUI as redeem fee, demonstrating that Set Protocol's module executed the redemption logic as designed. The attacker monetized the redeemed basket immediately and the sender's ETH balance increased by 134.411643345413003066 wei-denominated ETH net of gas, which is the realized economic gain reported in the incident analysis.
0x1ea0a2e88efceccb2dd93e6e5cb89e5421666caeefb1e6fc41b68168373da342, showing router 0xd129... calling helper 0x82c063... and the helper calling DebtIssuanceModuleV2 0x69a592....0xb7470fd67e997b73f55f85a6af0deb2c96194885, confirming protocol-side component transfer mechanics.0x82c063afefb226859abd427ae40167cb77174b68, showing selector 0x7bde82f2 forwarding to selector 0x5c833bfd without authorization.DebtIssuanceModuleV2 at 0x69a592d2129415a4a1d1b1e309c17051b7f28d57.