Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x55C08ca52497e2f1534B59E2917BF524D4765257
Balance 0 ETH
Nonce 1
Code Size 5908 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

5908 bytes
0x608060405234801561001057600080fd5b50600436106101735760003560e01c80636b32810b116100de578063983b2d5611610097578063d505accf11610071578063d505accf1461036f578063dd62ed3e14610382578063e30c3978146103ad578063f44637ba146103c057600080fd5b8063983b2d56146103365780639dc29fac14610349578063a9059cbb1461035c57600080fd5b80636b32810b1461028c57806370a08231146102a15780637ecebe00146102c157806386fe8b43146102e15780638da5cb5b146102e957806395d89b411461031457600080fd5b80633092afd5116101305780633092afd51461022a578063313ce5671461023d57806332cb6b0c146102575780633644e5151461026957806340c10f19146102715780634e71e0c81461028457600080fd5b8063028468581461017857806306fdde031461018d578063078dfbe7146101ca578063095ea7b3146101dd57806318160ddd1461020057806323b872dd14610217575b600080fd5b61018b6101863660046113ae565b6103d3565b005b6101b460405180604001604052806008815260200167155dd54813195b9960c21b81525081565b6040516101c191906113f9565b60405180910390f35b61018b6101d836600461143c565b610456565b6101f06101eb36600461147f565b610566565b60405190151581526020016101c1565b61020960055481565b6040519081526020016101c1565b6101f06102253660046114a9565b6105d3565b61018b6102383660046113ae565b6107df565b610245601281565b60405160ff90911681526020016101c1565b6102096a0d3c21bcecceda1000000081565b610209610855565b61018b61027f36600461147f565b610864565b61018b6108af565b61029461096d565b6040516101c191906114e5565b6102096102af3660046113ae565b60006020819052908152604090205481565b6102096102cf3660046113ae565b60026020526000908152604090205481565b610294610979565b6003546102fc906001600160a01b031681565b6040516001600160a01b0390911681526020016101c1565b6101b46040518060400160405280600381526020016255775560e81b81525081565b61018b6103443660046113ae565b610985565b61018b61035736600461147f565b6109fb565b6101f061036a36600461147f565b610a46565b61018b61037d366004611532565b610b8b565b6102096103903660046115a5565b600160209081526000928352604080842090915290825290205481565b6004546102fc906001600160a01b031681565b61018b6103ce3660046113ae565b610dde565b6003546001600160a01b031633146104065760405162461bcd60e51b81526004016103fd906115d8565b60405180910390fd5b610411600882610e54565b6104475760405162461bcd60e51b81526020600482015260076024820152662165786973747360c81b60448201526064016103fd565b610452600882610e79565b5050565b6003546001600160a01b031633146104805760405162461bcd60e51b81526004016103fd906115d8565b8115610544576001600160a01b03831615158061049a5750805b6104de5760405162461bcd60e51b81526020600482015260156024820152744f776e61626c653a207a65726f206164647265737360581b60448201526064016103fd565b6003546040516001600160a01b038086169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0385166001600160a01b031991821617909155600480549091169055505050565b600480546001600160a01b0385166001600160a01b0319909116179055505050565b3360008181526001602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906105c19086815260200190565b60405180910390a35060015b92915050565b6000811561079a576001600160a01b0384166000908152602081905260409020548281101561063d5760405162461bcd60e51b815260206004820152601660248201527545524332303a2062616c616e636520746f6f206c6f7760501b60448201526064016103fd565b836001600160a01b0316856001600160a01b031614610798576001600160a01b0385166000908152600160209081526040808320338452909152902054600019811461070257838110156106d35760405162461bcd60e51b815260206004820152601860248201527f45524332303a20616c6c6f77616e636520746f6f206c6f77000000000000000060448201526064016103fd565b6106dd8482611623565b6001600160a01b03871660009081526001602090815260408083203384529091529020555b6001600160a01b0385166107515760405162461bcd60e51b815260206004820152601660248201527545524332303a206e6f207a65726f206164647265737360501b60448201526064016103fd565b61075b8483611623565b6001600160a01b03808816600090815260208190526040808220939093559087168152908120805486929061079190849061163a565b9091555050505b505b826001600160a01b0316846001600160a01b03166000805160206116bf833981519152846040516107cd91815260200190565b60405180910390a35060019392505050565b6003546001600160a01b031633146108095760405162461bcd60e51b81526004016103fd906115d8565b610814600682610e54565b61084a5760405162461bcd60e51b81526020600482015260076024820152662165786973747360c81b60448201526064016103fd565b610452600682610e79565b600061085f610e8e565b905090565b61086f600633610e54565b6108a55760405162461bcd60e51b815260206004820152600760248201526610b6b4b73a32b960c91b60448201526064016103fd565b6104528282610eee565b6004546001600160a01b031633811461090a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e657260448201526064016103fd565b6003546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b039092166001600160a01b0319928316179055600480549091169055565b606061085f6006611016565b606061085f6008611016565b6003546001600160a01b031633146109af5760405162461bcd60e51b81526004016103fd906115d8565b6109ba600682610e54565b156109f05760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b60448201526064016103fd565b610452600682611023565b610a06600833610e54565b610a3c5760405162461bcd60e51b815260206004820152600760248201526610b13ab93732b960c91b60448201526064016103fd565b6104528282611038565b600081151580610a5e5750336001600160a01b038416145b15610b60573360009081526020819052604090205482811015610abc5760405162461bcd60e51b815260206004820152601660248201527545524332303a2062616c616e636520746f6f206c6f7760501b60448201526064016103fd565b336001600160a01b03851614610b5e576001600160a01b038416610b1b5760405162461bcd60e51b815260206004820152601660248201527545524332303a206e6f207a65726f206164647265737360501b60448201526064016103fd565b610b258382611623565b33600090815260208190526040808220929092556001600160a01b03861681529081208054859290610b5890849061163a565b90915550505b505b6040518281526001600160a01b0384169033906000805160206116bf833981519152906020016105c1565b6001600160a01b038716610be15760405162461bcd60e51b815260206004820152601860248201527f45524332303a204f776e65722063616e6e6f742062652030000000000000000060448201526064016103fd565b834210610c215760405162461bcd60e51b815260206004820152600e60248201526d115490cc8c0e88115e1c1a5c995960921b60448201526064016103fd565b6001600160a01b03871660008181526002602052604081208054600192610ccb927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928d928d928d9291610c7483611652565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810188905260e00160405160208183030381529060405280519060200120611100565b6040805160008152602081018083529290925260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610d19573d6000803e3d6000fd5b505050602060405103516001600160a01b031614610d795760405162461bcd60e51b815260206004820152601860248201527f45524332303a20496e76616c6964205369676e6174757265000000000000000060448201526064016103fd565b6001600160a01b038781166000818152600160209081526040808320948b168084529482529182902089905590518881527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6003546001600160a01b03163314610e085760405162461bcd60e51b81526004016103fd906115d8565b610e13600882610e54565b15610e495760405162461bcd60e51b815260206004820152600660248201526565786973747360d01b60448201526064016103fd565b610452600882611023565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6000610e72836001600160a01b038416611155565b6000467f00000000000000000000000000000000000000000000000000000000000000018114610ec657610ec181611248565b610ee8565b7f61c067aca3facbfcec2b9ba619c0bbc88261b073a95ee061f0368f5814382aee5b91505090565b6001600160a01b038216610f445760405162461bcd60e51b815260206004820152601c60248201527f5577553a206e6f206d696e7420746f207a65726f20616464726573730000000060448201526064016103fd565b600554610f519082611289565b6a0d3c21bcecceda100000001015610fa45760405162461bcd60e51b81526020600482015260166024820152750aaeeaa744088dedc4ee840cede40deeccae4409a82b60531b60448201526064016103fd565b80600554610fb2919061163a565b6005556001600160a01b03821660009081526020819052604081208054839290610fdd90849061163a565b90915550506040518181526001600160a01b038316906000906000805160206116bf833981519152906020015b60405180910390a35050565b60606000610e72836112e7565b6000610e72836001600160a01b038416611343565b6001600160a01b0382166000908152602081905260409020548111156110905760405162461bcd60e51b815260206004820152600d60248201526c084eae4dc40e8dede40daeac6d609b1b60448201526064016103fd565b80600560008282546110a29190611623565b90915550506001600160a01b038216600090815260208190526040812080548392906110cf908490611623565b90915550506040518181526000906001600160a01b038416906000805160206116bf8339815191529060200161100a565b600060405180604001604052806002815260200161190160f01b815250611125610e8e565b836040516020016111389392919061166b565b604051602081830303815290604052805190602001209050919050565b6000818152600183016020526040812054801561123e576000611179600183611623565b855490915060009061118d90600190611623565b90508181146111f25760008660000182815481106111ad576111ad611692565b90600052602060002001549050808760000184815481106111d0576111d0611692565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611203576112036116a8565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105cd565b60009150506105cd565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152908101829052306060820152600090608001611138565b600081611296818561163a565b91508110156105cd5760405162461bcd60e51b815260206004820152601860248201527f426f72696e674d6174683a20416464204f766572666c6f77000000000000000060448201526064016103fd565b60608160000180548060200260200160405190810160405280929190818152602001828054801561133757602002820191906000526020600020905b815481526020019060010190808311611323575b50505050509050919050565b600081815260018301602052604081205461138a575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105cd565b5060006105cd565b80356001600160a01b03811681146113a957600080fd5b919050565b6000602082840312156113c057600080fd5b610e7282611392565b60005b838110156113e45781810151838201526020016113cc565b838111156113f3576000848401525b50505050565b60208152600082518060208401526114188160408501602087016113c9565b601f01601f19169190910160400192915050565b803580151581146113a957600080fd5b60008060006060848603121561145157600080fd5b61145a84611392565b92506114686020850161142c565b91506114766040850161142c565b90509250925092565b6000806040838503121561149257600080fd5b61149b83611392565b946020939093013593505050565b6000806000606084860312156114be57600080fd5b6114c784611392565b92506114d560208501611392565b9150604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b818110156115265783516001600160a01b031683529284019291840191600101611501565b50909695505050505050565b600080600080600080600060e0888a03121561154d57600080fd5b61155688611392565b965061156460208901611392565b95506040880135945060608801359350608088013560ff8116811461158857600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156115b857600080fd5b6115c183611392565b91506115cf60208401611392565b90509250929050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6000828210156116355761163561160d565b500390565b6000821982111561164d5761164d61160d565b500190565b6000600182016116645761166461160d565b5060010190565b6000845161167d8184602089016113c9565b91909101928352506020820152604001919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212207c013370caf2dad11b6a87ead4e6ebf970b92dee827e6d0a064bce626836b27b64736f6c634300080f0033

