Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x0000000a3Fc396B89e4c11841B39D9dff85a5D05
Balance 0 ETH
Nonce 1
Code Size 4706 bytes
Indexed Transactions 1 (24,445,52924,445,529)
Gas Used (indexed) 909,725
External Etherscan · Sourcify

Contract Bytecode

4706 bytes
0x60806040526004361061008a5760003560e01c80638070c503116100595780638070c5031461012a578063b7c58d7a1461014a578063babcc5391461016a578063d38bfff4146101aa578063de792d5f146101ca57600080fd5b806308af4d8814610096578063238efcbc146100b857806326f91506146100cd5780635aa6e675146100ed57600080fd5b3661009157005b600080fd5b3480156100a257600080fd5b506100b66100b1366004610d35565b6101f7565b005b3480156100c457600080fd5b506100b6610246565b3480156100d957600080fd5b506100b66100e8366004610d9c565b6102af565b3480156100f957600080fd5b5060005461010d906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561013657600080fd5b5060015461010d906001600160a01b031681565b34801561015657600080fd5b506100b6610165366004610d35565b6103c6565b34801561017657600080fd5b5061019a610185366004610d35565b60026020526000908152604090205460ff1681565b6040519015158152602001610121565b3480156101b657600080fd5b506100b66101c5366004610d35565b610412565b3480156101d657600080fd5b506101ea6101e5366004610eb0565b610487565b604051610121919061101d565b6000546001600160a01b03163314610222576040516305189e0d60e21b815260040160405180910390fd5b6001600160a01b03166000908152600260205260409020805460ff19166001179055565b6001546001600160a01b03163314610271576040516305189e0d60e21b815260040160405180910390fd5b600080546001600160a01b03191633908117825560405190917fa6a85f15b976d399f39ad43e515e75910bac714bc55eeff6131fb90780d6f74691a2565b6000546001600160a01b031633146102da576040516305189e0d60e21b815260040160405180910390fd5b8382146102fa57604051632aa3c3bf60e11b815260040160405180910390fd5b60005b848110156103be5760008686838181106103195761031961107f565b905060200201602081019061032e9190610d35565b6001600160a01b0316036103635761035e828585848181106103525761035261107f565b905060200201356104cf565b6103ac565b6103ac8686838181106103785761037861107f565b905060200201602081019061038d9190610d35565b838686858181106103a0576103a061107f565b905060200201356104ef565b806103b6816110ab565b9150506102fd565b505050505050565b6000546001600160a01b031633146103f1576040516305189e0d60e21b815260040160405180910390fd5b6001600160a01b03166000908152600260205260409020805460ff19169055565b6000546001600160a01b0316331461043d576040516305189e0d60e21b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f1f95fb40be3a947982072902a887b521248d1d8931a39eb38f84f4d6fd758b6990600090a250565b3360009081526002602052604090205460609060ff166104ba57604051634ae18d2b60e11b815260040160405180910390fd5b6104c5848484610535565b90505b9392505050565b60005a60005a84865af16104eb5763b12d13eb6000526004601cfd5b5050565b816014528060345263a9059cbb60601b60005260206000604460106000875af13d15600160005114171661052b576390b8ec186000526004601cfd5b6000603452505050565b606060008080808487825b818110156108f0578a8a8281811061055a5761055a61107f565b90506020020135965060d887901c60001c60ff169550604086166000146105a6578a8a610586836110ab565b9250828181106105985761059861107f565b9050602002013594506105b7565b602887901b6001600160d01b031794505b6003861661062c576001600160a01b0387166105d48a89886108ff565b6040516105e191906110c4565b600060405180830381855af49150503d806000811461061c576040519150601f19603f3d011682016040523d82523d6000602084013e610621565b606091505b509094509250610854565b60016003871603610696576001600160a01b03871661064c8a89886108ff565b60405161065991906110c4565b6000604051808303816000865af19150503d806000811461061c576040519150601f19603f3d011682016040523d82523d6000602084013e610621565b600260038716036106fe576001600160a01b0387166106b68a89886108ff565b6040516106c391906110c4565b600060405180830381855afa9150503d806000811461061c576040519150601f19603f3d011682016040523d82523d6000602084013e610621565b600380871603610819576000808a8760f81c60ff16815181106107235761072361107f565b6020026020010151905080516020146107985760405162461bcd60e51b815260206004820152602c60248201527f5f657865637574653a2076616c75652063616c6c20686173206e6f2076616c7560448201526b329034b73234b1b0ba32b21760a11b60648201526084015b60405180910390fd5b602081015191506001600160a01b038916826107bc8d8c60088c901b60ff176108ff565b6040516107c991906110c4565b60006040518083038185875af1925050503d8060008114610806576040519150601f19603f3d011682016040523d82523d6000602084013e61080b565b606091505b509096509450610854915050565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c7479706560801b604482015260640161078f565b836108b957825115610867576044830192505b60008760001c600085511161089b57604051806040016040528060078152602001662ab735b737bbb760c91b81525061089d565b845b60405163ef3dcb2f60e01b815260040161078f939291906110e0565b60808616156108d6576108d189605889901b85610aff565b6108e8565b6108e589605889901b85610ba7565b98505b600101610540565b50969998505050505050505050565b606060008060005b602081101561093e578481602081106109225761092261107f565b1a915060fe1982011561093e5760209290920191600101610907565b5060408051808201909152602081018690529250600460006060815b6020811015610af0578781602081106109755761097561107f565b1a945060fe19850115610af0576080851615610aa15760fe8503610a3157601f19605f850116870160405260248388010186905281516020909401936000036109db57896040516020016109c9919061101d565b60405160208183030381529060405291505b8151603f9401938401601f19168701604052610a12826020896109ff8a6004611113565b60208751610a0d919061112c565b610cff565b60208251610a20919061112c565b610a2a9087611113565b9550610ae1565b60008a607f871681518110610a4857610a4861107f565b6020908102919091018101518051868b016024018a9052968701605f8101601f19168b0160405290910195909150610a8e8260008b610a888c6004611113565b85610cff565b610a988189611113565b97505050610ae1565b60008a607f871681518110610ab857610ab861107f565b6020908102919091018101518051603f9701968701601f19168a01604052015184890160240152505b6020929092019160010161095a565b50505083525090949350505050565b60f882901c60fe198101610b135750505050565b600082516020610b239190611113565b67ffffffffffffffff811115610b3b57610b3b610e1d565b6040519080825280601f01601f191660200182016040528015610b65576020820181803683370190505b5085607f841681518110610b7b57610b7b61107f565b602002602001018190529050610b978360008360208751610cff565b8251806020830152505050505050565b606060f883901c60fe198101610bc057849150506104c8565b6080811615610c725760fe8103610bec5782806020019051810190610be5919061113f565b9450610cf6565b602083810151908114610c545760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015269287661726961626c652960b01b606482015260840161078f565b508251601f19016020848101918252607f8316810287010152610cf6565b8251602014610cd45760405162461bcd60e51b815260206004820152602860248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015267287374617469632960c01b606482015260840161078f565b8285607f831681518110610cea57610cea61107f565b60200260200101819052505b50929392505050565b808260208501018286602089010160045afa505050505050565b80356001600160a01b0381168114610d3057600080fd5b919050565b600060208284031215610d4757600080fd5b6104c882610d19565b60008083601f840112610d6257600080fd5b50813567ffffffffffffffff811115610d7a57600080fd5b6020830191508360208260051b8501011115610d9557600080fd5b9250929050565b600080600080600060608688031215610db457600080fd5b853567ffffffffffffffff80821115610dcc57600080fd5b610dd889838a01610d50565b90975095506020880135915080821115610df157600080fd5b50610dfe88828901610d50565b9094509250610e11905060408701610d19565b90509295509295909350565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610e5c57610e5c610e1d565b604052919050565b600067ffffffffffffffff821115610e7e57610e7e610e1d565b5060051b60200190565b600067ffffffffffffffff821115610ea257610ea2610e1d565b50601f01601f191660200190565b60008060006040808587031215610ec657600080fd5b843567ffffffffffffffff80821115610ede57600080fd5b610eea88838901610d50565b9096509450602091508682013581811115610f0457600080fd5b8701601f81018913610f1557600080fd5b8035610f28610f2382610e64565b610e33565b81815260059190911b8201840190848101908b831115610f4757600080fd5b8584015b83811015610fbb57803586811115610f635760008081fd5b8501603f81018e13610f755760008081fd5b87810135610f85610f2382610e88565b8181528f8b838501011115610f9a5760008081fd5b818b84018b83013760009181018a0191909152845250918601918601610f4b565b50809750505050505050509250925092565b60005b83811015610fe8578181015183820152602001610fd0565b50506000910152565b60008151808452611009816020860160208601610fcd565b601f01601f19169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561107257603f19888603018452611060858351610ff1565b94509285019290850190600101611044565b5092979650505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016110bd576110bd611095565b5060010190565b600082516110d6818460208701610fcd565b9190910192915050565b8381526001600160a01b038316602082015260606040820181905260009061110a90830184610ff1565b95945050505050565b8082018082111561112657611126611095565b92915050565b8181038181111561112657611126611095565b6000602080838503121561115257600080fd5b825167ffffffffffffffff8082111561116a57600080fd5b818501915085601f83011261117e57600080fd5b815161118c610f2382610e64565b81815260059190911b830184019084810190888311156111ab57600080fd5b8585015b8381101561121f578051858111156111c75760008081fd5b8601603f81018b136111d95760008081fd5b8781015160406111eb610f2383610e88565b8281528d828486010111156112005760008081fd5b61120f838c8301848701610fcd565b86525050509186019186016111af565b509897505050505050505056fea264697066735822122039f30b6c89c5285ba3c20f26762735734a91cf327793e6c497ac42094598a39b64736f6c63430008140033

