FTM Price: $0.67 (-6.29%)
Gas: 27 GWei

Contract

0xE0B708753aab9d2Cc142ea52Cd7CD0c923A3389A
 

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Claim794594612024-04-16 9:15:082 hrs ago1713258908IN
0xE0B70875...923A3389A
0 FTM0.0067776123
Claim794552162024-04-16 6:56:014 hrs ago1713250561IN
0xE0B70875...923A3389A
0 FTM0.0081953929.21541933
Claim794380322024-04-15 22:22:3613 hrs ago1713219756IN
0xE0B70875...923A3389A
0 FTM0.015323352
Claim794269752024-04-15 18:56:0716 hrs ago1713207367IN
0xE0B70875...923A3389A
0 FTM0.016068252.05254502
Claim794268142024-04-15 18:53:1716 hrs ago1713207197IN
0xE0B70875...923A3389A
0 FTM0.0159527353
Claim794146602024-04-15 15:19:3420 hrs ago1713194374IN
0xE0B70875...923A3389A
0 FTM0.0148255552.85100657
Claim794138262024-04-15 15:04:5920 hrs ago1713193499IN
0xE0B70875...923A3389A
0 FTM0.0191344659
Claim793856692024-04-15 6:42:3928 hrs ago1713163359IN
0xE0B70875...923A3389A
0 FTM0.0153492150.86936293
Claim793846802024-04-15 6:19:3329 hrs ago1713161973IN
0xE0B70875...923A3389A
0 FTM0.0257517988
Claim793785652024-04-15 2:12:4733 hrs ago1713147167IN
0xE0B70875...923A3389A
0 FTM0.0076515527
Claim793785522024-04-15 2:12:1633 hrs ago1713147136IN
0xE0B70875...923A3389A
0 FTM0.0076515527
Claim793717252024-04-14 23:03:0636 hrs ago1713135786IN
0xE0B70875...923A3389A
0 FTM0.0105643437.92540063
Claim793522842024-04-14 16:14:1243 hrs ago1713111252IN
0xE0B70875...923A3389A
0 FTM0.0123550333
Claim793376532024-04-14 11:06:212 days ago1713092781IN
0xE0B70875...923A3389A
0 FTM0.0123770642
Claim793119552024-04-14 2:09:092 days ago1713060549IN
0xE0B70875...923A3389A
0 FTM0.06428971221.94275217
Claim793092002024-04-14 1:07:062 days ago1713056826IN
0xE0B70875...923A3389A
0 FTM0.07493013277.78549664
Claim792889682024-04-13 19:29:542 days ago1713036594IN
0xE0B70875...923A3389A
0 FTM0.0197804165
Claim792711052024-04-13 11:09:563 days ago1713006596IN
0xE0B70875...923A3389A
0 FTM0.0046813115.31813942
Claim792640902024-04-13 6:48:543 days ago1712990934IN
0xE0B70875...923A3389A
0 FTM0.0055991419
Claim792588812024-04-13 4:57:003 days ago1712984220IN
0xE0B70875...923A3389A
0 FTM0.0088033823
Claim792516192024-04-13 2:11:273 days ago1712974287IN
0xE0B70875...923A3389A
0 FTM0.0105886935.9570086
Claim792119762024-04-12 14:16:043 days ago1712931364IN
0xE0B70875...923A3389A
0 FTM0.0147660752.63897475
Claim791950822024-04-12 9:04:594 days ago1712912699IN
0xE0B70875...923A3389A
0 FTM0.0049040616.65320292
Claim791876732024-04-12 4:49:074 days ago1712897347IN
0xE0B70875...923A3389A
0 FTM0.03309558105
Claim791873522024-04-12 4:33:354 days ago1712896415IN
0xE0B70875...923A3389A
0 FTM0.003486989.93834306
View all transactions

Latest 1 internal transaction

Parent Txn Hash Block From To Value
649651832023-07-01 8:51:25290 days ago1688201485  Contract Creation0 FTM
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x82D862D1...e99A9E339
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
RewardsDistributor

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU AGPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at ftmscan.com on 2023-06-30
*/

// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;


// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}


interface IERC20 {
    function totalSupply() external view returns (uint256);
    function transfer(address recipient, uint amount) external returns (bool);
    function decimals() external view returns (uint8);
    function symbol() external view returns (string memory);
    function balanceOf(address) external view returns (uint);
    function transferFrom(address sender, address recipient, uint amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint);
    function approve(address spender, uint value) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}


interface IRewardsDistributor {
    function checkpoint_token() external;
    function checkpoint_total_supply() external;
}



interface IVotingEscrow {

    struct Point {
        int128 bias;
        int128 slope; // # -dweight / dt
        uint256 ts;
        uint256 blk; // block
    }

    function token() external view returns (address);
    function team() external returns (address);
    function epoch() external view returns (uint);
    function point_history(uint loc) external view returns (Point memory);
    function user_point_history(uint tokenId, uint loc) external view returns (Point memory);
    function user_point_epoch(uint tokenId) external view returns (uint);

    function ownerOf(uint) external view returns (address);
    function isApprovedOrOwner(address, uint) external view returns (bool);
    function transferFrom(address, address, uint) external;

    function voting(uint tokenId) external;
    function abstain(uint tokenId) external;
    function attach(uint tokenId) external;
    function detach(uint tokenId) external;

    function checkpoint() external;
    function deposit_for(uint tokenId, uint value) external;
    function create_lock_for(uint, uint, address) external returns (uint);

    function balanceOfNFT(uint) external view returns (uint);
    function totalSupply() external view returns (uint);
}


/*

@title Curve Fee Distribution modified for ve(3,3) emissions
@author Curve Finance, andrecronje
@license MIT

*/