Verified Source Code Partial Match

Compiler: v0.8.15+commit.e14f2714 EVM: london Optimization: Yes (200 runs)
UwU.sol 666 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract BoringOwnableData {
    address public owner;
    address public pendingOwner;
}

contract BoringOwnable is BoringOwnableData {
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /// @notice `owner` defaults to msg.sender on construction.
    constructor() {
        owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
    }

    /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.
    /// Can only be invoked by the current `owner`.
    /// @param newOwner Address of the new owner.
    /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.
    /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.
    function transferOwnership(
        address newOwner,
        bool direct,
        bool renounce
    ) public onlyOwner {
        if (direct) {
            // Checks
            require(newOwner != address(0) || renounce, "Ownable: zero address");

            // Effects
            emit OwnershipTransferred(owner, newOwner);
            owner = newOwner;
            pendingOwner = address(0);
        } else {
            // Effects
            pendingOwner = newOwner;
        }
    }

    /// @notice Needs to be called by `pendingOwner` to claim ownership.
    function claimOwnership() public {
        address _pendingOwner = pendingOwner;

        // Checks
        require(msg.sender == _pendingOwner, "Ownable: caller != pending owner");

        // Effects
        emit OwnershipTransferred(owner, _pendingOwner);
        owner = _pendingOwner;
        pendingOwner = address(0);
    }

    /// @notice Only allows the `owner` to execute the function.
    modifier onlyOwner() {
        require(msg.sender == owner, "Ownable: caller is not the owner");
        _;
    }
}