Verified Source Code Full Match

Compiler: v0.8.20+commit.a1b79de6 EVM: paris Optimization: Yes (200 runs)
AllMight.sol 116 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.20;

import "src/weiroll/VM.sol";
import "solady/utils/SafeTransferLib.sol";

/// @title  AllMight
/// @notice Weiroll implementation that allow to do literally anything.
/// @author Stake DAO
/// @custom:contact [email protected]
contract AllMight is VM {
    using SafeTransferLib for address;

    /// @notice Address of the governance contract.
    address public governance;

    /// @notice Address of the future governance contract.
    address public futureGovernance;

    /// @notice Address authorized to call the execute function.
    mapping(address => bool) public isAllowed;

    ////////////////////////////////////////////////////////////////
    /// --- EVENTS & ERRORS
    ///////////////////////////////////////////////////////////////

    /// @notice Event emitted when a new governance is proposed.
    event GovernanceProposed(address indexed newGovernance);

    /// @notice Event emitted when the governance is changed.
    event GovernanceChanged(address indexed newGovernance);

    /// @notice Throws if caller is not the governance.
    error GOVERNANCE();

    /// @notice Throws if caller is not allowed.
    error NOT_ALLOWED();

    /// @notice Throws if the length of the tokens and amounts arrays are not equal.
    error WRONG_LENGTH();

    ////////////////////////////////////////////////////////////////
    /// --- MODIFIERS
    ///////////////////////////////////////////////////////////////

    modifier onlyGovernance() {
        if (msg.sender != governance) revert GOVERNANCE();
        _;
    }

    modifier onlyAllowed() {
        if (!isAllowed[msg.sender]) revert NOT_ALLOWED();
        _;
    }

    constructor(address _governance) {
        governance = _governance;
    }

    ////////////////////////////////////////////////////////////////
    /// --- ADMIN FUNCTIONS
    ///////////////////////////////////////////////////////////////

    /// @notice Allow an address to call the execute function.
    /// @param _address Address to allow.
    function allowAddress(address _address) external onlyGovernance {
        isAllowed[_address] = true;
    }

    /// @notice Disallow an address to call the execute function.
    /// @param _address Address to disallow.
    function disallowAddress(address _address) external onlyGovernance {
        isAllowed[_address] = false;
    }

    /// @notice Transfer the governance to a new address.
    /// @param _governance Address of the new governance.
    function transferGovernance(address _governance) external onlyGovernance {
        emit GovernanceProposed(futureGovernance = _governance);
    }

    /// @notice Accept the governance transfer.
    function acceptGovernance() external {
        if (msg.sender != futureGovernance) revert GOVERNANCE();
        emit GovernanceChanged(governance = msg.sender);
    }

    /// @notice Withdraw ETH or ERC20 tokens from the contract.
    function withdraw(address[] calldata _tokens, uint256[] calldata _amount, address _recipient)
        external
        onlyGovernance
    {
        if (_tokens.length != _amount.length) revert WRONG_LENGTH();

        for (uint256 i = 0; i < _tokens.length; i++) {
            if (_tokens[i] == address(0)) {
                SafeTransferLib.safeTransferETH(_recipient, _amount[i]);
            } else {
                SafeTransferLib.safeTransfer(_tokens[i], _recipient, _amount[i]);
            }
        }
    }

    ////////////////////////////////////////////////////////////////
    /// --- EXECUTE FUNCTION
    ///////////////////////////////////////////////////////////////

    /// @notice Execute a list of commands.
    /// @param commands List of commands to execute.
    /// @param state State to execute the commands on.
    function execute(bytes32[] calldata commands, bytes[] memory state) external onlyAllowed returns (bytes[] memory) {
        return _execute(commands, state);
    }

    receive() external payable {}
}
VM.sol 120 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.11;

