ETH Price: $2,927.30 (+4.78%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw211360642024-11-07 13:26:3521 hrs ago1730985995IN
0x7e01A500...0A332B7b3
0 ETH0.00308316.20270584
Create Lock211032182024-11-02 23:24:595 days ago1730589899IN
0x7e01A500...0A332B7b3
0 ETH0.001412165.59692438
Withdraw210618272024-10-28 4:44:2311 days ago1730090663IN
0x7e01A500...0A332B7b3
0 ETH0.000705954.59449834
Withdraw210614922024-10-28 3:36:5911 days ago1730086619IN
0x7e01A500...0A332B7b3
0 ETH0.001437865.74520081
Withdraw209275692024-10-09 10:54:5930 days ago1728471299IN
0x7e01A500...0A332B7b3
0 ETH0.0030174619.63829912
Withdraw208916082024-10-04 10:37:5935 days ago1728038279IN
0x7e01A500...0A332B7b3
0 ETH0.001729446.91024786
Withdraw208047762024-09-22 7:58:5947 days ago1726991939IN
0x7e01A500...0A332B7b3
0 ETH0.0019257712.53335845
Withdraw207985562024-09-21 11:08:5947 days ago1726916939IN
0x7e01A500...0A332B7b3
0 ETH0.001397149.09294536
Withdraw207977532024-09-21 8:27:3548 days ago1726907255IN
0x7e01A500...0A332B7b3
0 ETH0.001034237.57390085
Create Lock207830312024-09-19 7:05:1150 days ago1726729511IN
0x7e01A500...0A332B7b3
0 ETH0.0029991112.92058801
Create Lock207428462024-09-13 16:20:3555 days ago1726244435IN
0x7e01A500...0A332B7b3
0 ETH0.002324539.15144141
Withdraw207199762024-09-10 11:39:5958 days ago1725968399IN
0x7e01A500...0A332B7b3
0 ETH0.001458699.4934897
Withdraw207190032024-09-10 8:24:4759 days ago1725956687IN
0x7e01A500...0A332B7b3
0 ETH0.000790945.79228084
Create Lock207189892024-09-10 8:21:5959 days ago1725956519IN
0x7e01A500...0A332B7b3
0 ETH0.001346465.40245877
Increase Unlock ...207131922024-09-09 12:56:2359 days ago1725886583IN
0x7e01A500...0A332B7b3
0 ETH0.000146386.07674247
Increase Amount207131892024-09-09 12:55:4759 days ago1725886547IN
0x7e01A500...0A332B7b3
0 ETH0.000148976.16934829
Increase Amount207123972024-09-09 10:15:5960 days ago1725876959IN
0x7e01A500...0A332B7b3
0 ETH0.000138995.75598032
Increase Amount207123932024-09-09 10:15:1160 days ago1725876911IN
0x7e01A500...0A332B7b3
0 ETH0.000133015.50849721
Withdraw205287312024-08-14 18:42:3585 days ago1723660955IN
0x7e01A500...0A332B7b3
0 ETH0.001410586.98439195
Withdraw204493052024-08-03 16:47:1196 days ago1722703631IN
0x7e01A500...0A332B7b3
0 ETH0.000877116.42330198
Withdraw204321392024-08-01 7:14:5999 days ago1722496499IN
0x7e01A500...0A332B7b3
0 ETH0.00098784.93994785
Withdraw203931022024-07-26 20:26:59104 days ago1722025619IN
0x7e01A500...0A332B7b3
0 ETH0.00065964.29284414
Withdraw203090312024-07-15 2:49:35116 days ago1721011775IN
0x7e01A500...0A332B7b3
0 ETH0.001221467.94953094
Withdraw203041902024-07-14 10:37:11117 days ago1720953431IN
0x7e01A500...0A332B7b3
0 ETH0.000375332.44278542
Withdraw203036242024-07-14 8:43:35117 days ago1720946615IN
0x7e01A500...0A332B7b3
0 ETH0.000985866.41621162
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
150502782022-06-30 12:11:33861 days ago1656591093  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
veOLAS

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion
File 1 of 5 : veOLAS.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import "@openzeppelin/contracts/governance/utils/IVotes.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "./interfaces/IErrors.sol";

/**
Votes have a weight depending on time, so that users are committed to the future of (whatever they are voting for).
Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (4 years).
Voting escrow has time-weighted votes derived from the amount of tokens locked. The maximum voting power can be
achieved with the longest lock possible. This way the users are incentivized to lock tokens for more time.
# w ^ = amount * time_locked / MAXTIME
# 1 +        /
#   |      /
#   |    /
#   |  /
#   |/
# 0 +--------+------> time
#       maxtime (4 years?)

We cannot really do block numbers per se because slope is per time, not per block, and per block could be fairly bad
because Ethereum changes its block times. What we can do is to extrapolate ***At functions.
*/

/// @title Voting Escrow OLAS - the workflow is ported from Curve Finance Vyper implementation
/// @author Aleksandr Kuperman - <[email protected]>
/// Code ported from: https://github.com/curvefi/curve-dao-contracts/blob/master/contracts/VotingEscrow.vy
/// and: https://github.com/solidlyexchange/solidly/blob/master/contracts/ve.sol

/* This VotingEscrow is based on the OLAS token that has the following specifications:
*  - For the first 10 years there will be the cap of 1 billion (1e27) tokens;
*  - After 10 years, the inflation rate is 2% per year.
* The maximum number of tokens for each year then can be calculated from the formula: 2^n = 1e27 * (1.02)^x,
* where n is the specified number of bits that is sufficient to store and not overflow the total supply,
* and x is the number of years. We limit n by 128, thus it would take 1340+ years to reach that total supply.
* The amount for each locker is eventually cannot overcome this number as well, and thus uint128 is sufficient.
*
* We then limit the time in seconds to last until the value of 2^64 - 1, or for the next 583+ billion years.
* The number of blocks is essentially cannot be bigger than the number of seconds, and thus it is safe to assume
* that uint64 for the number of blocks is also sufficient.
*
* We also limit the individual deposit amount to be no bigger than 2^96 - 1, or the value of total supply in 220+ years.
* This limitation is dictated by the fact that there will be at least several accounts with locked tokens, and the
* sum of all of them cannot be bigger than the total supply. Checking the limit of deposited / increased amount
* allows us to perform the unchecked operation on adding the amounts.
*
* The rest of calculations throughout the contract do not go beyond specified limitations. The contract was checked
* by echidna and the results can be found in the audit section of the repository.
*
* These specified limits allowed us to have storage-added structs to be bound by 2*256 and 1*256 bit sizes
* respectively, thus limiting the gas amount compared to using bigger variable sizes.
*
* Note that after 220 years it is no longer possible to deposit / increase the locked amount to be bigger than 2^96 - 1.
* It is going to be not safe to use this contract for governance after 1340 years.
*/

// Struct for storing balance and unlock time
// The struct size is one storage slot of uint256 (128 + 64 + padding)
struct LockedBalance {
    // Token amount. It will never practically be bigger. Initial OLAS cap is 1 bn tokens, or 1e27.
    // After 10 years, the inflation rate is 2% per year. It would take 1340+ years to reach 2^128 - 1
    uint128 amount;
    // Unlock time. It will never practically be bigger
    uint64 endTime;
}

// Structure for voting escrow points
// The struct size is two storage slots of 2 * uint256 (128 + 128 + 64 + 64 + 128)
struct PointVoting {
    // w(i) = at + b (bias)
    int128 bias;
    // dw / dt = a (slope)
    int128 slope;
    // Timestamp. It will never practically be bigger than 2^64 - 1
    uint64 ts;
    // Block number. It will not be bigger than the timestamp
    uint64 blockNumber;
    // Token amount. It will never practically be bigger. Initial OLAS cap is 1 bn tokens, or 1e27.
    // After 10 years, the inflation rate is 2% per year. It would take 1340+ years to reach 2^128 - 1
    uint128 balance;
}

/// @notice This token supports the ERC20 interface specifications except for transfers and approvals.
contract veOLAS is IErrors, IVotes, IERC20, IERC165 {
    enum DepositType {
        DEPOSIT_FOR_TYPE,
        CREATE_LOCK_TYPE,
        INCREASE_LOCK_AMOUNT,
        INCREASE_UNLOCK_TIME
    }

    event Deposit(address indexed account, uint256 amount, uint256 locktime, DepositType depositType, uint256 ts);
    event Withdraw(address indexed account, uint256 amount, uint256 ts);
    event Supply(uint256 previousSupply, uint256 currentSupply);

    // 1 week time
    uint64 internal constant WEEK = 1 weeks;
    // Maximum lock time (4 years)
    uint256 internal constant MAXTIME = 4 * 365 * 86400;
    // Maximum lock time (4 years) in int128
    int128 internal constant IMAXTIME = 4 * 365 * 86400;
    // Number of decimals
    uint8 public constant decimals = 18;

    // Token address
    address public immutable token;
    // Total token supply
    uint256 public supply;
    // Mapping of account address => LockedBalance
    mapping(address => LockedBalance) public mapLockedBalances;

    // Total number of economical checkpoints (starting from zero)
    uint256 public totalNumPoints;
    // Mapping of point Id => point
    mapping(uint256 => PointVoting) public mapSupplyPoints;
    // Mapping of account address => PointVoting[point Id]
    mapping(address => PointVoting[]) public mapUserPoints;
    // Mapping of time => signed slope change
    mapping(uint64 => int128) public mapSlopeChanges;

    // Voting token name
    string public name;
    // Voting token symbol
    string public symbol;

    /// @dev Contract constructor
    /// @param _token Token address.
    /// @param _name Token name.
    /// @param _symbol Token symbol.
    constructor(address _token, string memory _name, string memory _symbol)
    {
        token = _token;
        name = _name;
        symbol = _symbol;
        // Create initial point such that default timestamp and block number are not zero
        // See cast specification in the PointVoting structure
        mapSupplyPoints[0] = PointVoting(0, 0, uint64(block.timestamp), uint64(block.number), 0);
    }

    /// @dev Gets the most recently recorded user point for `account`.
    /// @param account Account address.
    /// @return pv Last checkpoint.
    function getLastUserPoint(address account) external view returns (PointVoting memory pv) {
        uint256 lastPointNumber = mapUserPoints[account].length;
        if (lastPointNumber > 0) {
            pv = mapUserPoints[account][lastPointNumber - 1];
        }
    }

    /// @dev Gets the number of user points.
    /// @param account Account address.
    /// @return accountNumPoints Number of user points.
    function getNumUserPoints(address account) external view returns (uint256 accountNumPoints) {
        accountNumPoints = mapUserPoints[account].length;
    }

    /// @dev Gets the checkpoint structure at number `idx` for `account`.
    /// @param account User wallet address.
    /// @param idx User point number.
    /// @return The requested checkpoint.
    function getUserPoint(address account, uint256 idx) external view returns (PointVoting memory) {
        return mapUserPoints[account][idx];
    }

    /// @dev Record global and per-user data to checkpoint.
    /// @param account Account address. User checkpoint is skipped if the address is zero.
    /// @param oldLocked Previous locked amount / end lock time for the user.
    /// @param newLocked New locked amount / end lock time for the user.
    /// @param curSupply Current total supply (to avoid using a storage total supply variable)
    function _checkpoint(
        address account,
        LockedBalance memory oldLocked,
        LockedBalance memory newLocked,
        uint128 curSupply
    ) internal {
        PointVoting memory uOld;
        PointVoting memory uNew;
        int128 oldDSlope;
        int128 newDSlope;
        uint256 curNumPoint = totalNumPoints;

        if (account != address(0)) {
            // Calculate slopes and biases
            // Kept at zero when they have to
            if (oldLocked.endTime > block.timestamp && oldLocked.amount > 0) {
                uOld.slope = int128(oldLocked.amount) / IMAXTIME;
                uOld.bias = uOld.slope * int128(uint128(oldLocked.endTime - uint64(block.timestamp)));
            }
            if (newLocked.endTime > block.timestamp && newLocked.amount > 0) {
                uNew.slope = int128(newLocked.amount) / IMAXTIME;
                uNew.bias = uNew.slope * int128(uint128(newLocked.endTime - uint64(block.timestamp)));
            }

            // Reads values of scheduled changes in the slope
            // oldLocked.endTime can be in the past and in the future
            // newLocked.endTime can ONLY be in the FUTURE unless everything is expired: then zeros
            oldDSlope = mapSlopeChanges[oldLocked.endTime];
            if (newLocked.endTime > 0) {
                if (newLocked.endTime == oldLocked.endTime) {
                    newDSlope = oldDSlope;
                } else {
                    newDSlope = mapSlopeChanges[newLocked.endTime];
                }
            }
        }

        PointVoting memory lastPoint;
        if (curNumPoint > 0) {
            lastPoint = mapSupplyPoints[curNumPoint];
        } else {
            // If no point is created yet, we take the actual time and block parameters
            lastPoint = PointVoting(0, 0, uint64(block.timestamp), uint64(block.number), 0);
        }
        uint64 lastCheckpoint = lastPoint.ts;
        // initialPoint is used for extrapolation to calculate the block number and save them
        // as we cannot figure that out in exact values from inside of the contract
        PointVoting memory initialPoint = lastPoint;
        uint256 block_slope; // dblock/dt
        if (block.timestamp > lastPoint.ts) {
            // This 1e18 multiplier is needed for the numerator to be bigger than the denominator
            // We need to calculate this in > uint64 size (1e18 is > 2^59 multiplied by 2^64).
            block_slope = (1e18 * uint256(block.number - lastPoint.blockNumber)) / uint256(block.timestamp - lastPoint.ts);
        }
        // If last point is already recorded in this block, slope == 0, but we know the block already in this case
        // Go over weeks to fill in the history and (or) calculate what the current point is
        {
            // The timestamp is rounded and < 2^64-1
            uint64 tStep = (lastCheckpoint / WEEK) * WEEK;
            for (uint256 i = 0; i < 255; ++i) {
                // Hopefully it won't happen that this won't get used in 5 years!
                // If it does, users will be able to withdraw but vote weight will be broken
                // This is always practically < 2^64-1
                unchecked {
                    tStep += WEEK;
                }
                int128 dSlope;
                if (tStep > block.timestamp) {
                    tStep = uint64(block.timestamp);
                } else {
                    dSlope = mapSlopeChanges[tStep];
                }
                lastPoint.bias -= lastPoint.slope * int128(int64(tStep - lastCheckpoint));
                lastPoint.slope += dSlope;
                if (lastPoint.bias < 0) {
                    // This could potentially happen, but fuzzer didn't find available "real" combinations
                    lastPoint.bias = 0;
                }
                if (lastPoint.slope < 0) {
                    // This cannot happen - just in case. Again, fuzzer didn't reach this
                    lastPoint.slope = 0;
                }
                lastCheckpoint = tStep;
                lastPoint.ts = tStep;
                // After division by 1e18 the uint64 size can be reclaimed
                lastPoint.blockNumber = initialPoint.blockNumber + uint64((block_slope * uint256(tStep - initialPoint.ts)) / 1e18);
                lastPoint.balance = initialPoint.balance;
                // In order for the overflow of total number of economical checkpoints (starting from zero)
                // The _checkpoint() call must happen n >(2^256 -1)/255 or n > ~1e77/255 > ~1e74 times
                unchecked {
                    curNumPoint += 1;    
                }
                if (tStep == block.timestamp) {
                    lastPoint.blockNumber = uint64(block.number);
                    lastPoint.balance = curSupply;
                    break;
                } else {
                    mapSupplyPoints[curNumPoint] = lastPoint;
                }
            }
        }

        totalNumPoints = curNumPoint;

        // Now mapSupplyPoints is filled until current time
        if (account != address(0)) {
            // If last point was in this block, the slope change has been already applied. In such case we have 0 slope(s)
            lastPoint.slope += (uNew.slope - uOld.slope);
            lastPoint.bias += (uNew.bias - uOld.bias);
            if (lastPoint.slope < 0) {
                lastPoint.slope = 0;
            }
            if (lastPoint.bias < 0) {
                lastPoint.bias = 0;
            }
        }

        // Record the last updated point
        mapSupplyPoints[curNumPoint] = lastPoint;

        if (account != address(0)) {
            // Schedule the slope changes (slope is going down)
            // We subtract new_user_slope from [newLocked.endTime]
            // and add old_user_slope to [oldLocked.endTime]
            if (oldLocked.endTime > block.timestamp) {
                // oldDSlope was <something> - uOld.slope, so we cancel that
                oldDSlope += uOld.slope;
                if (newLocked.endTime == oldLocked.endTime) {
                    oldDSlope -= uNew.slope; // It was a new deposit, not extension
                }
                mapSlopeChanges[oldLocked.endTime] = oldDSlope;
            }

            if (newLocked.endTime > block.timestamp && newLocked.endTime > oldLocked.endTime) {
                newDSlope -= uNew.slope; // old slope disappeared at this point
                mapSlopeChanges[newLocked.endTime] = newDSlope;
                // else: we recorded it already in oldDSlope
            }
            // Now handle user history
            uNew.ts = uint64(block.timestamp);
            uNew.blockNumber = uint64(block.number);
            uNew.balance = newLocked.amount;
            mapUserPoints[account].push(uNew);
        }
    }

    /// @dev Record global data to checkpoint.
    function checkpoint() external {
        _checkpoint(address(0), LockedBalance(0, 0), LockedBalance(0, 0), uint128(supply));
    }

    /// @dev Deposits and locks tokens for a specified account.
    /// @param account Target address for the locked amount.
    /// @param amount Amount to deposit.
    /// @param unlockTime New time when to unlock the tokens, or 0 if unchanged.
    /// @param lockedBalance Previous locked amount / end time.
    /// @param depositType Deposit type.
    function _depositFor(
        address account,
        uint256 amount,
        uint256 unlockTime,
        LockedBalance memory lockedBalance,
        DepositType depositType
    ) internal {
        uint256 supplyBefore = supply;
        uint256 supplyAfter;
        // Cannot overflow because the total supply << 2^128-1
        unchecked {
            supplyAfter = supplyBefore + amount;
            supply = supplyAfter;
        }
        // Get the old locked data
        LockedBalance memory oldLocked;
        (oldLocked.amount, oldLocked.endTime) = (lockedBalance.amount, lockedBalance.endTime);
        // Adding to the existing lock, or if a lock is expired - creating a new one
        // This cannot be larger than the total supply
        unchecked {
            lockedBalance.amount += uint128(amount);
        }
        if (unlockTime > 0) {
            lockedBalance.endTime = uint64(unlockTime);
        }
        mapLockedBalances[account] = lockedBalance;

        // Possibilities:
        // Both oldLocked.endTime could be current or expired (>/< block.timestamp)
        // amount == 0 (extend lock) or amount > 0 (add to lock or extend lock)
        // lockedBalance.endTime > block.timestamp (always)
        _checkpoint(account, oldLocked, lockedBalance, uint128(supplyAfter));
        if (amount > 0) {
            // OLAS is a solmate-based ERC20 token with optimized transferFrom() that either returns true or reverts
            IERC20(token).transferFrom(msg.sender, address(this), amount);
        }

        emit Deposit(account, amount, lockedBalance.endTime, depositType, block.timestamp);
        emit Supply(supplyBefore, supplyAfter);
    }

    /// @dev Deposits `amount` tokens for `account` and adds to the lock.
    /// @dev Anyone (even a smart contract) can deposit for someone else, but
    ///      cannot extend their locktime and deposit for a brand new user.
    /// @param account Account address.
    /// @param amount Amount to add.
    function depositFor(address account, uint256 amount) external {
        LockedBalance memory lockedBalance = mapLockedBalances[account];
        // Check if the amount is zero
        if (amount == 0) {
            revert ZeroValue();
        }
        // The locked balance must already exist
        if (lockedBalance.amount == 0) {
            revert NoValueLocked(account);
        }
        // Check the lock expiry
        if (lockedBalance.endTime < (block.timestamp + 1)) {
            revert LockExpired(msg.sender, lockedBalance.endTime, block.timestamp);
        }
        // Since in the _depositFor() we have the unchecked sum of amounts, this is needed to prevent unsafe behavior.
        // After 10 years, the inflation rate is 2% per year. It would take 220+ years to reach 2^96 - 1 total supply
        if (amount > type(uint96).max) {
            revert Overflow(amount, type(uint96).max);
        }

        _depositFor(account, amount, 0, lockedBalance, DepositType.DEPOSIT_FOR_TYPE);
    }

    /// @dev Deposits `amount` tokens for `msg.sender` and locks for `unlockTime`.
    /// @param amount Amount to deposit.
    /// @param unlockTime Time when tokens unlock, rounded down to a whole week.
    function createLock(uint256 amount, uint256 unlockTime) external {
        _createLockFor(msg.sender, amount, unlockTime);
    }

    /// @dev Deposits `amount` tokens for `account` and locks for `unlockTime`.
    /// @notice Tokens are taken from `msg.sender`'s balance.
    /// @param account Account address.
    /// @param amount Amount to deposit.
    /// @param unlockTime Time when tokens unlock, rounded down to a whole week.
    function createLockFor(address account, uint256 amount, uint256 unlockTime) external {
        // Check if the account address is zero
        if (account == address(0)) {
            revert ZeroAddress();
        }

        _createLockFor(account, amount, unlockTime);
    }

    /// @dev Deposits `amount` tokens for `account` and locks for `unlockTime`.
    /// @notice Tokens are taken from `msg.sender`'s balance.
    /// @param account Account address.
    /// @param amount Amount to deposit.
    /// @param unlockTime Time when tokens unlock, rounded down to a whole week.
    function _createLockFor(address account, uint256 amount, uint256 unlockTime) private {
        // Check if the amount is zero
        if (amount == 0) {
            revert ZeroValue();
        }
        // Lock time is rounded down to weeks
        // Cannot practically overflow because block.timestamp + unlockTime (max 4 years) << 2^64-1
        unchecked {
            unlockTime = ((block.timestamp + unlockTime) / WEEK) * WEEK;
        }
        LockedBalance memory lockedBalance = mapLockedBalances[account];
        // The locked balance must be zero in order to start the lock
        if (lockedBalance.amount > 0) {
            revert LockedValueNotZero(account, uint256(lockedBalance.amount));
        }
        // Check for the lock time correctness
        if (unlockTime < (block.timestamp + 1)) {
            revert UnlockTimeIncorrect(account, block.timestamp, unlockTime);
        }
        // Check for the lock time not to exceed the MAXTIME
        if (unlockTime > block.timestamp + MAXTIME) {
            revert MaxUnlockTimeReached(account, block.timestamp + MAXTIME, unlockTime);
        }
        // After 10 years, the inflation rate is 2% per year. It would take 220+ years to reach 2^96 - 1 total supply
        if (amount > type(uint96).max) {
            revert Overflow(amount, type(uint96).max);
        }

        _depositFor(account, amount, unlockTime, lockedBalance, DepositType.CREATE_LOCK_TYPE);
    }

    /// @dev Deposits `amount` additional tokens for `msg.sender` without modifying the unlock time.
    /// @param amount Amount of tokens to deposit and add to the lock.
    function increaseAmount(uint256 amount) external {
        LockedBalance memory lockedBalance = mapLockedBalances[msg.sender];
        // Check if the amount is zero
        if (amount == 0) {
            revert ZeroValue();
        }
        // The locked balance must already exist
        if (lockedBalance.amount == 0) {
            revert NoValueLocked(msg.sender);
        }
        // Check the lock expiry
        if (lockedBalance.endTime < (block.timestamp + 1)) {
            revert LockExpired(msg.sender, lockedBalance.endTime, block.timestamp);
        }
        // Check the max possible amount to add, that must be less than the total supply
        // After 10 years, the inflation rate is 2% per year. It would take 220+ years to reach 2^96 - 1 total supply
        if (amount > type(uint96).max) {
            revert Overflow(amount, type(uint96).max);
        }

        _depositFor(msg.sender, amount, 0, lockedBalance, DepositType.INCREASE_LOCK_AMOUNT);
    }

    /// @dev Extends the unlock time.
    /// @param unlockTime New tokens unlock time.
    function increaseUnlockTime(uint256 unlockTime) external {
        LockedBalance memory lockedBalance = mapLockedBalances[msg.sender];
        // Cannot practically overflow because block.timestamp + unlockTime (max 4 years) << 2^64-1
        unchecked {
            unlockTime = ((block.timestamp + unlockTime) / WEEK) * WEEK;
        }
        // The locked balance must already exist
        if (lockedBalance.amount == 0) {
            revert NoValueLocked(msg.sender);
        }
        // Check the lock expiry
        if (lockedBalance.endTime < (block.timestamp + 1)) {
            revert LockExpired(msg.sender, lockedBalance.endTime, block.timestamp);
        }
        // Check for the lock time correctness
        if (unlockTime < (lockedBalance.endTime + 1)) {
            revert UnlockTimeIncorrect(msg.sender, lockedBalance.endTime, unlockTime);
        }
        // Check for the lock time not to exceed the MAXTIME
        if (unlockTime > block.timestamp + MAXTIME) {
            revert MaxUnlockTimeReached(msg.sender, block.timestamp + MAXTIME, unlockTime);
        }

        _depositFor(msg.sender, 0, unlockTime, lockedBalance, DepositType.INCREASE_UNLOCK_TIME);
    }

    /// @dev Withdraws all tokens for `msg.sender`. Only possible if the lock has expired.
    function withdraw() external {
        LockedBalance memory lockedBalance = mapLockedBalances[msg.sender];
        if (lockedBalance.endTime > block.timestamp) {
            revert LockNotExpired(msg.sender, lockedBalance.endTime, block.timestamp);
        }
        uint256 amount = uint256(lockedBalance.amount);

        mapLockedBalances[msg.sender] = LockedBalance(0, 0);
        uint256 supplyBefore = supply;
        uint256 supplyAfter;
        // The amount cannot be less than the total supply
        unchecked {
            supplyAfter = supplyBefore - amount;
            supply = supplyAfter;
        }
        // oldLocked can have either expired <= timestamp or zero end
        // lockedBalance has only 0 end
        // Both can have >= 0 amount
        _checkpoint(msg.sender, lockedBalance, LockedBalance(0, 0), uint128(supplyAfter));

        emit Withdraw(msg.sender, amount, block.timestamp);
        emit Supply(supplyBefore, supplyAfter);

        // OLAS is a solmate-based ERC20 token with optimized transfer() that either returns true or reverts
        IERC20(token).transfer(msg.sender, amount);
    }

    /// @dev Finds a closest point that has a specified block number.
    /// @param blockNumber Block to find.
    /// @param account Account address for user points.
    /// @return point Point with the approximate index number for the specified block.
    /// @return minPointNumber Point number.
    function _findPointByBlock(uint256 blockNumber, address account) internal view
        returns (PointVoting memory point, uint256 minPointNumber)
    {
        // Get the last available point number
        uint256 maxPointNumber;
        if (account == address(0)) {
            maxPointNumber = totalNumPoints;
        } else {
            maxPointNumber = mapUserPoints[account].length;
            if (maxPointNumber == 0) {
                return (point, minPointNumber);
            }
            // Already checked for > 0 in this case
            unchecked {
                maxPointNumber -= 1;
            }
        }

        // Binary search that will be always enough for 128-bit numbers
        for (uint256 i = 0; i < 128; ++i) {
            if ((minPointNumber + 1) > maxPointNumber) {
                break;
            }
            uint256 mid = (minPointNumber + maxPointNumber + 1) / 2;

            // Choose the source of points
            if (account == address(0)) {
                point = mapSupplyPoints[mid];
            } else {
                point = mapUserPoints[account][mid];
            }

            if (point.blockNumber < (blockNumber + 1)) {
                minPointNumber = mid;
            } else {
                maxPointNumber = mid - 1;
            }
        }

        // Get the found point
        if (account == address(0)) {
            point = mapSupplyPoints[minPointNumber];
        } else {
            point = mapUserPoints[account][minPointNumber];
        }
    }

    /// @dev Gets the voting power for an `account` at time `ts`.
    /// @param account Account address.
    /// @param ts Time to get voting power at.
    /// @return vBalance Account voting power.
    function _balanceOfLocked(address account, uint64 ts) internal view returns (uint256 vBalance) {
        uint256 pointNumber = mapUserPoints[account].length;
        if (pointNumber > 0) {
            PointVoting memory uPoint = mapUserPoints[account][pointNumber - 1];
            uPoint.bias -= uPoint.slope * int128(int64(ts) - int64(uPoint.ts));
            if (uPoint.bias > 0) {
                vBalance = uint256(int256(uPoint.bias));
            }
        }
    }

    /// @dev Gets the account balance in native token.
    /// @param account Account address.
    /// @return balance Account balance.
    function balanceOf(address account) public view override returns (uint256 balance) {
        balance = uint256(mapLockedBalances[account].amount);
    }

    /// @dev Gets the `account`'s lock end time.
    /// @param account Account address.
    /// @return unlockTime Lock end time.
    function lockedEnd(address account) external view returns (uint256 unlockTime) {
        unlockTime = uint256(mapLockedBalances[account].endTime);
    }

    /// @dev Gets the account balance at a specific block number.
    /// @param account Account address.
    /// @param blockNumber Block number.
    /// @return balance Account balance.
    function balanceOfAt(address account, uint256 blockNumber) external view returns (uint256 balance) {
        // Find point with the closest block number to the provided one
        (PointVoting memory uPoint, ) = _findPointByBlock(blockNumber, account);
        // If the block number at the point index is bigger than the specified block number, the balance was zero
        if (uPoint.blockNumber < (blockNumber + 1)) {
            balance = uint256(uPoint.balance);
        }
    }

    /// @dev Gets the voting power.
    /// @param account Account address.
    function getVotes(address account) public view override returns (uint256) {
        return _balanceOfLocked(account, uint64(block.timestamp));
    }

    /// @dev Gets the block time adjustment for two neighboring points.
    /// @param blockNumber Block number.
    /// @return point Point with the specified block number (or closest to it).
    /// @return blockTime Adjusted block time of the neighboring point.
    function _getBlockTime(uint256 blockNumber) internal view returns (PointVoting memory point, uint256 blockTime) {
        // Check the block number to be in the past or equal to the current block
        if (blockNumber > block.number) {
            revert WrongBlockNumber(blockNumber, block.number);
        }
        // Get the minimum historical point with the provided block number
        uint256 minPointNumber;
        (point, minPointNumber) = _findPointByBlock(blockNumber, address(0));

        uint256 dBlock;
        uint256 dt;
        if (minPointNumber < totalNumPoints) {
            PointVoting memory pointNext = mapSupplyPoints[minPointNumber + 1];
            dBlock = pointNext.blockNumber - point.blockNumber;
            dt = pointNext.ts - point.ts;
        } else {
            dBlock = block.number - point.blockNumber;
            dt = block.timestamp - point.ts;
        }
        blockTime = point.ts;
        if (dBlock > 0) {
            blockTime += (dt * (blockNumber - point.blockNumber)) / dBlock;
        }
    }

    /// @dev Gets voting power at a specific block number.
    /// @param account Account address.
    /// @param blockNumber Block number.
    /// @return balance Voting balance / power.
    function getPastVotes(address account, uint256 blockNumber) public view override returns (uint256 balance) {
        // Find the user point for the provided block number
        (PointVoting memory uPoint, ) = _findPointByBlock(blockNumber, account);

        // Get block time adjustment.
        (, uint256 blockTime) = _getBlockTime(blockNumber);

        // Calculate bias based on a block time
        uPoint.bias -= uPoint.slope * int128(int64(uint64(blockTime)) - int64(uPoint.ts));
        if (uPoint.bias > 0) {
            balance = uint256(uint128(uPoint.bias));
        }
    }

    /// @dev Calculate total voting power at some point in the past.
    /// @param lastPoint The point (bias/slope) to start the search from.
    /// @param ts Time to calculate the total voting power at.
    /// @return vSupply Total voting power at that time.
    function _supplyLockedAt(PointVoting memory lastPoint, uint64 ts) internal view returns (uint256 vSupply) {
        // The timestamp is rounded and < 2^64-1
        uint64 tStep = (lastPoint.ts / WEEK) * WEEK;
        for (uint256 i = 0; i < 255; ++i) {
            // This is always practically < 2^64-1
            unchecked {
                tStep += WEEK;
            }
            int128 dSlope;
            if (tStep > ts) {
                tStep = ts;
            } else {
                dSlope = mapSlopeChanges[tStep];
            }
            lastPoint.bias -= lastPoint.slope * int128(int64(tStep) - int64(lastPoint.ts));
            if (tStep == ts) {
                break;
            }
            lastPoint.slope += dSlope;
            lastPoint.ts = tStep;
        }

        if (lastPoint.bias > 0) {
            vSupply = uint256(uint128(lastPoint.bias));
        }
    }

    /// @dev Gets total token supply.
    /// @return Total token supply.
    function totalSupply() public view override returns (uint256) {
        return supply;
    }

    /// @dev Gets total token supply at a specific block number.
    /// @param blockNumber Block number.
    /// @return supplyAt Supply at the specified block number.
    function totalSupplyAt(uint256 blockNumber) external view returns (uint256 supplyAt) {
        // Find point with the closest block number to the provided one
        (PointVoting memory sPoint, ) = _findPointByBlock(blockNumber, address(0));
        // If the block number at the point index is bigger than the specified block number, the balance was zero
        if (sPoint.blockNumber < (blockNumber + 1)) {
            supplyAt = uint256(sPoint.balance);
        }
    }

    /// @dev Calculates total voting power at time `ts`.
    /// @param ts Time to get total voting power at.
    /// @return Total voting power.
    function totalSupplyLockedAtT(uint256 ts) public view returns (uint256) {
        PointVoting memory lastPoint = mapSupplyPoints[totalNumPoints];
        return _supplyLockedAt(lastPoint, uint64(ts));
    }

    /// @dev Calculates current total voting power.
    /// @return Total voting power.
    function totalSupplyLocked() public view returns (uint256) {
        return totalSupplyLockedAtT(block.timestamp);
    }

    /// @dev Calculate total voting power at some point in the past.
    /// @param blockNumber Block number to calculate the total voting power at.
    /// @return Total voting power.
    function getPastTotalSupply(uint256 blockNumber) public view override returns (uint256) {
        (PointVoting memory sPoint, uint256 blockTime) = _getBlockTime(blockNumber);
        // Now dt contains info on how far are we beyond the point
        return _supplyLockedAt(sPoint, uint64(blockTime));
    }

    /// @dev Gets information about the interface support.
    /// @param interfaceId A specified interface Id.
    /// @return True if this contract implements the interface defined by interfaceId.
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC20).interfaceId || interfaceId == type(IVotes).interfaceId ||
            interfaceId == type(IERC165).interfaceId;
    }

    /// @dev Reverts the transfer of this token.
    function transfer(address to, uint256 amount) external virtual override returns (bool) {
        revert NonTransferable(address(this));
    }

    /// @dev Reverts the approval of this token.
    function approve(address spender, uint256 amount) external virtual override returns (bool) {
        revert NonTransferable(address(this));
    }

    /// @dev Reverts the transferFrom of this token.
    function transferFrom(address from, address to, uint256 amount) external virtual override returns (bool) {
        revert NonTransferable(address(this));
    }

    /// @dev Reverts the allowance of this token.
    function allowance(address owner, address spender) external view virtual override returns (uint256)
    {
        revert NonTransferable(address(this));
    }

    /// @dev Reverts delegates of this token.
    function delegates(address account) external view virtual override returns (address)
    {
        revert NonDelegatable(address(this));
    }

    /// @dev Reverts delegate for this token.
    function delegate(address delegatee) external virtual override
    {
        revert NonDelegatable(address(this));
    }

    /// @dev Reverts delegateBySig for this token.
    function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s)
    external virtual override
    {
        revert NonDelegatable(address(this));
    }
}

