ETH Price: $3,320.79 (+2.41%)

Contract

0xDCb6CB6a719570AB8b8880464870b8f76011EAD6
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Create Lock With...176052982023-07-02 9:00:35569 days ago1688288435IN
0xDCb6CB6a...76011EAD6
0 ETH0.0021943713.45103303
Increase Amount175724502023-06-27 18:25:11574 days ago1687890311IN
0xDCb6CB6a...76011EAD6
0 ETH0.0007284113.60777875
Create Lock With...173541222023-05-28 1:02:11605 days ago1685235731IN
0xDCb6CB6a...76011EAD6
0 ETH0.0041469528.39639116
Increase Amount173436572023-05-26 13:46:59606 days ago1685108819IN
0xDCb6CB6a...76011EAD6
0 ETH0.0019105535.7
Create Lock With...173411642023-05-26 5:21:35606 days ago1685078495IN
0xDCb6CB6a...76011EAD6
0 ETH0.0042010125.74560531
Create Lock With...173292472023-05-24 13:09:11608 days ago1684933751IN
0xDCb6CB6a...76011EAD6
0 ETH0.01284978.75
Create Lock With...172985772023-05-20 5:31:47612 days ago1684560707IN
0xDCb6CB6a...76011EAD6
0 ETH0.00484529.69662061
Create Lock With...172809222023-05-17 17:50:11615 days ago1684345811IN
0xDCb6CB6a...76011EAD6
0 ETH0.0116311171.30144615
Create Lock With...172758902023-05-17 0:44:35616 days ago1684284275IN
0xDCb6CB6a...76011EAD6
0 ETH0.0064452844.13429134
Increase Amount172692842023-05-16 2:21:47617 days ago1684203707IN
0xDCb6CB6a...76011EAD6
0 ETH0.0031143658.18080365
Create Lock With...172692802023-05-16 2:20:59617 days ago1684203659IN
0xDCb6CB6a...76011EAD6
0 ETH0.0100341161.49334162
Create Lock With...172664242023-05-15 16:40:47617 days ago1684168847IN
0xDCb6CB6a...76011EAD6
0 ETH0.0124807676.49309363
Create Lock With...172658352023-05-15 14:41:11617 days ago1684161671IN
0xDCb6CB6a...76011EAD6
0 ETH0.0111183461.69114945

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
VEZTH

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 20000 runs

Other Settings:
default evmVersion
File 1 of 9 : VEZTH.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "@solmate/auth/Owned.sol";
import "@solmate/utils/ReentrancyGuard.sol";
import "@solmate/utils/SafeCastLib.sol";

import {IVotingEscrow} from "./interfaces/IVotingEscrow.sol";
import {IBlocklist} from "./interfaces/IBlocklist.sol";
import {SafeTransferLib, ERC20} from "@solmate/utils/SafeTransferLib.sol";