import "src/weiroll/CommandBuilder.sol";

abstract contract VM {
    using CommandBuilder for bytes[];

    uint256 constant FLAG_CT_DELEGATECALL = 0x00;
    uint256 constant FLAG_CT_CALL = 0x01;
    uint256 constant FLAG_CT_STATICCALL = 0x02;
    uint256 constant FLAG_CT_VALUECALL = 0x03;
    uint256 constant FLAG_CT_MASK = 0x03;
    uint256 constant FLAG_EXTENDED_COMMAND = 0x40;
    uint256 constant FLAG_TUPLE_RETURN = 0x80;

    uint256 constant SHORT_COMMAND_FILL = 0x000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    address immutable self;

    error ExecutionFailed(uint256 command_index, address target, string message);

    constructor() {
        self = address(this);
    }

    function _execute(bytes32[] calldata commands, bytes[] memory state) internal returns (bytes[] memory) {
        bytes32 command;
        uint256 flags;
        bytes32 indices;

        bool success;
        bytes memory outdata;

        uint256 commandsLength = commands.length;
        for (uint256 i; i < commandsLength;) {
            command = commands[i];
            flags = uint256(command >> 216) & 0xFF; // more efficient
            // flags = uint256(uint8(bytes1(command << 32))); // more readable

            if (flags & FLAG_EXTENDED_COMMAND != 0) {
                indices = commands[++i];
            } else {
                indices = bytes32(uint256(command << 40) | SHORT_COMMAND_FILL);
            }

            if (flags & FLAG_CT_MASK == FLAG_CT_DELEGATECALL) {
                (success, outdata) = address(uint160(uint256(command))).delegatecall( // target
                    // inputs
                    state.buildInputs(
                        //selector
                        bytes4(command),
                        indices
                    )
                );
            } else if (flags & FLAG_CT_MASK == FLAG_CT_CALL) {
                (success, outdata) = address(uint160(uint256(command))).call( // target
                    // inputs
                    state.buildInputs(
                        //selector
                        bytes4(command),
                        indices
                    )
                );
            } else if (flags & FLAG_CT_MASK == FLAG_CT_STATICCALL) {
                (success, outdata) = address(uint160(uint256(command))).staticcall( // target
                    // inputs
                    state.buildInputs(
                        //selector
                        bytes4(command),
                        indices
                    )
                );
            } else if (flags & FLAG_CT_MASK == FLAG_CT_VALUECALL) {
                uint256 callEth;
                bytes memory v = state[uint8(bytes1(indices))];
                require(v.length == 32, "_execute: value call has no value indicated.");
                assembly {
                    callEth := mload(add(v, 0x20))
                }
                (success, outdata) = address(uint160(uint256(command))).call{ // target
                    value: callEth
                }(
                    // inputs
                    state.buildInputs(
                        //selector
                        bytes4(command),
                        bytes32(uint256(indices << 8) | CommandBuilder.IDX_END_OF_ARGS)
                    )
                );
            } else {
                revert("Invalid calltype");
            }

            if (!success) {
                if (outdata.length > 0) {
                    assembly {
                        outdata := add(outdata, 68)
                    }
                }
                revert ExecutionFailed({
                    command_index: 0,
                    target: address(uint160(uint256(command))),
                    message: outdata.length > 0 ? string(outdata) : "Unknown"
                });
            }

            if (flags & FLAG_TUPLE_RETURN != 0) {
                state.writeTuple(bytes1(command << 88), outdata);
            } else {
                state = state.writeOutputs(bytes1(command << 88), outdata);
            }
            unchecked {
                ++i;
            }
        }
        return state;
    }
}
CommandBuilder.sol 152 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

