ETH Price: $1,854.80 (-13.49%)
 

Overview

Max Total Supply

8,000,000,000 KPOP

Holders

920 ( -0.435%)

Transfers

-
7 ( 16.67%)

Market

Price

$0.00 @ 0.000000 ETH (-13.42%)

Onchain Market Cap

-

Circulating Supply Market Cap

$525,687.60

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

$KPOP is the first token to unify the explosiveness of K-POP, the mechanics of meme culture, and the momentum of fandom.

Market

Volume (24H):$147,238.41
Market Capitalization:$525,687.60
Circulating Supply:6,484,200,010.00 KPOP
Market Data Source: Coinmarketcap

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
KPop

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {ERC20Votes} from "solady/src/tokens/ERC20Votes.sol";

/**
 * @title Kpop Token Contract
 *
 * @author Niftydude
 *
 * @notice This contract implements the ERC20 KPop token.
 */
contract KPop is ERC20Votes {
    string private symbol_;
    string private name_;

    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Initializes contract by minting the specified amount of tokens to the specified address.
     *
     * @param _totalSupply amount of tokens to mint in wei
     * @param _mintTo address to mint tokens to
     * @param _name name of the token
     * @param _symbol symbol of the token
     */
    constructor(
        uint256 _totalSupply,
        address _mintTo,
        string memory _name,
        string memory _symbol
    ) {
        symbol_ = _symbol;
        name_ = _name;

        _mint(_mintTo, _totalSupply);
    }

    /**
     * @notice Burns the specified amount of tokens from the caller's account.
     *
     * @param _amount The amount of tokens to burn.
     */
    function burn(uint256 _amount) external {
        _burn(msg.sender, _amount);
    }

    /**
     * @notice Burns the specified amount of tokens from the specified account.
     *
     * @param _account The address of the account to burn tokens from.
     * @param _amount The amount of tokens to burn.
     */
    function burnFrom(address _account, uint256 _amount) public virtual {
        _spendAllowance(_account, msg.sender, _amount);
        _burn(_account, _amount);
    }

    /**
     * @notice Override the transfer function to prevent transferring to the zero address.
     *
     * @param _to The address of the account to transfer tokens to.
     * @param _amount The amount of tokens to transfer.
     */
    function transfer(
        address _to,
        uint256 _amount
    ) public override returns (bool) {
        if (_to == address(0)) revert ERC20InvalidReceiver(address(0));

        return super.transfer(_to, _amount);
    }

    /**
     * @notice Override the transferFrom function to prevent transferring to the zero address.
     *
     * @param _from The address of the account to transfer tokens from.
     * @param _to The address of the account to transfer tokens to.
     * @param _amount The amount of tokens to transfer.
     */
    function transferFrom(
        address _from,
        address _to,
        uint256 _amount
    ) public override returns (bool) {
        if (_to == address(0)) revert ERC20InvalidReceiver(address(0));

        return super.transferFrom(_from, _to, _amount);
    }

    /**
     * @notice Returns the name of the token.
     */
    function name() public view override returns (string memory) {
        return name_;
    }

    /**
     * @notice Returns the symbol of the token.
     */
    function symbol() public view override returns (string memory) {
        return symbol_;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple ERC20 + EIP-2612 implementation.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)
///
/// @dev Note:
/// - The ERC20 standard allows minting and transferring to and from the zero address,
///   minting and transferring zero tokens, as well as self-approvals.
///   For performance, this implementation WILL NOT revert for such actions.
///   Please add any checks with overrides if desired.
/// - The `permit` function uses the ecrecover precompile (0x1).
///
/// If you are overriding:
/// - NEVER violate the ERC20 invariant:
///   the total sum of all balances must be equal to `totalSupply()`.
/// - Check that the overridden function is actually used in the function you want to
///   change the behavior of. Much of the code has been manually inlined for performance.
abstract contract ERC20 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The total supply has overflowed.
    error TotalSupplyOverflow();

    /// @dev The allowance has overflowed.
    error AllowanceOverflow();

    /// @dev The allowance has underflowed.
    error AllowanceUnderflow();

    /// @dev Insufficient balance.
    error InsufficientBalance();

    /// @dev Insufficient allowance.
    error InsufficientAllowance();

    /// @dev The permit is invalid.
    error InvalidPermit();

    /// @dev The permit has expired.
    error PermitExpired();

    /// @dev The allowance of Permit2 is fixed at infinity.
    error Permit2AllowanceIsFixedAtInfinity();

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

    /// @dev Emitted when `amount` tokens is transferred from `from` to `to`.
    event Transfer(address indexed from, address indexed to, uint256 amount);

    /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`.
    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`.
    uint256 private constant _TRANSFER_EVENT_SIGNATURE =
        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;

    /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`.
    uint256 private constant _APPROVAL_EVENT_SIGNATURE =
        0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;

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

    /// @dev The storage slot for the total supply.
    uint256 private constant _TOTAL_SUPPLY_SLOT = 0x05345cdf77eb68f44c;

    /// @dev The balance slot of `owner` is given by:
    /// ```
    ///     mstore(0x0c, _BALANCE_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let balanceSlot := keccak256(0x0c, 0x20)
    /// ```
    uint256 private constant _BALANCE_SLOT_SEED = 0x87a211a2;

    /// @dev The allowance slot of (`owner`, `spender`) is given by:
    /// ```
    ///     mstore(0x20, spender)
    ///     mstore(0x0c, _ALLOWANCE_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let allowanceSlot := keccak256(0x0c, 0x34)
    /// ```
    uint256 private constant _ALLOWANCE_SLOT_SEED = 0x7f5e9f20;

    /// @dev The nonce slot of `owner` is given by:
    /// ```
    ///     mstore(0x0c, _NONCES_SLOT_SEED)
    ///     mstore(0x00, owner)
    ///     let nonceSlot := keccak256(0x0c, 0x20)
    /// ```
    uint256 private constant _NONCES_SLOT_SEED = 0x38377508;

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

    /// @dev `(_NONCES_SLOT_SEED << 16) | 0x1901`.
    uint256 private constant _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX = 0x383775081901;

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 private constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    /// @dev `keccak256("1")`.
    /// If you need to use a different version, override `_versionHash`.
    bytes32 private constant _DEFAULT_VERSION_HASH =
        0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;

    /// @dev `keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")`.
    bytes32 private constant _PERMIT_TYPEHASH =
        0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;

    /// @dev The canonical Permit2 address.
    /// For signature-based allowance granting for single transaction ERC20 `transferFrom`.
    /// Enabled by default. To disable, override `_givePermit2InfiniteAllowance()`.
    /// [Github](https://github.com/Uniswap/permit2)
    /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)
    address internal constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;

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

    /// @dev Returns the name of the token.
    function name() public view virtual returns (string memory);

    /// @dev Returns the symbol of the token.
    function symbol() public view virtual returns (string memory);

    /// @dev Returns the decimals places of the token.
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

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

    /// @dev Returns the amount of tokens in existence.
    function totalSupply() public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_TOTAL_SUPPLY_SLOT)
        }
    }

    /// @dev Returns the amount of tokens owned by `owner`.
    function balanceOf(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`.
    function allowance(address owner, address spender)
        public
        view
        virtual
        returns (uint256 result)
    {
        if (_givePermit2InfiniteAllowance()) {
            if (spender == _PERMIT2) return type(uint256).max;
        }
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x34))
        }
    }

    /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
    ///
    /// Emits a {Approval} event.
    function approve(address spender, uint256 amount) public virtual returns (bool) {
        if (_givePermit2InfiniteAllowance()) {
            /// @solidity memory-safe-assembly
            assembly {
                // If `spender == _PERMIT2 && amount != type(uint256).max`.
                if iszero(or(xor(shr(96, shl(96, spender)), _PERMIT2), iszero(not(amount)))) {
                    mstore(0x00, 0x3f68539a) // `Permit2AllowanceIsFixedAtInfinity()`.
                    revert(0x1c, 0x04)
                }
            }
        }
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the allowance slot and store the amount.
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x34), amount)
            // Emit the {Approval} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c)))
        }
        return true;
    }

    /// @dev Transfer `amount` tokens from the caller to `to`.
    ///
    /// Requirements:
    /// - `from` must at least have `amount`.
    ///
    /// Emits a {Transfer} event.
    function transfer(address to, uint256 amount) public virtual returns (bool) {
        _beforeTokenTransfer(msg.sender, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, caller())
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, caller(), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(msg.sender, to, amount);
        return true;
    }

    /// @dev Transfers `amount` tokens from `from` to `to`.
    ///
    /// Note: Does not update the allowance if it is the maximum uint256 value.
    ///
    /// Requirements:
    /// - `from` must at least have `amount`.
    /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`.
    ///
    /// Emits a {Transfer} event.
    function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {
        _beforeTokenTransfer(from, to, amount);
        // Code duplication is for zero-cost abstraction if possible.
        if (_givePermit2InfiniteAllowance()) {
            /// @solidity memory-safe-assembly
            assembly {
                let from_ := shl(96, from)
                if iszero(eq(caller(), _PERMIT2)) {
                    // Compute the allowance slot and load its value.
                    mstore(0x20, caller())
                    mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED))
                    let allowanceSlot := keccak256(0x0c, 0x34)
                    let allowance_ := sload(allowanceSlot)
                    // If the allowance is not the maximum uint256 value.
                    if not(allowance_) {
                        // Revert if the amount to be transferred exceeds the allowance.
                        if gt(amount, allowance_) {
                            mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.
                            revert(0x1c, 0x04)
                        }
                        // Subtract and store the updated allowance.
                        sstore(allowanceSlot, sub(allowance_, amount))
                    }
                }
                // Compute the balance slot and load its value.
                mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))
                let fromBalanceSlot := keccak256(0x0c, 0x20)
                let fromBalance := sload(fromBalanceSlot)
                // Revert if insufficient balance.
                if gt(amount, fromBalance) {
                    mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                    revert(0x1c, 0x04)
                }
                // Subtract and store the updated balance.
                sstore(fromBalanceSlot, sub(fromBalance, amount))
                // Compute the balance slot of `to`.
                mstore(0x00, to)
                let toBalanceSlot := keccak256(0x0c, 0x20)
                // Add and store the updated balance of `to`.
                // Will not overflow because the sum of all user balances
                // cannot exceed the maximum uint256 value.
                sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
                // Emit the {Transfer} event.
                mstore(0x20, amount)
                log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                let from_ := shl(96, from)
                // Compute the allowance slot and load its value.
                mstore(0x20, caller())
                mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED))
                let allowanceSlot := keccak256(0x0c, 0x34)
                let allowance_ := sload(allowanceSlot)
                // If the allowance is not the maximum uint256 value.
                if not(allowance_) {
                    // Revert if the amount to be transferred exceeds the allowance.
                    if gt(amount, allowance_) {
                        mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.
                        revert(0x1c, 0x04)
                    }
                    // Subtract and store the updated allowance.
                    sstore(allowanceSlot, sub(allowance_, amount))
                }
                // Compute the balance slot and load its value.
                mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))
                let fromBalanceSlot := keccak256(0x0c, 0x20)
                let fromBalance := sload(fromBalanceSlot)
                // Revert if insufficient balance.
                if gt(amount, fromBalance) {
                    mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                    revert(0x1c, 0x04)
                }
                // Subtract and store the updated balance.
                sstore(fromBalanceSlot, sub(fromBalance, amount))
                // Compute the balance slot of `to`.
                mstore(0x00, to)
                let toBalanceSlot := keccak256(0x0c, 0x20)
                // Add and store the updated balance of `to`.
                // Will not overflow because the sum of all user balances
                // cannot exceed the maximum uint256 value.
                sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
                // Emit the {Transfer} event.
                mstore(0x20, amount)
                log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))
            }
        }
        _afterTokenTransfer(from, to, amount);
        return true;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          EIP-2612                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev For more performance, override to return the constant value
    /// of `keccak256(bytes(name()))` if `name()` will never change.
    function _constantNameHash() internal view virtual returns (bytes32 result) {}

    /// @dev If you need a different value, override this function.
    function _versionHash() internal view virtual returns (bytes32 result) {
        result = _DEFAULT_VERSION_HASH;
    }

    /// @dev For inheriting contracts to increment the nonce.
    function _incrementNonce(address owner) internal virtual {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x0c, _NONCES_SLOT_SEED)
            mstore(0x00, owner)
            let nonceSlot := keccak256(0x0c, 0x20)
            sstore(nonceSlot, add(1, sload(nonceSlot)))
        }
    }

    /// @dev Returns the current nonce for `owner`.
    /// This value is used to compute the signature for EIP-2612 permit.
    function nonces(address owner) public view virtual returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the nonce slot and load its value.
            mstore(0x0c, _NONCES_SLOT_SEED)
            mstore(0x00, owner)
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`,
    /// authorized by a signed approval by `owner`.
    ///
    /// Emits a {Approval} event.
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        if (_givePermit2InfiniteAllowance()) {
            /// @solidity memory-safe-assembly
            assembly {
                // If `spender == _PERMIT2 && value != type(uint256).max`.
                if iszero(or(xor(shr(96, shl(96, spender)), _PERMIT2), iszero(not(value)))) {
                    mstore(0x00, 0x3f68539a) // `Permit2AllowanceIsFixedAtInfinity()`.
                    revert(0x1c, 0x04)
                }
            }
        }
        bytes32 nameHash = _constantNameHash();
        //  We simply calculate it on-the-fly to allow for cases where the `name` may change.
        if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));
        bytes32 versionHash = _versionHash();
        /// @solidity memory-safe-assembly
        assembly {
            // Revert if the block timestamp is greater than `deadline`.
            if gt(timestamp(), deadline) {
                mstore(0x00, 0x1a15a3cc) // `PermitExpired()`.
                revert(0x1c, 0x04)
            }
            let m := mload(0x40) // Grab the free memory pointer.
            // Clean the upper 96 bits.
            owner := shr(96, shl(96, owner))
            spender := shr(96, shl(96, spender))
            // Compute the nonce slot and load its value.
            mstore(0x0e, _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX)
            mstore(0x00, owner)
            let nonceSlot := keccak256(0x0c, 0x20)
            let nonceValue := sload(nonceSlot)
            // Prepare the domain separator.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            mstore(0x2e, keccak256(m, 0xa0))
            // Prepare the struct hash.
            mstore(m, _PERMIT_TYPEHASH)
            mstore(add(m, 0x20), owner)
            mstore(add(m, 0x40), spender)
            mstore(add(m, 0x60), value)
            mstore(add(m, 0x80), nonceValue)
            mstore(add(m, 0xa0), deadline)
            mstore(0x4e, keccak256(m, 0xc0))
            // Prepare the ecrecover calldata.
            mstore(0x00, keccak256(0x2c, 0x42))
            mstore(0x20, and(0xff, v))
            mstore(0x40, r)
            mstore(0x60, s)
            let t := staticcall(gas(), 1, 0x00, 0x80, 0x20, 0x20)
            // If the ecrecover fails, the returndatasize will be 0x00,
            // `owner` will be checked if it equals the hash at 0x00,
            // which evaluates to false (i.e. 0), and we will revert.
            // If the ecrecover succeeds, the returndatasize will be 0x20,
            // `owner` will be compared against the returned address at 0x20.
            if iszero(eq(mload(returndatasize()), owner)) {
                mstore(0x00, 0xddafbaef) // `InvalidPermit()`.
                revert(0x1c, 0x04)
            }
            // Increment and store the updated nonce.
            sstore(nonceSlot, add(nonceValue, t)) // `t` is 1 if ecrecover succeeds.
            // Compute the allowance slot and store the value.
            // The `owner` is already at slot 0x20.
            mstore(0x40, or(shl(160, _ALLOWANCE_SLOT_SEED), spender))
            sstore(keccak256(0x2c, 0x34), value)
            // Emit the {Approval} event.
            log3(add(m, 0x60), 0x20, _APPROVAL_EVENT_SIGNATURE, owner, spender)
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero pointer.
        }
    }

    /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit.
    function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) {
        bytes32 nameHash = _constantNameHash();
        //  We simply calculate it on-the-fly to allow for cases where the `name` may change.
        if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));
        bytes32 versionHash = _versionHash();
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Grab the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            result := keccak256(m, 0xa0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL MINT FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Mints `amount` tokens to `to`, increasing the total supply.
    ///
    /// Emits a {Transfer} event.
    function _mint(address to, uint256 amount) internal virtual {
        _beforeTokenTransfer(address(0), to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let totalSupplyBefore := sload(_TOTAL_SUPPLY_SLOT)
            let totalSupplyAfter := add(totalSupplyBefore, amount)
            // Revert if the total supply overflows.
            if lt(totalSupplyAfter, totalSupplyBefore) {
                mstore(0x00, 0xe5cfe957) // `TotalSupplyOverflow()`.
                revert(0x1c, 0x04)
            }
            // Store the updated total supply.
            sstore(_TOTAL_SUPPLY_SLOT, totalSupplyAfter)
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, 0, shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(address(0), to, amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  INTERNAL BURN FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Burns `amount` tokens from `from`, reducing the total supply.
    ///
    /// Emits a {Transfer} event.
    function _burn(address from, uint256 amount) internal virtual {
        _beforeTokenTransfer(from, address(0), amount);
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the balance slot and load its value.
            mstore(0x0c, _BALANCE_SLOT_SEED)
            mstore(0x00, from)
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Subtract and store the updated total supply.
            sstore(_TOTAL_SUPPLY_SLOT, sub(sload(_TOTAL_SUPPLY_SLOT), amount))
            // Emit the {Transfer} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, shl(96, from)), 0)
        }
        _afterTokenTransfer(from, address(0), amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL TRANSFER FUNCTIONS                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Moves `amount` of tokens from `from` to `to`.
    function _transfer(address from, address to, uint256 amount) internal virtual {
        _beforeTokenTransfer(from, to, amount);
        /// @solidity memory-safe-assembly
        assembly {
            let from_ := shl(96, from)
            // Compute the balance slot and load its value.
            mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))
            let fromBalanceSlot := keccak256(0x0c, 0x20)
            let fromBalance := sload(fromBalanceSlot)
            // Revert if insufficient balance.
            if gt(amount, fromBalance) {
                mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.
                revert(0x1c, 0x04)
            }
            // Subtract and store the updated balance.
            sstore(fromBalanceSlot, sub(fromBalance, amount))
            // Compute the balance slot of `to`.
            mstore(0x00, to)
            let toBalanceSlot := keccak256(0x0c, 0x20)
            // Add and store the updated balance of `to`.
            // Will not overflow because the sum of all user balances
            // cannot exceed the maximum uint256 value.
            sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))
            // Emit the {Transfer} event.
            mstore(0x20, amount)
            log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))
        }
        _afterTokenTransfer(from, to, amount);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                INTERNAL ALLOWANCE FUNCTIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Updates the allowance of `owner` for `spender` based on spent `amount`.
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        if (_givePermit2InfiniteAllowance()) {
            if (spender == _PERMIT2) return; // Do nothing, as allowance is infinite.
        }
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the allowance slot and load its value.
            mstore(0x20, spender)
            mstore(0x0c, _ALLOWANCE_SLOT_SEED)
            mstore(0x00, owner)
            let allowanceSlot := keccak256(0x0c, 0x34)
            let allowance_ := sload(allowanceSlot)
            // If the allowance is not the maximum uint256 value.
            if not(allowance_) {
                // Revert if the amount to be transferred exceeds the allowance.
                if gt(amount, allowance_) {
                    mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.
                    revert(0x1c, 0x04)
                }
                // Subtract and store the updated allowance.
                sstore(allowanceSlot, sub(allowance_, amount))
            }
        }
    }

    /// @dev Sets `amount` as the allowance of `spender` over the tokens of `owner`.
    ///
    /// Emits a {Approval} event.
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        if (_givePermit2InfiniteAllowance()) {
            /// @solidity memory-safe-assembly
            assembly {
                // If `spender == _PERMIT2 && amount != type(uint256).max`.
                if iszero(or(xor(shr(96, shl(96, spender)), _PERMIT2), iszero(not(amount)))) {
                    mstore(0x00, 0x3f68539a) // `Permit2AllowanceIsFixedAtInfinity()`.
                    revert(0x1c, 0x04)
                }
            }
        }
        /// @solidity memory-safe-assembly
        assembly {
            let owner_ := shl(96, owner)
            // Compute the allowance slot and store the amount.
            mstore(0x20, spender)
            mstore(0x0c, or(owner_, _ALLOWANCE_SLOT_SEED))
            sstore(keccak256(0x0c, 0x34), amount)
            // Emit the {Approval} event.
            mstore(0x00, amount)
            log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, shr(96, owner_), shr(96, mload(0x2c)))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HOOKS TO OVERRIDE                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Hook that is called before any transfer of tokens.
    /// This includes minting and burning.
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}

    /// @dev Hook that is called after any transfer of tokens.
    /// This includes minting and burning.
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}

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

    /// @dev Returns whether to fix the Permit2 contract's allowance at infinity.
    ///
    /// This value should be kept constant after contract initialization,
    /// or else the actual allowance values may not match with the {Approval} events.
    /// For best performance, return a compile-time constant for zero-cost abstraction.
    function _givePermit2InfiniteAllowance() internal view virtual returns (bool) {
        return true;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import {ERC20} from "./ERC20.sol";

/// @notice ERC20 with votes based on ERC5805 and ERC6372.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20Votes.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Votes.sol)
abstract contract ERC20Votes is ERC20 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The timepoint is in the future.
    error ERC5805FutureLookup();

    /// @dev The ERC5805 signature to set a delegate has expired.
    error ERC5805DelegateSignatureExpired();

    /// @dev The ERC5805 signature to set a delegate is invalid.
    error ERC5805DelegateInvalidSignature();

    /// @dev Out-of-bounds access for the checkpoints.
    error ERC5805CheckpointIndexOutOfBounds();

    /// @dev Arithmetic overflow when pushing a new checkpoint.
    error ERC5805CheckpointValueOverflow();

    /// @dev Arithmetic underflow when pushing a new checkpoint.
    error ERC5805CheckpointValueUnderflow();

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

    /// @dev The delegate of `delegator` is changed from `from` to `to`.
    event DelegateChanged(address indexed delegator, address indexed from, address indexed to);

    /// @dev The votes balance of `delegate` is changed from `oldValue` to `newValue`.
    event DelegateVotesChanged(address indexed delegate, uint256 oldValue, uint256 newValue);

    /// @dev `keccak256(bytes("DelegateChanged(address,address,address)"))`.
    uint256 private constant _DELEGATE_CHANGED_EVENT_SIGNATURE =
        0x3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f;

    /// @dev `keccak256(bytes("DelegateVotesChanged(address,uint256,uint256)"))`.
    uint256 private constant _DELEGATE_VOTES_CHANGED_EVENT_SIGNATURE =
        0xdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724;

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

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 private constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    /// @dev `keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)")`.
    bytes32 private constant _ERC5805_DELEGATION_TYPEHASH =
        0xe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf;

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

    /// @dev The slot of a delegate is given by:
    /// ```
    ///     mstore(0x04, _ERC20_VOTES_MASTER_SLOT_SEED)
    ///     mstore(0x00, account)
    ///     let delegateSlot := keccak256(0x0c, 0x18)
    /// ```
    /// The checkpoints length slot of a delegate is given by:
    /// ```
    ///     mstore(0x04, _ERC20_VOTES_MASTER_SLOT_SEED)
    ///     mstore(0x00, delegate)
    ///     let lengthSlot := keccak256(0x0c, 0x17)
    ///     let length := and(0xffffffffffff, shr(48, sload(lengthSlot)))
    /// ```
    /// The total checkpoints length slot is `_ERC20_VOTES_MASTER_SLOT_SEED << 96`.
    ///
    /// The `i`-th checkpoint slot is given by:
    /// ```
    ///     let checkpointSlot := add(i, lengthSlot)
    ///     let key := and(sload(checkpointSlot), 0xffffffffffff)
    ///     let value := shr(96, sload(checkpointSlot))
    ///     if eq(value, address()) { value := sload(not(checkpointSlot)) }
    /// ```
    uint256 private constant _ERC20_VOTES_MASTER_SLOT_SEED = 0xff466c9f;

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

    /// @dev Returns the clock mode.
    function CLOCK_MODE() public view virtual returns (string memory) {
        return "mode=blocknumber&from=default";
    }

    /// @dev Returns the current clock.
    function clock() public view virtual returns (uint48 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := number()
            // Branch-less out-of-gas revert if `block.number >= 2 ** 48`.
            returndatacopy(returndatasize(), returndatasize(), sub(0, shr(48, number())))
        }
    }

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

    /// @dev Returns the latest amount of voting units for `account`.
    function getVotes(address account) public view virtual returns (uint256) {
        return _checkpointLatest(_delegateCheckpointsSlot(account));
    }

    /// @dev Returns the latest amount of voting units `account` has before or during `timepoint`.
    function getPastVotes(address account, uint256 timepoint)
        public
        view
        virtual
        returns (uint256)
    {
        if (timepoint >= clock()) _revertERC5805FutureLookup();
        return _checkpointUpperLookupRecent(_delegateCheckpointsSlot(account), timepoint);
    }

    /// @dev Returns the current voting delegate of `delegator`.
    function delegates(address delegator) public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x04, _ERC20_VOTES_MASTER_SLOT_SEED)
            mstore(0x00, delegator)
            result := sload(keccak256(0x0c, 0x18))
        }
    }

    /// @dev Set the voting delegate of the caller to `delegatee`.
    function delegate(address delegatee) public virtual {
        _delegate(msg.sender, delegatee);
    }

    /// @dev Sets the voting delegate of the signature signer to `delegatee`.
    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        address signer;
        bytes32 nameHash = _constantNameHash();
        //  We simply calculate it on-the-fly to allow for cases where the `name` may change.
        if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));
        bytes32 versionHash = _versionHash();
        /// @solidity memory-safe-assembly
        assembly {
            if gt(timestamp(), expiry) {
                mstore(0x00, 0x3480e9e1) // `ERC5805DelegateSignatureExpired()`.
                revert(0x1c, 0x04)
            }
            let m := mload(0x40)
            // Prepare the struct hash.
            mstore(0x00, _ERC5805_DELEGATION_TYPEHASH)
            mstore(0x20, shr(96, shl(96, delegatee)))
            mstore(0x40, nonce)
            mstore(0x60, expiry)
            mstore(0x40, keccak256(0x00, 0x80))
            mstore(0x00, 0x1901) // Store "\x19\x01".
            // Prepare the domain separator.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), nameHash)
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            mstore(0x20, keccak256(m, 0xa0))
            // Prepare the ecrecover calldata.
            mstore(0x00, keccak256(0x1e, 0x42))
            mstore(0x20, and(0xff, v))
            mstore(0x40, r)
            mstore(0x60, s)
            signer := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
            mstore(0x40, m) // Restore the free memory pointer.
            mstore(0x60, 0) // Restore the zero pointer.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            expiry := iszero(returndatasize()) // Reuse `expiry` to denote `ecrecover` failure.
        }
        if ((nonces(signer) ^ nonce) | expiry != 0) {
            /// @solidity memory-safe-assembly
            assembly {
                mstore(0x00, 0x1838d95c) // `ERC5805DelegateInvalidSignature()`.
                revert(0x1c, 0x04)
            }
        }
        _incrementNonce(signer);
        _delegate(signer, delegatee);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*              OTHER VOTE PUBLIC VIEW FUNCTIONS              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the number of checkpoints for `account`.
    function checkpointCount(address account) public view virtual returns (uint256 result) {
        result = _delegateCheckpointsSlot(account);
        /// @solidity memory-safe-assembly
        assembly {
            result := shr(208, shl(160, sload(result)))
        }
    }

    /// @dev Returns the voting checkpoint for `account` at index `i`.
    function checkpointAt(address account, uint256 i)
        public
        view
        virtual
        returns (uint48 checkpointClock, uint256 checkpointValue)
    {
        uint256 lengthSlot = _delegateCheckpointsSlot(account);
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(lt(i, shr(208, shl(160, sload(lengthSlot))))) {
                mstore(0x00, 0x86df9d10) // `ERC5805CheckpointIndexOutOfBounds()`.
                revert(0x1c, 0x04)
            }
            let checkpointPacked := sload(add(i, lengthSlot))
            checkpointClock := and(0xffffffffffff, checkpointPacked)
            checkpointValue := shr(96, checkpointPacked)
            if eq(checkpointValue, address()) { checkpointValue := sload(not(add(i, lengthSlot))) }
        }
    }

    /// @dev Returns the latest amount of total voting units.
    function getVotesTotalSupply() public view virtual returns (uint256) {
        return _checkpointLatest(_ERC20_VOTES_MASTER_SLOT_SEED << 96);
    }

    /// @dev Returns the latest amount of total voting units before or during `timepoint`.
    function getPastVotesTotalSupply(uint256 timepoint) public view virtual returns (uint256) {
        if (timepoint >= clock()) _revertERC5805FutureLookup();
        return _checkpointUpperLookupRecent(_ERC20_VOTES_MASTER_SLOT_SEED << 96, timepoint);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the amount of voting units `delegator` has control over.
    /// Override if you need a different formula.
    function _getVotingUnits(address delegator) internal view virtual returns (uint256) {
        return balanceOf(delegator);
    }

    /// @dev ERC20 after token transfer internal hook.
    function _afterTokenTransfer(address from, address to, uint256 amount)
        internal
        virtual
        override
    {
        _transferVotingUnits(from, to, amount);
    }

    /// @dev Used in `_afterTokenTransfer(address from, address to, uint256 amount)`.
    function _transferVotingUnits(address from, address to, uint256 amount) internal virtual {
        if (from == address(0)) {
            _checkpointPushDiff(_ERC20_VOTES_MASTER_SLOT_SEED << 96, clock(), amount, true);
        }
        if (to == address(0)) {
            _checkpointPushDiff(_ERC20_VOTES_MASTER_SLOT_SEED << 96, clock(), amount, false);
        }
        _moveDelegateVotes(delegates(from), delegates(to), amount);
    }

    /// @dev Transfer `amount` of delegated votes from `from` to `to`.
    /// Emits a {DelegateVotesChanged} event for each change of delegated votes.
    function _moveDelegateVotes(address from, address to, uint256 amount) internal virtual {
        if (amount == uint256(0)) return;
        (uint256 fromCleaned, uint256 toCleaned) = (uint256(uint160(from)), uint256(uint160(to)));
        if (fromCleaned == toCleaned) return;
        if (fromCleaned != 0) {
            (uint256 oldValue, uint256 newValue) =
                _checkpointPushDiff(_delegateCheckpointsSlot(from), clock(), amount, false);
            /// @solidity memory-safe-assembly
            assembly {
                // Emit the {DelegateVotesChanged} event.
                mstore(0x00, oldValue)
                mstore(0x20, newValue)
                log2(0x00, 0x40, _DELEGATE_VOTES_CHANGED_EVENT_SIGNATURE, fromCleaned)
            }
        }
        if (toCleaned != 0) {
            (uint256 oldValue, uint256 newValue) =
                _checkpointPushDiff(_delegateCheckpointsSlot(to), clock(), amount, true);
            /// @solidity memory-safe-assembly
            assembly {
                // Emit the {DelegateVotesChanged} event.
                mstore(0x00, oldValue)
                mstore(0x20, newValue)
                log2(0x00, 0x40, _DELEGATE_VOTES_CHANGED_EVENT_SIGNATURE, toCleaned)
            }
        }
    }

    /// @dev Delegates all of `account`'s voting units to `delegatee`.
    /// Emits the {DelegateChanged} and {DelegateVotesChanged} events.
    function _delegate(address account, address delegatee) internal virtual {
        address from;
        /// @solidity memory-safe-assembly
        assembly {
            let to := shr(96, shl(96, delegatee))
            mstore(0x04, _ERC20_VOTES_MASTER_SLOT_SEED)
            mstore(0x00, account)
            let delegateSlot := keccak256(0x0c, 0x18)
            from := sload(delegateSlot)
            sstore(delegateSlot, to)
            // Emit the {DelegateChanged} event.
            log4(0x00, 0x00, _DELEGATE_CHANGED_EVENT_SIGNATURE, shr(96, mload(0x0c)), from, to)
        }
        _moveDelegateVotes(from, delegatee, _getVotingUnits(account));
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the delegate checkpoints slot for `account`.
    function _delegateCheckpointsSlot(address account) private pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x04, _ERC20_VOTES_MASTER_SLOT_SEED)
            mstore(0x00, account)
            result := keccak256(0x0c, 0x17)
        }
    }

    /// @dev Pushes a checkpoint.
    function _checkpointPushDiff(uint256 lengthSlot, uint256 key, uint256 amount, bool isAdd)
        private
        returns (uint256 oldValue, uint256 newValue)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let lengthSlotPacked := sload(lengthSlot)
            for { let n := shr(208, shl(160, lengthSlotPacked)) } 1 {} {
                if iszero(n) {
                    if iszero(or(isAdd, iszero(amount))) {
                        mstore(0x00, 0x5915f686) // `ERC5805CheckpointValueUnderflow()`.
                        revert(0x1c, 0x04)
                    }
                    newValue := amount
                    if iszero(or(eq(newValue, address()), shr(160, newValue))) {
                        sstore(lengthSlot, or(or(key, shl(48, 1)), shl(96, newValue)))
                        break
                    }
                    sstore(lengthSlot, or(or(key, shl(48, 1)), shl(96, address())))
                    sstore(not(lengthSlot), newValue)
                    break
                }
                let checkpointSlot := add(sub(n, 1), lengthSlot)
                let lastPacked := sload(checkpointSlot)
                oldValue := shr(96, lastPacked)
                if eq(oldValue, address()) { oldValue := sload(not(checkpointSlot)) }
                for {} 1 {} {
                    if iszero(isAdd) {
                        newValue := sub(oldValue, amount)
                        if iszero(gt(newValue, oldValue)) { break }
                        mstore(0x00, 0x5915f686) // `ERC5805CheckpointValueUnderflow()`.
                        revert(0x1c, 0x04)
                    }
                    newValue := add(oldValue, amount)
                    if iszero(lt(newValue, oldValue)) { break }
                    mstore(0x00, 0x9dbbeb75) // `ERC5805CheckpointValueOverflow()`.
                    revert(0x1c, 0x04)
                }
                let lastKey := and(0xffffffffffff, lastPacked)
                if iszero(eq(lastKey, key)) {
                    n := add(1, n)
                    checkpointSlot := add(1, checkpointSlot)
                    sstore(lengthSlot, add(shl(48, 1), lengthSlotPacked))
                }
                if or(gt(lastKey, key), shr(48, n)) { invalid() }
                if iszero(or(eq(newValue, address()), shr(160, newValue))) {
                    sstore(checkpointSlot, or(or(key, shl(48, n)), shl(96, newValue)))
                    break
                }
                sstore(checkpointSlot, or(or(key, shl(48, n)), shl(96, address())))
                sstore(not(checkpointSlot), newValue)
                break
            }
        }
    }

    /// @dev Returns the latest value in the checkpoints.
    function _checkpointLatest(uint256 lengthSlot) private view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := shr(208, shl(160, sload(lengthSlot)))
            if result {
                lengthSlot := add(sub(result, 1), lengthSlot) // Reuse for `checkpointSlot`.
                result := shr(96, sload(lengthSlot))
                if eq(result, address()) { result := sload(not(lengthSlot)) }
            }
        }
    }

    /// @dev Returns checkpoint value with the largest key that is less than or equal to `key`.
    function _checkpointUpperLookupRecent(uint256 lengthSlot, uint256 key)
        private
        view
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let l := 0 // Low.
            let h := shr(208, shl(160, sload(lengthSlot))) // High.
            // Start the binary search nearer to the right to optimize for recent checkpoints.
            for {} iszero(lt(h, 6)) {} {
                let m := shl(4, lt(0xffff, h))
                m := shl(shr(1, or(m, shl(3, lt(0xff, shr(m, h))))), 16)
                m := shr(1, add(m, div(h, m)))
                m := shr(1, add(m, div(h, m)))
                m := shr(1, add(m, div(h, m)))
                m := shr(1, add(m, div(h, m)))
                m := shr(1, add(m, div(h, m)))
                m := sub(h, shr(1, add(m, div(h, m)))) // Approx `h - sqrt(h)`.
                if iszero(lt(key, and(sload(add(m, lengthSlot)), 0xffffffffffff))) {
                    l := add(1, m)
                    break
                }
                h := m
                break
            }
            // Binary search.
            for {} lt(l, h) {} {
                let m := shr(1, add(l, h)) // Won't overflow in practice.
                if iszero(lt(key, and(sload(add(m, lengthSlot)), 0xffffffffffff))) {
                    l := add(1, m)
                    continue
                }
                h := m
            }
            let checkpointSlot := add(sub(h, 1), lengthSlot)
            result := mul(iszero(iszero(h)), shr(96, sload(checkpointSlot)))
            if eq(result, address()) { result := sload(not(checkpointSlot)) }
        }
    }

    /// @dev Reverts with `ERC5805FutureLookup()`.
    function _revertERC5805FutureLookup() private pure {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0xf9874464) // `ERC5805FutureLookup()`.
            revert(0x1c, 0x04)
        }
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"address","name":"_mintTo","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AllowanceOverflow","type":"error"},{"inputs":[],"name":"AllowanceUnderflow","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[],"name":"ERC5805CheckpointIndexOutOfBounds","type":"error"},{"inputs":[],"name":"ERC5805CheckpointValueOverflow","type":"error"},{"inputs":[],"name":"ERC5805CheckpointValueUnderflow","type":"error"},{"inputs":[],"name":"ERC5805DelegateInvalidSignature","type":"error"},{"inputs":[],"name":"ERC5805DelegateSignatureExpired","type":"error"},{"inputs":[],"name":"ERC5805FutureLookup","type":"error"},{"inputs":[],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidPermit","type":"error"},{"inputs":[],"name":"Permit2AllowanceIsFixedAtInfinity","type":"error"},{"inputs":[],"name":"PermitExpired","type":"error"},{"inputs":[],"name":"TotalSupplyOverflow","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"result","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"i","type":"uint256"}],"name":"checkpointAt","outputs":[{"internalType":"uint48","name":"checkpointClock","type":"uint48"},{"internalType":"uint256","name":"checkpointValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"checkpointCount","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"result","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastVotesTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVotesTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50604051611aa7380380611aa783398101604081905261002f9161048a565b600061003b828261059e565b506001610048838261059e565b50610053838561005c565b5050505061065c565b6805345cdf77eb68f44c54818101818110156100805763e5cfe9576000526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52816000526020600c208181540181555080602052600c5160601c60007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a36100e3600083836100ec565b5050565b505050565b6100e78383836001600160a01b03831661012f5761012c6fff466c9f00000000000000000000000061011c6101a5565b65ffffffffffff168360016101b4565b50505b6001600160a01b03821661016c576101696fff466c9f0000000000000000000000006101596101a5565b65ffffffffffff168360006101b4565b50505b6100e76101878463ff466c9f6004526000526018600c205490565b61019f8463ff466c9f6004526000526018600c205490565b836102e6565b43603081901c6000033d3d3e90565b60008085548060a01b60d01c8061021c57851585176101db57635915f6866000526004601cfd5b8592508260a01c3084141761020157606083901b871766010000000000001788556102db565b3060601b8717660100000000000017885587198390556102db565b87600182030180548060601c95503086036102375781195495505b866102575787860394508585111561027257635915f6866000526004601cfd5b87860194508585101561027257639dbbeb756000526004601cfd5b65ffffffffffff1688811461029957660100000000000084018a5560019283019291909101905b8260301c89821117156102a857fe5b508360a01c308514176102c8578360601b8260301b8917178155506102db565b3060601b8260301b891717815583811955505b505094509492505050565b806102f057505050565b6001600160a01b0380841690831680820361030c575050505050565b811561036b5760008061034761032f8863ff466c9f6004526000526017600c2090565b6103376101a5565b65ffffffffffff168760006101b4565b91509150816000528060205283600080516020611a8783398151915260406000a250505b80156103ca576000806103a661038e8763ff466c9f6004526000526017600c2090565b6103966101a5565b65ffffffffffff168760016101b4565b91509150816000528060205282600080516020611a8783398151915260406000a250505b5050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126103f857600080fd5b81516001600160401b03811115610411576104116103d1565b604051601f8201601f19908116603f011681016001600160401b038111828210171561043f5761043f6103d1565b60405281815283820160200185101561045757600080fd5b60005b828110156104765760208186018101518383018201520161045a565b506000918101602001919091529392505050565b600080600080608085870312156104a057600080fd5b845160208601519094506001600160a01b03811681146104bf57600080fd5b60408601519093506001600160401b038111156104db57600080fd5b6104e7878288016103e7565b606087015190935090506001600160401b0381111561050557600080fd5b610511878288016103e7565b91505092959194509250565b600181811c9082168061053157607f821691505b60208210810361055157634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156100e757806000526020600020601f840160051c8101602085101561057e5750805b601f840160051c820191505b818110156103ca576000815560010161058a565b81516001600160401b038111156105b7576105b76103d1565b6105cb816105c5845461051d565b84610557565b6020601f8211600181146105ff57600083156105e75750848201515b600019600385901b1c1916600184901b1784556103ca565b600084815260208120601f198516915b8281101561062f578785015182556020948501946001909201910161060f565b508482101561064d5786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b61141c8061066b6000396000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c806376a82342116100de5780639ab24eb011610097578063c7a2f1de11610071578063c7a2f1de146103c8578063cd63c4d2146103db578063d505accf146103e3578063dd62ed3e146103f657600080fd5b80639ab24eb01461038f578063a9059cbb146103a2578063c3cda520146103b557600080fd5b806376a82342146102d157806379cc6790146102fe5780637ecebe001461031157806384a0e0821461033757806391ddadf41461036857806395d89b411461038757600080fd5b80633a46b1a8116101305780633a46b1a8146101fd57806342966c68146102105780634bf5d7e914610225578063587cde1e1461025e5780635c19a95c1461029857806370a08231146102ab57600080fd5b806306fdde0314610178578063095ea7b31461019657806318160ddd146101b957806323b872dd146101d3578063313ce567146101e65780633644e515146101f5575b600080fd5b610180610409565b60405161018d91906111a5565b60405180910390f35b6101a96101a436600461120a565b61049b565b604051901515815260200161018d565b6805345cdf77eb68f44c545b60405190815260200161018d565b6101a96101e1366004611234565b610520565b6040516012815260200161018d565b6101c5610564565b6101c561020b36600461120a565b6105e1565b61022361021e366004611271565b610628565b005b60408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c740000006020820152610180565b61028061026c36600461128a565b63ff466c9f6004526000526018600c205490565b6040516001600160a01b03909116815260200161018d565b6102236102a636600461128a565b610635565b6101c56102b936600461128a565b6387a211a2600c908152600091909152602090205490565b6101c56102df36600461128a565b63ff466c9f6004526000526017600c205460301c65ffffffffffff1690565b61022361030c36600461120a565b61063f565b6101c561031f36600461128a565b6338377508600c908152600091909152602090205490565b61034a61034536600461120a565b610658565b6040805165ffffffffffff909316835260208301919091520161018d565b6103706106bd565b60405165ffffffffffff909116815260200161018d565b6101806106cc565b6101c561039d36600461128a565b6106db565b6101a96103b036600461120a565b6106fc565b6102236103c33660046112b6565b610732565b6101c56103d6366004611271565b6108a2565b6101c56108d3565b6102236103f136600461130e565b6108ea565b6101c5610404366004611379565b610aa6565b606060018054610418906113ac565b80601f0160208091040260200160405190810160405280929190818152602001828054610444906113ac565b80156104915780601f1061046657610100808354040283529160200191610491565b820191906000526020600020905b81548152906001019060200180831161047457829003601f168201915b5050505050905090565b60006001600160a01b0383166e22d473030f116ddee9f6b43ac78ba318821915176104ce57633f68539a6000526004601cfd5b82602052637f5e9f20600c5233600052816034600c205581600052602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560206000a35060015b92915050565b60006001600160a01b0383166105515760405163ec442f0560e01b8152600060048201526024015b60405180910390fd5b61055c848484610aed565b949350505050565b60008061056f610409565b805190602001209050604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815260208101929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69082015246606082015230608082015260a09020919050565b60006105eb6106bd565b65ffffffffffff16821061060157610601610bcb565b61062161061b8463ff466c9f6004526000526017600c2090565b83610bd9565b9392505050565b6106323382610ca8565b50565b6106323382610d27565b61064a823383610d8f565b6106548282610ca8565b5050565b60008060006106748563ff466c9f6004526000526017600c2090565b9050805460a01b60d01c8410610692576386df9d106000526004601cfd5b8381015465ffffffffffff8116935060601c91503082036106b557808401195491505b509250929050565b43603081901c6000033d3d3e90565b606060008054610418906113ac565b600061051a6106f78363ff466c9f6004526000526017600c2090565b610df5565b60006001600160a01b0383166107285760405163ec442f0560e01b815260006004820152602401610548565b6106218383610e22565b60008061073d610409565b8051906020012090507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64287101561077d57633480e9e16000526004601cfd5b6040517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf6000528960601b60601c602052886040528760605260806000206040526119016000527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815282602082015281604082015246606082015230608082015260a081206020526042601e206000528660ff166020528560405284606052602060016080600060015afa519350806040525060006060523d1596508688610858856338377508600c908152600091909152602090205490565b18171561086d57631838d95c6000526004601cfd5b61088d836338377508600c52806000526020600c20805460010181555050565b610897838a610d27565b505050505050505050565b60006108ac6106bd565b65ffffffffffff1682106108c2576108c2610bcb565b61051a63ff466c9f60601b83610bd9565b60006108e563ff466c9f60601b610df5565b905090565b6001600160a01b0386166e22d473030f116ddee9f6b43ac78ba3188519151761091b57633f68539a6000526004601cfd5b6000610925610409565b8051906020012090507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64286101561096557631a15a3cc6000526004601cfd5b6040518960601b60601c99508860601b60601c985065383775081901600e52896000526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f835284602084015283604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528b60208401528a60408401528960608401528060808401528860a084015260c08320604e526042602c206000528760ff1660205286604052856060526020806080600060015afa8c3d5114610a515763ddafbaef6000526004601cfd5b0190556303faf4f960a51b89176040526034602c20889055888a7f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a36040525050600060605250505050505050565b60006e22d473030f116ddee9f6b43ac78ba2196001600160a01b03831601610ad1575060001961051a565b50602052637f5e9f20600c908152600091909152603490205490565b60008360601b6e22d473030f116ddee9f6b43ac78ba33314610b445733602052637f5e9f208117600c526034600c208054801915610b415780851115610b3b576313be252b6000526004601cfd5b84810382555b50505b6387a211a28117600c526020600c20805480851115610b6b5763f4d678b86000526004601cfd5b84810382555050836000526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350610bc1848484610ea8565b5060019392505050565b63f98744646000526004601cfd5b600080835460a01b60d01c60068110610c4e57601061ffff821160041b82811c60ff1060031b17600190811c9190911b80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c81038581015465ffffffffffff168510610c4b576001019150610c4e565b90505b5b80821015610c805780820160011c65ffffffffffff86820154168510610c79576001019150610c4f565b9050610c4f565b8460018203019150815460601c81151502925050308203610ca15780195491505b5092915050565b6387a211a2600c52816000526020600c20805480831115610cd15763f4d678b86000526004601cfd5b82900390556805345cdf77eb68f44c8054829003905560008181526001600160a01b0383167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602083a361065482600083610ea8565b60008160601b60601c63ff466c9f600452836000526018600c2080549250818155508082600c5160601c7f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f600080a450610d8a8183610d8586610eb3565b610ecd565b505050565b6e22d473030f116ddee9f6b43ac78ba2196001600160a01b03831601610db457505050565b81602052637f5e9f20600c52826000526034600c208054801915610dee5780831115610de8576313be252b6000526004601cfd5b82810382555b5050505050565b6000815460a01b60d01c90508015610e1d570160001901805460601c308103610e1d57508019545b919050565b60006387a211a2600c52336000526020600c20805480841115610e4d5763f4d678b86000526004601cfd5b83810382555050826000526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3610e9f338484610ea8565b50600192915050565b610d8a838383610fdb565b6387a211a2600c908152600082815260209091205461051a565b80610ed757505050565b6001600160a01b03808416908316808203610ef3575050505050565b8115610f6457600080610f2e610f168863ff466c9f6004526000526017600c2090565b610f1e6106bd565b65ffffffffffff1687600061107c565b915091508160005280602052837fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72460406000a250505b8015610dee57600080610f9f610f878763ff466c9f6004526000526017600c2090565b610f8f6106bd565b65ffffffffffff1687600161107c565b915091508160005280602052827fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72460406000a250505050505050565b6001600160a01b03831661100f5761100c63ff466c9f60601b610ffc6106bd565b65ffffffffffff1683600161107c565b50505b6001600160a01b0382166110435761104063ff466c9f60601b6110306106bd565b65ffffffffffff1683600061107c565b50505b610d8a61105e8463ff466c9f6004526000526018600c205490565b6110768463ff466c9f6004526000526018600c205490565b83610ecd565b60008085548060a01b60d01c806110de57851585176110a357635915f6866000526004601cfd5b8592508260a01c308414176110c657606083901b8717600160301b17885561119a565b3060601b8717600160301b178855871983905561119a565b87600182030180548060601c95503086036110f95781195495505b866111195787860394508585111561113457635915f6866000526004601cfd5b87860194508585101561113457639dbbeb756000526004601cfd5b65ffffffffffff1688811461115857600160301b84018a5560019283019291909101905b8260301c898211171561116757fe5b508360a01c30851417611187578360601b8260301b89171781555061119a565b3060601b8260301b891717815583811955505b505094509492505050565b602081526000825180602084015260005b818110156111d357602081860181015160408684010152016111b6565b506000604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b0381168114610e1d57600080fd5b6000806040838503121561121d57600080fd5b611226836111f3565b946020939093013593505050565b60008060006060848603121561124957600080fd5b611252846111f3565b9250611260602085016111f3565b929592945050506040919091013590565b60006020828403121561128357600080fd5b5035919050565b60006020828403121561129c57600080fd5b610621826111f3565b803560ff81168114610e1d57600080fd5b60008060008060008060c087890312156112cf57600080fd5b6112d8876111f3565b955060208701359450604087013593506112f4606088016112a5565b9598949750929560808101359460a0909101359350915050565b600080600080600080600060e0888a03121561132957600080fd5b611332886111f3565b9650611340602089016111f3565b9550604088013594506060880135935061135c608089016112a5565b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561138c57600080fd5b611395836111f3565b91506113a3602084016111f3565b90509250929050565b600181811c908216806113c057607f821691505b6020821081036113e057634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212208e6ebb22a7f75d05237410a43ec83f55055448c52aef803e92f65a8a5578d74564736f6c634300081c0033dec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724000000000000000000000000000000000000000019d971e4fe8401e7400000000000000000000000000000008b5756f6ff9b6689c75e22ae82005747a9f7fc14000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000e4f4646494349414c204b2d504f5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044b504f5000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101735760003560e01c806376a82342116100de5780639ab24eb011610097578063c7a2f1de11610071578063c7a2f1de146103c8578063cd63c4d2146103db578063d505accf146103e3578063dd62ed3e146103f657600080fd5b80639ab24eb01461038f578063a9059cbb146103a2578063c3cda520146103b557600080fd5b806376a82342146102d157806379cc6790146102fe5780637ecebe001461031157806384a0e0821461033757806391ddadf41461036857806395d89b411461038757600080fd5b80633a46b1a8116101305780633a46b1a8146101fd57806342966c68146102105780634bf5d7e914610225578063587cde1e1461025e5780635c19a95c1461029857806370a08231146102ab57600080fd5b806306fdde0314610178578063095ea7b31461019657806318160ddd146101b957806323b872dd146101d3578063313ce567146101e65780633644e515146101f5575b600080fd5b610180610409565b60405161018d91906111a5565b60405180910390f35b6101a96101a436600461120a565b61049b565b604051901515815260200161018d565b6805345cdf77eb68f44c545b60405190815260200161018d565b6101a96101e1366004611234565b610520565b6040516012815260200161018d565b6101c5610564565b6101c561020b36600461120a565b6105e1565b61022361021e366004611271565b610628565b005b60408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c740000006020820152610180565b61028061026c36600461128a565b63ff466c9f6004526000526018600c205490565b6040516001600160a01b03909116815260200161018d565b6102236102a636600461128a565b610635565b6101c56102b936600461128a565b6387a211a2600c908152600091909152602090205490565b6101c56102df36600461128a565b63ff466c9f6004526000526017600c205460301c65ffffffffffff1690565b61022361030c36600461120a565b61063f565b6101c561031f36600461128a565b6338377508600c908152600091909152602090205490565b61034a61034536600461120a565b610658565b6040805165ffffffffffff909316835260208301919091520161018d565b6103706106bd565b60405165ffffffffffff909116815260200161018d565b6101806106cc565b6101c561039d36600461128a565b6106db565b6101a96103b036600461120a565b6106fc565b6102236103c33660046112b6565b610732565b6101c56103d6366004611271565b6108a2565b6101c56108d3565b6102236103f136600461130e565b6108ea565b6101c5610404366004611379565b610aa6565b606060018054610418906113ac565b80601f0160208091040260200160405190810160405280929190818152602001828054610444906113ac565b80156104915780601f1061046657610100808354040283529160200191610491565b820191906000526020600020905b81548152906001019060200180831161047457829003601f168201915b5050505050905090565b60006001600160a01b0383166e22d473030f116ddee9f6b43ac78ba318821915176104ce57633f68539a6000526004601cfd5b82602052637f5e9f20600c5233600052816034600c205581600052602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560206000a35060015b92915050565b60006001600160a01b0383166105515760405163ec442f0560e01b8152600060048201526024015b60405180910390fd5b61055c848484610aed565b949350505050565b60008061056f610409565b805190602001209050604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815260208101929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69082015246606082015230608082015260a09020919050565b60006105eb6106bd565b65ffffffffffff16821061060157610601610bcb565b61062161061b8463ff466c9f6004526000526017600c2090565b83610bd9565b9392505050565b6106323382610ca8565b50565b6106323382610d27565b61064a823383610d8f565b6106548282610ca8565b5050565b60008060006106748563ff466c9f6004526000526017600c2090565b9050805460a01b60d01c8410610692576386df9d106000526004601cfd5b8381015465ffffffffffff8116935060601c91503082036106b557808401195491505b509250929050565b43603081901c6000033d3d3e90565b606060008054610418906113ac565b600061051a6106f78363ff466c9f6004526000526017600c2090565b610df5565b60006001600160a01b0383166107285760405163ec442f0560e01b815260006004820152602401610548565b6106218383610e22565b60008061073d610409565b8051906020012090507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64287101561077d57633480e9e16000526004601cfd5b6040517fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf6000528960601b60601c602052886040528760605260806000206040526119016000527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815282602082015281604082015246606082015230608082015260a081206020526042601e206000528660ff166020528560405284606052602060016080600060015afa519350806040525060006060523d1596508688610858856338377508600c908152600091909152602090205490565b18171561086d57631838d95c6000526004601cfd5b61088d836338377508600c52806000526020600c20805460010181555050565b610897838a610d27565b505050505050505050565b60006108ac6106bd565b65ffffffffffff1682106108c2576108c2610bcb565b61051a63ff466c9f60601b83610bd9565b60006108e563ff466c9f60601b610df5565b905090565b6001600160a01b0386166e22d473030f116ddee9f6b43ac78ba3188519151761091b57633f68539a6000526004601cfd5b6000610925610409565b8051906020012090507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc64286101561096557631a15a3cc6000526004601cfd5b6040518960601b60601c99508860601b60601c985065383775081901600e52896000526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f835284602084015283604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528b60208401528a60408401528960608401528060808401528860a084015260c08320604e526042602c206000528760ff1660205286604052856060526020806080600060015afa8c3d5114610a515763ddafbaef6000526004601cfd5b0190556303faf4f960a51b89176040526034602c20889055888a7f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a36040525050600060605250505050505050565b60006e22d473030f116ddee9f6b43ac78ba2196001600160a01b03831601610ad1575060001961051a565b50602052637f5e9f20600c908152600091909152603490205490565b60008360601b6e22d473030f116ddee9f6b43ac78ba33314610b445733602052637f5e9f208117600c526034600c208054801915610b415780851115610b3b576313be252b6000526004601cfd5b84810382555b50505b6387a211a28117600c526020600c20805480851115610b6b5763f4d678b86000526004601cfd5b84810382555050836000526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350610bc1848484610ea8565b5060019392505050565b63f98744646000526004601cfd5b600080835460a01b60d01c60068110610c4e57601061ffff821160041b82811c60ff1060031b17600190811c9190911b80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c81038581015465ffffffffffff168510610c4b576001019150610c4e565b90505b5b80821015610c805780820160011c65ffffffffffff86820154168510610c79576001019150610c4f565b9050610c4f565b8460018203019150815460601c81151502925050308203610ca15780195491505b5092915050565b6387a211a2600c52816000526020600c20805480831115610cd15763f4d678b86000526004601cfd5b82900390556805345cdf77eb68f44c8054829003905560008181526001600160a01b0383167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602083a361065482600083610ea8565b60008160601b60601c63ff466c9f600452836000526018600c2080549250818155508082600c5160601c7f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f600080a450610d8a8183610d8586610eb3565b610ecd565b505050565b6e22d473030f116ddee9f6b43ac78ba2196001600160a01b03831601610db457505050565b81602052637f5e9f20600c52826000526034600c208054801915610dee5780831115610de8576313be252b6000526004601cfd5b82810382555b5050505050565b6000815460a01b60d01c90508015610e1d570160001901805460601c308103610e1d57508019545b919050565b60006387a211a2600c52336000526020600c20805480841115610e4d5763f4d678b86000526004601cfd5b83810382555050826000526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3610e9f338484610ea8565b50600192915050565b610d8a838383610fdb565b6387a211a2600c908152600082815260209091205461051a565b80610ed757505050565b6001600160a01b03808416908316808203610ef3575050505050565b8115610f6457600080610f2e610f168863ff466c9f6004526000526017600c2090565b610f1e6106bd565b65ffffffffffff1687600061107c565b915091508160005280602052837fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72460406000a250505b8015610dee57600080610f9f610f878763ff466c9f6004526000526017600c2090565b610f8f6106bd565b65ffffffffffff1687600161107c565b915091508160005280602052827fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a72460406000a250505050505050565b6001600160a01b03831661100f5761100c63ff466c9f60601b610ffc6106bd565b65ffffffffffff1683600161107c565b50505b6001600160a01b0382166110435761104063ff466c9f60601b6110306106bd565b65ffffffffffff1683600061107c565b50505b610d8a61105e8463ff466c9f6004526000526018600c205490565b6110768463ff466c9f6004526000526018600c205490565b83610ecd565b60008085548060a01b60d01c806110de57851585176110a357635915f6866000526004601cfd5b8592508260a01c308414176110c657606083901b8717600160301b17885561119a565b3060601b8717600160301b178855871983905561119a565b87600182030180548060601c95503086036110f95781195495505b866111195787860394508585111561113457635915f6866000526004601cfd5b87860194508585101561113457639dbbeb756000526004601cfd5b65ffffffffffff1688811461115857600160301b84018a5560019283019291909101905b8260301c898211171561116757fe5b508360a01c30851417611187578360601b8260301b89171781555061119a565b3060601b8260301b891717815583811955505b505094509492505050565b602081526000825180602084015260005b818110156111d357602081860181015160408684010152016111b6565b506000604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b0381168114610e1d57600080fd5b6000806040838503121561121d57600080fd5b611226836111f3565b946020939093013593505050565b60008060006060848603121561124957600080fd5b611252846111f3565b9250611260602085016111f3565b929592945050506040919091013590565b60006020828403121561128357600080fd5b5035919050565b60006020828403121561129c57600080fd5b610621826111f3565b803560ff81168114610e1d57600080fd5b60008060008060008060c087890312156112cf57600080fd5b6112d8876111f3565b955060208701359450604087013593506112f4606088016112a5565b9598949750929560808101359460a0909101359350915050565b600080600080600080600060e0888a03121561132957600080fd5b611332886111f3565b9650611340602089016111f3565b9550604088013594506060880135935061135c608089016112a5565b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561138c57600080fd5b611395836111f3565b91506113a3602084016111f3565b90509250929050565b600181811c908216806113c057607f821691505b6020821081036113e057634e487b7160e01b600052602260045260246000fd5b5091905056fea26469706673582212208e6ebb22a7f75d05237410a43ec83f55055448c52aef803e92f65a8a5578d74564736f6c634300081c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000000000000019d971e4fe8401e7400000000000000000000000000000008b5756f6ff9b6689c75e22ae82005747a9f7fc14000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000e4f4646494349414c204b2d504f5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044b504f5000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _totalSupply (uint256): 8000000000000000000000000000
Arg [1] : _mintTo (address): 0x8B5756F6FF9b6689c75E22aE82005747A9F7FC14
Arg [2] : _name (string): OFFICIAL K-POP
Arg [3] : _symbol (string): KPOP

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000019d971e4fe8401e740000000
Arg [1] : 0000000000000000000000008b5756f6ff9b6689c75e22ae82005747a9f7fc14
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [4] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [5] : 4f4646494349414c204b2d504f50000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [7] : 4b504f5000000000000000000000000000000000000000000000000000000000


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.