contract VEZTH is IVotingEscrow, Owned {
    using SafeCastLib for uint256;

    struct LockedBalance {
        uint128 amount;
        uint64 end;
        uint64 start;
    }

    struct Point {
        uint128 amount;
        uint128 index;
    }

    uint256 private constant _SCALE = 7 days;
    uint256 private constant _MAX_TIME = 365 days;
    uint256 private constant _MIN_TIME = 14 days;
    uint256 private constant _INCREASE = 4;

    // comming soon
    // bytes32 private constant _DELEGATION_TYPEHASH =
    // keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");

    // Voting token
    string public constant name = "Vote Escrowed ZTH";
    string public constant symbol = "veZTH";
    uint8 public constant decimals = 18;
    ERC20 public immutable token;

    mapping(uint256 => Point) private _totalUnlockAtEpoch;
    mapping(address => mapping(uint256 => Point)) private _userUnlockAtEpoch;

    address public penaltyRecipient; // receives collected penalty payments
    uint256 public maxPenalty = 1e18; // penalty for quitters with MAXTIME remaining lock
    address public blocklist;
    mapping(address => LockedBalance) public locked;

    /**
     * @notice Initializes state
     * @param _penaltyRecipient The recipient of penalty paid by lock quitters
     * @param _token The token locked in order to obtain voting power
     */
    constructor(address _penaltyRecipient, address _token) Owned(msg.sender) {
        token = ERC20(_token);
        penaltyRecipient = _penaltyRecipient;
    }

    function lockEnd(address account) external view returns (uint256) {
        return locked[account].end;
    }

    /**
     * @dev Gets the current votes balance for `account`
     */
    function balanceOf(address account) external view returns (uint256) {
        return getVotes(account);
    }

    /**
     * @dev Gets the current total votes balance for all locked tokens.
     */
    function totalSupply() external view returns (uint256) {
        return _getVotes(_totalUnlockAtEpoch);
    }

    /**
     * @dev Gets the current votes balance for `account`
     */
    function getVotes(address account) public view returns (uint256) {
        return _getVotes(_userUnlockAtEpoch[account]);
    }

    function _getVotes(mapping(uint256 => Point) storage points) private view returns (uint256) {
        uint256 epoch = _getEpoch(block.timestamp); 
        uint256 max = _MAX_TIME / _SCALE;
        uint256 powers;
        //  max lookup is 52 times
        for (uint256 i = 1; i <= max; i++) {
            Point memory p = points[epoch + i];
            powers += uint256(p.index) - uint256(p.amount) * block.timestamp;
        }
        return (powers * _INCREASE) / _MAX_TIME;
    }

    function createLock(uint256 value, uint256 unlockTime) external checkBlocklist {
        _createLock(msg.sender, value, unlockTime);
    }

    function createLockWithPermit(uint256 value, uint256 unlockTime, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
        external
        checkBlocklist
    {
        // permit max
        ERC20(address(token)).permit(msg.sender, address(this), type(uint256).max, deadline, v, r, s);
        _createLock(msg.sender, value, unlockTime);
    }

    function _createLock(address account, uint256 value, uint256 unlockTime) internal {
        LockedBalance memory lock = locked[account];
        if (lock.amount > 0) revert WithdrawOldTokensFirst();
        if (value == 0) revert ZeroValue();
        if (unlockTime <  block.timestamp + _MIN_TIME) revert InsufficientLockTime();
        if (unlockTime > block.timestamp + _MAX_TIME) {
            revert ExceedsMaxLockTime();
        }

        // Transfer tokens
        SafeTransferLib.safeTransferFrom(token, msg.sender, address(this), value);

        locked[account] = LockedBalance({
            amount: value.safeCastTo128(),
            end: unlockTime.safeCastTo64(),
            start: block.timestamp.safeCastTo64()
        });
        uint256 epoch = _getEpoch(unlockTime);
        _writePoint(account, epoch, value, unlockTime, true);
        emit CreateLock(account, value, unlockTime);
    }

    function _writePoint(address account, uint256 epoch, uint256 value, uint256 unlocktime, bool isAdd) private {
        Point memory point = _userUnlockAtEpoch[account][epoch];
        Point memory totalPoint = _totalUnlockAtEpoch[epoch];

        if (isAdd) {
            uint128 delta = (value * unlocktime).safeCastTo128();
            uint128 v = value.safeCastTo128();
            point.amount += v;
            point.index += delta;
            totalPoint.amount += v;
            totalPoint.index += delta;
        } else {
            uint128 delta = (value * unlocktime).safeCastTo128();
            uint128 v = value.safeCastTo128();
            point.amount -= v;
            point.index -= delta;
            totalPoint.amount -= v;
            totalPoint.index -= delta;
        }
        _userUnlockAtEpoch[account][epoch] = point;
        _totalUnlockAtEpoch[epoch] = totalPoint;
    }

    function increaseAmount(uint256 value) external {
        LockedBalance memory lock = locked[msg.sender];
        if (value == 0) revert ZeroValue();
        if (lock.amount == 0) revert CreateLockFirst();
        if (lock.end <= block.timestamp) revert LockExpired();

        // Update state
        // Transfer tokens
        SafeTransferLib.safeTransferFrom(token, msg.sender, address(this), value);
        // Update state
        locked[msg.sender].amount = (lock.amount + value).safeCastTo128();

        uint256 epoch = _getEpoch(lock.end);
        _writePoint(msg.sender, epoch, value, lock.end, true);
        emit IncreaseAmount(msg.sender, value, lock.end);
    }

    function increaseUnlockTime(uint256 unlockTime) external {
        LockedBalance memory lock = locked[msg.sender];
        if (lock.amount == 0) revert CreateLockFirst();

        if (unlockTime > block.timestamp + _MAX_TIME) {
            revert ExceedsMaxLockTime();
        }
        if (unlockTime <= block.timestamp) revert InsufficientLockTime();
        if (unlockTime <= lock.end) revert InsufficientLockTime();

        // Update state
        locked[msg.sender].end = unlockTime.safeCastTo64();
        uint256 oldEpoch = _getEpoch(lock.end);
        uint256 epoch = _getEpoch(unlockTime);
        _writePoint(msg.sender, oldEpoch, lock.amount, lock.end, false);
        _writePoint(msg.sender, epoch, lock.amount, unlockTime, true);

        emit IncreaseUnlockTime(msg.sender, lock.amount, lock.end);
    }

    function withdraw() external {
        LockedBalance memory lock = locked[msg.sender];
        if (lock.amount == 0) revert MissingLock();
        if (lock.end > block.timestamp) revert LockNotExpired();

        // Update state
        locked[msg.sender] = LockedBalance(0, 0, 0);
        uint256 epoch = _getEpoch(lock.end);
        _writePoint(msg.sender, epoch, lock.amount, lock.end, false);

        // Transfer tokens
        SafeTransferLib.safeTransfer(token, msg.sender, lock.amount);

        emit Unlock(msg.sender, lock.amount, 0);
    }

    function quitLock() external {
        LockedBalance memory lock = locked[msg.sender];
        if (lock.amount == 0) revert MissingLock();
        if (lock.end <= block.timestamp) revert LockExpired();

        // Update state
        locked[msg.sender].amount = 0;
        locked[msg.sender].end = 0;

        uint256 epoch = _getEpoch(lock.end);
        _writePoint(msg.sender, epoch, lock.amount, lock.end, false);

        // Collect penalty
        uint256 penalty = (lock.amount * _calculatePenaltyRate(lock.end)) / 1e18;
        if (lock.amount < penalty) penalty = lock.amount;

        SafeTransferLib.safeTransfer(token, penaltyRecipient, penalty);
        SafeTransferLib.safeTransfer(token, msg.sender, lock.amount - penalty);
        emit Unlock(msg.sender, lock.amount, penalty);
    }

    /// @notice Returns the penalty rate for a given lock expiration
    /// @param end The lock's expiration
    /// @return The penalty rate applicable to the lock
    /// @dev The penalty rate decreases linearly at the same rate as a lock's voting power
    /// in order to compensate for votes unlocked without committing to the lock expiration
    function getPenaltyRate(uint256 end) external view returns (uint256) {
        if (end <= block.timestamp) return 0;
        return _calculatePenaltyRate(end);
    }

    // Calculate penalty rate
    // Penalty rate decreases linearly at the same rate as a lock's voting power
    // in order to compensate for votes used
    function _calculatePenaltyRate(uint256 end) internal view returns (uint256) {
        // We know that end > block.timestamp because expired locks cannot be quitted
        return ((end - block.timestamp) * maxPenalty) / _MAX_TIME;
    }

    function _getEpoch(uint256 unlockTime) private pure returns (uint256) {
        return unlockTime / _SCALE;
    }

    /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ///
    ///       Owner Functions       ///
    /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ///

    /// @notice Updates the blocklist contract
    function updateBlocklist(address _addr) external onlyOwner {
        blocklist = _addr;
        emit UpdateBlocklist(_addr);
    }

    /// @notice Updates the recipient of the accumulated penalty paid by quitters
    function updatePenaltyRecipient(address _addr) external onlyOwner {
        penaltyRecipient = _addr;
        emit UpdatePenaltyRecipient(_addr);
    }

    /**
     * @notice Updates the quitlock penalty
     * @dev use case:
     *  1. Removes quitlock penalty by setting it to zero.
     *  2. Migrat to a new  VotingEscrow contract.
     */
    function updatePenalty(uint256 penalty) external onlyOwner {
        maxPenalty = penalty;
        emit UpdatePenalty(penalty);
    }

    /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ///
    ///      Disable ERC20 functions ///
    /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ///
    function allowance(address, address) external pure returns (uint256) {
        return 0;
    }

    function approve(address, uint256) external pure returns (bool) {
        return false;
    }

    function transfer(address, uint256) external pure returns (bool) {
        revert("Disabled");
    }

    function transferFrom(address, address, uint256) external pure returns (bool) {
        revert("Disabled");
    }

    /**
     * ====== others
     */

    modifier checkBlocklist() {
        if (blocklist != address(0)) {
            require(!IBlocklist(blocklist).isBlocked(msg.sender), "Blocked contract");
        }
        _;
    }

    event UpdatePenalty(uint256 penalty);
    event UpdateBlocklist(address indexed blocklist);
    event UpdatePenaltyRecipient(address indexed recipient);
    event CollectPenalty(uint256 amount, address indexed recipient);
    event Unlock(address account, uint256 value, uint256 penalty);
    event CreateLock(address indexed account, uint256 value, uint256 unlockTime);
    event IncreaseUnlockTime(address account, uint256 value, uint256 unlockTime);
    event IncreaseAmount(address account, uint256 value, uint256 unlockTime);

    error LockExpired(); // lock expired
    error CreateLockFirst(); // create lock first
    error InsufficientLockTime(); // insufficient lock time
    error ExceedsMaxLockTime(); // exceeds max lock time
    error MissingLock(); // no lock found
    error LockNotExpired(); // lock not expired
    error OnlyBlocklist(); // only callable by the blocklist contract
    error WithdrawOldTokensFirst(); // Withdraw old tokens first
    error ZeroValue(); // Zero value
}

File 2 of 9 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnershipTransferred(address indexed user, address indexed newOwner);

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

File 3 of 9 : ReentrancyGuard.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    uint256 private locked = 1;

    modifier nonReentrant() virtual {
        require(locked == 1, "REENTRANCY");

        locked = 2;

        _;

        locked = 1;
    }
}