library CommandBuilder {
    uint256 constant IDX_VARIABLE_LENGTH = 0x80;
    uint256 constant IDX_VALUE_MASK = 0x7f;
    uint256 constant IDX_END_OF_ARGS = 0xff;
    uint256 constant IDX_USE_STATE = 0xfe;

    function buildInputs(bytes[] memory state, bytes4 selector, bytes32 indices)
        internal
        view
        returns (bytes memory ret)
    {
        uint256 free; // Pointer to first free byte in tail part of message
        uint256 idx;

        // Determine the length of the encoded data
        for (uint256 i; i < 32;) {
            idx = uint8(indices[i]);
            if (idx == IDX_END_OF_ARGS) break;
            unchecked {
                free += 32;
            }
            unchecked {
                ++i;
            }
        }

        // Encode it
        uint256 bytesWritten;
        assembly {
            ret := mload(0x40)
            bytesWritten := add(bytesWritten, 4)
            mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
            mstore(add(ret, 32), selector)
        }
        uint256 count = 0;
        bytes memory stateData; // Optionally encode the current state if the call requires it
        for (uint256 i; i < 32;) {
            idx = uint8(indices[i]);
            if (idx == IDX_END_OF_ARGS) break;

            if (idx & IDX_VARIABLE_LENGTH != 0) {
                if (idx == IDX_USE_STATE) {
                    assembly {
                        bytesWritten := add(bytesWritten, 32)
                        mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
                        mstore(add(add(ret, 36), count), free)
                    }
                    if (stateData.length == 0) {
                        stateData = abi.encode(state);
                    }
                    assembly {
                        bytesWritten := add(bytesWritten, mload(stateData))
                        mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
                    }
                    memcpy(stateData, 32, ret, free + 4, stateData.length - 32);
                    free += stateData.length - 32;
                } else {
                    bytes memory stateVar = state[idx & IDX_VALUE_MASK];
                    uint256 arglen = stateVar.length;

                    // Variable length data; put a pointer in the slot and write the data at the end
                    assembly {
                        bytesWritten := add(bytesWritten, 32)
                        mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
                        mstore(add(add(ret, 36), count), free)
                    }
                    assembly {
                        bytesWritten := add(bytesWritten, arglen)
                        mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
                    }
                    memcpy(stateVar, 0, ret, free + 4, arglen);
                    free += arglen;
                }
            } else {
                // Fixed length data; write it directly
                bytes memory stateVar = state[idx & IDX_VALUE_MASK];
                assembly {
                    bytesWritten := add(bytesWritten, mload(stateVar))
                    mstore(0x40, add(ret, and(add(add(bytesWritten, 0x20), 0x1f), not(0x1f))))
                    mstore(add(add(ret, 36), count), mload(add(stateVar, 32)))
                }
            }
            unchecked {
                count += 32;
            }
            unchecked {
                ++i;
            }
        }
        assembly {
            mstore(ret, bytesWritten)
        }
    }

    function writeOutputs(bytes[] memory state, bytes1 index, bytes memory output)
        internal
        pure
        returns (bytes[] memory)
    {
        uint256 idx = uint8(index);
        if (idx == IDX_END_OF_ARGS) return state;

        if (idx & IDX_VARIABLE_LENGTH != 0) {
            if (idx == IDX_USE_STATE) {
                state = abi.decode(output, (bytes[]));
            } else {
                // Check the first field is 0x20 (because we have only a single return value)
                uint256 argptr;
                assembly {
                    argptr := mload(add(output, 32))
                }
                require(argptr == 32, "Only one return value permitted (variable)");

                assembly {
                    // Overwrite the first word of the return data with the length - 32
                    mstore(add(output, 32), sub(mload(output), 32))
                    // Insert a pointer to the return data, starting at the second word, into state
                    mstore(add(add(state, 32), mul(and(idx, IDX_VALUE_MASK), 32)), add(output, 32))
                }
            }
        } else {
            // Single word
            require(output.length == 32, "Only one return value permitted (static)");

            state[idx & IDX_VALUE_MASK] = output;
        }

        return state;
    }

    function writeTuple(bytes[] memory state, bytes1 index, bytes memory output) internal view {
        uint256 idx = uint256(uint8(index));
        if (idx == IDX_END_OF_ARGS) return;

        bytes memory entry = state[idx & IDX_VALUE_MASK] = new bytes(output.length + 32);

        memcpy(output, 0, entry, 32, output.length);
        assembly {
            let l := mload(output)
            mstore(add(entry, 32), l)
        }
    }

    function memcpy(bytes memory src, uint256 srcidx, bytes memory dest, uint256 destidx, uint256 len) internal view {
        assembly {
            pop(staticcall(gas(), 4, add(add(src, 32), srcidx), len, add(add(dest, 32), destidx), len))
        }
    }
}
SafeTransferLib.sol 381 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for gas griefing protection.
/// - For ERC20s, this implementation won't check that a token has code,
///   responsibility is delegated to the caller.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
    uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // If gas griefing protection is needed, please use the force variants.
    //
    // The regular variants:
    // - Forwards all remaining gas to the target.
    // - Reverts if the target reverts.
    // - Reverts if the current contract has insufficient balance.
    //
    // The force variants:
    // - Forwards with an optional gas stipend
    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
    // - If the target reverts, or if the gas stipend is exhausted,
    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
    // - Reverts if the current contract has insufficient balance.
    //
    // The try variants:
    // - Forwards with a mandatory gas stipend.
    // - Instead of reverting, returns whether the transfer succeeded.

    /// @dev Sends `amount` (in wei) ETH to `to`.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`.
    function safeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer all the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, selfbalance(), gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(gasStipend, to, amount, gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) {
                    returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
                }
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gasStipend, to, selfbalance(), gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) {
                    returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
                }
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) {
                    returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
                }
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), gas(), 0x00, gas(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) {
                    returndatacopy(gas(), returndatasize(), shr(20, gas())) // For gas estimation.
                }
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, amount, gas(), 0x00, gas(), 0x00)
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function trySafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, selfbalance(), gas(), 0x00, gas(), 0x00)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have their entire balance approved for
    /// the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to)
        internal
        returns (uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x14, to) // Store the `to` argument.
            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
    /// then retries the approval again (some tokens, e.g. USDT, requires this).
    /// Reverts upon failure.
    function safeApproveWithRetry(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, retrying upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                )
            ) {
                mstore(0x34, 0) // Store 0 for the `amount`.
                mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
                pop(call(gas(), token, 0, 0x10, 0x44, 0x00, 0x00)) // Reset the approval.
                mstore(0x34, amount) // Store back the original `amount`.
                // Retry the approval, reverting upon failure.
                if iszero(
                    and(
                        or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
                        call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    )
                ) {
                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            amount :=
                mul(
                    mload(0x20),
                    and( // The arguments of `and` are evaluated from right to left.
                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                    )
                )
        }
    }
}

Read Contract

futureGovernance 0x8070c503 → address
governance 0x5aa6e675 → address
isAllowed 0xbabcc539 → bool

Write Contract 6 functions

These functions modify contract state and require a wallet transaction to execute.

acceptGovernance 0x238efcbc
No parameters
allowAddress 0x08af4d88
address _address
disallowAddress 0xb7c58d7a
address _address
execute 0xde792d5f
bytes32[] commands
bytes[] state
returns: bytes[]
transferGovernance 0xd38bfff4
address _governance
withdraw 0x26f91506
address[] _tokens
uint256[] _amount
address _recipient

Top Interactions

AddressTxnsSentReceived
0x90569D8A...Fc75 1 1

Recent Transactions

CSV
|
Hash Method Block Age From/To Value Txn Fee Type
0x80f63c2a...d3f7f6 0xde792d5f 24,445,529 IN 0x90569D8A...Fc75 0 ETH EIP-1559