File 2 of 5 : IVotes.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)
pragma solidity ^0.8.0;

/**
 * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
 *
 * _Available since v4.5._
 */
interface IVotes {
    /**
     * @dev Emitted when an account changes their delegate.
     */
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /**
     * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
     */
    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

    /**
     * @dev Returns the current amount of votes that `account` has.
     */
    function getVotes(address account) external view returns (uint256);

    /**
     * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).
     */
    function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);

    /**
     * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).
     *
     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
     * vote.
     */
    function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);

    /**
     * @dev Returns the delegate that `account` has chosen.
     */
    function delegates(address account) external view returns (address);

    /**
     * @dev Delegates votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) external;

    /**
     * @dev Delegates votes from signer to `delegatee`.
     */
    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

File 3 of 5 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

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

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

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 4 of 5 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 5 of 5 : IErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

/// @dev Errors.
interface IErrors {
    /// @dev Only `owner` has a privilege, but the `sender` was provided.
    /// @param sender Sender address.
    /// @param owner Required sender address as an owner.
    error OwnerOnly(address sender, address owner);

    /// @dev Provided zero address.
    error ZeroAddress();

    /// @dev Zero value when it has to be different from zero.
    error ZeroValue();

    /// @dev Non-zero value when it has to be zero.
    error NonZeroValue();

    /// @dev Wrong length of two arrays.
    /// @param numValues1 Number of values in a first array.
    /// @param numValues2 Numberf of values in a second array.
    error WrongArrayLength(uint256 numValues1, uint256 numValues2);

    /// @dev Value overflow.
    /// @param provided Overflow value.
    /// @param max Maximum possible value.
    error Overflow(uint256 provided, uint256 max);

    /// @dev Token is non-transferable.
    /// @param account Token address.
    error NonTransferable(address account);

    /// @dev Token is non-delegatable.
    /// @param account Token address.
    error NonDelegatable(address account);

    /// @dev Insufficient token allowance.
    /// @param provided Provided amount.
    /// @param expected Minimum expected amount.
    error InsufficientAllowance(uint256 provided, uint256 expected);

    /// @dev No existing lock value is found.
    /// @param account Address that is checked for the locked value.
    error NoValueLocked(address account);

    /// @dev Locked value is not zero.
    /// @param account Address that is checked for the locked value.
    /// @param amount Locked amount.
    error LockedValueNotZero(address account, uint256 amount);

    /// @dev Value lock is expired.
    /// @param account Address that is checked for the locked value.
    /// @param deadline The lock expiration deadline.
    /// @param curTime Current timestamp.
    error LockExpired(address account, uint256 deadline, uint256 curTime);

    /// @dev Value lock is not expired.
    /// @param account Address that is checked for the locked value.
    /// @param deadline The lock expiration deadline.
    /// @param curTime Current timestamp.
    error LockNotExpired(address account, uint256 deadline, uint256 curTime);

    /// @dev Provided unlock time is incorrect.
    /// @param account Address that is checked for the locked value.
    /// @param minUnlockTime Minimal unlock time that can be set.
    /// @param providedUnlockTime Provided unlock time.
    error UnlockTimeIncorrect(address account, uint256 minUnlockTime, uint256 providedUnlockTime);

    /// @dev Provided unlock time is bigger than the maximum allowed.
    /// @param account Address that is checked for the locked value.
    /// @param maxUnlockTime Max unlock time that can be set.
    /// @param providedUnlockTime Provided unlock time.
    error MaxUnlockTimeReached(address account, uint256 maxUnlockTime, uint256 providedUnlockTime);

    /// @dev Provided block number is incorrect (has not been processed yet).
    /// @param providedBlockNumber Provided block number.
    /// @param actualBlockNumber Actual block number.
    error WrongBlockNumber(uint256 providedBlockNumber, uint256 actualBlockNumber);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"provided","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"curTime","type":"uint256"}],"name":"LockExpired","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"curTime","type":"uint256"}],"name":"LockNotExpired","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LockedValueNotZero","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"maxUnlockTime","type":"uint256"},{"internalType":"uint256","name":"providedUnlockTime","type":"uint256"}],"name":"MaxUnlockTimeReached","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NoValueLocked","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NonDelegatable","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NonTransferable","type":"error"},{"inputs":[],"name":"NonZeroValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"provided","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"Overflow","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"OwnerOnly","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"minUnlockTime","type":"uint256"},{"internalType":"uint256","name":"providedUnlockTime","type":"uint256"}],"name":"UnlockTimeIncorrect","type":"error"},{"inputs":[{"internalType":"uint256","name":"numValues1","type":"uint256"},{"internalType":"uint256","name":"numValues2","type":"uint256"}],"name":"WrongArrayLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"providedBlockNumber","type":"uint256"},{"internalType":"uint256","name":"actualBlockNumber","type":"uint256"}],"name":"WrongBlockNumber","type":"error"},{"inputs":[],"name":"ZeroAddress","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":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"locktime","type":"uint256"},{"indexed":false,"internalType":"enum veOLAS.DepositType","name":"depositType","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentSupply","type":"uint256"}],"name":"Supply","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":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","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":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"balanceOfAt","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"name":"createLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"name":"createLockFor","outputs":[],"stateMutability":"nonpayable","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":"account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getLastUserPoint","outputs":[{"components":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint64","name":"ts","type":"uint64"},{"internalType":"uint64","name":"blockNumber","type":"uint64"},{"internalType":"uint128","name":"balance","type":"uint128"}],"internalType":"struct PointVoting","name":"pv","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getNumUserPoints","outputs":[{"internalType":"uint256","name":"accountNumPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPastTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"getUserPoint","outputs":[{"components":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint64","name":"ts","type":"uint64"},{"internalType":"uint64","name":"blockNumber","type":"uint64"},{"internalType":"uint128","name":"balance","type":"uint128"}],"internalType":"struct PointVoting","name":"","type":"tuple"}],"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":"amount","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":"lockedEnd","outputs":[{"internalType":"uint256","name":"unlockTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mapLockedBalances","outputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint64","name":"endTime","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"mapSlopeChanges","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapSupplyPoints","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint64","name":"ts","type":"uint64"},{"internalType":"uint64","name":"blockNumber","type":"uint64"},{"internalType":"uint128","name":"balance","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapUserPoints","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint64","name":"ts","type":"uint64"},{"internalType":"uint64","name":"blockNumber","type":"uint64"},{"internalType":"uint128","name":"balance","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalNumPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"internalType":"uint256","name":"supplyAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupplyLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ts","type":"uint256"}],"name":"totalSupplyLockedAtT","outputs":[{"internalType":"uint256","name":"","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"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b5060405162003ab338038062003ab3833981016040819052620000349162000210565b6001600160a01b03831660805260066200004f838262000329565b5060076200005e828262000329565b50506040805160a081018252600080825260208083018281526001600160401b0342811695850195865243811660608601908152608086018581529480526003909352935190516001600160801b03908116600160801b908102928216929092177f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff5594517f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92f00805493519451871690920293851668010000000000000000026001600160801b0319939093169416939093171790921691909117905550620003f59050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200016b57600080fd5b81516001600160401b038082111562000188576200018862000143565b604051601f8301601f19908116603f01168101908282118183101715620001b357620001b362000143565b81604052838152602092508683858801011115620001d057600080fd5b600091505b83821015620001f45785820183015181830184015290820190620001d5565b83821115620002065760008385830101525b9695505050505050565b6000806000606084860312156200022657600080fd5b83516001600160a01b03811681146200023e57600080fd5b60208501519093506001600160401b03808211156200025c57600080fd5b6200026a8783880162000159565b935060408601519150808211156200028157600080fd5b50620002908682870162000159565b9150509250925092565b600181811c90821680620002af57607f821691505b602082108103620002d057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200032457600081815260208120601f850160051c81016020861015620002ff5750805b601f850160051c820191505b8181101562000320578281556001016200030b565b5050505b505050565b81516001600160401b0381111562000345576200034562000143565b6200035d816200035684546200029a565b84620002d6565b602080601f8311600181146200039557600084156200037c5750858301515b600019600386901b1c1916600185901b17855562000320565b600085815260208120601f198616915b82811015620003c657888601518255948401946001909101908401620003a5565b5085821015620003e55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6080516136946200041f6000396000818161078901528181610fe2015261181001526136946000f3fe608060405234801561001057600080fd5b50600436106102925760003560e01c8063587cde1e116101605780639ab24eb0116100d8578063c2c4c5c11161008c578063c4698ee511610071578063c4698ee514610763578063dd62ed3e14610776578063fc0c546a1461078457600080fd5b8063c2c4c5c11461074d578063c3cda5201461075557600080fd5b8063b0a34fdd116100bd578063b0a34fdd146106aa578063b18f270214610727578063b52c05fe1461073a57600080fd5b80639ab24eb014610697578063a9059cbb146103b057600080fd5b806378888dbf1161012f5780638e539e8c116101145780638e539e8c1461066957806395d89b411461067c578063981b24d01461068457600080fd5b806378888dbf146106205780637c616fe61461065657600080fd5b8063587cde1e1461057a5780635c19a95c146105b257806370a08231146105c557806370ab0a841461060d57600080fd5b806329b55ca71161020e578063474177ec116101c25780634ee2cd7e116101a75780634ee2cd7e1461052957806353acfabd1461053c578063583419221461057257600080fd5b8063474177ec146104cc5780634deafcae146104d557600080fd5b8063313ce567116101f3578063313ce567146104975780633a46b1a8146104b15780633ccfd60b146104c457600080fd5b806329b55ca7146104715780632f4f21e21461048457600080fd5b8063095ea7b31161026557806318160ddd1161024a57806318160ddd146103d857806318b21348146103e057806323b872dd1461046357600080fd5b8063095ea7b3146103b057806315456eba146103c357600080fd5b806301ffc9a714610297578063025fc7d8146102bf578063047fc9aa1461038457806306fdde031461039b575b600080fd5b6102aa6102a5366004612eaa565b6107ab565b60405190151581526020015b60405180910390f35b6103366102cd366004612eec565b60036020526000908152604090208054600190910154600f82810b927001000000000000000000000000000000009081900490910b9167ffffffffffffffff8082169268010000000000000000830490911691046fffffffffffffffffffffffffffffffff1685565b60408051600f96870b81529490950b602085015267ffffffffffffffff928316948401949094521660608201526fffffffffffffffffffffffffffffffff909116608082015260a0016102b6565b61038d60005481565b6040519081526020016102b6565b6103a3610890565b6040516102b69190612f05565b6102aa6103be366004612fa1565b61091e565b6103d66103d1366004612eec565b61095a565b005b60005461038d565b6104326103ee366004612fcb565b6001602052600090815260409020546fffffffffffffffffffffffffffffffff811690700100000000000000000000000000000000900467ffffffffffffffff1682565b604080516fffffffffffffffffffffffffffffffff909316835267ffffffffffffffff9091166020830152016102b6565b6102aa6103be366004612fe6565b6103d661047f366004613022565b610b16565b6103d6610492366004612fa1565b610b73565b61049f601281565b60405160ff90911681526020016102b6565b61038d6104bf366004612fa1565b610d57565b6103d6610ddb565b61038d60025481565b61038d6104e3366004612fcb565b73ffffffffffffffffffffffffffffffffffffffff16600090815260016020526040902054700100000000000000000000000000000000900467ffffffffffffffff1690565b61038d610537366004612fa1565b61106b565b61038d61054a366004612fcb565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b61038d6110bc565b61058d610588366004612fcb565b6110cc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102b6565b6103d66105c0366004612fcb565b611103565b61038d6105d3366004612fcb565b73ffffffffffffffffffffffffffffffffffffffff166000908152600160205260409020546fffffffffffffffffffffffffffffffff1690565b61033661061b366004612fa1565b611137565b61064361062e366004613055565b600560205260009081526040902054600f0b81565b604051600f9190910b81526020016102b6565b6103d6610664366004612eec565b6111bf565b61038d610677366004612eec565b6113dc565b6103a3611400565b61038d610692366004612eec565b61140d565b61038d6106a5366004612fcb565b61145e565b6106bd6106b8366004612fa1565b61146a565b6040516102b69190600060a0820190508251600f0b82526020830151600f0b6020830152604083015167ffffffffffffffff808216604085015280606086015116606085015250506fffffffffffffffffffffffffffffffff608084015116608083015292915050565b61038d610735366004612eec565b61155b565b6103d661074836600461307f565b6115f7565b6103d6611602565b6103d66105c03660046130a1565b6106bd610771366004612fcb565b611639565b61038d6103be366004613101565b61058d7f000000000000000000000000000000000000000000000000000000000000000081565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f36372b0700000000000000000000000000000000000000000000000000000000148061083e57507fffffffff0000000000000000000000000000000000000000000000000000000082167fe90fb3f600000000000000000000000000000000000000000000000000000000145b8061088a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6006805461089d90613134565b80601f01602080910402602001604051908101604052809291908181526020018280546108c990613134565b80156109165780601f106108eb57610100808354040283529160200191610916565b820191906000526020600020905b8154815290600101906020018083116108f957829003601f168201915b505050505081565b6040517f9c21e7b20000000000000000000000000000000000000000000000000000000081523060048201526000906024015b60405180910390fd5b3360009081526001602090815260408083208151808301909252546fffffffffffffffffffffffffffffffff81168252700100000000000000000000000000000000900467ffffffffffffffff1691810191909152908290036109e9576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516fffffffffffffffffffffffffffffffff16600003610a38576040517f1ff847b6000000000000000000000000000000000000000000000000000000008152336004820152602401610951565b610a434260016131b0565b816020015167ffffffffffffffff161015610aa85760208101516040517fd78507e100000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff9091166024820152426044820152606401610951565b6bffffffffffffffffffffffff821115610b03576040517f7ae59685000000000000000000000000000000000000000000000000000000008152600481018390526bffffffffffffffffffffffff6024820152604401610951565b610b12338360008460026116cc565b5050565b73ffffffffffffffffffffffffffffffffffffffff8316610b63576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b6e83838361192f565b505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602090815260408083208151808301909252546fffffffffffffffffffffffffffffffff81168252700100000000000000000000000000000000900467ffffffffffffffff169181019190915290829003610c18576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516fffffffffffffffffffffffffffffffff16600003610c7d576040517f1ff847b600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610951565b610c884260016131b0565b816020015167ffffffffffffffff161015610ced5760208101516040517fd78507e100000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff9091166024820152426044820152606401610951565b6bffffffffffffffffffffffff821115610d48576040517f7ae59685000000000000000000000000000000000000000000000000000000008152600481018390526bffffffffffffffffffffffff6024820152604401610951565b610b6e838360008460006116cc565b600080610d648385611b4f565b5090506000610d7284611f6a565b915050816040015181610d8591906131c8565b60070b8260200151610d979190613231565b82518390610da69083906132e7565b600f90810b90915283516000910b13159050610dd35781516fffffffffffffffffffffffffffffffff1692505b505092915050565b336000908152600160209081526040918290208251808401909352546fffffffffffffffffffffffffffffffff81168352700100000000000000000000000000000000900467ffffffffffffffff16908201819052421015610e875760208101516040517fab0246b300000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff9091166024820152426044820152606401610951565b805160408051808201825260008082526020808301828152338084526001835285842094518554925167ffffffffffffffff16700100000000000000000000000000000000027fffffffffffffffff0000000000000000000000000000000000000000000000009093166fffffffffffffffffffffffffffffffff9182161792909217909455825495168086038084558551808701909652838652918501929092529093929091610f3a9186908461216d565b6040805184815242602082015233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a260408051838152602081018390527f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c910160405180910390a16040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a9059cbb906044016020604051808303816000875af1158015611040573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611064919061334e565b5050505050565b6000806110788385611b4f565b5090506110868360016131b0565b816060015167ffffffffffffffff1610156110b55780608001516fffffffffffffffffffffffffffffffff1691505b5092915050565b60006110c74261155b565b905090565b6040517f535db4ec000000000000000000000000000000000000000000000000000000008152306004820152600090602401610951565b6040517f535db4ec000000000000000000000000000000000000000000000000000000008152306004820152602401610951565b6004602052816000526040600020818154811061115357600080fd5b600091825260209091206002909102018054600190910154600f82810b945070010000000000000000000000000000000092839004900b925067ffffffffffffffff8082169268010000000000000000830490911691046fffffffffffffffffffffffffffffffff1685565b336000908152600160209081526040918290208251808401909352546fffffffffffffffffffffffffffffffff81168352700100000000000000000000000000000000900467ffffffffffffffff169082015262093a80804284010402915080600001516fffffffffffffffffffffffffffffffff16600003611270576040517f1ff847b6000000000000000000000000000000000000000000000000000000008152336004820152602401610951565b61127b4260016131b0565b816020015167ffffffffffffffff1610156112e05760208101516040517fd78507e100000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff9091166024820152426044820152606401610951565b60208101516112f090600161339f565b67ffffffffffffffff168210156113525760208101516040517f311d1bf900000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff909116602482015260448101839052606401610951565b611360630784ce00426131b0565b8211156113cd5733611376630784ce00426131b0565b6040517fc172987b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260448101839052606401610951565b610b12336000848460036116cc565b60008060006113ea84611f6a565b915091506113f88282612c35565b949350505050565b6007805461089d90613134565b60008061141b836000611b4f565b5090506114298360016131b0565b816060015167ffffffffffffffff1610156114585780608001516fffffffffffffffffffffffffffffffff1691505b50919050565b600061088a8242612d66565b6040805160a08101825260008082526020808301829052828401829052606083018290526080830182905273ffffffffffffffffffffffffffffffffffffffff8616825260049052919091208054839081106114c8576114c86133cb565b60009182526020918290206040805160a0810182526002939093029091018054600f81810b855270010000000000000000000000000000000091829004900b948401949094526001015467ffffffffffffffff808216928401929092526801000000000000000081049091166060830152919091046fffffffffffffffffffffffffffffffff1660808201529392505050565b6002546000908152600360209081526040808320815160a0810183528154600f81810b835270010000000000000000000000000000000091829004900b9482019490945260019091015467ffffffffffffffff8082169383019390935268010000000000000000810490921660608201529190046fffffffffffffffffffffffffffffffff1660808201526115f08184612c35565b9392505050565b610b1233838361192f565b60408051808201825260008082526020808301829052835180850190945281845283018190528054611637939192919061216d565b565b6040805160a08101825260008082526020808301829052828401829052606083018290526080830182905273ffffffffffffffffffffffffffffffffffffffff8516825260049052919091205480156114585773ffffffffffffffffffffffffffffffffffffffff831660009081526004602052604090206116bc6001836133fa565b815481106114c8576114c86133cb565b600080548581018083556040805180820190915283815260208101939093529091845160208087015167ffffffffffffffff16908301526fffffffffffffffffffffffffffffffff90811682528551880116855285156117375767ffffffffffffffff861660208601525b73ffffffffffffffffffffffffffffffffffffffff88166000908152600160209081526040909120865181549288015167ffffffffffffffff16700100000000000000000000000000000000027fffffffffffffffff0000000000000000000000000000000000000000000000009093166fffffffffffffffffffffffffffffffff909116179190911790556117cf8882878561216d565b8615611894576040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018890527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906323b872dd906064016020604051808303816000875af115801561186e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611892919061334e565b505b8773ffffffffffffffffffffffffffffffffffffffff167fbe9cf0e939c614fad640a623a53ba0a807c8cb503c4c4c8dacabe27b86ff2dd588876020015187426040516118e49493929190613411565b60405180910390a260408051848152602081018490527f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c910160405180910390a15050505050505050565b81600003611969576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a808042830173ffffffffffffffffffffffffffffffffffffffff86166000908152600160209081526040918290208251808401909352546fffffffffffffffffffffffffffffffff811680845270010000000000000000000000000000000090910467ffffffffffffffff16918301919091529290910492909202925015611a535780516040517f89bf64dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526fffffffffffffffffffffffffffffffff9091166024820152604401610951565b611a5e4260016131b0565b821015611abc576040517f311d1bf900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015242602482015260448101839052606401610951565b611aca630784ce00426131b0565b821115611ae05783611376630784ce00426131b0565b6bffffffffffffffffffffffff831115611b3b576040517f7ae59685000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff6024820152604401610951565b611b498484848460016116cc565b50505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101829052908073ffffffffffffffffffffffffffffffffffffffff8416611b9f5750600254611bf7565b5073ffffffffffffffffffffffffffffffffffffffff831660009081526004602052604081205490819003611bd45750611f63565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b60005b6080811015611df05781611c0f8460016131b0565b11611df05760006002611c2284866131b0565b611c2d9060016131b0565b611c379190613471565b905073ffffffffffffffffffffffffffffffffffffffff8616611ce357600081815260036020908152604091829020825160a0810184528154600f81810b835270010000000000000000000000000000000091829004900b9382019390935260019091015467ffffffffffffffff80821694830194909452680100000000000000008104909316606082015291046fffffffffffffffffffffffffffffffff1660808201529450611da9565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600460205260409020805482908110611d1a57611d1a6133cb565b60009182526020918290206040805160a0810182526002939093029091018054600f81810b855270010000000000000000000000000000000091829004900b948401949094526001015467ffffffffffffffff808216928401929092526801000000000000000081049091166060830152919091046fffffffffffffffffffffffffffffffff16608082015294505b611db48760016131b0565b856060015167ffffffffffffffff161015611dd157809350611ddf565b611ddc6001826133fa565b92505b50611de981613485565b9050611bfa565b5073ffffffffffffffffffffffffffffffffffffffff8416611e9b57600082815260036020908152604091829020825160a0810184528154600f81810b835270010000000000000000000000000000000091829004900b9382019390935260019091015467ffffffffffffffff80821694830194909452680100000000000000008104909316606082015291046fffffffffffffffffffffffffffffffff1660808201529250611f61565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600460205260409020805483908110611ed257611ed26133cb565b60009182526020918290206040805160a0810182526002939093029091018054600f81810b855270010000000000000000000000000000000091829004900b948401949094526001015467ffffffffffffffff808216928401929092526801000000000000000081049091166060830152919091046fffffffffffffffffffffffffffffffff16608082015292505b505b9250929050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081018290529043831115611fd8576040517f8633967e00000000000000000000000000000000000000000000000000000000815260048101849052436024820152604401610951565b6000611fe5846000611b4f565b600254919450915060009081908310156120da5760006003816120098660016131b0565b81526020808201929092526040908101600020815160a0810183528154600f81810b835270010000000000000000000000000000000091829004900b9482019490945260019091015467ffffffffffffffff808216938301939093526801000000000000000081049092166060808301829052939092046fffffffffffffffffffffffffffffffff166080820152918801519192506120a891906134bd565b67ffffffffffffffff169250856040015181604001516120c891906134bd565b67ffffffffffffffff16915050612112565b60608501516120f39067ffffffffffffffff16436133fa565b9150846040015167ffffffffffffffff164261210f91906133fa565b90505b604085015167ffffffffffffffff16935081156121655781856060015167ffffffffffffffff168761214491906133fa565b61214e90836134e6565b6121589190613471565b61216290856131b0565b93505b505050915091565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805160a081018252600080825260208201819052918101829052606081018290526080810191909152600254600090819073ffffffffffffffffffffffffffffffffffffffff8916156123655742886020015167ffffffffffffffff16118015612216575087516fffffffffffffffffffffffffffffffff1615155b1561226557875161222c90630784ce0090613523565b600f0b6020808701919091528801516122469042906134bd565b67ffffffffffffffff16856020015161225f9190613231565b600f0b85525b42876020015167ffffffffffffffff16118015612294575086516fffffffffffffffffffffffffffffffff1615155b156122e35786516122aa90630784ce0090613523565b600f0b6020808601919091528701516122c49042906134bd565b67ffffffffffffffff1684602001516122dd9190613231565b600f0b84525b60208089015167ffffffffffffffff908116600090815260058352604090205491890151600f9290920b9450161561236557876020015167ffffffffffffffff16876020015167ffffffffffffffff160361234057829150612365565b60208088015167ffffffffffffffff16600090815260059091526040902054600f0b91505b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915281156124245750600081815260036020908152604091829020825160a0810184528154600f81810b835270010000000000000000000000000000000091829004900b9382019390935260019091015467ffffffffffffffff80821694830194909452680100000000000000008104909316606082015291046fffffffffffffffffffffffffffffffff16608082015261247d565b6040518060a001604052806000600f0b81526020016000600f0b81526020014267ffffffffffffffff1681526020014367ffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090505b604081015181600067ffffffffffffffff83164211156124e85760408401516124b09067ffffffffffffffff16426133fa565b60608501516124c99067ffffffffffffffff16436133fa565b6124db90670de0b6b3a76400006134e6565b6124e59190613471565b90505b600062093a806124f88186613597565b61250291906135be565b905060005b60ff8110156127585762093a80820191506000428367ffffffffffffffff16111561253457429250612553565b5067ffffffffffffffff8216600090815260056020526040902054600f0b5b61255d86846134bd565b60070b876020015161256f9190613231565b8751889061257e9083906132e7565b600f0b9052506020870180518291906125989083906135ee565b600f90810b90915288516000910b121590506125b357600087525b60008760200151600f0b12156125cb57600060208801525b67ffffffffffffffff83166040808901919091528501519295508592670de0b6b3a7640000906125fb90856134bd565b61260f9067ffffffffffffffff16866134e6565b6126199190613471565b8560600151612628919061339f565b67ffffffffffffffff90811660608901526080808701516fffffffffffffffffffffffffffffffff1690890152600198909801974290841603612693575067ffffffffffffffff431660608701526fffffffffffffffffffffffffffffffff8c166080870152612758565b506000878152600360209081526040918290208851918901516fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000009184168202178255928901516001909101805460608b015160808c015167ffffffffffffffff9485167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316929092176801000000000000000094909116939093029290921783169190921690920291909117905561275181613485565b9050612507565b5050600285905573ffffffffffffffffffffffffffffffffffffffff8d16156127f9578860200151886020015161278f91906132e7565b846020018181516127a091906135ee565b600f0b905250885188516127b491906132e7565b845185906127c39083906135ee565b600f90810b90915260208601516000910b121590506127e457600060208501525b60008460000151600f0b12156127f957600084525b6000858152600360209081526040918290208651918701516fffffffffffffffffffffffffffffffff92831670010000000000000000000000000000000091841682021782559287015160019091018054606089015160808a015167ffffffffffffffff9485167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316929092176801000000000000000094909116939093029290921783169190921690920291909117905573ffffffffffffffffffffffffffffffffffffffff8d1615612c2657428c6020015167ffffffffffffffff16111561297e5760208901516128ee90886135ee565b96508b6020015167ffffffffffffffff168b6020015167ffffffffffffffff160361292557602088015161292290886132e7565b96505b60208c81015167ffffffffffffffff16600090815260059091526040902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff89161790555b428b6020015167ffffffffffffffff161180156129b657508b6020015167ffffffffffffffff168b6020015167ffffffffffffffff16115b15612a255760208801516129ca90876132e7565b60208c81015167ffffffffffffffff16600090815260059091526040902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff831617905595505b42886040019067ffffffffffffffff16908167ffffffffffffffff168152505043886060019067ffffffffffffffff16908167ffffffffffffffff16815250508a6000015188608001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff1681525050600460008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002088908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000160006101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff16021790555060208201518160000160106101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060608201518160010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060808201518160010160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555050505b50505050505050505050505050565b60008062093a80808560400151612c4c9190613597565b612c5691906135be565b905060005b60ff811015612d3a5762093a808201915060008467ffffffffffffffff168367ffffffffffffffff161115612c9257849250612cb1565b5067ffffffffffffffff8216600090815260056020526040902054600f0b5b6040860151612cc090846131c8565b60070b8660200151612cd29190613231565b86518790612ce19083906132e7565b600f0b90525067ffffffffffffffff80861690841603612d015750612d3a565b8086602001818151612d1391906135ee565b600f0b9052505067ffffffffffffffff82166040860152612d3381613485565b9050612c5b565b5060008460000151600f0b13156110b557505090516fffffffffffffffffffffffffffffffff16919050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526004602052604081205480156110b55773ffffffffffffffffffffffffffffffffffffffff84166000908152600460205260408120612dc26001846133fa565b81548110612dd257612dd26133cb565b60009182526020918290206040805160a0810182526002939093029091018054600f81810b855270010000000000000000000000000000000091829004900b948401949094526001015467ffffffffffffffff808216928401839052680100000000000000008204166060840152929092046fffffffffffffffffffffffffffffffff1660808201529150612e6790856131c8565b60070b8160200151612e799190613231565b81518290612e889083906132e7565b600f90810b90915282516000910b13159050610dd35751600f0b949350505050565b600060208284031215612ebc57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146115f057600080fd5b600060208284031215612efe57600080fd5b5035919050565b600060208083528351808285015260005b81811015612f3257858101830151858201604001528201612f16565b81811115612f44576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612f9c57600080fd5b919050565b60008060408385031215612fb457600080fd5b612fbd83612f78565b946020939093013593505050565b600060208284031215612fdd57600080fd5b6115f082612f78565b600080600060608486031215612ffb57600080fd5b61300484612f78565b925061301260208501612f78565b9150604084013590509250925092565b60008060006060848603121561303757600080fd5b61304084612f78565b95602085013595506040909401359392505050565b60006020828403121561306757600080fd5b813567ffffffffffffffff811681146115f057600080fd5b6000806040838503121561309257600080fd5b50508035926020909101359150565b60008060008060008060c087890312156130ba57600080fd5b6130c387612f78565b95506020870135945060408701359350606087013560ff811681146130e757600080fd5b9598949750929560808101359460a0909101359350915050565b6000806040838503121561311457600080fd5b61311d83612f78565b915061312b60208401612f78565b90509250929050565b600181811c9082168061314857607f821691505b602082108103611458577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156131c3576131c3613181565b500190565b60008160070b8360070b60008112817fffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000183128115161561320b5761320b613181565b81677fffffffffffffff01831381161561322757613227613181565b5090039392505050565b600081600f0b83600f0b6f7fffffffffffffffffffffffffffffff60008213600084138383048511828216161561326a5761326a613181565b7fffffffffffffffffffffffffffffffff8000000000000000000000000000000060008512868205861281841616156132a5576132a5613181565b600087129250858205871284841616156132c1576132c1613181565b858505871281841616156132d7576132d7613181565b5050509290910295945050505050565b600081600f0b83600f0b60008112817fffffffffffffffffffffffffffffffff800000000000000000000000000000000183128115161561332a5761332a613181565b816f7fffffffffffffffffffffffffffffff01831381161561322757613227613181565b60006020828403121561336057600080fd5b815180151581146115f057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff8083168185168083038211156133c2576133c2613181565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008282101561340c5761340c613181565b500390565b84815267ffffffffffffffff84166020820152608081016004841061345f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60408201939093526060015292915050565b60008261348057613480613370565b500490565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036134b6576134b6613181565b5060010190565b600067ffffffffffffffff838116908316818110156134de576134de613181565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561351e5761351e613181565b500290565b600081600f0b83600f0b8061353a5761353a613370565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81147fffffffffffffffffffffffffffffffff800000000000000000000000000000008314161561358e5761358e613181565b90059392505050565b600067ffffffffffffffff808416806135b2576135b2613370565b92169190910492915050565b600067ffffffffffffffff808316818516818304811182151516156135e5576135e5613181565b02949350505050565b600081600f0b83600f0b60008212826f7fffffffffffffffffffffffffffffff0382138115161561362157613621613181565b827fffffffffffffffffffffffffffffffff8000000000000000000000000000000003821281161561365557613655613181565b5001939250505056fea2646970667358221220f99e7957a96c37b1b0b686b8989f714f8bc39f7695601819d3ce0d5e52590c9264736f6c634300080f00330000000000000000000000000001a500a6b18995b03f44bb040a5ffc28e45cb0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000012566f74696e6720457363726f77204f4c41530000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000676654f4c41530000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102925760003560e01c8063587cde1e116101605780639ab24eb0116100d8578063c2c4c5c11161008c578063c4698ee511610071578063c4698ee514610763578063dd62ed3e14610776578063fc0c546a1461078457600080fd5b8063c2c4c5c11461074d578063c3cda5201461075557600080fd5b8063b0a34fdd116100bd578063b0a34fdd146106aa578063b18f270214610727578063b52c05fe1461073a57600080fd5b80639ab24eb014610697578063a9059cbb146103b057600080fd5b806378888dbf1161012f5780638e539e8c116101145780638e539e8c1461066957806395d89b411461067c578063981b24d01461068457600080fd5b806378888dbf146106205780637c616fe61461065657600080fd5b8063587cde1e1461057a5780635c19a95c146105b257806370a08231146105c557806370ab0a841461060d57600080fd5b806329b55ca71161020e578063474177ec116101c25780634ee2cd7e116101a75780634ee2cd7e1461052957806353acfabd1461053c578063583419221461057257600080fd5b8063474177ec146104cc5780634deafcae146104d557600080fd5b8063313ce567116101f3578063313ce567146104975780633a46b1a8146104b15780633ccfd60b146104c457600080fd5b806329b55ca7146104715780632f4f21e21461048457600080fd5b8063095ea7b31161026557806318160ddd1161024a57806318160ddd146103d857806318b21348146103e057806323b872dd1461046357600080fd5b8063095ea7b3146103b057806315456eba146103c357600080fd5b806301ffc9a714610297578063025fc7d8146102bf578063047fc9aa1461038457806306fdde031461039b575b600080fd5b6102aa6102a5366004612eaa565b6107ab565b60405190151581526020015b60405180910390f35b6103366102cd366004612eec565b60036020526000908152604090208054600190910154600f82810b927001000000000000000000000000000000009081900490910b9167ffffffffffffffff8082169268010000000000000000830490911691046fffffffffffffffffffffffffffffffff1685565b60408051600f96870b81529490950b602085015267ffffffffffffffff928316948401949094521660608201526fffffffffffffffffffffffffffffffff909116608082015260a0016102b6565b61038d60005481565b6040519081526020016102b6565b6103a3610890565b6040516102b69190612f05565b6102aa6103be366004612fa1565b61091e565b6103d66103d1366004612eec565b61095a565b005b60005461038d565b6104326103ee366004612fcb565b6001602052600090815260409020546fffffffffffffffffffffffffffffffff811690700100000000000000000000000000000000900467ffffffffffffffff1682565b604080516fffffffffffffffffffffffffffffffff909316835267ffffffffffffffff9091166020830152016102b6565b6102aa6103be366004612fe6565b6103d661047f366004613022565b610b16565b6103d6610492366004612fa1565b610b73565b61049f601281565b60405160ff90911681526020016102b6565b61038d6104bf366004612fa1565b610d57565b6103d6610ddb565b61038d60025481565b61038d6104e3366004612fcb565b73ffffffffffffffffffffffffffffffffffffffff16600090815260016020526040902054700100000000000000000000000000000000900467ffffffffffffffff1690565b61038d610537366004612fa1565b61106b565b61038d61054a366004612fcb565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b61038d6110bc565b61058d610588366004612fcb565b6110cc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102b6565b6103d66105c0366004612fcb565b611103565b61038d6105d3366004612fcb565b73ffffffffffffffffffffffffffffffffffffffff166000908152600160205260409020546fffffffffffffffffffffffffffffffff1690565b61033661061b366004612fa1565b611137565b61064361062e366004613055565b600560205260009081526040902054600f0b81565b604051600f9190910b81526020016102b6565b6103d6610664366004612eec565b6111bf565b61038d610677366004612eec565b6113dc565b6103a3611400565b61038d610692366004612eec565b61140d565b61038d6106a5366004612fcb565b61145e565b6106bd6106b8366004612fa1565b61146a565b6040516102b69190600060a0820190508251600f0b82526020830151600f0b6020830152604083015167ffffffffffffffff808216604085015280606086015116606085015250506fffffffffffffffffffffffffffffffff608084015116608083015292915050565b61038d610735366004612eec565b61155b565b6103d661074836600461307f565b6115f7565b6103d6611602565b6103d66105c03660046130a1565b6106bd610771366004612fcb565b611639565b61038d6103be366004613101565b61058d7f0000000000000000000000000001a500a6b18995b03f44bb040a5ffc28e45cb081565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f36372b0700000000000000000000000000000000000000000000000000000000148061083e57507fffffffff0000000000000000000000000000000000000000000000000000000082167fe90fb3f600000000000000000000000000000000000000000000000000000000145b8061088a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6006805461089d90613134565b80601f01602080910402602001604051908101604052809291908181526020018280546108c990613134565b80156109165780601f106108eb57610100808354040283529160200191610916565b820191906000526020600020905b8154815290600101906020018083116108f957829003601f168201915b505050505081565b6040517f9c21e7b20000000000000000000000000000000000000000000000000000000081523060048201526000906024015b60405180910390fd5b3360009081526001602090815260408083208151808301909252546fffffffffffffffffffffffffffffffff81168252700100000000000000000000000000000000900467ffffffffffffffff1691810191909152908290036109e9576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516fffffffffffffffffffffffffffffffff16600003610a38576040517f1ff847b6000000000000000000000000000000000000000000000000000000008152336004820152602401610951565b610a434260016131b0565b816020015167ffffffffffffffff161015610aa85760208101516040517fd78507e100000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff9091166024820152426044820152606401610951565b6bffffffffffffffffffffffff821115610b03576040517f7ae59685000000000000000000000000000000000000000000000000000000008152600481018390526bffffffffffffffffffffffff6024820152604401610951565b610b12338360008460026116cc565b5050565b73ffffffffffffffffffffffffffffffffffffffff8316610b63576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b6e83838361192f565b505050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602090815260408083208151808301909252546fffffffffffffffffffffffffffffffff81168252700100000000000000000000000000000000900467ffffffffffffffff169181019190915290829003610c18576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516fffffffffffffffffffffffffffffffff16600003610c7d576040517f1ff847b600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610951565b610c884260016131b0565b816020015167ffffffffffffffff161015610ced5760208101516040517fd78507e100000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff9091166024820152426044820152606401610951565b6bffffffffffffffffffffffff821115610d48576040517f7ae59685000000000000000000000000000000000000000000000000000000008152600481018390526bffffffffffffffffffffffff6024820152604401610951565b610b6e838360008460006116cc565b600080610d648385611b4f565b5090506000610d7284611f6a565b915050816040015181610d8591906131c8565b60070b8260200151610d979190613231565b82518390610da69083906132e7565b600f90810b90915283516000910b13159050610dd35781516fffffffffffffffffffffffffffffffff1692505b505092915050565b336000908152600160209081526040918290208251808401909352546fffffffffffffffffffffffffffffffff81168352700100000000000000000000000000000000900467ffffffffffffffff16908201819052421015610e875760208101516040517fab0246b300000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff9091166024820152426044820152606401610951565b805160408051808201825260008082526020808301828152338084526001835285842094518554925167ffffffffffffffff16700100000000000000000000000000000000027fffffffffffffffff0000000000000000000000000000000000000000000000009093166fffffffffffffffffffffffffffffffff9182161792909217909455825495168086038084558551808701909652838652918501929092529093929091610f3a9186908461216d565b6040805184815242602082015233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a260408051838152602081018390527f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c910160405180910390a16040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018490527f0000000000000000000000000001a500a6b18995b03f44bb040a5ffc28e45cb073ffffffffffffffffffffffffffffffffffffffff169063a9059cbb906044016020604051808303816000875af1158015611040573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611064919061334e565b5050505050565b6000806110788385611b4f565b5090506110868360016131b0565b816060015167ffffffffffffffff1610156110b55780608001516fffffffffffffffffffffffffffffffff1691505b5092915050565b60006110c74261155b565b905090565b6040517f535db4ec000000000000000000000000000000000000000000000000000000008152306004820152600090602401610951565b6040517f535db4ec000000000000000000000000000000000000000000000000000000008152306004820152602401610951565b6004602052816000526040600020818154811061115357600080fd5b600091825260209091206002909102018054600190910154600f82810b945070010000000000000000000000000000000092839004900b925067ffffffffffffffff8082169268010000000000000000830490911691046fffffffffffffffffffffffffffffffff1685565b336000908152600160209081526040918290208251808401909352546fffffffffffffffffffffffffffffffff81168352700100000000000000000000000000000000900467ffffffffffffffff169082015262093a80804284010402915080600001516fffffffffffffffffffffffffffffffff16600003611270576040517f1ff847b6000000000000000000000000000000000000000000000000000000008152336004820152602401610951565b61127b4260016131b0565b816020015167ffffffffffffffff1610156112e05760208101516040517fd78507e100000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff9091166024820152426044820152606401610951565b60208101516112f090600161339f565b67ffffffffffffffff168210156113525760208101516040517f311d1bf900000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff909116602482015260448101839052606401610951565b611360630784ce00426131b0565b8211156113cd5733611376630784ce00426131b0565b6040517fc172987b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260448101839052606401610951565b610b12336000848460036116cc565b60008060006113ea84611f6a565b915091506113f88282612c35565b949350505050565b6007805461089d90613134565b60008061141b836000611b4f565b5090506114298360016131b0565b816060015167ffffffffffffffff1610156114585780608001516fffffffffffffffffffffffffffffffff1691505b50919050565b600061088a8242612d66565b6040805160a08101825260008082526020808301829052828401829052606083018290526080830182905273ffffffffffffffffffffffffffffffffffffffff8616825260049052919091208054839081106114c8576114c86133cb565b60009182526020918290206040805160a0810182526002939093029091018054600f81810b855270010000000000000000000000000000000091829004900b948401949094526001015467ffffffffffffffff808216928401929092526801000000000000000081049091166060830152919091046fffffffffffffffffffffffffffffffff1660808201529392505050565b6002546000908152600360209081526040808320815160a0810183528154600f81810b835270010000000000000000000000000000000091829004900b9482019490945260019091015467ffffffffffffffff8082169383019390935268010000000000000000810490921660608201529190046fffffffffffffffffffffffffffffffff1660808201526115f08184612c35565b9392505050565b610b1233838361192f565b60408051808201825260008082526020808301829052835180850190945281845283018190528054611637939192919061216d565b565b6040805160a08101825260008082526020808301829052828401829052606083018290526080830182905273ffffffffffffffffffffffffffffffffffffffff8516825260049052919091205480156114585773ffffffffffffffffffffffffffffffffffffffff831660009081526004602052604090206116bc6001836133fa565b815481106114c8576114c86133cb565b600080548581018083556040805180820190915283815260208101939093529091845160208087015167ffffffffffffffff16908301526fffffffffffffffffffffffffffffffff90811682528551880116855285156117375767ffffffffffffffff861660208601525b73ffffffffffffffffffffffffffffffffffffffff88166000908152600160209081526040909120865181549288015167ffffffffffffffff16700100000000000000000000000000000000027fffffffffffffffff0000000000000000000000000000000000000000000000009093166fffffffffffffffffffffffffffffffff909116179190911790556117cf8882878561216d565b8615611894576040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018890527f0000000000000000000000000001a500a6b18995b03f44bb040a5ffc28e45cb073ffffffffffffffffffffffffffffffffffffffff16906323b872dd906064016020604051808303816000875af115801561186e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611892919061334e565b505b8773ffffffffffffffffffffffffffffffffffffffff167fbe9cf0e939c614fad640a623a53ba0a807c8cb503c4c4c8dacabe27b86ff2dd588876020015187426040516118e49493929190613411565b60405180910390a260408051848152602081018490527f5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c910160405180910390a15050505050505050565b81600003611969576040517f7c946ed700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a808042830173ffffffffffffffffffffffffffffffffffffffff86166000908152600160209081526040918290208251808401909352546fffffffffffffffffffffffffffffffff811680845270010000000000000000000000000000000090910467ffffffffffffffff16918301919091529290910492909202925015611a535780516040517f89bf64dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526fffffffffffffffffffffffffffffffff9091166024820152604401610951565b611a5e4260016131b0565b821015611abc576040517f311d1bf900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015242602482015260448101839052606401610951565b611aca630784ce00426131b0565b821115611ae05783611376630784ce00426131b0565b6bffffffffffffffffffffffff831115611b3b576040517f7ae59685000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff6024820152604401610951565b611b498484848460016116cc565b50505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101829052908073ffffffffffffffffffffffffffffffffffffffff8416611b9f5750600254611bf7565b5073ffffffffffffffffffffffffffffffffffffffff831660009081526004602052604081205490819003611bd45750611f63565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b60005b6080811015611df05781611c0f8460016131b0565b11611df05760006002611c2284866131b0565b611c2d9060016131b0565b611c379190613471565b905073ffffffffffffffffffffffffffffffffffffffff8616611ce357600081815260036020908152604091829020825160a0810184528154600f81810b835270010000000000000000000000000000000091829004900b9382019390935260019091015467ffffffffffffffff80821694830194909452680100000000000000008104909316606082015291046fffffffffffffffffffffffffffffffff1660808201529450611da9565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600460205260409020805482908110611d1a57611d1a6133cb565b60009182526020918290206040805160a0810182526002939093029091018054600f81810b855270010000000000000000000000000000000091829004900b948401949094526001015467ffffffffffffffff808216928401929092526801000000000000000081049091166060830152919091046fffffffffffffffffffffffffffffffff16608082015294505b611db48760016131b0565b856060015167ffffffffffffffff161015611dd157809350611ddf565b611ddc6001826133fa565b92505b50611de981613485565b9050611bfa565b5073ffffffffffffffffffffffffffffffffffffffff8416611e9b57600082815260036020908152604091829020825160a0810184528154600f81810b835270010000000000000000000000000000000091829004900b9382019390935260019091015467ffffffffffffffff80821694830194909452680100000000000000008104909316606082015291046fffffffffffffffffffffffffffffffff1660808201529250611f61565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600460205260409020805483908110611ed257611ed26133cb565b60009182526020918290206040805160a0810182526002939093029091018054600f81810b855270010000000000000000000000000000000091829004900b948401949094526001015467ffffffffffffffff808216928401929092526801000000000000000081049091166060830152919091046fffffffffffffffffffffffffffffffff16608082015292505b505b9250929050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081018290529043831115611fd8576040517f8633967e00000000000000000000000000000000000000000000000000000000815260048101849052436024820152604401610951565b6000611fe5846000611b4f565b600254919450915060009081908310156120da5760006003816120098660016131b0565b81526020808201929092526040908101600020815160a0810183528154600f81810b835270010000000000000000000000000000000091829004900b9482019490945260019091015467ffffffffffffffff808216938301939093526801000000000000000081049092166060808301829052939092046fffffffffffffffffffffffffffffffff166080820152918801519192506120a891906134bd565b67ffffffffffffffff169250856040015181604001516120c891906134bd565b67ffffffffffffffff16915050612112565b60608501516120f39067ffffffffffffffff16436133fa565b9150846040015167ffffffffffffffff164261210f91906133fa565b90505b604085015167ffffffffffffffff16935081156121655781856060015167ffffffffffffffff168761214491906133fa565b61214e90836134e6565b6121589190613471565b61216290856131b0565b93505b505050915091565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805160a081018252600080825260208201819052918101829052606081018290526080810191909152600254600090819073ffffffffffffffffffffffffffffffffffffffff8916156123655742886020015167ffffffffffffffff16118015612216575087516fffffffffffffffffffffffffffffffff1615155b1561226557875161222c90630784ce0090613523565b600f0b6020808701919091528801516122469042906134bd565b67ffffffffffffffff16856020015161225f9190613231565b600f0b85525b42876020015167ffffffffffffffff16118015612294575086516fffffffffffffffffffffffffffffffff1615155b156122e35786516122aa90630784ce0090613523565b600f0b6020808601919091528701516122c49042906134bd565b67ffffffffffffffff1684602001516122dd9190613231565b600f0b84525b60208089015167ffffffffffffffff908116600090815260058352604090205491890151600f9290920b9450161561236557876020015167ffffffffffffffff16876020015167ffffffffffffffff160361234057829150612365565b60208088015167ffffffffffffffff16600090815260059091526040902054600f0b91505b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915281156124245750600081815260036020908152604091829020825160a0810184528154600f81810b835270010000000000000000000000000000000091829004900b9382019390935260019091015467ffffffffffffffff80821694830194909452680100000000000000008104909316606082015291046fffffffffffffffffffffffffffffffff16608082015261247d565b6040518060a001604052806000600f0b81526020016000600f0b81526020014267ffffffffffffffff1681526020014367ffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff1681525090505b604081015181600067ffffffffffffffff83164211156124e85760408401516124b09067ffffffffffffffff16426133fa565b60608501516124c99067ffffffffffffffff16436133fa565b6124db90670de0b6b3a76400006134e6565b6124e59190613471565b90505b600062093a806124f88186613597565b61250291906135be565b905060005b60ff8110156127585762093a80820191506000428367ffffffffffffffff16111561253457429250612553565b5067ffffffffffffffff8216600090815260056020526040902054600f0b5b61255d86846134bd565b60070b876020015161256f9190613231565b8751889061257e9083906132e7565b600f0b9052506020870180518291906125989083906135ee565b600f90810b90915288516000910b121590506125b357600087525b60008760200151600f0b12156125cb57600060208801525b67ffffffffffffffff83166040808901919091528501519295508592670de0b6b3a7640000906125fb90856134bd565b61260f9067ffffffffffffffff16866134e6565b6126199190613471565b8560600151612628919061339f565b67ffffffffffffffff90811660608901526080808701516fffffffffffffffffffffffffffffffff1690890152600198909801974290841603612693575067ffffffffffffffff431660608701526fffffffffffffffffffffffffffffffff8c166080870152612758565b506000878152600360209081526040918290208851918901516fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000009184168202178255928901516001909101805460608b015160808c015167ffffffffffffffff9485167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316929092176801000000000000000094909116939093029290921783169190921690920291909117905561275181613485565b9050612507565b5050600285905573ffffffffffffffffffffffffffffffffffffffff8d16156127f9578860200151886020015161278f91906132e7565b846020018181516127a091906135ee565b600f0b905250885188516127b491906132e7565b845185906127c39083906135ee565b600f90810b90915260208601516000910b121590506127e457600060208501525b60008460000151600f0b12156127f957600084525b6000858152600360209081526040918290208651918701516fffffffffffffffffffffffffffffffff92831670010000000000000000000000000000000091841682021782559287015160019091018054606089015160808a015167ffffffffffffffff9485167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909316929092176801000000000000000094909116939093029290921783169190921690920291909117905573ffffffffffffffffffffffffffffffffffffffff8d1615612c2657428c6020015167ffffffffffffffff16111561297e5760208901516128ee90886135ee565b96508b6020015167ffffffffffffffff168b6020015167ffffffffffffffff160361292557602088015161292290886132e7565b96505b60208c81015167ffffffffffffffff16600090815260059091526040902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff89161790555b428b6020015167ffffffffffffffff161180156129b657508b6020015167ffffffffffffffff168b6020015167ffffffffffffffff16115b15612a255760208801516129ca90876132e7565b60208c81015167ffffffffffffffff16600090815260059091526040902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff831617905595505b42886040019067ffffffffffffffff16908167ffffffffffffffff168152505043886060019067ffffffffffffffff16908167ffffffffffffffff16815250508a6000015188608001906fffffffffffffffffffffffffffffffff1690816fffffffffffffffffffffffffffffffff1681525050600460008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002088908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000160006101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff16021790555060208201518160000160106101000a8154816fffffffffffffffffffffffffffffffff0219169083600f0b6fffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060608201518160010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060808201518160010160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555050505b50505050505050505050505050565b60008062093a80808560400151612c4c9190613597565b612c5691906135be565b905060005b60ff811015612d3a5762093a808201915060008467ffffffffffffffff168367ffffffffffffffff161115612c9257849250612cb1565b5067ffffffffffffffff8216600090815260056020526040902054600f0b5b6040860151612cc090846131c8565b60070b8660200151612cd29190613231565b86518790612ce19083906132e7565b600f0b90525067ffffffffffffffff80861690841603612d015750612d3a565b8086602001818151612d1391906135ee565b600f0b9052505067ffffffffffffffff82166040860152612d3381613485565b9050612c5b565b5060008460000151600f0b13156110b557505090516fffffffffffffffffffffffffffffffff16919050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526004602052604081205480156110b55773ffffffffffffffffffffffffffffffffffffffff84166000908152600460205260408120612dc26001846133fa565b81548110612dd257612dd26133cb565b60009182526020918290206040805160a0810182526002939093029091018054600f81810b855270010000000000000000000000000000000091829004900b948401949094526001015467ffffffffffffffff808216928401839052680100000000000000008204166060840152929092046fffffffffffffffffffffffffffffffff1660808201529150612e6790856131c8565b60070b8160200151612e799190613231565b81518290612e889083906132e7565b600f90810b90915282516000910b13159050610dd35751600f0b949350505050565b600060208284031215612ebc57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146115f057600080fd5b600060208284031215612efe57600080fd5b5035919050565b600060208083528351808285015260005b81811015612f3257858101830151858201604001528201612f16565b81811115612f44576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612f9c57600080fd5b919050565b60008060408385031215612fb457600080fd5b612fbd83612f78565b946020939093013593505050565b600060208284031215612fdd57600080fd5b6115f082612f78565b600080600060608486031215612ffb57600080fd5b61300484612f78565b925061301260208501612f78565b9150604084013590509250925092565b60008060006060848603121561303757600080fd5b61304084612f78565b95602085013595506040909401359392505050565b60006020828403121561306757600080fd5b813567ffffffffffffffff811681146115f057600080fd5b6000806040838503121561309257600080fd5b50508035926020909101359150565b60008060008060008060c087890312156130ba57600080fd5b6130c387612f78565b95506020870135945060408701359350606087013560ff811681146130e757600080fd5b9598949750929560808101359460a0909101359350915050565b6000806040838503121561311457600080fd5b61311d83612f78565b915061312b60208401612f78565b90509250929050565b600181811c9082168061314857607f821691505b602082108103611458577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156131c3576131c3613181565b500190565b60008160070b8360070b60008112817fffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000183128115161561320b5761320b613181565b81677fffffffffffffff01831381161561322757613227613181565b5090039392505050565b600081600f0b83600f0b6f7fffffffffffffffffffffffffffffff60008213600084138383048511828216161561326a5761326a613181565b7fffffffffffffffffffffffffffffffff8000000000000000000000000000000060008512868205861281841616156132a5576132a5613181565b600087129250858205871284841616156132c1576132c1613181565b858505871281841616156132d7576132d7613181565b5050509290910295945050505050565b600081600f0b83600f0b60008112817fffffffffffffffffffffffffffffffff800000000000000000000000000000000183128115161561332a5761332a613181565b816f7fffffffffffffffffffffffffffffff01831381161561322757613227613181565b60006020828403121561336057600080fd5b815180151581146115f057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff8083168185168083038211156133c2576133c2613181565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008282101561340c5761340c613181565b500390565b84815267ffffffffffffffff84166020820152608081016004841061345f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60408201939093526060015292915050565b60008261348057613480613370565b500490565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036134b6576134b6613181565b5060010190565b600067ffffffffffffffff838116908316818110156134de576134de613181565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561351e5761351e613181565b500290565b600081600f0b83600f0b8061353a5761353a613370565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81147fffffffffffffffffffffffffffffffff800000000000000000000000000000008314161561358e5761358e613181565b90059392505050565b600067ffffffffffffffff808416806135b2576135b2613370565b92169190910492915050565b600067ffffffffffffffff808316818516818304811182151516156135e5576135e5613181565b02949350505050565b600081600f0b83600f0b60008212826f7fffffffffffffffffffffffffffffff0382138115161561362157613621613181565b827fffffffffffffffffffffffffffffffff8000000000000000000000000000000003821281161561365557613655613181565b5001939250505056fea2646970667358221220f99e7957a96c37b1b0b686b8989f714f8bc39f7695601819d3ce0d5e52590c9264736f6c634300080f0033

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

0000000000000000000000000001a500a6b18995b03f44bb040a5ffc28e45cb0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000012566f74696e6720457363726f77204f4c41530000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000676654f4c41530000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _token (address): 0x0001A500A6B18995B03f44bb040A5fFc28E45CB0
Arg [1] : _name (string): Voting Escrow OLAS
Arg [2] : _symbol (string): veOLAS

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000001a500a6b18995b03f44bb040a5ffc28e45cb0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [4] : 566f74696e6720457363726f77204f4c41530000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [6] : 76654f4c41530000000000000000000000000000000000000000000000000000


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  ]
[ 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.