contract Domain {
    bytes32 private constant DOMAIN_SEPARATOR_SIGNATURE_HASH = keccak256("EIP712Domain(uint256 chainId,address verifyingContract)");
    // See https://eips.ethereum.org/EIPS/eip-191
    string private constant EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA = "\x19\x01";

    // solhint-disable var-name-mixedcase
    bytes32 private immutable _DOMAIN_SEPARATOR;
    uint256 private immutable DOMAIN_SEPARATOR_CHAIN_ID;

    /// @dev Calculate the DOMAIN_SEPARATOR
    function _calculateDomainSeparator(uint256 chainId) private view returns (bytes32) {
        return keccak256(
            abi.encode(
                DOMAIN_SEPARATOR_SIGNATURE_HASH,
                chainId,
                address(this)
            )
        );
    }

    constructor() {
        uint256 chainId; assembly {chainId := chainid()}
        _DOMAIN_SEPARATOR = _calculateDomainSeparator(DOMAIN_SEPARATOR_CHAIN_ID = chainId);
    }

    /// @dev Return the DOMAIN_SEPARATOR
    // It's named internal to allow making it public from the contract that uses it by creating a simple view function
    // with the desired public name, such as DOMAIN_SEPARATOR or domainSeparator.
    // solhint-disable-next-line func-name-mixedcase
    function _domainSeparator() internal view returns (bytes32) {
        uint256 chainId; assembly {chainId := chainid()}
        return chainId == DOMAIN_SEPARATOR_CHAIN_ID ? _DOMAIN_SEPARATOR : _calculateDomainSeparator(chainId);
    }

    function _getDigest(bytes32 dataHash) internal view returns (bytes32 digest) {
        digest =
            keccak256(
                abi.encodePacked(
                    EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA,
                    _domainSeparator(),
                    dataHash
                )
            );
    }
}

interface IERC20 {
    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;
}

// Data part taken out for building of contracts that receive delegate calls
contract ERC20Data {
    /// @notice owner > balance mapping.
    mapping(address => uint256) public balanceOf;
    /// @notice owner > spender > allowance mapping.
    mapping(address => mapping(address => uint256)) public allowance;
    /// @notice owner > nonce mapping. Used in `permit`.
    mapping(address => uint256) public nonces;
}

abstract contract ERC20 is IERC20, Domain {
    /// @notice owner > balance mapping.
    mapping(address => uint256) public override balanceOf;
    /// @notice owner > spender > allowance mapping.
    mapping(address => mapping(address => uint256)) public override allowance;
    /// @notice owner > nonce mapping. Used in `permit`.
    mapping(address => uint256) public nonces;

    /// @notice Transfers `amount` tokens from `msg.sender` to `to`.
    /// @param to The address to move the tokens.
    /// @param amount of the tokens to move.
    /// @return (bool) Returns True if succeeded.
    function transfer(address to, uint256 amount) public returns (bool) {
        // If `amount` is 0, or `msg.sender` is `to` nothing happens
        if (amount != 0 || msg.sender == to) {
            uint256 srcBalance = balanceOf[msg.sender];
            require(srcBalance >= amount, "ERC20: balance too low");
            if (msg.sender != to) {
                require(to != address(0), "ERC20: no zero address"); // Moved down so low balance calls safe some gas

                balanceOf[msg.sender] = srcBalance - amount; // Underflow is checked
                balanceOf[to] += amount;
            }
        }
        emit Transfer(msg.sender, to, amount);
        return true;
    }

    /// @notice Transfers `amount` tokens from `from` to `to`. Caller needs approval for `from`.
    /// @param from Address to draw tokens from.
    /// @param to The address to move the tokens.
    /// @param amount The token amount to move.
    /// @return (bool) Returns True if succeeded.
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public returns (bool) {
        // If `amount` is 0, or `from` is `to` nothing happens
        if (amount != 0) {
            uint256 srcBalance = balanceOf[from];
            require(srcBalance >= amount, "ERC20: balance too low");

            if (from != to) {
                uint256 spenderAllowance = allowance[from][msg.sender];
                // If allowance is infinite, don't decrease it to save on gas (breaks with EIP-20).
                if (spenderAllowance != type(uint256).max) {
                    require(spenderAllowance >= amount, "ERC20: allowance too low");
                    allowance[from][msg.sender] = spenderAllowance - amount; // Underflow is checked
                }
                require(to != address(0), "ERC20: no zero address"); // Moved down so other failed calls safe some gas

                balanceOf[from] = srcBalance - amount; // Underflow is checked
                balanceOf[to] += amount;
            }
        }
        emit Transfer(from, to, amount);
        return true;
    }

    /// @notice Approves `amount` from sender to be spend by `spender`.
    /// @param spender Address of the party that can draw from msg.sender's account.
    /// @param amount The maximum collective amount that `spender` can draw.
    /// @return (bool) Returns True if approved.
    function approve(address spender, uint256 amount) public override returns (bool) {
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32) {
        return _domainSeparator();
    }

    // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    bytes32 private constant PERMIT_SIGNATURE_HASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;

    /// @notice Approves `value` from `owner_` to be spend by `spender`.
    /// @param owner_ Address of the owner.
    /// @param spender The address of the spender that gets approved to draw from `owner_`.
    /// @param value The maximum collective amount that `spender` can draw.
    /// @param deadline This permit must be redeemed before this deadline (UTC timestamp in seconds).
    function permit(
        address owner_,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external override {
        require(owner_ != address(0), "ERC20: Owner cannot be 0");
        require(block.timestamp < deadline, "ERC20: Expired");
        require(
            ecrecover(_getDigest(keccak256(abi.encode(PERMIT_SIGNATURE_HASH, owner_, spender, value, nonces[owner_]++, deadline))), v, r, s) ==
                owner_,
            "ERC20: Invalid Signature"
        );
        allowance[owner_][spender] = value;
        emit Approval(owner_, spender, value);
    }
}

library BoringMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
        require((c = a + b) >= b, "BoringMath: Add Overflow");
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {
        require((c = a - b) <= a, "BoringMath: Underflow");
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
        require(b == 0 || (c = a * b) / b == a, "BoringMath: Mul Overflow");
    }
}

library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastValue;
                // Update the index for the moved value
                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        return _values(set._inner);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

/// @title UwU
/// @author 0xForklend
contract UwU is ERC20, BoringOwnable {
    using BoringMath for uint256;
    using EnumerableSet for EnumerableSet.AddressSet;

    string public constant symbol = "UwU";
    string public constant name = "UwU Lend";
    uint8 public constant decimals = 18;
    uint256 public override totalSupply;
    uint256 public constant MAX_SUPPLY = 16 * 1e24;
    EnumerableSet.AddressSet private minters;
    EnumerableSet.AddressSet private burners;

    function mint(address to, uint256 amount) public isMinter {
      _mint(to, amount);
    }

    function burn(address to, uint256 amount) public isBurner {
      _burn(to, amount);
    }

    function _mint(address to, uint256 amount) internal {
      require(to != address(0), "UwU: no mint to zero address");
      require(MAX_SUPPLY >= totalSupply.add(amount), "UwU: Don't go over MAX");
      totalSupply = totalSupply + amount;
      balanceOf[to] += amount;
      emit Transfer(address(0), to, amount);
    }

    function _burn(address to, uint256 amount) internal {
      require(balanceOf[to] >= amount, "Burn too much");
      totalSupply -= amount;
      balanceOf[to] -= amount;
      emit Transfer(to, address(0), amount);
    }

    function addMinter(address who) public onlyOwner {
      require(!minters.contains(who), 'exists');
      minters.add(who);
    }

    function removeMinter(address who) public onlyOwner {
      require(minters.contains(who), '!exists');
      minters.remove(who);
    }

    function getMinters() public view returns(address[] memory) {
      return minters.values();
    }

    function addBurner(address who) public onlyOwner {
      require(!burners.contains(who), 'exists');
      burners.add(who);
    }

    function removeBurner(address who) public onlyOwner {
      require(burners.contains(who), '!exists');
      burners.remove(who);
    }

    function getBurners() public view returns(address[] memory) {
      return burners.values();
    }

    modifier isMinter() {
      require(minters.contains(msg.sender), '!minter');
      _;
    }

    modifier isBurner() {
      require(burners.contains(msg.sender), '!burner');
      _;
    }
}

Read Contract

DOMAIN_SEPARATOR 0x3644e515 → bytes32
MAX_SUPPLY 0x32cb6b0c → uint256
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
decimals 0x313ce567 → uint8
getBurners 0x86fe8b43 → address[]
getMinters 0x6b32810b → address[]
name 0x06fdde03 → string
nonces 0x7ecebe00 → uint256
owner 0x8da5cb5b → address
pendingOwner 0xe30c3978 → address
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256

Write Contract 12 functions

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

addBurner 0xf44637ba
address who
addMinter 0x983b2d56
address who
approve 0x095ea7b3
address spender
uint256 amount
returns: bool
burn 0x9dc29fac
address to
uint256 amount
claimOwnership 0x4e71e0c8
No parameters
mint 0x40c10f19
address to
uint256 amount
permit 0xd505accf
address owner_
address spender
uint256 value
uint256 deadline
uint8 v
bytes32 r
bytes32 s
removeBurner 0x02846858
address who
removeMinter 0x3092afd5
address who
transfer 0xa9059cbb
address to
uint256 amount
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 amount
returns: bool
transferOwnership 0x078dfbe7
address newOwner
bool direct
bool renounce

Recent Transactions

No transactions found for this address