Skip to content

Instantly share code, notes, and snippets.

@this-is-chainlight
Last active July 28, 2023 12:58
Show Gist options
  • Save this-is-chainlight/027af8760bb0b43425c602e4c471a0bf to your computer and use it in GitHub Desktop.
Save this-is-chainlight/027af8760bb0b43425c602e4c471a0bf to your computer and use it in GitHub Desktop.
// 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 {}
}
forge test --rpc-url https://api.wemix.com/ --fork-block-number 23958960 -vv
[PASS] testWhiteHatCollateral() (gas: 701788)
Logs:
  Number of WEMIX required:  13798304184455
  Number of WEMIX$ required:  3162021424247517622460
  Rescued WEMIX:  3068158418797418525930

[PASS] testWhiteHatStaking() (gas: 2644965)
Logs:
  57435823591293683146987 57405956983660559967289
  57420377804311485268082 57420377804311485268082
  Rescued WEMIX:  6005754750099999223501

Approve cWEMIX to the white hat contract for utilization

cast send --rpc-url https://api.wemix.com/ --legacy --private-key $CL_PRIVATE_KEY --value 0.5ether $VICTIM_ADDRESS
cast send --rpc-url https://api.wemix.com/ --legacy --private-key $VICTIM_PRIVATE_KEY 'approve(address,uint256)' $CWEMIX $CHAINLIGHT_WHITEHAT_CONTRACT_ADDRESS 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Deploy white hat contract

forge create ./test/1.sol:WhiteHat --rpc-url https://api.wemix.com/ --private-key $CL_PRIVATE_KEY --legacy

Transfer NFT to rescue staked WEMIX

cast send --rpc-url https://api.wemix.com/ --legacy --private-key $VICTIM_PRIVATE_KEY 'transferFrom(address,address,uint256)' $VICTIM_ADDRESS $CHAINLIGHT_ADDRESS $STAKING_NFT_ID
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment