Skip to content

Commit

Permalink
add old version
Browse files Browse the repository at this point in the history
  • Loading branch information
massun-onibakuchi committed May 29, 2024
1 parent 3c02a37 commit d239139
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 6 deletions.
17 changes: 11 additions & 6 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
GrimReaperHuffTest:testLiquidate() (gas: 390412)
GrimReaperHuffTest:testLiquidate(uint256,address) (runs: 256, μ: 390235, ~: 390503)
GrimReaperHuffTest:testOnlyOwner(address) (runs: 256, μ: 20247, ~: 20247)
GrimReaperHuffTest:testLiquidate(uint256,address) (runs: 257, μ: 390236, ~: 390503)
GrimReaperHuffTest:testOnlyOwner(address) (runs: 257, μ: 20247, ~: 20247)
GrimReaperHuffTest:testRecoverERC20() (gas: 330912)
GrimReaperHuffTest:testRevertIfLiquidationFail() (gas: 52407)
GrimReaperHuffV0Test:testLiquidate() (gas: 390428)
GrimReaperHuffV0Test:testLiquidate(uint256,address) (runs: 257, μ: 390004, ~: 390519)
GrimReaperHuffV0Test:testOnlyOwner(address) (runs: 257, μ: 20257, ~: 20257)
GrimReaperHuffV0Test:testRecoverERC20() (gas: 330803)
GrimReaperHuffV0Test:testRevertIfLiquidationFail() (gas: 52429)
GrimReaperSolTest:testLiquidate() (gas: 390820)
GrimReaperSolTest:testLiquidate(uint256,address) (runs: 256, μ: 390395, ~: 390912)
GrimReaperSolTest:testOnlyOwner(address) (runs: 256, μ: 18934, ~: 18934)
GrimReaperSolTest:testLiquidate(uint256,address) (runs: 257, μ: 390397, ~: 390912)
GrimReaperSolTest:testOnlyOwner(address) (runs: 257, μ: 18934, ~: 18934)
GrimReaperSolTest:testRecoverERC20() (gas: 331740)
GrimReaperSolTest:testRevertIfLiquidationFail() (gas: 51145)
OptimizedGrimReaperSolTest:testLiquidate() (gas: 390477)
OptimizedGrimReaperSolTest:testLiquidate(uint256,address) (runs: 256, μ: 390299, ~: 390562)
OptimizedGrimReaperSolTest:testOnlyOwner(address) (runs: 256, μ: 20400, ~: 20400)
OptimizedGrimReaperSolTest:testLiquidate(uint256,address) (runs: 257, μ: 390300, ~: 390561)
OptimizedGrimReaperSolTest:testOnlyOwner(address) (runs: 257, μ: 20400, ~: 20400)
OptimizedGrimReaperSolTest:testRecoverERC20() (gas: 330864)
OptimizedGrimReaperSolTest:testRevertIfLiquidationFail() (gas: 52467)
173 changes: 173 additions & 0 deletions src/GrimReaperV0.huff
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// SPDX-License-Identifier: GPL-3.0-or-later

// Interface
#define function approve(address spender, uint256 value) nonpayable returns (bool)
#define function balanceOf(address) view returns (uint256)
#define function transfer(address,uint256) nonpayable returns ()

#define function recoverERC20(address) nonpayable returns ()
#define function liquidationCall(address collateralAsset,address debtAsset,address user,uint256 debtToCover,bool receiveAToken) nonpayable returns ()

// Storage and constants
#define constant OWNER = 0x0000000000000000000000000000000000000003
#define constant POOL = 0x794a61358D6845594F94dc1DB02A252b5b4814aD


// ref: https://github.com/abigger87/subway-rs/blob/ee51bbca28503174acc6ae6d1f9723be262d884d/contracts/src/Sandwich.huff