File 4 of 9 : SafeCastLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Safe unsigned integer casting library that reverts on overflow.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeCastLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol)
library SafeCastLib {
    function safeCastTo248(uint256 x) internal pure returns (uint248 y) {
        require(x < 1 << 248);

        y = uint248(x);
    }

    function safeCastTo240(uint256 x) internal pure returns (uint240 y) {
        require(x < 1 << 240);

        y = uint240(x);
    }

    function safeCastTo232(uint256 x) internal pure returns (uint232 y) {
        require(x < 1 << 232);

        y = uint232(x);
    }

    function safeCastTo224(uint256 x) internal pure returns (uint224 y) {
        require(x < 1 << 224);

        y = uint224(x);
    }

    function safeCastTo216(uint256 x) internal pure returns (uint216 y) {
        require(x < 1 << 216);

        y = uint216(x);
    }

    function safeCastTo208(uint256 x) internal pure returns (uint208 y) {
        require(x < 1 << 208);

        y = uint208(x);
    }

    function safeCastTo200(uint256 x) internal pure returns (uint200 y) {
        require(x < 1 << 200);

        y = uint200(x);
    }

    function safeCastTo192(uint256 x) internal pure returns (uint192 y) {
        require(x < 1 << 192);

        y = uint192(x);
    }
    
    function safeCastTo184(uint256 x) internal pure returns (uint184 y) {
        require(x < 1 << 184);

        y = uint184(x);
    }

    function safeCastTo176(uint256 x) internal pure returns (uint176 y) {
        require(x < 1 << 176);

        y = uint176(x);
    }

    function safeCastTo168(uint256 x) internal pure returns (uint168 y) {
        require(x < 1 << 168);

        y = uint168(x);
    }

    function safeCastTo160(uint256 x) internal pure returns (uint160 y) {
        require(x < 1 << 160);

        y = uint160(x);
    }

    function safeCastTo152(uint256 x) internal pure returns (uint152 y) {
        require(x < 1 << 152);

        y = uint152(x);
    }

    function safeCastTo144(uint256 x) internal pure returns (uint144 y) {
        require(x < 1 << 144);

        y = uint144(x);
    }

    function safeCastTo136(uint256 x) internal pure returns (uint136 y) {
        require(x < 1 << 136);

        y = uint136(x);
    }

    function safeCastTo128(uint256 x) internal pure returns (uint128 y) {
        require(x < 1 << 128);

        y = uint128(x);
    }

    function safeCastTo120(uint256 x) internal pure returns (uint120 y) {
        require(x < 1 << 120);

        y = uint120(x);
    }

    function safeCastTo112(uint256 x) internal pure returns (uint112 y) {
        require(x < 1 << 112);

        y = uint112(x);
    }

    function safeCastTo104(uint256 x) internal pure returns (uint104 y) {
        require(x < 1 << 104);

        y = uint104(x);
    }

    function safeCastTo96(uint256 x) internal pure returns (uint96 y) {
        require(x < 1 << 96);

        y = uint96(x);
    }

    function safeCastTo88(uint256 x) internal pure returns (uint88 y) {
        require(x < 1 << 88);

        y = uint88(x);
    }

    function safeCastTo80(uint256 x) internal pure returns (uint80 y) {
        require(x < 1 << 80);

        y = uint80(x);
    }

    function safeCastTo72(uint256 x) internal pure returns (uint72 y) {
        require(x < 1 << 72);

        y = uint72(x);
    }

    function safeCastTo64(uint256 x) internal pure returns (uint64 y) {
        require(x < 1 << 64);

        y = uint64(x);
    }

    function safeCastTo56(uint256 x) internal pure returns (uint56 y) {
        require(x < 1 << 56);

        y = uint56(x);
    }

    function safeCastTo48(uint256 x) internal pure returns (uint48 y) {
        require(x < 1 << 48);

        y = uint48(x);
    }

    function safeCastTo40(uint256 x) internal pure returns (uint40 y) {
        require(x < 1 << 40);

        y = uint40(x);
    }

    function safeCastTo32(uint256 x) internal pure returns (uint32 y) {
        require(x < 1 << 32);

        y = uint32(x);
    }

    function safeCastTo24(uint256 x) internal pure returns (uint24 y) {
        require(x < 1 << 24);

        y = uint24(x);
    }

    function safeCastTo16(uint256 x) internal pure returns (uint16 y) {
        require(x < 1 << 16);

        y = uint16(x);
    }

    function safeCastTo8(uint256 x) internal pure returns (uint8 y) {
        require(x < 1 << 8);

        y = uint8(x);
    }
}

File 5 of 9 : IVotingEscrow.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.19;

import "forge-std/interfaces/IERC20.sol";

interface IVotingEscrow is IERC20 {

    /**
     * @notice Returns the vote power of `account`.
    */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @notice Returns the total vote power of all locked tokens.
    */
    function totalSupply() external view returns (uint256);
    /**
     * @dev Returns the current amount of votes that `account` has.
     * it is same with balanceOf(account)
     */
    function getVotes(address account) external view returns (uint256);

    /**
     * @notice Creates a new lock for `value` tokens that will unlock at `unlockTime`. 
     * @param value The number of tokens to be locked.
     * @param unlockTime The unix timestamp when the tokens will unlock.
     */
    function createLock(uint256 value, uint256 unlockTime) external;

    /**
     * @notice Creates a new lock for `value` tokens that will unlock at `unlockTime`,
     * and `account` can permit to spend.
     * @dev `deadline`, `v`, `r`, `s` are used for permit.
     * @param value The number of tokens to be locked.
     * @param unlockTime The unix timestamp when the tokens will unlock.
     * @param deadline The time at which to expire the signature.
     * @param v The recovery byte of the signature.
     * @param r Half of the ECDSA signature pair.
     * @param s Half of the ECDSA signature pair.
     */
    function createLockWithPermit(
        uint256 value,
        uint256 unlockTime,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Increase the amount of tokens that are locked.
     * @dev The lock must be exiting and not expired.
     * @param value The number of tokens to be increased.
     */
    function increaseAmount(uint256 value) external;

    /**
     * @notice Increase the unlock time of the lock.
     * @dev The lock must be exiting and not expired.
     * @param unlockTime The new unix timestamp when the tokens will unlock.
     */
    function increaseUnlockTime(uint256 unlockTime) external;

    /**
     * @notice Withdraws the tokens that have been unlocked.
     * @dev The lock must be expired.
     */
    function withdraw() external;

    /**
     * @notice Force withdraws the tokens that have been unlocked, and you will be charged a penalty.
     */
    function quitLock() external;

}

File 6 of 9 : IBlocklist.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.19;

interface IBlocklist {
    function isBlocked(address addr) external view returns (bool);
}

File 7 of 9 : SafeTransferLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

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

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
            mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

File 8 of 9 : IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;

/// @dev Interface of the ERC20 standard as defined in the EIP.
/// @dev This includes the optional name, symbol, and decimals metadata.
interface IERC20 {
    /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`).
    event Transfer(address indexed from, address indexed to, uint256 value);

    /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value`
    /// is the new allowance.
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /// @notice Returns the amount of tokens in existence.
    function totalSupply() external view returns (uint256);

    /// @notice Returns the amount of tokens owned by `account`.
    function balanceOf(address account) external view returns (uint256);

    /// @notice Moves `amount` tokens from the caller's account to `to`.
    function transfer(address to, uint256 amount) external returns (bool);

    /// @notice Returns the remaining number of tokens that `spender` is allowed
    /// to spend on behalf of `owner`
    function allowance(address owner, address spender) external view returns (uint256);

    /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens.
    /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
    function approve(address spender, uint256 amount) external returns (bool);

    /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism.
    /// `amount` is then deducted from the caller's allowance.
    function transferFrom(address from, address to, uint256 amount) external returns (bool);

    /// @notice Returns the name of the token.
    function name() external view returns (string memory);

    /// @notice Returns the symbol of the token.
    function symbol() external view returns (string memory);