contract RewardsDistributor is IRewardsDistributor {

    event CheckpointToken(
        uint time,
        uint tokens
    );

    event Claimed(
        uint tokenId,
        uint amount,
        uint claim_epoch,
        uint max_epoch
    );

    uint constant WEEK = 7 * 86400;

    uint public start_time;
    uint public time_cursor;
    mapping(uint => uint) public time_cursor_of;
    mapping(uint => uint) public user_epoch_of;

    uint public last_token_time;
    uint[1000000000000000] public tokens_per_week;

    address public voting_escrow;
    address public token;
    uint public token_last_balance;

    uint[1000000000000000] public ve_supply;

    address public depositor;

    constructor(address _voting_escrow) {
        uint _t = block.timestamp / WEEK * WEEK;
        start_time = _t;
        last_token_time = _t;
        time_cursor = _t;
        address _token = IVotingEscrow(_voting_escrow).token();
        token = _token;
        voting_escrow = _voting_escrow;
        depositor = msg.sender;
        require(IERC20(_token).approve(_voting_escrow, type(uint).max));
    }

    function timestamp() external view returns (uint) {
        return block.timestamp / WEEK * WEEK;
    }

    function _checkpoint_token() internal {
        uint token_balance = IERC20(token).balanceOf(address(this));
        uint to_distribute = token_balance - token_last_balance;
        token_last_balance = token_balance;

        uint t = last_token_time;
        uint since_last = block.timestamp - t;
        last_token_time = block.timestamp;
        uint this_week = t / WEEK * WEEK;
        uint next_week = 0;

        for (uint i = 0; i < 20; i++) {
            next_week = this_week + WEEK;
            if (block.timestamp < next_week) {
                if (since_last == 0 && block.timestamp == t) {
                    tokens_per_week[this_week] += to_distribute;
                } else {
                    tokens_per_week[this_week] += to_distribute * (block.timestamp - t) / since_last;
                }
                break;
            } else {
                if (since_last == 0 && next_week == t) {
                    tokens_per_week[this_week] += to_distribute;
                } else {
                    tokens_per_week[this_week] += to_distribute * (next_week - t) / since_last;
                }
            }
            t = next_week;
            this_week = next_week;
        }
        emit CheckpointToken(block.timestamp, to_distribute);
    }

    function checkpoint_token() external {
        assert(msg.sender == depositor);
        _checkpoint_token();
    }

    function _find_timestamp_epoch(address ve, uint _timestamp) internal view returns (uint) {
        uint _min = 0;
        uint _max = IVotingEscrow(ve).epoch();
        for (uint i = 0; i < 128; i++) {
            if (_min >= _max) break;
            uint _mid = (_min + _max + 2) / 2;
            IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(_mid);
            if (pt.ts <= _timestamp) {
                _min = _mid;
            } else {
                _max = _mid - 1;
            }
        }
        return _min;
    }

    function _find_timestamp_user_epoch(address ve, uint tokenId, uint _timestamp, uint max_user_epoch) internal view returns (uint) {
        uint _min = 0;
        uint _max = max_user_epoch;
        for (uint i = 0; i < 128; i++) {
            if (_min >= _max) break;
            uint _mid = (_min + _max + 2) / 2;
            IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(tokenId, _mid);
            if (pt.ts <= _timestamp) {
                _min = _mid;
            } else {
                _max = _mid -1;
            }
        }
        return _min;
    }

    function ve_for_at(uint _tokenId, uint _timestamp) external view returns (uint) {
        address ve = voting_escrow;
        uint max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);
        uint epoch = _find_timestamp_user_epoch(ve, _tokenId, _timestamp, max_user_epoch);
        IVotingEscrow.Point memory pt = IVotingEscrow(ve).user_point_history(_tokenId, epoch);
        return Math.max(uint(int256(pt.bias - pt.slope * (int128(int256(_timestamp - pt.ts))))), 0);
    }

    function _checkpoint_total_supply() internal {
        address ve = voting_escrow;
        uint t = time_cursor;
        uint rounded_timestamp = block.timestamp / WEEK * WEEK;
        IVotingEscrow(ve).checkpoint();

        for (uint i = 0; i < 20; i++) {
            if (t > rounded_timestamp) {
                break;
            } else {
                uint epoch = _find_timestamp_epoch(ve, t);
                IVotingEscrow.Point memory pt = IVotingEscrow(ve).point_history(epoch);
                int128 dt = 0;
                if (t > pt.ts) {
                    dt = int128(int256(t - pt.ts));
                }
                ve_supply[t] = Math.max(uint(int256(pt.bias - pt.slope * dt)), 0);
            }
            t += WEEK;
        }
        time_cursor = t;
    }

    function checkpoint_total_supply() external {
        _checkpoint_total_supply();
    }

    function _claim(uint _tokenId, address ve, uint _last_token_time) internal returns (uint) {
        uint user_epoch = 0;
        uint to_distribute = 0;

        uint max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);
        uint _start_time = start_time;

        if (max_user_epoch == 0) return 0;

        uint week_cursor = time_cursor_of[_tokenId];
        if (week_cursor == 0) {
            user_epoch = _find_timestamp_user_epoch(ve, _tokenId, _start_time, max_user_epoch);
        } else {
            user_epoch = user_epoch_of[_tokenId];
        }

        if (user_epoch == 0) user_epoch = 1;

        IVotingEscrow.Point memory user_point = IVotingEscrow(ve).user_point_history(_tokenId, user_epoch);

        if (week_cursor == 0) week_cursor = (user_point.ts + WEEK - 1) / WEEK * WEEK;
        if (week_cursor >= last_token_time) return 0;
        if (week_cursor < _start_time) week_cursor = _start_time;

        IVotingEscrow.Point memory old_user_point;

        for (uint i = 0; i < 50; i++) {
            if (week_cursor >= _last_token_time) break;

            if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {
                user_epoch += 1;
                old_user_point = user_point;
                if (user_epoch > max_user_epoch) {
                    user_point = IVotingEscrow.Point(0,0,0,0);
                } else {
                    user_point = IVotingEscrow(ve).user_point_history(_tokenId, user_epoch);
                }
            } else {
                int128 dt = int128(int256(week_cursor - old_user_point.ts));
                uint balance_of = Math.max(uint(int256(old_user_point.bias - dt * old_user_point.slope)), 0);
                if (balance_of == 0 && user_epoch > max_user_epoch) break;
                if (balance_of != 0) {
                    to_distribute += balance_of * tokens_per_week[week_cursor] / ve_supply[week_cursor];
                }
                week_cursor += WEEK;
            }
        }

        user_epoch = Math.min(max_user_epoch, user_epoch - 1);
        user_epoch_of[_tokenId] = user_epoch;
        time_cursor_of[_tokenId] = week_cursor;

        emit Claimed(_tokenId, to_distribute, user_epoch, max_user_epoch);

        return to_distribute;
    }

    function _claimable(uint _tokenId, address ve, uint _last_token_time) internal view returns (uint) {
        uint user_epoch = 0;
        uint to_distribute = 0;

        uint max_user_epoch = IVotingEscrow(ve).user_point_epoch(_tokenId);
        uint _start_time = start_time;

        if (max_user_epoch == 0) return 0;

        uint week_cursor = time_cursor_of[_tokenId];
        if (week_cursor == 0) {
            user_epoch = _find_timestamp_user_epoch(ve, _tokenId, _start_time, max_user_epoch);
        } else {
            user_epoch = user_epoch_of[_tokenId];
        }

        if (user_epoch == 0) user_epoch = 1;

        IVotingEscrow.Point memory user_point = IVotingEscrow(ve).user_point_history(_tokenId, user_epoch);

        if (week_cursor == 0) week_cursor = (user_point.ts + WEEK - 1) / WEEK * WEEK;
        if (week_cursor >= last_token_time) return 0;
        if (week_cursor < _start_time) week_cursor = _start_time;

        IVotingEscrow.Point memory old_user_point;

        for (uint i = 0; i < 50; i++) {
            if (week_cursor >= _last_token_time) break;

            if (week_cursor >= user_point.ts && user_epoch <= max_user_epoch) {
                user_epoch += 1;
                old_user_point = user_point;
                if (user_epoch > max_user_epoch) {
                    user_point = IVotingEscrow.Point(0,0,0,0);
                } else {
                    user_point = IVotingEscrow(ve).user_point_history(_tokenId, user_epoch);
                }
            } else {
                int128 dt = int128(int256(week_cursor - old_user_point.ts));
                uint balance_of = Math.max(uint(int256(old_user_point.bias - dt * old_user_point.slope)), 0);
                if (balance_of == 0 && user_epoch > max_user_epoch) break;
                if (balance_of != 0) {
                    to_distribute += balance_of * tokens_per_week[week_cursor] / ve_supply[week_cursor];
                }
                week_cursor += WEEK;
            }
        }

        return to_distribute;
    }

    function claimable(uint _tokenId) external view returns (uint) {
        uint _last_token_time = last_token_time / WEEK * WEEK;
        return _claimable(_tokenId, voting_escrow, _last_token_time);
    }

    function claim(uint _tokenId) external returns (uint) {
        if (block.timestamp >= time_cursor) _checkpoint_total_supply();
        uint _last_token_time = last_token_time;
        _last_token_time = _last_token_time / WEEK * WEEK;
        uint amount = _claim(_tokenId, voting_escrow, _last_token_time);
        if (amount != 0) {
            IVotingEscrow(voting_escrow).deposit_for(_tokenId, amount);
            token_last_balance -= amount;
        }
        return amount;
    }

    function claim_many(uint[] memory _tokenIds) external returns (bool) {
        if (block.timestamp >= time_cursor) _checkpoint_total_supply();
        uint _last_token_time = last_token_time;
        _last_token_time = _last_token_time / WEEK * WEEK;
        address _voting_escrow = voting_escrow;
        uint total = 0;

        for (uint i = 0; i < _tokenIds.length; i++) {
            uint _tokenId = _tokenIds[i];
            if (_tokenId == 0) break;
            uint amount = _claim(_tokenId, _voting_escrow, _last_token_time);
            if (amount != 0) {
                IVotingEscrow(_voting_escrow).deposit_for(_tokenId, amount);
                total += amount;
            }
        }
        if (total != 0) {
            token_last_balance -= total;
        }

        return true;
    }

    // Once off event on contract initialize
    function setDepositor(address _depositor) external {
        require(msg.sender == depositor);
        depositor = _depositor;
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_voting_escrow","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"CheckpointToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claim_epoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"max_epoch","type":"uint256"}],"name":"Claimed","type":"event"},{"inputs":[],"name":"checkpoint_token","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"checkpoint_total_supply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"claim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"claim_many","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"claimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"last_token_time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_depositor","type":"address"}],"name":"setDepositor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"start_time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"time_cursor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"time_cursor_of","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token_last_balance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokens_per_week","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"user_epoch_of","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"ve_for_at","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ve_supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voting_escrow","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063834ee417116100ad578063d4dafba811610071578063d4dafba81461024a578063dfe050311461025d578063edf5999714610276578063f2c098b714610289578063fc0c546a1461029c57600080fd5b8063834ee417146101ed578063b21ed502146101f6578063b80777ea146101fe578063c7c4ff4614610206578063d1d58b251461023757600080fd5b8063379607f5116100f4578063379607f514610194578063486d25fe146101a757806368809889146101c75780637f58e8f8146101da578063811a40fe146101e357600080fd5b8063127dcbd31461012657806316aea5c0146101425780631f1db0431461016257806322b04bfc14610185575b600080fd5b61012f60015481565b6040519081526020015b60405180910390f35b61012f610150366004611566565b60036020526000908152604090205481565b6101756101703660046115c6565b6102b5565b6040519015158152602001610139565b61012f66038d7ea4c680075481565b61012f6101a2366004611566565b6103fb565b61012f6101b5366004611566565b60026020526000908152604090205481565b61012f6101d536600461166c565b6104e5565b61012f60045481565b6101eb610628565b005b61012f60005481565b6101eb610652565b61012f61065a565b66071afd498d00085461021f906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b61012f610245366004611566565b610679565b61012f610258366004611566565b6106b9565b66038d7ea4c680055461021f906001600160a01b031681565b61012f610284366004611566565b6106dc565b6101eb61029736600461168e565b6106f2565b66038d7ea4c680065461021f906001600160a01b031681565b600060015442106102c8576102c8610737565b60045462093a806102d981836116cd565b6102e391906116ef565b66038d7ea4c68005549091506001600160a01b03166000805b85518110156103cb5760008682815181106103195761031961170e565b602002602001015190508060000361033157506103cb565b600061033e8286886108da565b905080156103b657604051631dd33fc560e31b815260048101839052602481018290526001600160a01b0386169063ee99fe2890604401600060405180830381600087803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505080846103b39190611724565b93505b505080806103c39061173c565b9150506102fc565b5080156103f0578066038d7ea4c6800760008282546103ea9190611755565b90915550505b506001949350505050565b6000600154421061040e5761040e610737565b60045462093a8061041f81836116cd565b61042991906116ef565b66038d7ea4c680055490915060009061044d9085906001600160a01b0316846108da565b905080156104de5766038d7ea4c6800554604051631dd33fc560e31b815260048101869052602481018390526001600160a01b039091169063ee99fe2890604401600060405180830381600087803b1580156104a857600080fd5b505af11580156104bc573d6000803e3d6000fd5b505050508066038d7ea4c6800760008282546104d89190611755565b90915550505b9392505050565b66038d7ea4c680055460405163391044d760e21b8152600481018490526000916001600160a01b0316908290829063e441135c90602401602060405180830381865afa158015610539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055d919061176c565b9050600061056d83878785610cfe565b6040516309bb79ed60e11b815260048101889052602481018290529091506000906001600160a01b03851690631376f3da90604401608060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061179c565b905061061d8160400151876105f89190611755565b8260200151610607919061180e565b825161061391906118ac565b600f0b6000610df2565b979650505050505050565b66071afd498d0008546001600160a01b03163314610648576106486118fc565b610650610e08565b565b610650610737565b600062093a8061066a81426116cd565b61067491906116ef565b905090565b60008062093a808060045461068e91906116cd565b61069891906116ef565b66038d7ea4c68005549091506104de9084906001600160a01b031683611065565b66038d7ea4c680088166038d7ea4c6800081106106d557600080fd5b0154905081565b60058166038d7ea4c6800081106106d557600080fd5b66071afd498d0008546001600160a01b0316331461070f57600080fd5b66071afd498d000880546001600160a01b0319166001600160a01b0392909216919091179055565b66038d7ea4c68005546001546001600160a01b0390911690600062093a8061075f81426116cd565b61076991906116ef565b9050826001600160a01b031663c2c4c5c16040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107a657600080fd5b505af11580156107ba573d6000803e3d6000fd5b5050505060005b60148110156108d2578183116108d25760006107dd8585611402565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0387169063d1febfb990602401608060405180830381865afa158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c919061179c565b90506000816040015186111561086e57604082015161086b9087611755565b90505b61088d818360200151610881919061180e565b835161061391906118ac565b66038d7ea4c680088766038d7ea4c6800081106108ac576108ac61170e565b01555050506108be62093a8084611724565b9250806108ca8161173c565b9150506107c1565b505060015550565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa158015610928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094c919061176c565b600080549192508290036109675760009450505050506104de565b600088815260026020526040812054908190036109915761098a888a8486610cfe565b94506109a3565b60008981526003602052604090205494505b846000036109b057600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa1580156109ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a23919061179c565b905081600003610a685762093a8080600162093a808460400151610a479190611724565b610a519190611755565b610a5b91906116cd565b610a6591906116ef565b91505b6004548210610a8057600096505050505050506104de565b82821015610a8c578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b6032811015610c735789841015610c735782604001518410158015610ad65750858811155b15610b9c57610ae6600189611724565b975082915085881115610b255760405180608001604052806000600f0b81526020016000600f0b81526020016000815260200160008152509250610c61565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061179c565b9250610c61565b6000826040015185610bae9190611755565b90506000610bd1846020015183610bc5919061180e565b855161061391906118ac565b905080158015610be05750878a115b15610bec575050610c73565b8015610c4f5766038d7ea4c680088666038d7ea4c680008110610c1157610c1161170e565b015460058766038d7ea4c680008110610c2c57610c2c61170e565b0154610c3890836116ef565b610c4291906116cd565b610c4c908a611724565b98505b610c5c62093a8087611724565b955050505b80610c6b8161173c565b915050610ab1565b50610c8885610c8360018a611755565b611557565b60008c8152600360209081526040808320849055600282529182902086905581518e8152908101899052908101829052606081018790529097507fcae2990aa9af8eb1c64713b7eddb3a80bf18e49a94a13fe0d0002b5d61d58f009060800160405180910390a150939998505050505050505050565b60008082815b6080811015610de65781831015610de65760006002610d238486611724565b610d2e906002611724565b610d3891906116cd565b6040516309bb79ed60e11b8152600481018a9052602481018290529091506000906001600160a01b038b1690631376f3da90604401608060405180830381865afa158015610d8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dae919061179c565b905087816040015111610dc357819450610dd1565b610dce600183611755565b93505b50508080610dde9061173c565b915050610d04565b50909695505050505050565b6000818311610e0157816104de565b5090919050565b66038d7ea4c68006546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7b919061176c565b9050600066038d7ea4c680075482610e939190611755565b66038d7ea4c680078390556004549091506000610eb08242611755565b426004559050600062093a80610ec681856116cd565b610ed091906116ef565b90506000805b601481101561102357610eec62093a8084611724565b915081421015610f755783158015610f0357508442145b15610f3d578560058466038d7ea4c680008110610f2257610f2261170e565b016000828254610f329190611724565b909155506110239050565b83610f488642611755565b610f5290886116ef565b610f5c91906116cd565b60058466038d7ea4c680008110610f2257610f2261170e565b83158015610f8257508482145b15610fbc578560058466038d7ea4c680008110610fa157610fa161170e565b016000828254610fb19190611724565b9091555061100a9050565b83610fc78684611755565b610fd190886116ef565b610fdb91906116cd565b60058466038d7ea4c680008110610ff457610ff461170e565b0160008282546110049190611724565b90915550505b819450819250808061101b9061173c565b915050610ed6565b5060408051428152602081018790527fce749457b74e10f393f2c6b1ce4261b78791376db5a3f501477a809f03f500d6910160405180910390a1505050505050565b60405163391044d760e21b8152600481018490526000908190819081906001600160a01b0387169063e441135c90602401602060405180830381865afa1580156110b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d7919061176c565b600080549192508290036110f25760009450505050506104de565b6000888152600260205260408120549081900361111c57611115888a8486610cfe565b945061112e565b60008981526003602052604090205494505b8460000361113b57600194505b6040516309bb79ed60e11b8152600481018a9052602481018690526000906001600160a01b038a1690631376f3da90604401608060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae919061179c565b9050816000036111f35762093a8080600162093a8084604001516111d29190611724565b6111dc9190611755565b6111e691906116cd565b6111f091906116ef565b91505b600454821061120b57600096505050505050506104de565b82821015611217578291505b6040805160808101825260008082526020820181905291810182905260608101829052905b60328110156113f257898410156113f257826040015184101580156112615750858811155b1561132757611271600189611724565b9750829150858811156112b05760405180608001604052806000600f0b81526020016000600f0b815260200160008152602001600081525092506113e0565b6040516309bb79ed60e11b8152600481018d9052602481018990526001600160a01b038c1690631376f3da90604401608060405180830381865afa1580156112fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611320919061179c565b92506113e0565b60008260400151856113399190611755565b90506000611350846020015183610bc5919061180e565b90508015801561135f5750878a115b1561136b5750506113f2565b80156113ce5766038d7ea4c680088666038d7ea4c6800081106113905761139061170e565b015460058766038d7ea4c6800081106113ab576113ab61170e565b01546113b790836116ef565b6113c191906116cd565b6113cb908a611724565b98505b6113db62093a8087611724565b955050505b806113ea8161173c565b91505061123c565b50949a9950505050505050505050565b600080600090506000846001600160a01b031663900cf0cf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611449573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146d919061176c565b905060005b608081101561154d578183101561154d57600060026114918486611724565b61149c906002611724565b6114a691906116cd565b60405163d1febfb960e01b8152600481018290529091506000906001600160a01b0389169063d1febfb990602401608060405180830381865afa1580156114f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611515919061179c565b90508681604001511161152a57819450611538565b611535600183611755565b93505b505080806115459061173c565b915050611472565b5090949350505050565b6000818310610e0157816104de565b60006020828403121561157857600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156115be576115be61157f565b604052919050565b600060208083850312156115d957600080fd5b823567ffffffffffffffff808211156115f157600080fd5b818501915085601f83011261160557600080fd5b8135818111156116175761161761157f565b8060051b9150611628848301611595565b818152918301840191848101908884111561164257600080fd5b938501935b8385101561166057843582529385019390850190611647565b98975050505050505050565b6000806040838503121561167f57600080fd5b50508035926020909101359150565b6000602082840312156116a057600080fd5b81356001600160a01b03811681146104de57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000826116ea57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615611709576117096116b7565b500290565b634e487b7160e01b600052603260045260246000fd5b60008219821115611737576117376116b7565b500190565b60006001820161174e5761174e6116b7565b5060010190565b600082821015611767576117676116b7565b500390565b60006020828403121561177e57600080fd5b5051919050565b8051600f81900b811461179757600080fd5b919050565b6000608082840312156117ae57600080fd5b6040516080810181811067ffffffffffffffff821117156117d1576117d161157f565b6040526117dd83611785565b81526117eb60208401611785565b602082015260408301516040820152606083015160608201528091505092915050565b600081600f0b83600f0b60016001607f1b0360008213600084138383048511828216161561183e5761183e6116b7565b6f7fffffffffffffffffffffffffffffff19600085128281168783058712161561186a5761186a6116b7565b60008712925085820587128484161615611886576118866116b7565b8585058712818416161561189c5761189c6116b7565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156118d7576118d76116b7565b8160016001607f1b030183138116156118f2576118f26116b7565b5090039392505050565b634e487b7160e01b600052600160045260246000fdfea2646970667358221220df39fa4149f6a026a6d05b7f018116456ad78482d46afe7b6da486093c631dbd64736f6c634300080d0033

