Last active
January 9, 2023 05:53
-
-
Save PedroCailleret/6ff8f0641127da5201e78af07dc3e79c to your computer and use it in GitHub Desktop.
This file contains hidden or 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: MIT | |
| pragma solidity 0.8.4; | |
| /// THIS IS A WIP. IT'S BROKEN! | |
| /// DON'T GET THIS EVEN NEAR PRODUCTION | |
| /// _ _ _ _ _ |_|_ | |
| /// (_|_\| | |\/(_||_|| | | |
| /// | |
| contract AsmVault { | |
| /// @dev ToDo: Fix arithmetic overflow. | |
| /// ███ Storage ████████████████████████████████████████████████████████████ | |
| IERC20 public immutable token; | |
| uint256 public totalSupply; | |
| mapping(address => uint256) public balanceOf; | |
| bool private lckd; | |
| modifier noReentrancy() { | |
| require(!lckd, "REENTRANCY"); | |
| lckd = true; | |
| _; | |
| lckd = false; | |
| } | |
| /// ███ Constructor ████████████████████████████████████████████████████████ | |
| constructor(address _token) { | |
| token = IERC20(_token); | |
| } | |
| /// ███ External ███████████████████████████████████████████████████████████ | |
| function deposit(uint256 _amount) external noReentrancy { | |
| address _token = address(token); | |
| assembly { | |
| function encodeAddr(head, val0) -> tail { | |
| tail := add(head, 32) | |
| mstore(head, and(val0, sub(shl(160, 1), 1))) | |
| } | |
| function decodeUint(head, end) -> val0 { | |
| if slt(sub(end, head), 32) { | |
| revert(val0, val0) | |
| } | |
| val0 := mload(head) | |
| } | |
| function endAlloc(memPtr, size) { | |
| let newFreePtr := add(memPtr, and(add(size, 31), not(31))) | |
| if or( | |
| gt(newFreePtr, 0xffffffffffffffff), | |
| lt(newFreePtr, memPtr) | |
| ) { | |
| mstore(0, shl(224, 0x4e487b71)) | |
| mstore(4, 0x41) | |
| revert(0, 0x24) | |
| } | |
| mstore(64, newFreePtr) | |
| } | |
| function encodeAddrUint(head, val0, value1, value2) -> tail { | |
| tail := add(head, 96) | |
| let _1 := sub(shl(160, 1), 1) | |
| mstore(head, and(val0, _1)) | |
| mstore(add(head, 32), and(value1, _1)) | |
| mstore(add(head, 64), value2) | |
| } | |
| function decodeBool(head, end) -> val0 { | |
| if slt(sub(end, head), 32) { | |
| revert(val0, val0) | |
| } | |
| let value := mload(head) | |
| if iszero(eq(value, iszero(iszero(value)))) { | |
| revert(val0, val0) | |
| } | |
| val0 := value | |
| } | |
| let _shares := 0 | |
| let _1 := sload(_shares) | |
| switch iszero(_1) | |
| case 0 { | |
| let expr := mul(_amount, _1) | |
| let expr_address := and(_token, sub(shl(160, 1), 1)) | |
| if iszero(extcodesize(expr_address)) { | |
| revert(_shares, _shares) | |
| } | |
| let _2 := mload(64) | |
| mstore(_2, shl(224, 0x70a08231)) | |
| let _3 := staticcall( | |
| gas(), | |
| expr_address, | |
| _2, | |
| sub(encodeAddr(add(_2, 4), address()), _2), | |
| _2, | |
| 32 | |
| ) | |
| if iszero(_3) { | |
| returndatacopy(0, 0, returndatasize()) | |
| revert(0, returndatasize()) | |
| } | |
| let expr_1 := _shares | |
| if _3 { | |
| endAlloc(_2, returndatasize()) | |
| expr_1 := decodeUint(_2, add(_2, returndatasize())) | |
| } | |
| _shares := div(expr, expr_1) | |
| } | |
| default { | |
| _shares := _amount | |
| } | |
| // fun_mint(caller(), _shares) | |
| sstore(0x00, add(sload(0x00), _shares)) | |
| mstore(0x00, and(caller(), sub(shl(160, 1), 1))) | |
| mstore(0x20, 0x01) | |
| let stdout := keccak256(0x00, 0x40) | |
| sstore(stdout, add(sload(stdout), _shares)) | |
| let addr := and(_token, sub(shl(160, 1), 1)) | |
| if iszero(extcodesize(addr)) { | |
| revert(0, 0) | |
| } | |
| let _4 := mload(64) | |
| mstore(_4, shl(224, 0x23b872dd)) | |
| let _5 := call( | |
| gas(), | |
| addr, | |
| 0, | |
| _4, | |
| sub( | |
| encodeAddrUint(add(_4, 4), caller(), address(), _amount), | |
| _4 | |
| ), | |
| _4, | |
| 32 | |
| ) | |
| if iszero(_5) { | |
| returndatacopy(0, 0, returndatasize()) | |
| revert(0, returndatasize()) | |
| } | |
| if _5 { | |
| endAlloc(_4, returndatasize()) | |
| pop(decodeBool(_4, add(_4, returndatasize()))) | |
| } | |
| } | |
| } | |
| function withdraw(uint256 _shares) external noReentrancy { | |
| address _token = address(token); | |
| assembly { | |
| function encodeAddr(head, val0) -> tail { | |
| tail := add(head, 32) | |
| mstore(head, and(val0, sub(shl(160, 1), 1))) | |
| } | |
| function endAlloc(memPtr, size) { | |
| let newFreePtr := add(memPtr, and(add(size, 31), not(31))) | |
| if or( | |
| gt(newFreePtr, 0xffffffffffffffff), | |
| lt(newFreePtr, memPtr) | |
| ) { | |
| mstore(0, shl(224, 0x4e487b71)) | |
| mstore(4, 0x41) | |
| revert(0, 0x24) | |
| } | |
| mstore(64, newFreePtr) | |
| } | |
| function decodeUint(head, end) -> val0 { | |
| if slt(sub(end, head), 32) { | |
| revert(val0, val0) | |
| } | |
| val0 := mload(head) | |
| } | |
| function panic() { | |
| mstore(0, shl(224, 0x4e487b71)) | |
| mstore(4, 0x11) | |
| revert(0, 0x24) | |
| } | |
| function encodeAddr_uint256(head, val0, value1) -> tail { | |
| tail := add(head, 64) | |
| mstore(head, and(val0, sub(shl(160, 1), 1))) | |
| mstore(add(head, 32), value1) | |
| } | |
| function decodeBool(head, end) -> val0 { | |
| if slt(sub(end, head), 32) { | |
| revert(val0, val0) | |
| } | |
| let value := mload(head) | |
| if iszero(eq(value, iszero(iszero(value)))) { | |
| revert(val0, val0) | |
| } | |
| val0 := value | |
| } | |
| let addr := and(_token, sub(shl(160, 1), 1)) | |
| if iszero(extcodesize(addr)) { | |
| revert(0, 0) | |
| } | |
| let _1 := mload(64) | |
| mstore(_1, shl(224, 0x70a08231)) | |
| let _2 := staticcall( | |
| gas(), | |
| addr, | |
| _1, | |
| sub(encodeAddr(add(_1, 4), address()), _1), | |
| _1, | |
| 32 | |
| ) | |
| if iszero(_2) { | |
| returndatacopy(0, 0, returndatasize()) | |
| revert(0, returndatasize()) | |
| } | |
| let expr := 0 | |
| if _2 { | |
| endAlloc(_1, returndatasize()) | |
| expr := decodeUint(_1, add(_1, returndatasize())) | |
| } | |
| let expr_1 := mul(_shares, expr) | |
| let expr_2 := mul(expr_1, sload(0)) | |
| let x := sload(0x00) | |
| if lt(x, _shares) { | |
| panic() | |
| } | |
| sstore(0x00, sub(x, _shares)) | |
| mstore(0x00, and(caller(), sub(shl(160, 1), 1))) | |
| mstore(0x20, 0x01) | |
| let y := keccak256(0x00, 0x40) | |
| let stdout := sload(y) | |
| if lt(stdout, _shares) { | |
| panic() | |
| } | |
| sstore(y, sub(stdout, _shares)) | |
| // burn(caller(), _shares) | |
| if iszero(extcodesize(addr)) { | |
| revert(0, 0) | |
| } | |
| let _3 := mload(64) | |
| mstore(_3, shl(224, 0xa9059cbb)) | |
| let head := add(_3, 4) | |
| // tail := add(head, 64) | |
| let _4 := call( | |
| gas(), | |
| addr, | |
| 0, | |
| _3, | |
| sub(encodeAddr_uint256(head, caller(), expr_2), _3), | |
| _3, | |
| 32 | |
| ) | |
| if iszero(_4) { | |
| returndatacopy(0, 0, returndatasize()) | |
| revert(0, returndatasize()) | |
| } | |
| if _4 { | |
| endAlloc(_3, returndatasize()) | |
| pop(decodeBool(_3, add(_3, returndatasize()))) | |
| } | |
| } | |
| } | |
| /// ███ Internal ███████████████████████████████████████████████████████████ | |
| // function _mint(address _to, uint256 _shares) internal { | |
| // assembly { | |
| // sstore(0x00, add(sload(0x00), _shares)) | |
| // mstore(0x00, and(_to, sub(shl(160, 1), 1))) | |
| // mstore(0x20, 0x01) | |
| // let stdout := keccak256(0x00, 0x40) | |
| // sstore(stdout, add(sload(stdout), _shares)) | |
| // } | |
| // } | |
| // function _burn(address _from, uint256 _shares) internal { | |
| // assembly { | |
| // function panic() { | |
| // mstore(0, shl(224, 0x4e487b71)) | |
| // mstore(4, 0x11) | |
| // revert(0, 0x24) | |
| // } | |
| // let x := sload(0x00) | |
| // if lt(x, _shares) { | |
| // panic() | |
| // } | |
| // sstore(0x00, sub(x, _shares)) | |
| // mstore(0x00, and(_from, sub(shl(160, 1), 1))) | |
| // mstore(0x20, 0x01) | |
| // let y := keccak256(0x00, 0x40) | |
| // let stdout := sload(y) | |
| // if lt(stdout, _shares) { | |
| // panic() | |
| // } | |
| // sstore(y, sub(stdout, _shares)) | |
| // } | |
| // } | |
| } | |
| /// ███ Lib ████████████████████████████████████████████████████████████████ | |
| interface IERC20 { | |
| function transferFrom( | |
| address sender, | |
| address recipient, | |
| uint256 amount | |
| ) external returns (bool); | |
| function transfer(address recipient, uint256 amount) | |
| external | |
| returns (bool); | |
| function approve(address spender, uint256 amount) | |
| external | |
| returns (bool); | |
| function totalSupply() | |
| external | |
| view | |
| returns (uint256); | |
| function balanceOf(address account) | |
| external | |
| view | |
| returns (uint256); | |
| function allowance(address owner, address spender) | |
| external | |
| view | |
| returns (uint256); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment