Skip to content

Instantly share code, notes, and snippets.

@PedroCailleret
Last active January 9, 2023 05:53
Show Gist options
  • Select an option

  • Save PedroCailleret/6ff8f0641127da5201e78af07dc3e79c to your computer and use it in GitHub Desktop.

Select an option

Save PedroCailleret/6ff8f0641127da5201e78af07dc3e79c to your computer and use it in GitHub Desktop.
// 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