Deployed Bytecode Sourcemap

15427:11456:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15760:23;;;;;;;;;160:25:1;;;148:2;133:18;15760:23:0;;;;;;;;15840:42;;;;;;:::i;:::-;;;;;;;;;;;;;;25865:826;;;;;;:::i;:::-;;:::i;:::-;;;1909:14:1;;1902:22;1884:41;;1872:2;1857:18;25865:826:0;1744:187:1;16041:30:0;;;;;;25359:498;;;;;;:::i;:::-;;:::i;15790:43::-;;;;;;:::i;:::-;;;;;;;;;;;;;;19304:492;;;;;;:::i;:::-;;:::i;15891:27::-;;;;;;18011:117;;;:::i;:::-;;15731:22;;;;;;20617:89;;;:::i;16585:105::-;;;:::i;16128:24::-;;;;;-1:-1:-1;;;;;16128:24:0;;;;;;-1:-1:-1;;;;;2353:32:1;;;2335:51;;2323:2;2308:18;16128:24:0;2189:203:1;25145:206:0;;;;;;:::i;:::-;;:::i;16080:39::-;;;;;;:::i;:::-;;:::i;15979:28::-;;;;;-1:-1:-1;;;;;15979:28:0;;;15925:45;;;;;;:::i;:::-;;:::i;26745:135::-;;;;;;:::i;:::-;;:::i;16014:20::-;;;;;-1:-1:-1;;;;;16014:20:0;;;25865:826;25928:4;25968:11;;25949:15;:30;25945:62;;25981:26;:24;:26::i;:::-;26042:15;;15713:9;26087:23;15713:9;26042:15;26087:23;:::i;:::-;:30;;;;:::i;:::-;26153:13;;26068:49;;-1:-1:-1;;;;;;26153:13:0;26128:22;;26204:376;26225:9;:16;26221:1;:20;26204:376;;;26263:13;26279:9;26289:1;26279:12;;;;;;;;:::i;:::-;;;;;;;26263:28;;26310:8;26322:1;26310:13;26306:24;;26325:5;;;26306:24;26345:11;26359:50;26366:8;26376:14;26392:16;26359:6;:50::i;:::-;26345:64;-1:-1:-1;26428:11:0;;26424:145;;26460:59;;-1:-1:-1;;;26460:59:0;;;;;3521:25:1;;;3562:18;;;3555:34;;;-1:-1:-1;;;;;26460:41:0;;;;;3494:18:1;;26460:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26547:6;26538:15;;;;;:::i;:::-;;;26424:145;26248:332;;26243:3;;;;;:::i;:::-;;;;26204:376;;;-1:-1:-1;26594:10:0;;26590:70;;26643:5;26621:18;;:27;;;;;;;:::i;:::-;;;;-1:-1:-1;;26590:70:0;-1:-1:-1;26679:4:0;;25865:826;-1:-1:-1;;;;25865:826:0:o;25359:498::-;25407:4;25447:11;;25428:15;:30;25424:62;;25460:26;:24;:26::i;:::-;25521:15;;15713:9;25566:23;15713:9;25521:15;25566:23;:::i;:::-;:30;;;;:::i;:::-;25638:13;;25547:49;;-1:-1:-1;25607:11:0;;25621:49;;25628:8;;-1:-1:-1;;;;;25638:13:0;25547:49;25621:6;:49::i;:::-;25607:63;-1:-1:-1;25685:11:0;;25681:145;;25727:13;;25713:58;;-1:-1:-1;;;25713:58:0;;;;;3521:25:1;;;3562:18;;;3555:34;;;-1:-1:-1;;;;;25727:13:0;;;;25713:40;;3494:18:1;;25713:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25808:6;25786:18;;:28;;;;;;;:::i;:::-;;;;-1:-1:-1;;25681:145:0;25843:6;25359:498;-1:-1:-1;;;25359:498:0:o;19304:492::-;19408:13;;19454:44;;-1:-1:-1;;;19454:44:0;;;;;160:25:1;;;19378:4:0;;-1:-1:-1;;;;;19408:13:0;;19378:4;;19408:13;;19454:34;;133:18:1;;19454:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19432:66;;19509:10;19522:68;19549:2;19553:8;19563:10;19575:14;19522:26;:68::i;:::-;19633:53;;-1:-1:-1;;;19633:53:0;;;;;3521:25:1;;;3562:18;;;3555:34;;;19509:81:0;;-1:-1:-1;19601:29:0;;-1:-1:-1;;;;;19633:36:0;;;;;3494:18:1;;19633:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19601:85;;19704:84;19774:2;:5;;;19761:10;:18;;;;:::i;:::-;19735:2;:8;;;:47;;;;:::i;:::-;19725:7;;:57;;;;:::i;:::-;19718:65;;19786:1;19704:8;:84::i;:::-;19697:91;19304:492;-1:-1:-1;;;;;;;19304:492:0:o;18011:117::-;18080:9;;-1:-1:-1;;;;;18080:9:0;18066:10;:23;18059:31;;;;:::i;:::-;18101:19;:17;:19::i;:::-;18011:117::o;20617:89::-;20672:26;:24;:26::i;16585:105::-;16629:4;15713:9;16653:22;15713:9;16653:15;:22;:::i;:::-;:29;;;;:::i;:::-;16646:36;;16585:105;:::o;25145:206::-;25202:4;25219:21;15713:9;;25243:15;;:22;;;;:::i;:::-;:29;;;;:::i;:::-;25311:13;;25219:53;;-1:-1:-1;25290:53:0;;25301:8;;-1:-1:-1;;;;;25311:13:0;25219:53;25290:10;:53::i;16080:39::-;;;;;;;;;;;;;;;-1:-1:-1;16080:39:0;:::o;15925:45::-;;;;;;;;;;;26745:135;26829:9;;-1:-1:-1;;;;;26829:9:0;26815:10;:23;26807:32;;;;;;26850:9;:22;;-1:-1:-1;;;;;;26850:22:0;-1:-1:-1;;;;;26850:22:0;;;;;;;;;;26745:135::o;19804:805::-;19873:13;;;19906:11;-1:-1:-1;;;;;19873:13:0;;;;19860:10;15713:9;19953:22;15713:9;19953:15;:22;:::i;:::-;:29;;;;:::i;:::-;19928:54;;20007:2;-1:-1:-1;;;;;19993:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20041:6;20036:540;20057:2;20053:1;:6;20036:540;;;20089:17;20085:1;:21;20127:5;20081:460;20173:10;20186:28;20208:2;20212:1;20186:21;:28::i;:::-;20265:38;;-1:-1:-1;;;20265:38:0;;;;;160:25:1;;;20173:41:0;;-1:-1:-1;20233:29:0;;-1:-1:-1;;;;;20265:31:0;;;;;133:18:1;;20265:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;20233:70;;20322:9;20362:2;:5;;;20358:1;:9;20354:88;;;20415:5;;;;20411:9;;:1;:9;:::i;:::-;20392:30;;20354:88;20475:50;20517:2;20506;:8;;;:13;;;;:::i;:::-;20496:7;;:23;;;;:::i;20475:50::-;20460:9;20470:1;20460:12;;;;;;;:::i;:::-;;:65;-1:-1:-1;;;20555:9:0;15713;20555;;:::i;:::-;;-1:-1:-1;20061:3:0;;;;:::i;:::-;;;;20036:540;;;-1:-1:-1;;20586:11:0;:15;-1:-1:-1;19804:805:0:o;20714:2323::-;20902:44;;-1:-1:-1;;;20902:44:0;;;;;160:25:1;;;20798:4:0;;;;;;;;-1:-1:-1;;;;;20902:34:0;;;;;133:18:1;;20902:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;20957:16;20976:10;;20880:66;;-1:-1:-1;21003:19:0;;;20999:33;;21031:1;21024:8;;;;;;;;20999:33;21045:16;21064:24;;;:14;:24;;;;;;;21103:16;;;21099:200;;21149:69;21176:2;21180:8;21190:11;21203:14;21149:26;:69::i;:::-;21136:82;;21099:200;;;21264:23;;;;:13;:23;;;;;;;-1:-1:-1;21099:200:0;21315:10;21329:1;21315:15;21311:35;;21345:1;21332:14;;21311:35;21399:58;;-1:-1:-1;;;21399:58:0;;;;;3521:25:1;;;3562:18;;;3555:34;;;21359:37:0;;-1:-1:-1;;;;;21399:36:0;;;;;3494:18:1;;21399:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21359:98;;21474:11;21489:1;21474:16;21470:76;;15713:9;;21530:1;15713:9;21507:10;:13;;;:20;;;;:::i;:::-;:24;;;;:::i;:::-;21506:33;;;;:::i;:::-;:40;;;;:::i;:::-;21492:54;;21470:76;21576:15;;21561:11;:30;21557:44;;21600:1;21593:8;;;;;;;;;;21557:44;21630:11;21616;:25;21612:56;;;21657:11;21643:25;;21612:56;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21735:1022:0;21756:2;21752:1;:6;21735:1022;;;21799:16;21784:11;:31;21780:42;21817:5;21780:42;21858:10;:13;;;21843:11;:28;;:60;;;;;21889:14;21875:10;:28;;21843:60;21839:907;;;21924:15;21938:1;21924:15;;:::i;:::-;;;21975:10;21958:27;;22021:14;22008:10;:27;22004:237;;;22073:28;;;;;;;;22093:1;22073:28;;;;;;22095:1;22073:28;;;;;;22097:1;22073:28;;;;22099:1;22073:28;;;22060:41;;21839:907;;22004:237;22163:58;;-1:-1:-1;;;22163:58:0;;;;;3521:25:1;;;3562:18;;;3555:34;;;-1:-1:-1;;;;;22163:36:0;;;;;3494:18:1;;22163:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22150:71;;21839:907;;;22281:9;22321:14;:17;;;22307:11;:31;;;;:::i;:::-;22281:59;;22359:15;22377:74;22425:14;:20;;;22420:2;:25;;;;:::i;:::-;22398:19;;:47;;;;:::i;22377:74::-;22359:92;-1:-1:-1;22474:15:0;;:46;;;;;22506:14;22493:10;:27;22474:46;22470:57;;;22522:5;;;;22470:57;22550:15;;22546:147;;22651:9;22661:11;22651:22;;;;;;;:::i;:::-;;;22620:15;22636:11;22620:28;;;;;;;:::i;:::-;;;22607:41;;:10;:41;:::i;:::-;:66;;;;:::i;:::-;22590:83;;;;:::i;:::-;;;22546:147;22711:19;15713:9;22711:19;;:::i;:::-;;;22262:484;;21839:907;21760:3;;;;:::i;:::-;;;;21735:1022;;;-1:-1:-1;22782:40:0;22791:14;22807;22820:1;22807:10;:14;:::i;:::-;22782:8;:40::i;:::-;22833:23;;;;:13;:23;;;;;;;;:36;;;22880:14;:24;;;;;;:38;;;22936:60;;6501:25:1;;;6542:18;;;6535:34;;;6585:18;;;6578:34;;;6643:2;6628:18;;6621:34;;;22833:36:0;;-1:-1:-1;22936:60:0;;6488:3:1;6473:19;22936:60:0;;;;;;;-1:-1:-1;23016:13:0;;20714:2323;-1:-1:-1;;;;;;;;;20714:2323:0:o;18699:597::-;18822:4;;18875:14;18822:4;18900:367;18921:3;18917:1;:7;18900:367;;;18958:4;18950;:12;18946:23;18964:5;18946:23;18984:9;19016:1;18997:11;19004:4;18997;:11;:::i;:::-;:15;;19011:1;18997:15;:::i;:::-;18996:21;;;;:::i;:::-;19064:51;;-1:-1:-1;;;19064:51:0;;;;;3521:25:1;;;3562:18;;;3555:34;;;18984:33:0;;-1:-1:-1;19032:29:0;;-1:-1:-1;;;;;19064:36:0;;;;;3494:18:1;;19064:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19032:83;;19143:10;19134:2;:5;;;:19;19130:126;;19181:4;19174:11;;19130:126;;;19233:7;19239:1;19233:4;:7;:::i;:::-;19226:14;;19130:126;18931:336;;18926:3;;;;;:::i;:::-;;;;18900:367;;;-1:-1:-1;19284:4:0;;18699:597;-1:-1:-1;;;;;;18699:597:0:o;433:106::-;491:7;522:1;518;:5;:13;;530:1;518:13;;;-1:-1:-1;526:1:0;;511:20;-1:-1:-1;433:106:0:o;16698:1305::-;16775:5;;16768:38;;-1:-1:-1;;;16768:38:0;;16800:4;16768:38;;;2335:51:1;16747:18:0;;-1:-1:-1;;;;;16775:5:0;;16768:23;;2308:18:1;;16768:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;16747:59;;16817:18;16854;;16838:13;:34;;;;:::i;:::-;16883:18;:34;;;16939:15;;16817:55;;-1:-1:-1;16930:6:0;16983:19;16939:15;16983;:19;:::i;:::-;17031:15;17013;:33;16965:37;-1:-1:-1;17057:14:0;15713:9;17074:8;15713:9;17074:1;:8;:::i;:::-;:15;;;;:::i;:::-;17057:32;;17100:14;17136:6;17131:802;17152:2;17148:1;:6;17131:802;;;17188:16;15713:9;17188;:16;:::i;:::-;17176:28;;17241:9;17223:15;:27;17219:639;;;17275:15;;:39;;;;;17313:1;17294:15;:20;17275:39;17271:260;;;17369:13;17339:15;17355:9;17339:26;;;;;;;:::i;:::-;;;:43;;;;;;;:::i;:::-;;;;-1:-1:-1;17549:5:0;;-1:-1:-1;17549:5:0;17271:260;17501:10;17478:19;17496:1;17478:15;:19;:::i;:::-;17461:37;;:13;:37;:::i;:::-;:50;;;;:::i;:::-;17431:15;17447:9;17431:26;;;;;;;:::i;17219:639::-;17599:15;;:33;;;;;17631:1;17618:9;:14;17599:33;17595:248;;;17687:13;17657:15;17673:9;17657:26;;;;;;;:::i;:::-;;;:43;;;;;;;:::i;:::-;;;;-1:-1:-1;17595:248:0;;-1:-1:-1;17595:248:0;;17813:10;17796:13;17808:1;17796:9;:13;:::i;:::-;17779:31;;:13;:31;:::i;:::-;:44;;;;:::i;:::-;17749:15;17765:9;17749:26;;;;;;;:::i;:::-;;;:74;;;;;;;:::i;:::-;;;;-1:-1:-1;;17595:248:0;17876:9;17872:13;;17912:9;17900:21;;17156:3;;;;;:::i;:::-;;;;17131:802;;;-1:-1:-1;17948:47:0;;;17964:15;3521:25:1;;3577:2;3562:18;;3555:34;;;17948:47:0;;3494:18:1;17948:47:0;;;;;;;16736:1267;;;;;;16698:1305::o;23045:2092::-;23242:44;;-1:-1:-1;;;23242:44:0;;;;;160:25:1;;;23138:4:0;;;;;;;;-1:-1:-1;;;;;23242:34:0;;;;;133:18:1;;23242:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23297:16;23316:10;;23220:66;;-1:-1:-1;23343:19:0;;;23339:33;;23371:1;23364:8;;;;;;;;23339:33;23385:16;23404:24;;;:14;:24;;;;;;;23443:16;;;23439:200;;23489:69;23516:2;23520:8;23530:11;23543:14;23489:26;:69::i;:::-;23476:82;;23439:200;;;23604:23;;;;:13;:23;;;;;;;-1:-1:-1;23439:200:0;23655:10;23669:1;23655:15;23651:35;;23685:1;23672:14;;23651:35;23739:58;;-1:-1:-1;;;23739:58:0;;;;;3521:25:1;;;3562:18;;;3555:34;;;23699:37:0;;-1:-1:-1;;;;;23739:36:0;;;;;3494:18:1;;23739:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23699:98;;23814:11;23829:1;23814:16;23810:76;;15713:9;;23870:1;15713:9;23847:10;:13;;;:20;;;;:::i;:::-;:24;;;;:::i;:::-;23846:33;;;;:::i;:::-;:40;;;;:::i;:::-;23832:54;;23810:76;23916:15;;23901:11;:30;23897:44;;23940:1;23933:8;;;;;;;;;;23897:44;23970:11;23956;:25;23952:56;;;23997:11;23983:25;;23952:56;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24075:1022:0;24096:2;24092:1;:6;24075:1022;;;24139:16;24124:11;:31;24120:42;24157:5;24120:42;24198:10;:13;;;24183:11;:28;;:60;;;;;24229:14;24215:10;:28;;24183:60;24179:907;;;24264:15;24278:1;24264:15;;:::i;:::-;;;24315:10;24298:27;;24361:14;24348:10;:27;24344:237;;;24413:28;;;;;;;;24433:1;24413:28;;;;;;24435:1;24413:28;;;;;;24437:1;24413:28;;;;24439:1;24413:28;;;24400:41;;24179:907;;24344:237;24503:58;;-1:-1:-1;;;24503:58:0;;;;;3521:25:1;;;3562:18;;;3555:34;;;-1:-1:-1;;;;;24503:36:0;;;;;3494:18:1;;24503:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;24490:71;;24179:907;;;24621:9;24661:14;:17;;;24647:11;:31;;;;:::i;:::-;24621:59;;24699:15;24717:74;24765:14;:20;;;24760:2;:25;;;;:::i;24717:74::-;24699:92;-1:-1:-1;24814:15:0;;:46;;;;;24846:14;24833:10;:27;24814:46;24810:57;;;24862:5;;;;24810:57;24890:15;;24886:147;;24991:9;25001:11;24991:22;;;;;;;:::i;:::-;;;24960:15;24976:11;24960:28;;;;;;;:::i;:::-;;;24947:41;;:10;:41;:::i;:::-;:66;;;;:::i;:::-;24930:83;;;;:::i;:::-;;;24886:147;25051:19;15713:9;25051:19;;:::i;:::-;;;24602:484;;24179:907;24100:3;;;;:::i;:::-;;;;24075:1022;;;-1:-1:-1;25116:13:0;;23045:2092;-1:-1:-1;;;;;;;;;;23045:2092:0:o;18136:555::-;18219:4;18236:9;18248:1;18236:13;;18260:9;18286:2;-1:-1:-1;;;;;18272:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;18260:37;;18313:6;18308:354;18329:3;18325:1;:7;18308:354;;;18366:4;18358;:12;18354:23;18372:5;18354:23;18392:9;18424:1;18405:11;18412:4;18405;:11;:::i;:::-;:15;;18419:1;18405:15;:::i;:::-;18404:21;;;;:::i;:::-;18472:37;;-1:-1:-1;;;18472:37:0;;;;;160:25:1;;;18392:33:0;;-1:-1:-1;18440:29:0;;-1:-1:-1;;;;;18472:31:0;;;;;133:18:1;;18472:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;18440:69;;18537:10;18528:2;:5;;;:19;18524:127;;18575:4;18568:11;;18524:127;;;18627:8;18634:1;18627:4;:8;:::i;:::-;18620:15;;18524:127;18339:323;;18334:3;;;;;:::i;:::-;;;;18308:354;;;-1:-1:-1;18679:4:0;;18136:555;-1:-1:-1;;;;18136:555:0:o;615:106::-;673:7;704:1;700;:5;:13;;712:1;700:13;;196:180:1;255:6;308:2;296:9;287:7;283:23;279:32;276:52;;;324:1;321;314:12;276:52;-1:-1:-1;347:23:1;;196:180;-1:-1:-1;196:180:1:o;381:127::-;442:10;437:3;433:20;430:1;423:31;473:4;470:1;463:15;497:4;494:1;487:15;513:275;584:2;578:9;649:2;630:13;;-1:-1:-1;;626:27:1;614:40;;684:18;669:34;;705:22;;;666:62;663:88;;;731:18;;:::i;:::-;767:2;760:22;513:275;;-1:-1:-1;513:275:1:o;793:946::-;877:6;908:2;951;939:9;930:7;926:23;922:32;919:52;;;967:1;964;957:12;919:52;1007:9;994:23;1036:18;1077:2;1069:6;1066:14;1063:34;;;1093:1;1090;1083:12;1063:34;1131:6;1120:9;1116:22;1106:32;;1176:7;1169:4;1165:2;1161:13;1157:27;1147:55;;1198:1;1195;1188:12;1147:55;1234:2;1221:16;1256:2;1252;1249:10;1246:36;;;1262:18;;:::i;:::-;1308:2;1305:1;1301:10;1291:20;;1331:28;1355:2;1351;1347:11;1331:28;:::i;:::-;1393:15;;;1463:11;;;1459:20;;;1424:12;;;;1491:19;;;1488:39;;;1523:1;1520;1513:12;1488:39;1547:11;;;;1567:142;1583:6;1578:3;1575:15;1567:142;;;1649:17;;1637:30;;1600:12;;;;1687;;;;1567:142;;;1728:5;793:946;-1:-1:-1;;;;;;;;793:946:1:o;1936:248::-;2004:6;2012;2065:2;2053:9;2044:7;2040:23;2036:32;2033:52;;;2081:1;2078;2071:12;2033:52;-1:-1:-1;;2104:23:1;;;2174:2;2159:18;;;2146:32;;-1:-1:-1;1936:248:1:o;2397:286::-;2456:6;2509:2;2497:9;2488:7;2484:23;2480:32;2477:52;;;2525:1;2522;2515:12;2477:52;2551:23;;-1:-1:-1;;;;;2603:31:1;;2593:42;;2583:70;;2649:1;2646;2639:12;2688:127;2749:10;2744:3;2740:20;2737:1;2730:31;2780:4;2777:1;2770:15;2804:4;2801:1;2794:15;2820:217;2860:1;2886;2876:132;;2930:10;2925:3;2921:20;2918:1;2911:31;2965:4;2962:1;2955:15;2993:4;2990:1;2983:15;2876:132;-1:-1:-1;3022:9:1;;2820:217::o;3042:168::-;3082:7;3148:1;3144;3140:6;3136:14;3133:1;3130:21;3125:1;3118:9;3111:17;3107:45;3104:71;;;3155:18;;:::i;:::-;-1:-1:-1;3195:9:1;;3042:168::o;3215:127::-;3276:10;3271:3;3267:20;3264:1;3257:31;3307:4;3304:1;3297:15;3331:4;3328:1;3321:15;3600:128;3640:3;3671:1;3667:6;3664:1;3661:13;3658:39;;;3677:18;;:::i;:::-;-1:-1:-1;3713:9:1;;3600:128::o;3733:135::-;3772:3;3793:17;;;3790:43;;3813:18;;:::i;:::-;-1:-1:-1;3860:1:1;3849:13;;3733:135::o;3873:125::-;3913:4;3941:1;3938;3935:8;3932:34;;;3946:18;;:::i;:::-;-1:-1:-1;3983:9:1;;3873:125::o;4003:184::-;4073:6;4126:2;4114:9;4105:7;4101:23;4097:32;4094:52;;;4142:1;4139;4132:12;4094:52;-1:-1:-1;4165:16:1;;4003:184;-1:-1:-1;4003:184:1:o;4192:166::-;4270:13;;4323:2;4312:21;;;4302:32;;4292:60;;4348:1;4345;4338:12;4292:60;4192:166;;;:::o;4363:664::-;4455:6;4508:3;4496:9;4487:7;4483:23;4479:33;4476:53;;;4525:1;4522;4515:12;4476:53;4558:2;4552:9;4600:3;4592:6;4588:16;4670:6;4658:10;4655:22;4634:18;4622:10;4619:34;4616:62;4613:88;;;4681:18;;:::i;:::-;4717:2;4710:22;4756:39;4785:9;4756:39;:::i;:::-;4748:6;4741:55;4829:48;4873:2;4862:9;4858:18;4829:48;:::i;:::-;4824:2;4816:6;4812:15;4805:73;4932:2;4921:9;4917:18;4911:25;4906:2;4898:6;4894:15;4887:50;4991:2;4980:9;4976:18;4970:25;4965:2;4957:6;4953:15;4946:50;5015:6;5005:16;;;4363:664;;;;:::o;5032:698::-;5071:7;5119:1;5115:2;5104:17;5156:1;5152:2;5141:17;-1:-1:-1;;;;;5239:1:1;5234:3;5230:11;5269:1;5264:3;5260:11;5316:3;5312:2;5308:12;5303:3;5300:21;5295:2;5291;5287:11;5283:39;5280:65;;;5325:18;;:::i;:::-;-1:-1:-1;;5431:1:1;5422:11;;5449;;;5471:13;;;5462:23;;5445:41;5442:67;;;5489:18;;:::i;:::-;5537:1;5532:3;5528:11;5518:21;;5586:3;5582:2;5577:13;5572:3;5568:23;5563:2;5559;5555:11;5551:41;5548:67;;;5595:18;;:::i;:::-;5662:3;5658:2;5653:13;5648:3;5644:23;5639:2;5635;5631:11;5627:41;5624:67;;;5671:18;;:::i;:::-;-1:-1:-1;;;5711:13:1;;;;;5032:698;-1:-1:-1;;;;;5032:698:1:o;5735:398::-;5774:4;5819:1;5815:2;5804:17;5856:1;5852:2;5841:17;5886:1;5881:3;5877:11;5970:3;-1:-1:-1;;;;;5929:39:1;5925:49;5920:3;5916:59;5911:2;5904:10;5900:76;5897:102;;;5979:18;;:::i;:::-;6068:3;-1:-1:-1;;;;;6028:44:1;6023:3;6019:54;6015:2;6011:63;6008:89;;;6077:18;;:::i;:::-;-1:-1:-1;6114:13:1;;;5735:398;-1:-1:-1;;;5735:398:1:o;6138:127::-;6199:10;6194:3;6190:20;6187:1;6180:31;6230:4;6227:1;6220:15;6254:4;6251:1;6244:15

Swarm Source

ipfs://df39fa4149f6a026a6d05b7f018116456ad78482d46afe7b6da486093c631dbd

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.