/// @notice Fetches the token balance of the caller for the provided token
/// @notice Stack Input: [token]
/// @notice Stack Output: [balance, token]
#define macro STATIC_CALL_TOKEN_BALANCE_MINUS_ONE(err) = takes (1) returns (2) {
// Static Call token.balanceOf(address(this))
__FUNC_SIG(balanceOf) 0x00 mstore // [token]
address 0x20 mstore // [token]

0x20 // [retSize, token]
0x00 // [retOffset, retSize, token]
0x24 // [argSize, retOffset, retSize, token]
0x1c // [argOffset, argSize, retOffset, retSize, token]
dup5 // [to, argOffset, argSize, retOffset, retSize, token]
gas // [gas, to, argOffset, argSize, retOffset, retSize, token]
staticcall // [success, token]

// Validate successful call
iszero <err> jumpi // [token]
0x00 mload // [balance, token]
dup1 iszero skip jumpi
0x01 swap1 sub // [(balance - 1), token]
skip: // [(balance - 1) | 0, token]
}

/// @notice Receive profits from contract
#define macro RECOVER_ERC20() = takes (0) returns (0) {
0x04 calldataload // [token]

// Get the balance of this contract
STATIC_CALL_TOKEN_BALANCE_MINUS_ONE(error) // [balance, token]

// Call token.transfer(msg.sender, balance)
__FUNC_SIG(transfer) 0x00 mstore // [balance, token]
caller 0x20 mstore // [balance, token]
0x40 mstore // [token]

0x00 // [retSize, token]
0x00 // [retOffset, retSize, token]
0x44 // [argSize, retOffset, retSize, token]
0x1c // [argOffset, argSize, retOffset, retSize, token]
dup3 // [value, argOffset, argSize, retOffset, retSize, token]
dup6 // [to, value, argOffset, argSize, retOffset, retSize, token]
gas // [gas, to, value, argOffset, argSize, retOffset, retSize, token]
call // [success, token]

// Validate call success
iszero error jumpi stop
}

/// @notice Entry point for liquidation call
/// @dev calldata [address collateralAsset, address debtAsset, address user, uint128 debtToCover]
/// calldata is encoded with abi.encodePacked(collateralAsset,debtAsset,user,debtToCover)
///https://docs.soliditylang.org/en/v0.8.17/abi-spec.html#non-standard-packed-mode
#define macro EXECUTE_LIQUIDATION() = takes(0) returns(0) {
// input stack: []

// Unpack the calldata
// calldata is encoded with abi.encodePacked(address collateralAsset,address debtAsset,address user,uint128 debtToCover)
0x00 calldataload 0x60 shr // [col] - bytes 20
0x14 calldataload 0x60 shr // [debt, col] - bytes 20
0x28 calldataload 0x60 shr // [user, debt, col] - bytes 20
0x3c calldataload 0x80 shr // [debtToCover, user, debt, col] - uint128

// Call debtAsset.approve(pool, debtToCover)
// e.g. approve(address POOL,uint256 1000)
// store func sig at 0x00
__FUNC_SIG(approve) 0xe0 shl // [func_sig, debtToCover, user, debt, col]
0x00 mstore // [debtToCover, user, debt, col]
// after the operation
// Memory loc Data
// 0x00: 095ea7b300000000000000000000000000000000000000000000000000000000

// store POOL address at 0x04
[POOL] 0x04 mstore // [debtToCover, user, debt, col]
// after the operation
// Memory loc Data
// 0x00: 095ea7b3000000000000000000000000794a61358d6845594f94dc1db02a252b
// 0x20: 5b4814ad00000000000000000000000000000000000000000000000000000000

// store debtToCover at 0x24
dup1 0x24 mstore // [debtToCover, user, debt, col]
// after the operation
// Memory loc Data
// 0x00: 095ea7b3000000000000000000000000794a61358d6845594f94dc1db02a252b
// 0x20: 5b4814ad00000000000000000000000000000000000000000000000000000000
// 0x40: 000003e800000000000000000000000000000000000000000000000000000000

0x00 // [retSize, debtToCover, user, debt, col]
0x00 // [retOffset, retSize, debtToCover, user, debt, col]
0x44 // [argSize, retOffset, retSize, debtToCover, user, debt, col]
0x00 // [argOffset, argSize, retOffset, retSize, debtToCover, user, debt, col]
dup1 // [value, argOffset, argSize, retOffset, retSize, debtToCover, user, debt, col]
dup8 // [to, value, argOffset, argSize, retOffset, retSize, debtToCover, user, debt, col]
0x1388 gas sub // [(gas - 5000), to, value, argOffset, argSize, retOffset, retSize, debtToCover, user, debt, col]
call // [success, debtToCover, user, debt, col]

// Validate call success
iszero error jumpi // [debtToCover, user, debt, col]

// Call POOL.liquidationCall(collateralAsset, debtAsset, user, debtToCover, false)
__FUNC_SIG(liquidationCall) 0xe0 shl 0x00 mstore // [debtToCover, user, debt, col]
dup4 0x04 mstore // [debtToCover, user, debt, col]
dup3 0x24 mstore // [debtToCover, user, debt, col]
dup2 0x44 mstore // [debtToCover, user, debt, col]
dup1 0x64 mstore // [debtToCover, user, debt, col]
0x00 0x84 mstore // [debtToCover, user, debt, col]

// Execute the call
0x00 // [retSize, debtToCover, user, debt, col]
0x00 // [retOffset, retSize, debtToCover, user, debt, col]
0x104 // [argSize, retOffset, retSize, debtToCover, user, debt, col]
0x00 // [argOffset, argSize, retOffset, retSize, debtToCover, user, debt, col]
dup1 // [value, argOffset, argSize, retOffset, retSize, debtToCover, user, debt, col]
[POOL] // [to, value, argOffset, argSize, retOffset, retSize, debtToCover, user, debt, col]
0x1388 gas sub // [(gas - 5000), to, value, argOffset, argSize, retOffset, retSize, debtToCover, user, debt, col]
call // [success, debtToCover, user, debt, col]

// Validate call success
iszero error jumpi stop
}

/// @notice Revert, but still (3, 3) wgmi I guess
#define macro WAGMI() = takes (0) returns (0) {
0x03 dup1 revert
}
// Main
#define macro MAIN() = takes(0) returns(0) {
// here we dispatch based on the size of calldata instead of the function selector
/*
// pc = 0 there 100% of the time
// so its just a way to save a very very small amount of gas (1 gas)
// Get the function selector
// load 32 bytes starting from position 0 onto the stack (if the calldata is less than 32 bytes then it will be right padded with zeros).
// 0xE0 shr right shifts the calldata by 224 bits,
// leaving 32 bits or 4 bytes remaining on the stack.
pc calldataload 0xe0 shr // [func_sig]
dup1 __FUNC_SIG(recoverERC20) eq recover_erc20 jumpi // [selector]
*/

// Verify that the caller is the OWNER
caller [OWNER] eq iszero error jumpi // []

// Dispatcher to determine which function to execute
// 24 bytes call data `recoverERC20(address)`
calldatasize 0x24 eq recover_erc20 jumpi // []

// If no matching selector was found, call the liquidation function
EXECUTE_LIQUIDATION()

recover_erc20:
RECOVER_ERC20()
error:
WAGMI()

0x00 0x00 revert
}
6 changes: 6 additions & 0 deletions test/GrimReaper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,9 @@ contract GrimReaperHuffTest is OptimizedGrimReaperSolTest {
assertEq(debt.balanceOf(owner), balance - 1);
}
}

contract GrimReaperHuffV0Test is OptimizedGrimReaperSolTest {
function _deployGrimReaper() internal virtual override {
reaper = GrimReaper(HuffDeployer.deploy("GrimReaperV0"));
}
}

0 comments on commit d239139

Please sign in to comment.