    /// @notice Returns the decimals places of the token.
    function decimals() external view returns (uint8);
}

File 9 of 9 : ERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/=lib/openzeppelin-contracts/",
    "@solmate/=lib/solmate/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 20000
  },
  "metadata": {
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_penaltyRecipient","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CreateLockFirst","type":"error"},{"inputs":[],"name":"ExceedsMaxLockTime","type":"error"},{"inputs":[],"name":"InsufficientLockTime","type":"error"},{"inputs":[],"name":"LockExpired","type":"error"},{"inputs":[],"name":"LockNotExpired","type":"error"},{"inputs":[],"name":"MissingLock","type":"error"},{"inputs":[],"name":"OnlyBlocklist","type":"error"},{"inputs":[],"name":"WithdrawOldTokensFirst","type":"error"},{"inputs":[],"name":"ZeroValue","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":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"CollectPenalty","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockTime","type":"uint256"}],"name":"CreateLock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockTime","type":"uint256"}],"name":"IncreaseAmount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockTime","type":"uint256"}],"name":"IncreaseUnlockTime","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"penalty","type":"uint256"}],"name":"Unlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"blocklist","type":"address"}],"name":"UpdateBlocklist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"penalty","type":"uint256"}],"name":"UpdatePenalty","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"UpdatePenaltyRecipient","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocklist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"name":"createLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"unlockTime","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":"createLockWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"end","type":"uint256"}],"name":"getPenaltyRate","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":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"increaseAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"name":"increaseUnlockTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"lockEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"locked","outputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint64","name":"end","type":"uint64"},{"internalType":"uint64","name":"start","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPenalty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"penaltyRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quitLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"updateBlocklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"penalty","type":"uint256"}],"name":"updatePenalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"updatePenaltyRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a0604052670de0b6b3a76400006004553480156200001d57600080fd5b5060405162002572380380620025728339810160408190526200004091620000ca565b600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b03908116608052600380546001600160a01b0319169290911691909117905562000102565b80516001600160a01b0381168114620000c557600080fd5b919050565b60008060408385031215620000de57600080fd5b620000e983620000ad565b9150620000f960208401620000ad565b90509250929050565b60805161242a6200014860003960008181610549015281816106c101528181610a7901528181610ecb01528181610f0c015281816113ee0152611ef6015261242a6000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c80637c616fe6116100f9578063b52c05fe11610097578063dd62ed3e11610071578063dd62ed3e14610510578063e48907111461051e578063f2fde38b14610531578063fc0c546a1461054457600080fd5b8063b52c05fe14610433578063cbf9fe5f14610446578063d64e5396146104f057600080fd5b806392e93526116100d357806392e93526146103c357806395d89b41146103d65780639ab24eb014610412578063a9059cbb1461042557600080fd5b80637c616fe61461037d5780638372cd7e146103905780638da5cb5b146103a357600080fd5b8063313ce56711610166578063515770271161014057806351577027146103465780635200e79e1461035957806370a082311461036257806375c54eda1461037557600080fd5b8063313ce567146103115780633ccfd60b1461032b5780634684532e1461033357600080fd5b806315456eba116101a257806315456eba1461027f57806318160ddd1461029457806323792279146102aa57806323b872dd146102fe57600080fd5b8063012caae1146101c957806306fdde0314610213578063095ea7b31461025c575b600080fd5b6003546101e99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61024f6040518060400160405280601181526020017f566f746520457363726f776564205a544800000000000000000000000000000081525081565b60405161020a91906120b6565b61026f61026a36600461214b565b61056b565b604051901515815260200161020a565b61029261028d366004612175565b610574565b005b61029c6107ec565b60405190815260200161020a565b61029c6102b836600461218e565b73ffffffffffffffffffffffffffffffffffffffff16600090815260066020526040902054700100000000000000000000000000000000900467ffffffffffffffff1690565b61026f61030c3660046121b0565b6107fd565b610319601281565b60405160ff909116815260200161020a565b610292610867565b61029261034136600461218e565b610b0c565b610292610354366004612175565b610bfc565b61029c60045481565b61029c61037036600461218e565b610cb8565b610292610cc3565b61029261038b366004612175565b610fa4565b61029261039e3660046121ec565b61125f565b6000546101e99073ffffffffffffffffffffffffffffffffffffffff1681565b61029c6103d1366004612175565b611472565b61024f6040518060400160405280600581526020017f76655a544800000000000000000000000000000000000000000000000000000081525081565b61029c61042036600461218e565b61148c565b61026f61030c36600461214b565b610292610441366004612245565b6114ba565b6104b761045436600461218e565b6006602052600090815260409020546fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161020a565b6005546101e99073ffffffffffffffffffffffffffffffffffffffff1681565b61029c61026a366004612267565b61029261052c36600461218e565b6115e0565b61029261053f36600461218e565b6116d0565b6101e97f000000000000000000000000000000000000000000000000000000000000000081565b60005b92915050565b336000908152600660209081526040808320815160608101835290546fffffffffffffffffffffffffffffffff8116825267ffffffffffffffff7001000000000000000000000000000000008204811694830194909452780100000000000000000000000000000000000000000000000090049092169082015290829003610628576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516fffffffffffffffffffffffffffffffff16600003610675576040517f4cbcf00e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42816020015167ffffffffffffffff16116106bc576040517ff6fafba000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106e87f00000000000000000000000000000000000000000000000000000000000000003330856117c1565b80516107109061070b9084906fffffffffffffffffffffffffffffffff166122c9565b611887565b336000908152600660209081526040822080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9490941693909317909255908201516107789067ffffffffffffffff166118aa565b9050610796338285856020015167ffffffffffffffff1660016118b9565b6020808301516040805133815292830186905267ffffffffffffffff909116908201527f837403c20d32bb2d2c7f2a3d9a0e648369645c6fb8985cc0c5c9ddb0bacc5115906060015b60405180910390a1505050565b60006107f86001611b5e565b905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f44697361626c656400000000000000000000000000000000000000000000000060448201526000906064015b60405180910390fd5b336000908152600660209081526040808320815160608101835290546fffffffffffffffffffffffffffffffff811680835267ffffffffffffffff7001000000000000000000000000000000008304811695840195909552780100000000000000000000000000000000000000000000000090910490931691810191909152910361091e576040517f5a10eeb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42816020015167ffffffffffffffff161115610966576040517f6855a80200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051606081018252600080825260208083018281528385018381523384526006835294832093518454915195516fffffffffffffffffffffffffffffffff9091167fffffffffffffffff0000000000000000000000000000000000000000000000009092169190911770010000000000000000000000000000000067ffffffffffffffff968716021777ffffffffffffffffffffffffffffffffffffffffffffffff1678010000000000000000000000000000000000000000000000009186169190910217909255908301519091610a4091166118aa565b9050610a74338284600001516fffffffffffffffffffffffffffffffff16856020015167ffffffffffffffff1660006118b9565b610ab57f00000000000000000000000000000000000000000000000000000000000000003384600001516fffffffffffffffffffffffffffffffff16611c5d565b8151604080513381526fffffffffffffffffffffffffffffffff9092166020830152600082820152517ff7870c5b224cbc19873599e46ccfc7103934650509b1af0c3ce90138377c20049181900360600190a15050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161085e565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fb089f68ad820a83477076ed7bca5d94c6a56c0c85e82b7ed8df87507a1d6198b90600090a250565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161085e565b60048190556040518181527f913f55cddab919dfae78473c1ffa52c2f3add33c3b4997fa844d47e625e61a8c9060200160405180910390a150565b600061056e8261148c565b336000908152600660209081526040808320815160608101835290546fffffffffffffffffffffffffffffffff811680835267ffffffffffffffff70010000000000000000000000000000000083048116958401959095527801000000000000000000000000000000000000000000000000909104909316918101919091529103610d7a576040517f5a10eeb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42816020015167ffffffffffffffff1611610dc1576040517ff6fafba000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600660209081526040822080547fffffffffffffffff000000000000000000000000000000000000000000000000169055820151610e0e9067ffffffffffffffff166118aa565b9050610e42338284600001516fffffffffffffffffffffffffffffffff16856020015167ffffffffffffffff1660006118b9565b6000670de0b6b3a7640000610e64846020015167ffffffffffffffff16611d1c565b8451610e8291906fffffffffffffffffffffffffffffffff166122dc565b610e8c91906122f3565b90508083600001516fffffffffffffffffffffffffffffffff161015610ec2575081516fffffffffffffffffffffffffffffffff165b600354610f07907f00000000000000000000000000000000000000000000000000000000000000009073ffffffffffffffffffffffffffffffffffffffff1683611c5d565b610f537f0000000000000000000000000000000000000000000000000000000000000000338386600001516fffffffffffffffffffffffffffffffff16610f4e919061232e565b611c5d565b8251604080513381526fffffffffffffffffffffffffffffffff909216602083015281018290527ff7870c5b224cbc19873599e46ccfc7103934650509b1af0c3ce90138377c2004906060016107df565b336000908152600660209081526040808320815160608101835290546fffffffffffffffffffffffffffffffff811680835267ffffffffffffffff7001000000000000000000000000000000008304811695840195909552780100000000000000000000000000000000000000000000000090910490931691810191909152910361105b576040517f4cbcf00e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110696301e13380426122c9565b8211156110a2576040517f0c0a7be800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4282116110db576040517fa71da57a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff168211611122576040517fa71da57a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61112b82611d46565b336000908152600660209081526040822080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff95861602179055830151909161119191166118aa565b9050600061119e846118aa565b90506111d2338385600001516fffffffffffffffffffffffffffffffff16866020015167ffffffffffffffff1660006118b9565b6111f6338285600001516fffffffffffffffffffffffffffffffff168760016118b9565b8251602080850151604080513381526fffffffffffffffffffffffffffffffff9094169284019290925267ffffffffffffffff1682820152517f57298400ad5d00e0852d12f94505a8a775bf56b71f083d49159aefbf9c7c059d9181900360600190a150505050565b60055473ffffffffffffffffffffffffffffffffffffffff1615611376576005546040517ffbac395100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063fbac395190602401602060405180830381865afa1580156112eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130f9190612341565b15611376576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f426c6f636b656420636f6e747261637400000000000000000000000000000000604482015260640161085e565b6040517fd505accf0000000000000000000000000000000000000000000000000000000081523360048201523060248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60448201526064810185905260ff8416608482015260a4810183905260c481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063d505accf9060e401600060405180830381600087803b15801561144757600080fd5b505af115801561145b573d6000803e3d6000fd5b5050505061146a338787611d5d565b505050505050565b600042821161148357506000919050565b61056e82611d1c565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040812061056e90611b5e565b60055473ffffffffffffffffffffffffffffffffffffffff16156115d1576005546040517ffbac395100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063fbac395190602401602060405180830381865afa158015611546573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156a9190612341565b156115d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f426c6f636b656420636f6e747261637400000000000000000000000000000000604482015260640161085e565b6115dc338383611d5d565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611661576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161085e565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517ff5fad27d0b1a5f45f08a652a1e4502d75974a852e28d3502d4a978b7cfd900ba90600090a250565b60005473ffffffffffffffffffffffffffffffffffffffff163314611751576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161085e565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080611880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000604482015260640161085e565b5050505050565b600070010000000000000000000000000000000082106118a657600080fd5b5090565b600061056e62093a80836122f3565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260026020908152604080832087845282528083208151808301835290546fffffffffffffffffffffffffffffffff8082168352700100000000000000000000000000000000918290048116838601528986526001855294839020835180850190945254808616845204909316918101919091528215611a1357600061195d61070b86886122dc565b9050600061196a87611887565b9050808460000181815161197e9190612363565b6fffffffffffffffffffffffffffffffff169052506020840180518391906119a7908390612363565b6fffffffffffffffffffffffffffffffff169052508251819084906119cd908390612363565b6fffffffffffffffffffffffffffffffff169052506020830180518391906119f6908390612363565b6fffffffffffffffffffffffffffffffff16905250611ad3915050565b6000611a2261070b86886122dc565b90506000611a2f87611887565b90508084600001818151611a439190612393565b6fffffffffffffffffffffffffffffffff16905250602084018051839190611a6c908390612393565b6fffffffffffffffffffffffffffffffff16905250825181908490611a92908390612393565b6fffffffffffffffffffffffffffffffff16905250602083018051839190611abb908390612393565b6fffffffffffffffffffffffffffffffff1690525050505b73ffffffffffffffffffffffffffffffffffffffff9690961660009081526002602090815260408083209783529681528682208351938201516fffffffffffffffffffffffffffffffff948516700100000000000000000000000000000000918616820217909155600182529690912087519190970151908216911690940293909317909355505050565b600080611b6a426118aa565b90506000611b7f62093a806301e133806122f3565b9050600060015b828111611c395760008681611b9b84886122c9565b815260208082019290925260409081016000208151808301909252546fffffffffffffffffffffffffffffffff80821680845270010000000000000000000000000000000090920416928201929092529150611bf89042906122dc565b81602001516fffffffffffffffffffffffffffffffff16611c19919061232e565b611c2390846122c9565b9250508080611c31906123bc565b915050611b86565b506301e13380611c4a6004836122dc565b611c5491906122f3565b95945050505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611d16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015260640161085e565b50505050565b60006301e133806004544284611d32919061232e565b611d3c91906122dc565b61056e91906122f3565b60006801000000000000000082106118a657600080fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260066020908152604091829020825160608101845290546fffffffffffffffffffffffffffffffff811680835267ffffffffffffffff700100000000000000000000000000000000830481169484019490945278010000000000000000000000000000000000000000000000009091049092169281019290925215611e2a576040517fc1338bff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600003611e64576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e7162127500426122c9565b821015611eaa576040517fa71da57a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611eb86301e13380426122c9565b821115611ef1576040517f0c0a7be800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f1d7f00000000000000000000000000000000000000000000000000000000000000003330866117c1565b6040518060600160405280611f3185611887565b6fffffffffffffffffffffffffffffffff168152602001611f5184611d46565b67ffffffffffffffff168152602001611f6942611d46565b67ffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff8616600090815260066020908152604080832085518154938701519690920151851678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff96909516700100000000000000000000000000000000027fffffffffffffffff0000000000000000000000000000000000000000000000009093166fffffffffffffffffffffffffffffffff9092169190911791909117939093169190911790915561204e836118aa565b905061205e8582868660016118b9565b604080518581526020810185905273ffffffffffffffffffffffffffffffffffffffff8716917f7a5ab9a2688d59d992e38347d0765f7789af33b9fdbf1786dec603ae4a2975a6910160405180910390a25050505050565b600060208083528351808285015260005b818110156120e3578581018301518582016040015282016120c7565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461214657600080fd5b919050565b6000806040838503121561215e57600080fd5b61216783612122565b946020939093013593505050565b60006020828403121561218757600080fd5b5035919050565b6000602082840312156121a057600080fd5b6121a982612122565b9392505050565b6000806000606084860312156121c557600080fd5b6121ce84612122565b92506121dc60208501612122565b9150604084013590509250925092565b60008060008060008060c0878903121561220557600080fd5b863595506020870135945060408701359350606087013560ff8116811461222b57600080fd5b9598949750929560808101359460a0909101359350915050565b6000806040838503121561225857600080fd5b50508035926020909101359150565b6000806040838503121561227a57600080fd5b61228383612122565b915061229160208401612122565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561056e5761056e61229a565b808202811582820484141761056e5761056e61229a565b600082612329577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561056e5761056e61229a565b60006020828403121561235357600080fd5b815180151581146121a957600080fd5b6fffffffffffffffffffffffffffffffff81811683821601908082111561238c5761238c61229a565b5092915050565b6fffffffffffffffffffffffffffffffff82811682821603908082111561238c5761238c61229a565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123ed576123ed61229a565b506001019056fea26469706673582212204189c24916a54e2db72d6df17dcfcdbc384f26b9cf2d27c2e6764f874ef7f2be64736f6c63430008130033000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000a82b4758df44fcb124e26a9b441e59a0

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101c45760003560e01c80637c616fe6116100f9578063b52c05fe11610097578063dd62ed3e11610071578063dd62ed3e14610510578063e48907111461051e578063f2fde38b14610531578063fc0c546a1461054457600080fd5b8063b52c05fe14610433578063cbf9fe5f14610446578063d64e5396146104f057600080fd5b806392e93526116100d357806392e93526146103c357806395d89b41146103d65780639ab24eb014610412578063a9059cbb1461042557600080fd5b80637c616fe61461037d5780638372cd7e146103905780638da5cb5b146103a357600080fd5b8063313ce56711610166578063515770271161014057806351577027146103465780635200e79e1461035957806370a082311461036257806375c54eda1461037557600080fd5b8063313ce567146103115780633ccfd60b1461032b5780634684532e1461033357600080fd5b806315456eba116101a257806315456eba1461027f57806318160ddd1461029457806323792279146102aa57806323b872dd146102fe57600080fd5b8063012caae1146101c957806306fdde0314610213578063095ea7b31461025c575b600080fd5b6003546101e99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61024f6040518060400160405280601181526020017f566f746520457363726f776564205a544800000000000000000000000000000081525081565b60405161020a91906120b6565b61026f61026a36600461214b565b61056b565b604051901515815260200161020a565b61029261028d366004612175565b610574565b005b61029c6107ec565b60405190815260200161020a565b61029c6102b836600461218e565b73ffffffffffffffffffffffffffffffffffffffff16600090815260066020526040902054700100000000000000000000000000000000900467ffffffffffffffff1690565b61026f61030c3660046121b0565b6107fd565b610319601281565b60405160ff909116815260200161020a565b610292610867565b61029261034136600461218e565b610b0c565b610292610354366004612175565b610bfc565b61029c60045481565b61029c61037036600461218e565b610cb8565b610292610cc3565b61029261038b366004612175565b610fa4565b61029261039e3660046121ec565b61125f565b6000546101e99073ffffffffffffffffffffffffffffffffffffffff1681565b61029c6103d1366004612175565b611472565b61024f6040518060400160405280600581526020017f76655a544800000000000000000000000000000000000000000000000000000081525081565b61029c61042036600461218e565b61148c565b61026f61030c36600461214b565b610292610441366004612245565b6114ba565b6104b761045436600461218e565b6006602052600090815260409020546fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161020a565b6005546101e99073ffffffffffffffffffffffffffffffffffffffff1681565b61029c61026a366004612267565b61029261052c36600461218e565b6115e0565b61029261053f36600461218e565b6116d0565b6101e97f00000000000000000000000000000000a82b4758df44fcb124e26a9b441e59a081565b60005b92915050565b336000908152600660209081526040808320815160608101835290546fffffffffffffffffffffffffffffffff8116825267ffffffffffffffff7001000000000000000000000000000000008204811694830194909452780100000000000000000000000000000000000000000000000090049092169082015290829003610628576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516fffffffffffffffffffffffffffffffff16600003610675576040517f4cbcf00e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42816020015167ffffffffffffffff16116106bc576040517ff6fafba000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106e87f00000000000000000000000000000000a82b4758df44fcb124e26a9b441e59a03330856117c1565b80516107109061070b9084906fffffffffffffffffffffffffffffffff166122c9565b611887565b336000908152600660209081526040822080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9490941693909317909255908201516107789067ffffffffffffffff166118aa565b9050610796338285856020015167ffffffffffffffff1660016118b9565b6020808301516040805133815292830186905267ffffffffffffffff909116908201527f837403c20d32bb2d2c7f2a3d9a0e648369645c6fb8985cc0c5c9ddb0bacc5115906060015b60405180910390a1505050565b60006107f86001611b5e565b905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f44697361626c656400000000000000000000000000000000000000000000000060448201526000906064015b60405180910390fd5b336000908152600660209081526040808320815160608101835290546fffffffffffffffffffffffffffffffff811680835267ffffffffffffffff7001000000000000000000000000000000008304811695840195909552780100000000000000000000000000000000000000000000000090910490931691810191909152910361091e576040517f5a10eeb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42816020015167ffffffffffffffff161115610966576040517f6855a80200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051606081018252600080825260208083018281528385018381523384526006835294832093518454915195516fffffffffffffffffffffffffffffffff9091167fffffffffffffffff0000000000000000000000000000000000000000000000009092169190911770010000000000000000000000000000000067ffffffffffffffff968716021777ffffffffffffffffffffffffffffffffffffffffffffffff1678010000000000000000000000000000000000000000000000009186169190910217909255908301519091610a4091166118aa565b9050610a74338284600001516fffffffffffffffffffffffffffffffff16856020015167ffffffffffffffff1660006118b9565b610ab57f00000000000000000000000000000000a82b4758df44fcb124e26a9b441e59a03384600001516fffffffffffffffffffffffffffffffff16611c5d565b8151604080513381526fffffffffffffffffffffffffffffffff9092166020830152600082820152517ff7870c5b224cbc19873599e46ccfc7103934650509b1af0c3ce90138377c20049181900360600190a15050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161085e565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fb089f68ad820a83477076ed7bca5d94c6a56c0c85e82b7ed8df87507a1d6198b90600090a250565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161085e565b60048190556040518181527f913f55cddab919dfae78473c1ffa52c2f3add33c3b4997fa844d47e625e61a8c9060200160405180910390a150565b600061056e8261148c565b336000908152600660209081526040808320815160608101835290546fffffffffffffffffffffffffffffffff811680835267ffffffffffffffff70010000000000000000000000000000000083048116958401959095527801000000000000000000000000000000000000000000000000909104909316918101919091529103610d7a576040517f5a10eeb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42816020015167ffffffffffffffff1611610dc1576040517ff6fafba000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600660209081526040822080547fffffffffffffffff000000000000000000000000000000000000000000000000169055820151610e0e9067ffffffffffffffff166118aa565b9050610e42338284600001516fffffffffffffffffffffffffffffffff16856020015167ffffffffffffffff1660006118b9565b6000670de0b6b3a7640000610e64846020015167ffffffffffffffff16611d1c565b8451610e8291906fffffffffffffffffffffffffffffffff166122dc565b610e8c91906122f3565b90508083600001516fffffffffffffffffffffffffffffffff161015610ec2575081516fffffffffffffffffffffffffffffffff165b600354610f07907f00000000000000000000000000000000a82b4758df44fcb124e26a9b441e59a09073ffffffffffffffffffffffffffffffffffffffff1683611c5d565b610f537f00000000000000000000000000000000a82b4758df44fcb124e26a9b441e59a0338386600001516fffffffffffffffffffffffffffffffff16610f4e919061232e565b611c5d565b8251604080513381526fffffffffffffffffffffffffffffffff909216602083015281018290527ff7870c5b224cbc19873599e46ccfc7103934650509b1af0c3ce90138377c2004906060016107df565b336000908152600660209081526040808320815160608101835290546fffffffffffffffffffffffffffffffff811680835267ffffffffffffffff7001000000000000000000000000000000008304811695840195909552780100000000000000000000000000000000000000000000000090910490931691810191909152910361105b576040517f4cbcf00e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110696301e13380426122c9565b8211156110a2576040517f0c0a7be800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4282116110db576040517fa71da57a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff168211611122576040517fa71da57a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61112b82611d46565b336000908152600660209081526040822080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff95861602179055830151909161119191166118aa565b9050600061119e846118aa565b90506111d2338385600001516fffffffffffffffffffffffffffffffff16866020015167ffffffffffffffff1660006118b9565b6111f6338285600001516fffffffffffffffffffffffffffffffff168760016118b9565b8251602080850151604080513381526fffffffffffffffffffffffffffffffff9094169284019290925267ffffffffffffffff1682820152517f57298400ad5d00e0852d12f94505a8a775bf56b71f083d49159aefbf9c7c059d9181900360600190a150505050565b60055473ffffffffffffffffffffffffffffffffffffffff1615611376576005546040517ffbac395100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063fbac395190602401602060405180830381865afa1580156112eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130f9190612341565b15611376576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f426c6f636b656420636f6e747261637400000000000000000000000000000000604482015260640161085e565b6040517fd505accf0000000000000000000000000000000000000000000000000000000081523360048201523060248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60448201526064810185905260ff8416608482015260a4810183905260c481018290527f00000000000000000000000000000000a82b4758df44fcb124e26a9b441e59a073ffffffffffffffffffffffffffffffffffffffff169063d505accf9060e401600060405180830381600087803b15801561144757600080fd5b505af115801561145b573d6000803e3d6000fd5b5050505061146a338787611d5d565b505050505050565b600042821161148357506000919050565b61056e82611d1c565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040812061056e90611b5e565b60055473ffffffffffffffffffffffffffffffffffffffff16156115d1576005546040517ffbac395100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063fbac395190602401602060405180830381865afa158015611546573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156a9190612341565b156115d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f426c6f636b656420636f6e747261637400000000000000000000000000000000604482015260640161085e565b6115dc338383611d5d565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611661576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161085e565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517ff5fad27d0b1a5f45f08a652a1e4502d75974a852e28d3502d4a978b7cfd900ba90600090a250565b60005473ffffffffffffffffffffffffffffffffffffffff163314611751576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161085e565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080611880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000604482015260640161085e565b5050505050565b600070010000000000000000000000000000000082106118a657600080fd5b5090565b600061056e62093a80836122f3565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260026020908152604080832087845282528083208151808301835290546fffffffffffffffffffffffffffffffff8082168352700100000000000000000000000000000000918290048116838601528986526001855294839020835180850190945254808616845204909316918101919091528215611a1357600061195d61070b86886122dc565b9050600061196a87611887565b9050808460000181815161197e9190612363565b6fffffffffffffffffffffffffffffffff169052506020840180518391906119a7908390612363565b6fffffffffffffffffffffffffffffffff169052508251819084906119cd908390612363565b6fffffffffffffffffffffffffffffffff169052506020830180518391906119f6908390612363565b6fffffffffffffffffffffffffffffffff16905250611ad3915050565b6000611a2261070b86886122dc565b90506000611a2f87611887565b90508084600001818151611a439190612393565b6fffffffffffffffffffffffffffffffff16905250602084018051839190611a6c908390612393565b6fffffffffffffffffffffffffffffffff16905250825181908490611a92908390612393565b6fffffffffffffffffffffffffffffffff16905250602083018051839190611abb908390612393565b6fffffffffffffffffffffffffffffffff1690525050505b73ffffffffffffffffffffffffffffffffffffffff9690961660009081526002602090815260408083209783529681528682208351938201516fffffffffffffffffffffffffffffffff948516700100000000000000000000000000000000918616820217909155600182529690912087519190970151908216911690940293909317909355505050565b600080611b6a426118aa565b90506000611b7f62093a806301e133806122f3565b9050600060015b828111611c395760008681611b9b84886122c9565b815260208082019290925260409081016000208151808301909252546fffffffffffffffffffffffffffffffff80821680845270010000000000000000000000000000000090920416928201929092529150611bf89042906122dc565b81602001516fffffffffffffffffffffffffffffffff16611c19919061232e565b611c2390846122c9565b9250508080611c31906123bc565b915050611b86565b506301e13380611c4a6004836122dc565b611c5491906122f3565b95945050505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611d16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015260640161085e565b50505050565b60006301e133806004544284611d32919061232e565b611d3c91906122dc565b61056e91906122f3565b60006801000000000000000082106118a657600080fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260066020908152604091829020825160608101845290546fffffffffffffffffffffffffffffffff811680835267ffffffffffffffff700100000000000000000000000000000000830481169484019490945278010000000000000000000000000000000000000000000000009091049092169281019290925215611e2a576040517fc1338bff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600003611e64576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e7162127500426122c9565b821015611eaa576040517fa71da57a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611eb86301e13380426122c9565b821115611ef1576040517f0c0a7be800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f1d7f00000000000000000000000000000000a82b4758df44fcb124e26a9b441e59a03330866117c1565b6040518060600160405280611f3185611887565b6fffffffffffffffffffffffffffffffff168152602001611f5184611d46565b67ffffffffffffffff168152602001611f6942611d46565b67ffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff8616600090815260066020908152604080832085518154938701519690920151851678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff96909516700100000000000000000000000000000000027fffffffffffffffff0000000000000000000000000000000000000000000000009093166fffffffffffffffffffffffffffffffff9092169190911791909117939093169190911790915561204e836118aa565b905061205e8582868660016118b9565b604080518581526020810185905273ffffffffffffffffffffffffffffffffffffffff8716917f7a5ab9a2688d59d992e38347d0765f7789af33b9fdbf1786dec603ae4a2975a6910160405180910390a25050505050565b600060208083528351808285015260005b818110156120e3578581018301518582016040015282016120c7565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461214657600080fd5b919050565b6000806040838503121561215e57600080fd5b61216783612122565b946020939093013593505050565b60006020828403121561218757600080fd5b5035919050565b6000602082840312156121a057600080fd5b6121a982612122565b9392505050565b6000806000606084860312156121c557600080fd5b6121ce84612122565b92506121dc60208501612122565b9150604084013590509250925092565b60008060008060008060c0878903121561220557600080fd5b863595506020870135945060408701359350606087013560ff8116811461222b57600080fd5b9598949750929560808101359460a0909101359350915050565b6000806040838503121561225857600080fd5b50508035926020909101359150565b6000806040838503121561227a57600080fd5b61228383612122565b915061229160208401612122565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561056e5761056e61229a565b808202811582820484141761056e5761056e61229a565b600082612329577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8181038181111561056e5761056e61229a565b60006020828403121561235357600080fd5b815180151581146121a957600080fd5b6fffffffffffffffffffffffffffffffff81811683821601908082111561238c5761238c61229a565b5092915050565b6fffffffffffffffffffffffffffffffff82811682821603908082111561238c5761238c61229a565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123ed576123ed61229a565b506001019056fea26469706673582212204189c24916a54e2db72d6df17dcfcdbc384f26b9cf2d27c2e6764f874ef7f2be64736f6c63430008130033

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

000000000000000000000000000000000000000000000000000000000000dead00000000000000000000000000000000a82b4758df44fcb124e26a9b441e59a0

-----Decoded View---------------
Arg [0] : _penaltyRecipient (address): 0x000000000000000000000000000000000000dEaD
Arg [1] : _token (address): 0x00000000A82B4758df44fcB124e26a9B441E59a0

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000000000000000000000dead
Arg [1] : 00000000000000000000000000000000a82b4758df44fcb124e26a9b441e59a0


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.