ETH Price: $1,580.35 (-0.72%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Execute186188122023-11-21 8:00:11513 days ago1700553611IN
0x3FCcf08b...43E0581Ca
0 ETH0.0007483726.9101515
Execute185688472023-11-14 8:07:35520 days ago1699949255IN
0x3FCcf08b...43E0581Ca
0 ETH0.016242829.3636179
Execute185187442023-11-07 8:00:11527 days ago1699344011IN
0x3FCcf08b...43E0581Ca
0 ETH0.0235875720.54467734
Execute184687812023-10-31 8:00:11534 days ago1698739211IN
0x3FCcf08b...43E0581Ca
0 ETH0.0142173513.39519638
Execute184187882023-10-24 8:00:11541 days ago1698134411IN
0x3FCcf08b...43E0581Ca
0 ETH0.0154506213.40059818
Execute183687732023-10-17 8:02:59548 days ago1697529779IN
0x3FCcf08b...43E0581Ca
0 ETH0.007152536.74094436
Execute183187232023-10-10 8:00:11555 days ago1696924811IN
0x3FCcf08b...43E0581Ca
0 ETH0.00609325.74228098
Execute182689612023-10-03 8:56:59562 days ago1696323419IN
0x3FCcf08b...43E0581Ca
0 ETH0.00624435.88527744
Execute182240842023-09-27 2:21:11568 days ago1695781271IN
0x3FCcf08b...43E0581Ca
0 ETH0.010981639.52500902
Execute182186222023-09-26 8:00:11569 days ago1695715211IN
0x3FCcf08b...43E0581Ca
0 ETH0.004891046.96567686
Execute181686422023-09-19 8:02:59576 days ago1695110579IN
0x3FCcf08b...43E0581Ca
0 ETH0.0110265110.43675164
Execute181189212023-09-12 8:00:11583 days ago1694505611IN
0x3FCcf08b...43E0581Ca
0 ETH0.0106559510.04076497
Execute180689462023-09-05 8:00:11590 days ago1693900811IN
0x3FCcf08b...43E0581Ca
0 ETH0.0110073910.3734428
Execute180189622023-08-29 8:02:35597 days ago1693296155IN
0x3FCcf08b...43E0581Ca
0 ETH0.0197023818.56576959
Execute179689212023-08-22 8:00:11604 days ago1692691211IN
0x3FCcf08b...43E0581Ca
0 ETH0.0208148118.05597158
Execute179189112023-08-15 8:00:11611 days ago1692086411IN
0x3FCcf08b...43E0581Ca
0 ETH0.0164220815.47470564
Execute178688702023-08-08 8:00:11618 days ago1691481611IN
0x3FCcf08b...43E0581Ca
0 ETH0.0216613918.78858259
Execute178188302023-08-01 8:02:59625 days ago1690876979IN
0x3FCcf08b...43E0581Ca
0 ETH0.0225534321.25294963
Execute177687842023-07-25 8:00:11632 days ago1690272011IN
0x3FCcf08b...43E0581Ca
0 ETH0.0281307424.40223232
Execute177210352023-07-18 15:34:59639 days ago1689694499IN
0x3FCcf08b...43E0581Ca
0 ETH0.0466277443.94005998
Execute176691692023-07-11 8:24:35646 days ago1689063875IN
0x3FCcf08b...43E0581Ca
0 ETH0.0172388514.95257657
Execute176192602023-07-04 8:05:47653 days ago1688457947IN
0x3FCcf08b...43E0581Ca
0 ETH0.0194190618.29879785
Execute175694132023-06-27 8:05:35660 days ago1687853135IN
0x3FCcf08b...43E0581Ca
0 ETH0.0122319511.52604702
Execute175196072023-06-20 8:04:35667 days ago1687248275IN
0x3FCcf08b...43E0581Ca
0 ETH0.0135100712.73198652
Execute174697462023-06-13 8:00:11674 days ago1686643211IN
0x3FCcf08b...43E0581Ca
0 ETH0.0156730714.77233431
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

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

Contract Name:
BuybackPool

Compiler Version
v0.8.2+commit.661d1103

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 11 : BuybackPool.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import "../interfaces/IERC20.sol";
import "./interfaces/IBanana.sol";
import "./interfaces/IBananaDistributor.sol";
import "./interfaces/ITWAMM.sol";
import "./interfaces/ITWAMMPair.sol";
import "../utils/Ownable.sol";
import "../utils/AnalyticMath.sol";
import "../libraries/FullMath.sol";
import "../libraries/TransferHelper.sol";

contract BuybackPool is Ownable, AnalyticMath {
    using FullMath for uint256;

    event BuybackExecuted(uint256 orderId, uint256 amountIn, uint256 buyingRate, uint256 burned);
    event WithdrawAndBurn(uint256 orderId, uint256 burnAmount);

    address public immutable banana;
    address public immutable usdc;
    address public immutable twamm;
    address public immutable bananaDistributor;
    address public keeper;

    uint256 public lastBuyingRate;
    uint256 public priceT1;
    uint256 public priceT2;
    uint256 public rewardT1;
    uint256 public rewardT2;
    uint256 public priceIndex = 100;
    uint256 public rewardIndex = 50;
    uint256 public secondsPerBlock = 12;
    uint256 public secondsOfEpoch;
    uint256 public lastOrderId = type(uint256).max;
    uint256 public lastExecuteTime;
    uint256 public endTime;

    bool public initialized;
    bool public isStop;

    constructor(
        address banana_,
        address usdc_,
        address twamm_,
        address bananaDistributor_,
        address keeper_,
        uint256 secondsOfEpoch_,
        uint256 initPrice,
        uint256 initReward,
        uint256 startTime,
        uint256 endTime_
    ) {
        owner = msg.sender;
        banana = banana_;
        usdc = usdc_;
        twamm = twamm_;
        bananaDistributor = bananaDistributor_;
        keeper = keeper_;
        secondsOfEpoch = secondsOfEpoch_;
        priceT2 = initPrice;
        rewardT2 = initReward;
        lastExecuteTime = startTime;
        endTime = endTime_;
    }

    // function initBuyingRate(uint256 amountIn) external onlyOwner {
    //     require(!initialized, "already initialized");
    //     initialized = true;
    //     lastBuyingRate = amountIn / secondsOfEpoch;
    // }

    function updatePriceIndex(uint256 newPriceIndex) external onlyOwner {
        priceIndex = newPriceIndex;
    }

    function updateRewardIndex(uint256 newRewardIndex) external onlyOwner {
        rewardIndex = newRewardIndex;
    }

    function updateSecondsPerBlock(uint256 newSecondsPerBlock) external onlyOwner {
        secondsPerBlock = newSecondsPerBlock;
    }

    function updateSecondsOfEpoch(uint256 newSecondsOfEpoch) external onlyOwner {
        secondsOfEpoch = newSecondsOfEpoch;
    }

    function updateLastExecuteTime(uint256 newExecuteTime) external onlyOwner {
        lastExecuteTime = newExecuteTime;
    }

    function updateEndTime(uint256 endTime_) external onlyOwner {
        endTime = endTime_;
    }

    function updateStatus(bool isStop_) external onlyOwner {
        isStop = isStop_;
    }

    function updateKeeper(address keeper_) external onlyOwner {
        keeper = keeper_;
    }

    function resetPrice(uint256 newPriceT1, uint256 newPriceT2) external onlyOwner {
        priceT1 = newPriceT1;
        priceT2 = newPriceT2;
    }

    function resetReward(uint256 newRewardT1, uint256 newRewardT2) external onlyOwner {
        rewardT1 = newRewardT1;
        rewardT2 = newRewardT2;
    }

    function withdrawUsdc(address to) external onlyOwner {
        require(isStop, "not stop");
        uint256 usdcBalance = IERC20(usdc).balanceOf(address(this));
        TransferHelper.safeTransfer(usdc, to, usdcBalance);
    }

    function withdrawAndBurn(uint256 orderId) external onlyOwner {
        require(isStop, "not stop");
        address pair = ITWAMM(twamm).obtainPairAddress(usdc, banana);
        ITWAMMPair.Order memory order = ITWAMMPair(pair).getOrderDetails(orderId);
        require(block.number > order.expirationBlock, "not reach withdrawable block");
        ITWAMM(twamm).withdrawProceedsFromTermSwapTokenToToken(usdc, banana, orderId, block.timestamp);
        uint256 bananaBalance = IERC20(banana).balanceOf(address(this));
        require(bananaBalance > 0, "nothing to burn");
        IBanana(banana).burn(bananaBalance);
        emit WithdrawAndBurn(orderId, bananaBalance);
    }

    function execute() external {
        require(!isStop, "is stop");
        require(msg.sender == keeper, "only keeper");
        require(block.timestamp < endTime, "end");
        lastExecuteTime = lastExecuteTime + secondsOfEpoch;
        require(block.timestamp >= lastExecuteTime, "not reach execute time");
        require(lastExecuteTime + secondsOfEpoch > block.timestamp, "over next epoch time");

        uint256 burnAmount;
        if (lastOrderId != type(uint256).max) {
            address pair = ITWAMM(twamm).obtainPairAddress(usdc, banana);
            ITWAMMPair.Order memory order = ITWAMMPair(pair).getOrderDetails(lastOrderId);
            require(block.number > order.expirationBlock, "not reach withdrawable block");

            ITWAMM(twamm).withdrawProceedsFromTermSwapTokenToToken(usdc, banana, lastOrderId, block.timestamp);
            burnAmount = IERC20(banana).balanceOf(address(this));
            IBanana(banana).burn(burnAmount);
        }

        uint256 lastReward = IBananaDistributor(bananaDistributor).lastReward();
        if (rewardT1 > 0) {
            rewardT2 = rewardT1;
        }
        rewardT1 = lastReward;

        (uint256 reserve0, uint256 reserve1) = ITWAMM(twamm).obtainReserves(usdc, banana);
        uint256 currentPrice = reserve0.mulDiv(1e30, reserve1); // reserve0/reserve1 * 10**(18+decimalsUSDC-decimalsBANA)
        if (priceT1 > 0) {
            priceT2 = priceT1;
        }
        priceT1 = currentPrice;

        uint256 deltaTime = lastExecuteTime + secondsOfEpoch - block.timestamp;
        uint256 usdcBalance = IERC20(usdc).balanceOf(address(this));
        uint256 amountIn;
        if (!initialized) {
            amountIn = usdcBalance;
            lastBuyingRate = amountIn / deltaTime;
            initialized = true;
        } else {
            (uint256 pn, uint256 pd) = pow(priceT2, priceT1, priceIndex, 100);
            (uint256 rn, uint256 rd) = pow(rewardT1, rewardT2, rewardIndex, 100);
            lastBuyingRate = lastBuyingRate.mulDiv(pn, pd).mulDiv(rn, rd);
            amountIn = deltaTime * lastBuyingRate;
            if (amountIn > usdcBalance) {
                amountIn = usdcBalance;
                lastBuyingRate = amountIn / deltaTime;
            }
        }

        require(amountIn > 0, "buying amount is 0");
        IERC20(usdc).approve(twamm, amountIn);
        lastOrderId = ITWAMM(twamm).longTermSwapTokenToToken(
            usdc,
            banana,
            amountIn,
            deltaTime / (secondsPerBlock * 5),
            block.timestamp
        );

        emit BuybackExecuted(lastOrderId, amountIn, lastBuyingRate, burnAmount);
    }
}

File 2 of 11 : IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IERC20 {
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Transfer(address indexed from, address indexed to, uint256 value);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function totalSupply() external view returns (uint256);

    function balanceOf(address owner) external view returns (uint256);

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external pure returns (uint8);
}

File 3 of 11 : IBanana.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import "../../interfaces/IERC20.sol";

interface IBanana is IERC20 {
    event RedeemTimeChanged(uint256 oldRedeemTime, uint256 newRedeemTime);
    event Redeem(address indexed user, uint256 burntAmount, uint256 apeXAmount);

    function apeXToken() external view returns (address);
    function redeemTime() external view returns (uint256);

    function mint(address to, uint256 apeXAmount) external returns (uint256);
    function burn(uint256 amount) external returns (bool);
    function burnFrom(address from, uint256 amount) external returns (bool);
    function redeem(uint256 amount) external returns (uint256);
}

File 4 of 11 : IBananaDistributor.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

interface IBananaDistributor {
    function lastReward() external view returns (uint256);
}

File 5 of 11 : ITWAMM.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.0;

interface ITWAMM {
    function factory() external view returns (address);

    function WETH() external view returns (address);

    function obtainReserves(address token0, address token1) external view returns (uint256 reserve0, uint256 reserve1);

    function obtainTotalSupply(address token0, address token1) external view returns (uint256);

    function obtainPairAddress(address token0, address token1) external view returns (address);

    function createPairWrapper(
        address token0,
        address token1,
        uint256 deadline
    ) external returns (address pair);

    function addInitialLiquidity(
        address token0,
        address token1,
        uint256 amount0,
        uint256 amount1,
        uint256 deadline
    ) external returns (uint256 lpTokenAmount);

    function addInitialLiquidityETH(
        address token,
        uint256 amountToken,
        uint256 amountETH,
        uint256 deadline
    ) external payable returns (uint256 lpTokenAmount);

    function addLiquidity(
        address token0,
        address token1,
        uint256 lpTokenAmount,
        uint256 amountIn0Max,
        uint256 amountIn1Max,
        uint256 deadline
    ) external returns (uint256 amountIn0, uint256 amountIn1);

    function addLiquidityETH(
        address token,
        uint256 lpTokenAmount,
        uint256 amountTokenInMax,
        uint256 amountETHInMax,
        uint256 deadline
    ) external payable returns (uint256 amountTokenIn, uint256 amountETHIn);

    function withdrawLiquidity(
        address token0,
        address token1,
        uint256 lpTokenAmount,
        uint256 amountOut0Min,
        uint256 amountOut1Min,
        uint256 deadline
    ) external returns (uint256 amountOut0, uint256 amountOut1);

    function withdrawLiquidityETH(
        address token,
        uint256 lpTokenAmount,
        uint256 amountTokenOutMin,
        uint256 amountETHOutMin,
        uint256 deadline
    ) external returns (uint256 amountTokenOut, uint256 amountETHOut);

    function instantSwapTokenToToken(
        address token0,
        address token1,
        uint256 amountIn,
        uint256 amountOutMin,
        uint256 deadline
    ) external returns (uint256 amountOut);

    function instantSwapTokenToETH(
        address token,
        uint256 amountTokenIn,
        uint256 amountETHOutMin,
        uint256 deadline
    ) external returns (uint256 amountETHOut);

    function instantSwapETHToToken(
        address token,
        uint256 amountETHIn,
        uint256 amountTokenOutMin,
        uint256 deadline
    ) external payable returns (uint256 amountTokenOut);

    function longTermSwapTokenToToken(
        address token0,
        address token1,
        uint256 amountIn,
        uint256 numberOfBlockIntervals,
        uint256 deadline
    ) external returns (uint256 orderId);

    function longTermSwapTokenToETH(
        address token,
        uint256 amountTokenIn,
        uint256 numberOfBlockIntervals,
        uint256 deadline
    ) external returns (uint256 orderId);

    function longTermSwapETHToToken(
        address token,
        uint256 amountETHIn,
        uint256 numberOfBlockIntervals,
        uint256 deadline
    ) external payable returns (uint256 orderId);

    function cancelTermSwapTokenToToken(
        address token0,
        address token1,
        uint256 orderId,
        uint256 deadline
    ) external returns (uint256 unsoldAmount, uint256 purchasedAmount);

    function cancelTermSwapTokenToETH(
        address token,
        uint256 orderId,
        uint256 deadline
    ) external returns (uint256 unsoldTokenAmount, uint256 purchasedETHAmount);

    function cancelTermSwapETHToToken(
        address token,
        uint256 orderId,
        uint256 deadline
    ) external returns (uint256 unsoldETHAmount, uint256 purchasedTokenAmount);

    function withdrawProceedsFromTermSwapTokenToToken(
        address token0,
        address token1,
        uint256 orderId,
        uint256 deadline
    ) external returns (uint256 proceeds);

    function withdrawProceedsFromTermSwapTokenToETH(
        address token,
        uint256 orderId,
        uint256 deadline
    ) external returns (uint256 proceedsETH);

    function withdrawProceedsFromTermSwapETHToToken(
        address token,
        uint256 orderId,
        uint256 deadline
    ) external returns (uint256 proceedsToken);

    function executeVirtualOrdersWrapper(address pair, uint256 blockNumber) external;
}

File 6 of 11 : ITWAMMPair.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

interface ITWAMMPair {
    struct Order {
        uint256 id;
        uint256 expirationBlock;
        uint256 saleRate;
        address owner;
        address sellTokenId;
        address buyTokenId;
    }

    function getOrderDetails(uint256 orderId)
        external
        view
        returns (Order memory);
}

File 7 of 11 : Ownable.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

abstract contract Ownable {
    address public owner;
    address public pendingOwner;

    event NewOwner(address indexed oldOwner, address indexed newOwner);
    event NewPendingOwner(address indexed oldPendingOwner, address indexed newPendingOwner);

    modifier onlyOwner() {
        require(msg.sender == owner, "Ownable: REQUIRE_OWNER");
        _;
    }

    function setPendingOwner(address newPendingOwner) external onlyOwner {
        require(pendingOwner != newPendingOwner, "Ownable: ALREADY_SET");
        emit NewPendingOwner(pendingOwner, newPendingOwner);
        pendingOwner = newPendingOwner;
    }

    function acceptOwner() external {
        require(msg.sender == pendingOwner, "Ownable: REQUIRE_PENDING_OWNER");
        address oldOwner = owner;
        address oldPendingOwner = pendingOwner;
        owner = pendingOwner;
        pendingOwner = address(0);
        emit NewOwner(oldOwner, owner);
        emit NewPendingOwner(oldPendingOwner, pendingOwner);
    }
}

File 8 of 11 : AnalyticMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import "../libraries/IntegralMath.sol";

contract AnalyticMath {
    uint8 internal constant MIN_PRECISION = 32;
    uint8 internal constant MAX_PRECISION = 127;

    uint256 internal constant FIXED_1 = 1 << MAX_PRECISION;
    uint256 internal constant FIXED_2 = 2 << MAX_PRECISION;

    // Auto-generated via 'PrintLn2ScalingFactors.py'
    uint256 internal constant LN2_NUMERATOR   = 0x3f80fe03f80fe03f80fe03f80fe03f8;
    uint256 internal constant LN2_DENOMINATOR = 0x5b9de1d10bf4103d647b0955897ba80;

    // Auto-generated via 'PrintOptimalThresholds.py'
    uint256 internal constant OPT_LOG_MAX_VAL = 0x15bf0a8b1457695355fb8ac404e7a79e4;
    uint256 internal constant OPT_EXP_MAX_VAL = 0x800000000000000000000000000000000;

    uint256[MAX_PRECISION + 1] private maxExpArray;

    /**
      * @dev Should be executed either during construction or after construction (if too large for the constructor)
    */
    constructor() {
        initMaxExpArray();
    }

    /**
      * @dev Compute (a / b) ^ (c / d)
    */
    function pow(uint256 a, uint256 b, uint256 c, uint256 d) internal view returns (uint256, uint256) { unchecked {
        if (a >= b)
            return mulDivExp(mulDivLog(FIXED_1, a, b), c, d);
        (uint256 q, uint256 p) = mulDivExp(mulDivLog(FIXED_1, b, a), c, d);
        return (p, q);
    }}

    /**
      * @dev Compute log(a / b)
    */
    function log(uint256 a, uint256 b) internal pure returns (uint256, uint256) { unchecked {
        require(a >= b, "log: a < b");
        return (mulDivLog(FIXED_1, a, b), FIXED_1);
    }}

    /**
      * @dev Compute e ^ (a / b)
    */
    function exp(uint256 a, uint256 b) internal view returns (uint256, uint256) { unchecked {
        return mulDivExp(FIXED_1, a, b);
    }}

    /**
      * @dev Compute log(x / FIXED_1) * FIXED_1
    */
    function fixedLog(uint256 x) internal pure returns (uint256) { unchecked {
        if (x < OPT_LOG_MAX_VAL) {
            return optimalLog(x);
        }
        else {
            return generalLog(x);
        }
    }}

    /**
      * @dev Compute e ^ (x / FIXED_1) * FIXED_1
    */
    function fixedExp(uint256 x) internal view returns (uint256, uint256) { unchecked {
        if (x < OPT_EXP_MAX_VAL) {
            return (optimalExp(x), 1 << MAX_PRECISION);
        }
        else {
            uint8 precision = findPosition(x);
            return (generalExp(x >> (MAX_PRECISION - precision), precision), 1 << precision);
        }
    }}

    /**
      * @dev Compute log(x / FIXED_1) * FIXED_1
      * This functions assumes that x >= FIXED_1, because the output would be negative otherwise
    */
    function generalLog(uint256 x) internal pure returns (uint256) { unchecked {
        uint256 res = 0;

        // if x >= 2, then we compute the integer part of log2(x), which is larger than 0
        if (x >= FIXED_2) {
            uint8 count = IntegralMath.floorLog2(x / FIXED_1);
            x >>= count; // now x < 2
            res = count * FIXED_1;
        }

        // if x > 1, then we compute the fraction part of log2(x), which is larger than 0
        if (x > FIXED_1) {
            for (uint8 i = MAX_PRECISION; i > 0; --i) {
                x = (x * x) / FIXED_1; // now 1 < x < 4
                if (x >= FIXED_2) {
                    x >>= 1; // now 1 < x < 2
                    res += 1 << (i - 1);
                }
            }
        }

        return res * LN2_NUMERATOR / LN2_DENOMINATOR;
    }}

    /**
      * @dev Approximate e ^ x as (x ^ 0) / 0! + (x ^ 1) / 1! + ... + (x ^ n) / n!
      * Auto-generated via 'PrintFunctionGeneralExp.py'
      * Detailed description:
      * - This function returns "e ^ (x / 2 ^ precision) * 2 ^ precision", that is, the result is upshifted for accuracy
      * - The global "maxExpArray" maps each "precision" to "((maximumExponent + 1) << (MAX_PRECISION - precision)) - 1"
      * - The maximum permitted value for "x" is therefore given by "maxExpArray[precision] >> (MAX_PRECISION - precision)"
    */
    function generalExp(uint256 x, uint8 precision) internal pure returns (uint256) { unchecked {
        uint256 xi = x;
        uint256 res = 0;

        xi = (xi * x) >> precision; res += xi * 0x3442c4e6074a82f1797f72ac0000000; // add x^02 * (33! / 02!)
        xi = (xi * x) >> precision; res += xi * 0x116b96f757c380fb287fd0e40000000; // add x^03 * (33! / 03!)
        xi = (xi * x) >> precision; res += xi * 0x045ae5bdd5f0e03eca1ff4390000000; // add x^04 * (33! / 04!)
        xi = (xi * x) >> precision; res += xi * 0x00defabf91302cd95b9ffda50000000; // add x^05 * (33! / 05!)
        xi = (xi * x) >> precision; res += xi * 0x002529ca9832b22439efff9b8000000; // add x^06 * (33! / 06!)
        xi = (xi * x) >> precision; res += xi * 0x00054f1cf12bd04e516b6da88000000; // add x^07 * (33! / 07!)
        xi = (xi * x) >> precision; res += xi * 0x0000a9e39e257a09ca2d6db51000000; // add x^08 * (33! / 08!)
        xi = (xi * x) >> precision; res += xi * 0x000012e066e7b839fa050c309000000; // add x^09 * (33! / 09!)
        xi = (xi * x) >> precision; res += xi * 0x000001e33d7d926c329a1ad1a800000; // add x^10 * (33! / 10!)
        xi = (xi * x) >> precision; res += xi * 0x0000002bee513bdb4a6b19b5f800000; // add x^11 * (33! / 11!)
        xi = (xi * x) >> precision; res += xi * 0x00000003a9316fa79b88eccf2a00000; // add x^12 * (33! / 12!)
        xi = (xi * x) >> precision; res += xi * 0x0000000048177ebe1fa812375200000; // add x^13 * (33! / 13!)
        xi = (xi * x) >> precision; res += xi * 0x0000000005263fe90242dcbacf00000; // add x^14 * (33! / 14!)
        xi = (xi * x) >> precision; res += xi * 0x000000000057e22099c030d94100000; // add x^15 * (33! / 15!)
        xi = (xi * x) >> precision; res += xi * 0x0000000000057e22099c030d9410000; // add x^16 * (33! / 16!)
        xi = (xi * x) >> precision; res += xi * 0x00000000000052b6b54569976310000; // add x^17 * (33! / 17!)
        xi = (xi * x) >> precision; res += xi * 0x00000000000004985f67696bf748000; // add x^18 * (33! / 18!)
        xi = (xi * x) >> precision; res += xi * 0x000000000000003dea12ea99e498000; // add x^19 * (33! / 19!)
        xi = (xi * x) >> precision; res += xi * 0x00000000000000031880f2214b6e000; // add x^20 * (33! / 20!)
        xi = (xi * x) >> precision; res += xi * 0x000000000000000025bcff56eb36000; // add x^21 * (33! / 21!)
        xi = (xi * x) >> precision; res += xi * 0x000000000000000001b722e10ab1000; // add x^22 * (33! / 22!)
        xi = (xi * x) >> precision; res += xi * 0x0000000000000000001317c70077000; // add x^23 * (33! / 23!)
        xi = (xi * x) >> precision; res += xi * 0x00000000000000000000cba84aafa00; // add x^24 * (33! / 24!)
        xi = (xi * x) >> precision; res += xi * 0x00000000000000000000082573a0a00; // add x^25 * (33! / 25!)
        xi = (xi * x) >> precision; res += xi * 0x00000000000000000000005035ad900; // add x^26 * (33! / 26!)
        xi = (xi * x) >> precision; res += xi * 0x000000000000000000000002f881b00; // add x^27 * (33! / 27!)
        xi = (xi * x) >> precision; res += xi * 0x0000000000000000000000001b29340; // add x^28 * (33! / 28!)
        xi = (xi * x) >> precision; res += xi * 0x00000000000000000000000000efc40; // add x^29 * (33! / 29!)
        xi = (xi * x) >> precision; res += xi * 0x0000000000000000000000000007fe0; // add x^30 * (33! / 30!)
        xi = (xi * x) >> precision; res += xi * 0x0000000000000000000000000000420; // add x^31 * (33! / 31!)
        xi = (xi * x) >> precision; res += xi * 0x0000000000000000000000000000021; // add x^32 * (33! / 32!)
        xi = (xi * x) >> precision; res += xi * 0x0000000000000000000000000000001; // add x^33 * (33! / 33!)

        return res / 0x688589cc0e9505e2f2fee5580000000 + x + (1 << precision); // divide by 33! and then add x^1 / 1! + x^0 / 0!
    }}

    /**
      * @dev Compute log(x / FIXED_1) * FIXED_1
      * Input range: FIXED_1 <= x <= OPT_LOG_MAX_VAL - 1
      * Auto-generated via 'PrintFunctionOptimalLog.py'
      * Detailed description:
      * - Rewrite the input as a product of natural exponents and a single residual r, such that 1 < r < 2
      * - The natural logarithm of each (pre-calculated) exponent is the degree of the exponent
      * - The natural logarithm of r is calculated via Taylor series for log(1 + x), where x = r - 1
      * - The natural logarithm of the input is calculated by summing up the intermediate results above
      * - For example: log(250) = log(e^4 * e^1 * e^0.5 * 1.021692859) = 4 + 1 + 0.5 + log(1 + 0.021692859)
    */
    function optimalLog(uint256 x) internal pure returns (uint256) { unchecked {
        uint256 res = 0;

        uint256 y;
        uint256 z;
        uint256 w;

        if (x >= 0xd3094c70f034de4b96ff7d5b6f99fcd9) {res += 0x40000000000000000000000000000000; x = x * FIXED_1 / 0xd3094c70f034de4b96ff7d5b6f99fcd9;} // add 1 / 2^1
        if (x >= 0xa45af1e1f40c333b3de1db4dd55f29a8) {res += 0x20000000000000000000000000000000; x = x * FIXED_1 / 0xa45af1e1f40c333b3de1db4dd55f29a8;} // add 1 / 2^2
        if (x >= 0x910b022db7ae67ce76b441c27035c6a2) {res += 0x10000000000000000000000000000000; x = x * FIXED_1 / 0x910b022db7ae67ce76b441c27035c6a2;} // add 1 / 2^3
        if (x >= 0x88415abbe9a76bead8d00cf112e4d4a9) {res += 0x08000000000000000000000000000000; x = x * FIXED_1 / 0x88415abbe9a76bead8d00cf112e4d4a9;} // add 1 / 2^4
        if (x >= 0x84102b00893f64c705e841d5d4064bd4) {res += 0x04000000000000000000000000000000; x = x * FIXED_1 / 0x84102b00893f64c705e841d5d4064bd4;} // add 1 / 2^5
        if (x >= 0x8204055aaef1c8bd5c3259f4822735a3) {res += 0x02000000000000000000000000000000; x = x * FIXED_1 / 0x8204055aaef1c8bd5c3259f4822735a3;} // add 1 / 2^6
        if (x >= 0x810100ab00222d861931c15e39b44e9a) {res += 0x01000000000000000000000000000000; x = x * FIXED_1 / 0x810100ab00222d861931c15e39b44e9a;} // add 1 / 2^7
        if (x >= 0x808040155aabbbe9451521693554f734) {res += 0x00800000000000000000000000000000; x = x * FIXED_1 / 0x808040155aabbbe9451521693554f734;} // add 1 / 2^8

        z = y = x - FIXED_1;
        w = y * y / FIXED_1;
        res += z * (0x100000000000000000000000000000000 - y) / 0x100000000000000000000000000000000; z = z * w / FIXED_1; // add y^01 / 01 - y^02 / 02
        res += z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y) / 0x200000000000000000000000000000000; z = z * w / FIXED_1; // add y^03 / 03 - y^04 / 04
        res += z * (0x099999999999999999999999999999999 - y) / 0x300000000000000000000000000000000; z = z * w / FIXED_1; // add y^05 / 05 - y^06 / 06
        res += z * (0x092492492492492492492492492492492 - y) / 0x400000000000000000000000000000000; z = z * w / FIXED_1; // add y^07 / 07 - y^08 / 08
        res += z * (0x08e38e38e38e38e38e38e38e38e38e38e - y) / 0x500000000000000000000000000000000; z = z * w / FIXED_1; // add y^09 / 09 - y^10 / 10
        res += z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y) / 0x600000000000000000000000000000000; z = z * w / FIXED_1; // add y^11 / 11 - y^12 / 12
        res += z * (0x089d89d89d89d89d89d89d89d89d89d89 - y) / 0x700000000000000000000000000000000; z = z * w / FIXED_1; // add y^13 / 13 - y^14 / 14
        res += z * (0x088888888888888888888888888888888 - y) / 0x800000000000000000000000000000000;                      // add y^15 / 15 - y^16 / 16

        return res;
    }}

    /**
      * @dev Compute e ^ (x / FIXED_1) * FIXED_1
      * Input range: 0 <= x <= OPT_EXP_MAX_VAL - 1
      * Auto-generated via 'PrintFunctionOptimalExp.py'
      * Detailed description:
      * - Rewrite the input as a sum of binary exponents and a single residual r, as small as possible
      * - The exponentiation of each binary exponent is given (pre-calculated)
      * - The exponentiation of r is calculated via Taylor series for e^x, where x = r
      * - The exponentiation of the input is calculated by multiplying the intermediate results above
      * - For example: e^5.521692859 = e^(4 + 1 + 0.5 + 0.021692859) = e^4 * e^1 * e^0.5 * e^0.021692859
    */
    function optimalExp(uint256 x) internal pure returns (uint256) { unchecked {
        uint256 res = 0;

        uint256 y;
        uint256 z;

        z = y = x % 0x10000000000000000000000000000000; // get the input modulo 2^(-3)
        z = z * y / FIXED_1; res += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!)
        z = z * y / FIXED_1; res += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!)
        z = z * y / FIXED_1; res += z * 0x0168244fdac78000; // add y^04 * (20! / 04!)
        z = z * y / FIXED_1; res += z * 0x004807432bc18000; // add y^05 * (20! / 05!)
        z = z * y / FIXED_1; res += z * 0x000c0135dca04000; // add y^06 * (20! / 06!)
        z = z * y / FIXED_1; res += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!)
        z = z * y / FIXED_1; res += z * 0x000036e0f639b800; // add y^08 * (20! / 08!)
        z = z * y / FIXED_1; res += z * 0x00000618fee9f800; // add y^09 * (20! / 09!)
        z = z * y / FIXED_1; res += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!)
        z = z * y / FIXED_1; res += z * 0x0000000e30dce400; // add y^11 * (20! / 11!)
        z = z * y / FIXED_1; res += z * 0x000000012ebd1300; // add y^12 * (20! / 12!)
        z = z * y / FIXED_1; res += z * 0x0000000017499f00; // add y^13 * (20! / 13!)
        z = z * y / FIXED_1; res += z * 0x0000000001a9d480; // add y^14 * (20! / 14!)
        z = z * y / FIXED_1; res += z * 0x00000000001c6380; // add y^15 * (20! / 15!)
        z = z * y / FIXED_1; res += z * 0x000000000001c638; // add y^16 * (20! / 16!)
        z = z * y / FIXED_1; res += z * 0x0000000000001ab8; // add y^17 * (20! / 17!)
        z = z * y / FIXED_1; res += z * 0x000000000000017c; // add y^18 * (20! / 18!)
        z = z * y / FIXED_1; res += z * 0x0000000000000014; // add y^19 * (20! / 19!)
        z = z * y / FIXED_1; res += z * 0x0000000000000001; // add y^20 * (20! / 20!)
        res = res / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0!

        if ((x & 0x010000000000000000000000000000000) != 0) res = res * 0x1c3d6a24ed82218787d624d3e5eba95f9 / 0x18ebef9eac820ae8682b9793ac6d1e776; // multiply by e^2^(-3)
        if ((x & 0x020000000000000000000000000000000) != 0) res = res * 0x18ebef9eac820ae8682b9793ac6d1e778 / 0x1368b2fc6f9609fe7aceb46aa619baed4; // multiply by e^2^(-2)
        if ((x & 0x040000000000000000000000000000000) != 0) res = res * 0x1368b2fc6f9609fe7aceb46aa619baed5 / 0x0bc5ab1b16779be3575bd8f0520a9f21f; // multiply by e^2^(-1)
        if ((x & 0x080000000000000000000000000000000) != 0) res = res * 0x0bc5ab1b16779be3575bd8f0520a9f21e / 0x0454aaa8efe072e7f6ddbab84b40a55c9; // multiply by e^2^(+0)
        if ((x & 0x100000000000000000000000000000000) != 0) res = res * 0x0454aaa8efe072e7f6ddbab84b40a55c5 / 0x00960aadc109e7a3bf4578099615711ea; // multiply by e^2^(+1)
        if ((x & 0x200000000000000000000000000000000) != 0) res = res * 0x00960aadc109e7a3bf4578099615711d7 / 0x0002bf84208204f5977f9a8cf01fdce3d; // multiply by e^2^(+2)
        if ((x & 0x400000000000000000000000000000000) != 0) res = res * 0x0002bf84208204f5977f9a8cf01fdc307 / 0x0000003c6ab775dd0b95b4cbee7e65d11; // multiply by e^2^(+3)

        return res;
    }}

    /**
      * @dev The global "maxExpArray" is sorted in descending order, and therefore the following statements are equivalent:
      * - This function finds the position of [the smallest value in "maxExpArray" larger than or equal to "x"]
      * - This function finds the highest position of [a value in "maxExpArray" larger than or equal to "x"]
      * This function supports the rational approximation of "(a / b) ^ (c / d)" via "e ^ (log(a / b) * c / d)".
      * The value of "log(a / b)" is represented with an integer slightly smaller than "log(a / b) * 2 ^ precision".
      * The larger "precision" is, the more accurately this value represents the real value.
      * However, the larger "precision" is, the more bits are required in order to store this value.
      * And the exponentiation function, which takes "x" and calculates "e ^ x", is limited to a maximum exponent (a maximum value of "x").
      * This maximum exponent depends on the "precision" used, and it is given by "maxExpArray[precision] >> (MAX_PRECISION - precision)".
      * Hence we need to determine the highest precision which can be used for the given input, before calling the exponentiation function.
      * This allows us to compute the result with maximum accuracy and without exceeding 256 bits in any of the intermediate computations.
    */
    function findPosition(uint256 x) internal view returns (uint8) { unchecked {
        uint8 lo = MIN_PRECISION;
        uint8 hi = MAX_PRECISION;

        while (lo + 1 < hi) {
            uint8 mid = (lo + hi) / 2;
            if (maxExpArray[mid] >= x)
                lo = mid;
            else
                hi = mid;
        }

        if (maxExpArray[hi] >= x)
            return hi;
        if (maxExpArray[lo] >= x)
            return lo;

        revert("findPosition: x > max");
    }}

    /**
      * @dev Initialize internal data structure
      * Auto-generated via 'PrintMaxExpArray.py'
    */
    function initMaxExpArray() internal {
    //  maxExpArray[  0] = 0x6bffffffffffffffffffffffffffffffff;
    //  maxExpArray[  1] = 0x67ffffffffffffffffffffffffffffffff;
    //  maxExpArray[  2] = 0x637fffffffffffffffffffffffffffffff;
    //  maxExpArray[  3] = 0x5f6fffffffffffffffffffffffffffffff;
    //  maxExpArray[  4] = 0x5b77ffffffffffffffffffffffffffffff;
    //  maxExpArray[  5] = 0x57b3ffffffffffffffffffffffffffffff;
    //  maxExpArray[  6] = 0x5419ffffffffffffffffffffffffffffff;
    //  maxExpArray[  7] = 0x50a2ffffffffffffffffffffffffffffff;
    //  maxExpArray[  8] = 0x4d517fffffffffffffffffffffffffffff;
    //  maxExpArray[  9] = 0x4a233fffffffffffffffffffffffffffff;
    //  maxExpArray[ 10] = 0x47165fffffffffffffffffffffffffffff;
    //  maxExpArray[ 11] = 0x4429afffffffffffffffffffffffffffff;
    //  maxExpArray[ 12] = 0x415bc7ffffffffffffffffffffffffffff;
    //  maxExpArray[ 13] = 0x3eab73ffffffffffffffffffffffffffff;
    //  maxExpArray[ 14] = 0x3c1771ffffffffffffffffffffffffffff;
    //  maxExpArray[ 15] = 0x399e96ffffffffffffffffffffffffffff;
    //  maxExpArray[ 16] = 0x373fc47fffffffffffffffffffffffffff;
    //  maxExpArray[ 17] = 0x34f9e8ffffffffffffffffffffffffffff;
    //  maxExpArray[ 18] = 0x32cbfd5fffffffffffffffffffffffffff;
    //  maxExpArray[ 19] = 0x30b5057fffffffffffffffffffffffffff;
    //  maxExpArray[ 20] = 0x2eb40f9fffffffffffffffffffffffffff;
    //  maxExpArray[ 21] = 0x2cc8340fffffffffffffffffffffffffff;
    //  maxExpArray[ 22] = 0x2af09481ffffffffffffffffffffffffff;
    //  maxExpArray[ 23] = 0x292c5bddffffffffffffffffffffffffff;
    //  maxExpArray[ 24] = 0x277abdcdffffffffffffffffffffffffff;
    //  maxExpArray[ 25] = 0x25daf6657fffffffffffffffffffffffff;
    //  maxExpArray[ 26] = 0x244c49c65fffffffffffffffffffffffff;
    //  maxExpArray[ 27] = 0x22ce03cd5fffffffffffffffffffffffff;
    //  maxExpArray[ 28] = 0x215f77c047ffffffffffffffffffffffff;
    //  maxExpArray[ 29] = 0x1fffffffffffffffffffffffffffffffff;
    //  maxExpArray[ 30] = 0x1eaefdbdabffffffffffffffffffffffff;
    //  maxExpArray[ 31] = 0x1d6bd8b2ebffffffffffffffffffffffff;
        maxExpArray[ 32] = 0x1c35fedd14ffffffffffffffffffffffff;
        maxExpArray[ 33] = 0x1b0ce43b323fffffffffffffffffffffff;
        maxExpArray[ 34] = 0x19f0028ec1ffffffffffffffffffffffff;
        maxExpArray[ 35] = 0x18ded91f0e7fffffffffffffffffffffff;
        maxExpArray[ 36] = 0x17d8ec7f0417ffffffffffffffffffffff;
        maxExpArray[ 37] = 0x16ddc6556cdbffffffffffffffffffffff;
        maxExpArray[ 38] = 0x15ecf52776a1ffffffffffffffffffffff;
        maxExpArray[ 39] = 0x15060c256cb2ffffffffffffffffffffff;
        maxExpArray[ 40] = 0x1428a2f98d72ffffffffffffffffffffff;
        maxExpArray[ 41] = 0x13545598e5c23fffffffffffffffffffff;
        maxExpArray[ 42] = 0x1288c4161ce1dfffffffffffffffffffff;
        maxExpArray[ 43] = 0x11c592761c666fffffffffffffffffffff;
        maxExpArray[ 44] = 0x110a688680a757ffffffffffffffffffff;
        maxExpArray[ 45] = 0x1056f1b5bedf77ffffffffffffffffffff;
        maxExpArray[ 46] = 0x0faadceceeff8bffffffffffffffffffff;
        maxExpArray[ 47] = 0x0f05dc6b27edadffffffffffffffffffff;
        maxExpArray[ 48] = 0x0e67a5a25da4107fffffffffffffffffff;
        maxExpArray[ 49] = 0x0dcff115b14eedffffffffffffffffffff;
        maxExpArray[ 50] = 0x0d3e7a392431239fffffffffffffffffff;
        maxExpArray[ 51] = 0x0cb2ff529eb71e4fffffffffffffffffff;
        maxExpArray[ 52] = 0x0c2d415c3db974afffffffffffffffffff;
        maxExpArray[ 53] = 0x0bad03e7d883f69bffffffffffffffffff;
        maxExpArray[ 54] = 0x0b320d03b2c343d5ffffffffffffffffff;
        maxExpArray[ 55] = 0x0abc25204e02828dffffffffffffffffff;
        maxExpArray[ 56] = 0x0a4b16f74ee4bb207fffffffffffffffff;
        maxExpArray[ 57] = 0x09deaf736ac1f569ffffffffffffffffff;
        maxExpArray[ 58] = 0x0976bd9952c7aa957fffffffffffffffff;
        maxExpArray[ 59] = 0x09131271922eaa606fffffffffffffffff;
        maxExpArray[ 60] = 0x08b380f3558668c46fffffffffffffffff;
        maxExpArray[ 61] = 0x0857ddf0117efa215bffffffffffffffff;
        maxExpArray[ 62] = 0x07ffffffffffffffffffffffffffffffff;
        maxExpArray[ 63] = 0x07abbf6f6abb9d087fffffffffffffffff;
        maxExpArray[ 64] = 0x075af62cbac95f7dfa7fffffffffffffff;
        maxExpArray[ 65] = 0x070d7fb7452e187ac13fffffffffffffff;
        maxExpArray[ 66] = 0x06c3390ecc8af379295fffffffffffffff;
        maxExpArray[ 67] = 0x067c00a3b07ffc01fd6fffffffffffffff;
        maxExpArray[ 68] = 0x0637b647c39cbb9d3d27ffffffffffffff;
        maxExpArray[ 69] = 0x05f63b1fc104dbd39587ffffffffffffff;
        maxExpArray[ 70] = 0x05b771955b36e12f7235ffffffffffffff;
        maxExpArray[ 71] = 0x057b3d49dda84556d6f6ffffffffffffff;
        maxExpArray[ 72] = 0x054183095b2c8ececf30ffffffffffffff;
        maxExpArray[ 73] = 0x050a28be635ca2b888f77fffffffffffff;
        maxExpArray[ 74] = 0x04d5156639708c9db33c3fffffffffffff;
        maxExpArray[ 75] = 0x04a23105873875bd52dfdfffffffffffff;
        maxExpArray[ 76] = 0x0471649d87199aa990756fffffffffffff;
        maxExpArray[ 77] = 0x04429a21a029d4c1457cfbffffffffffff;
        maxExpArray[ 78] = 0x0415bc6d6fb7dd71af2cb3ffffffffffff;
        maxExpArray[ 79] = 0x03eab73b3bbfe282243ce1ffffffffffff;
        maxExpArray[ 80] = 0x03c1771ac9fb6b4c18e229ffffffffffff;
        maxExpArray[ 81] = 0x0399e96897690418f785257fffffffffff;
        maxExpArray[ 82] = 0x0373fc456c53bb779bf0ea9fffffffffff;
        maxExpArray[ 83] = 0x034f9e8e490c48e67e6ab8bfffffffffff;
        maxExpArray[ 84] = 0x032cbfd4a7adc790560b3337ffffffffff;
        maxExpArray[ 85] = 0x030b50570f6e5d2acca94613ffffffffff;
        maxExpArray[ 86] = 0x02eb40f9f620fda6b56c2861ffffffffff;
        maxExpArray[ 87] = 0x02cc8340ecb0d0f520a6af58ffffffffff;
        maxExpArray[ 88] = 0x02af09481380a0a35cf1ba02ffffffffff;
        maxExpArray[ 89] = 0x0292c5bdd3b92ec810287b1b3fffffffff;
        maxExpArray[ 90] = 0x0277abdcdab07d5a77ac6d6b9fffffffff;
        maxExpArray[ 91] = 0x025daf6654b1eaa55fd64df5efffffffff;
        maxExpArray[ 92] = 0x0244c49c648baa98192dce88b7ffffffff;
        maxExpArray[ 93] = 0x022ce03cd5619a311b2471268bffffffff;
        maxExpArray[ 94] = 0x0215f77c045fbe885654a44a0fffffffff;
        maxExpArray[ 95] = 0x01ffffffffffffffffffffffffffffffff;
        maxExpArray[ 96] = 0x01eaefdbdaaee7421fc4d3ede5ffffffff;
        maxExpArray[ 97] = 0x01d6bd8b2eb257df7e8ca57b09bfffffff;
        maxExpArray[ 98] = 0x01c35fedd14b861eb0443f7f133fffffff;
        maxExpArray[ 99] = 0x01b0ce43b322bcde4a56e8ada5afffffff;
        maxExpArray[100] = 0x019f0028ec1fff007f5a195a39dfffffff;
        maxExpArray[101] = 0x018ded91f0e72ee74f49b15ba527ffffff;
        maxExpArray[102] = 0x017d8ec7f04136f4e5615fd41a63ffffff;
        maxExpArray[103] = 0x016ddc6556cdb84bdc8d12d22e6fffffff;
        maxExpArray[104] = 0x015ecf52776a1155b5bd8395814f7fffff;
        maxExpArray[105] = 0x015060c256cb23b3b3cc3754cf40ffffff;
        maxExpArray[106] = 0x01428a2f98d728ae223ddab715be3fffff;
        maxExpArray[107] = 0x013545598e5c23276ccf0ede68034fffff;
        maxExpArray[108] = 0x01288c4161ce1d6f54b7f61081194fffff;
        maxExpArray[109] = 0x011c592761c666aa641d5a01a40f17ffff;
        maxExpArray[110] = 0x0110a688680a7530515f3e6e6cfdcdffff;
        maxExpArray[111] = 0x01056f1b5bedf75c6bcb2ce8aed428ffff;
        maxExpArray[112] = 0x00faadceceeff8a0890f3875f008277fff;
        maxExpArray[113] = 0x00f05dc6b27edad306388a600f6ba0bfff;
        maxExpArray[114] = 0x00e67a5a25da41063de1495d5b18cdbfff;
        maxExpArray[115] = 0x00dcff115b14eedde6fc3aa5353f2e4fff;
        maxExpArray[116] = 0x00d3e7a3924312399f9aae2e0f868f8fff;
        maxExpArray[117] = 0x00cb2ff529eb71e41582cccd5a1ee26fff;
        maxExpArray[118] = 0x00c2d415c3db974ab32a51840c0b67edff;
        maxExpArray[119] = 0x00bad03e7d883f69ad5b0a186184e06bff;
        maxExpArray[120] = 0x00b320d03b2c343d4829abd6075f0cc5ff;
        maxExpArray[121] = 0x00abc25204e02828d73c6e80bcdb1a95bf;
        maxExpArray[122] = 0x00a4b16f74ee4bb2040a1ec6c15fbbf2df;
        maxExpArray[123] = 0x009deaf736ac1f569deb1b5ae3f36c130f;
        maxExpArray[124] = 0x00976bd9952c7aa957f5937d790ef65037;
        maxExpArray[125] = 0x009131271922eaa6064b73a22d0bd4f2bf;
        maxExpArray[126] = 0x008b380f3558668c46c91c49a2f8e967b9;
        maxExpArray[127] = 0x00857ddf0117efa215952912839f6473e6;
    }

    // auxiliary function
    function mulDivLog(uint256 x, uint256 y, uint256 z) private pure returns (uint256) {
        return fixedLog(IntegralMath.mulDivF(x, y, z));
    }

    // auxiliary function
    function mulDivExp(uint256 x, uint256 y, uint256 z) private view returns (uint256, uint256) {
        return fixedExp(IntegralMath.mulDivF(x, y, z));
    }
}

File 9 of 11 : FullMath.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
    /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
    function mulDiv(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        // 512-bit multiply [prod1 prod0] = a * b
        // Compute the product mod 2**256 and mod 2**256 - 1
        // then 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

        // todo unchecked
        unchecked {
            assembly {
                let mm := mulmod(a, b, not(0))
                prod0 := mul(a, b)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division
            if (prod1 == 0) {
                require(denominator > 0);
                assembly {
                    result := div(prod0, denominator)
                }
                return result;
            }

            // Make sure the result is less than 2**256.
            // Also prevents denominator == 0
            require(denominator > prod1);

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

            // Make division exact by subtracting the remainder from [prod1 prod0]
            // Compute remainder using mulmod
            uint256 remainder;
            assembly {
                remainder := mulmod(a, b, denominator)
            }
            // Subtract 256 bit number from 512 bit number
            assembly {
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator
            // Compute largest power of two divisor of denominator.
            // Always >= 1.
            uint256 twos = (~denominator + 1) & denominator;
            // Divide denominator by power of two
            assembly {
                denominator := div(denominator, twos)
            }

            // Divide [prod1 prod0] by the factors of two
            assembly {
                prod0 := div(prod0, twos)
            }
            // Shift in bits from prod1 into prod0. For this we need
            // to flip `twos` such that it is 2**256 / twos.
            // If twos is zero, then it becomes one
            assembly {
                twos := add(div(sub(0, twos), twos), 1)
            }

            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
            // correct for four bits. That is, denominator * inv = 1 mod 2**4
            uint256 inv = (3 * denominator) ^ 2;
            // Now use 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.

            inv *= 2 - denominator * inv; // inverse mod 2**8
            inv *= 2 - denominator * inv; // inverse mod 2**16
            inv *= 2 - denominator * inv; // inverse mod 2**32
            inv *= 2 - denominator * inv; // inverse mod 2**64
            inv *= 2 - denominator * inv; // inverse mod 2**128
            inv *= 2 - denominator * inv; // 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 precoditions 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 * inv;
            return result;
        }
    }

    /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    function mulDivRoundingUp(
        uint256 a,
        uint256 b,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        result = mulDiv(a, b, denominator);
        if (mulmod(a, b, denominator) > 0) {
            require(result < type(uint256).max);
            result++;
        }
    }
}

File 10 of 11 : TransferHelper.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "TransferHelper::safeApprove: approve failed"
        );
    }

    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "TransferHelper::safeTransfer: transfer failed"
        );
    }

    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "TransferHelper::transferFrom: transferFrom failed"
        );
    }

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, "TransferHelper::safeTransferETH: ETH transfer failed");
    }
}

File 11 of 11 : IntegralMath.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

library IntegralMath {
    uint256 constant MAX_VAL = type(uint256).max;

    // reverts on overflow
    function safeAdd(uint256 x, uint256 y) internal pure returns (uint256) {
        return x + y;
    }

    // does not revert on overflow
    function unsafeAdd(uint256 x, uint256 y) internal pure returns (uint256) { unchecked {
        return x + y;
    }}

    // does not revert on overflow
    function unsafeSub(uint256 x, uint256 y) internal pure returns (uint256) { unchecked {
        return x - y;
    }}

    // does not revert on overflow
    function unsafeMul(uint256 x, uint256 y) internal pure returns (uint256) { unchecked {
        return x * y;
    }}

    // does not overflow
    function mulModMax(uint256 x, uint256 y) internal pure returns (uint256) { unchecked {
        return mulmod(x, y, MAX_VAL);
    }}

    // does not overflow
    function mulMod(uint256 x, uint256 y, uint256 z) internal pure returns (uint256) { unchecked {
        return mulmod(x, y, z);
    }}
    /**
      * @dev Compute the largest integer smaller than or equal to the binary logarithm of `n`
    */
    function floorLog2(uint256 n) internal pure returns (uint8) { unchecked {
        uint8 res = 0;

        if (n < 256) {
            // at most 8 iterations
            while (n > 1) {
                n >>= 1;
                res += 1;
            }
        }
        else {
            // exactly 8 iterations
            for (uint8 s = 128; s > 0; s >>= 1) {
                if (n >= 1 << s) {
                    n >>= s;
                    res |= s;
                }
            }
        }

        return res;
    }}

    /**
      * @dev Compute the largest integer smaller than or equal to the square root of `n`
    */
    function floorSqrt(uint256 n) internal pure returns (uint256) { unchecked {
        if (n > 0) {
            uint256 x = n / 2 + 1;
            uint256 y = (x + n / x) / 2;
            while (x > y) {
                x = y;
                y = (x + n / x) / 2;
            }
            return x;
        }
        return 0;
    }}

    /**
      * @dev Compute the smallest integer larger than or equal to the square root of `n`
    */
    function ceilSqrt(uint256 n) internal pure returns (uint256) { unchecked {
        uint256 x = floorSqrt(n);
        return x ** 2 == n ? x : x + 1;
    }}

    /**
      * @dev Compute the largest integer smaller than or equal to the cubic root of `n`
    */
    function floorCbrt(uint256 n) internal pure returns (uint256) { unchecked {
        uint256 x = 0;
        for (uint256 y = 1 << 255; y > 0; y >>= 3) {
            x <<= 1;
            uint256 z = 3 * x * (x + 1) + 1;
            if (n / y >= z) {
                n -= y * z;
                x += 1;
            }
        }
        return x;
    }}

    /**
      * @dev Compute the smallest integer larger than or equal to the cubic root of `n`
    */
    function ceilCbrt(uint256 n) internal pure returns (uint256) { unchecked {
        uint256 x = floorCbrt(n);
        return x ** 3 == n ? x : x + 1;
    }}

    /**
      * @dev Compute the nearest integer to the quotient of `n` and `d` (or `n / d`)
    */
    function roundDiv(uint256 n, uint256 d) internal pure returns (uint256) { unchecked {
        return n / d + (n % d) / (d - d / 2);
    }}

    /**
      * @dev Compute the largest integer smaller than or equal to `x * y / z`
    */
    function mulDivF(uint256 x, uint256 y, uint256 z) internal pure returns (uint256) { unchecked {
        (uint256 xyh, uint256 xyl) = mul512(x, y);
        if (xyh == 0) { // `x * y < 2 ^ 256`
            return xyl / z;
        }
        if (xyh < z) { // `x * y / z < 2 ^ 256`
            uint256 m = mulMod(x, y, z);                    // `m = x * y % z`
            (uint256 nh, uint256 nl) = sub512(xyh, xyl, m); // `n = x * y - m` hence `n / z = floor(x * y / z)`
            if (nh == 0) { // `n < 2 ^ 256`
                return nl / z;
            }
            uint256 p = unsafeSub(0, z) & z; // `p` is the largest power of 2 which `z` is divisible by
            uint256 q = div512(nh, nl, p);   // `n` is divisible by `p` because `n` is divisible by `z` and `z` is divisible by `p`
            uint256 r = inv256(z / p);       // `z / p = 1 mod 2` hence `inverse(z / p) = 1 mod 2 ^ 256`
            return unsafeMul(q, r);          // `q * r = (n / p) * inverse(z / p) = n / z`
        }
        revert(); // `x * y / z >= 2 ^ 256`
    }}

    /**
      * @dev Compute the smallest integer larger than or equal to `x * y / z`
    */
    function mulDivC(uint256 x, uint256 y, uint256 z) internal pure returns (uint256) { unchecked {
        uint256 w = mulDivF(x, y, z);
        if (mulMod(x, y, z) > 0)
            return safeAdd(w, 1);
        return w;
    }}

    /**
      * @dev Compute the value of `x * y`
    */
    function mul512(uint256 x, uint256 y) private pure returns (uint256, uint256) { unchecked {
        uint256 p = mulModMax(x, y);
        uint256 q = unsafeMul(x, y);
        if (p >= q)
            return (p - q, q);
        return (unsafeSub(p, q) - 1, q);
    }}

    /**
      * @dev Compute the value of `2 ^ 256 * xh + xl - y`, where `2 ^ 256 * xh + xl >= y`
    */
    function sub512(uint256 xh, uint256 xl, uint256 y) private pure returns (uint256, uint256) { unchecked {
        if (xl >= y)
            return (xh, xl - y);
        return (xh - 1, unsafeSub(xl, y));
    }}

    /**
      * @dev Compute the value of `(2 ^ 256 * xh + xl) / pow2n`, where `xl` is divisible by `pow2n`
    */
    function div512(uint256 xh, uint256 xl, uint256 pow2n) private pure returns (uint256) { unchecked {
        uint256 pow2nInv = unsafeAdd(unsafeSub(0, pow2n) / pow2n, 1); // `1 << (256 - n)`
        return unsafeMul(xh, pow2nInv) | (xl / pow2n); // `(xh << (256 - n)) | (xl >> n)`
    }}

    /**
      * @dev Compute the inverse of `d` modulo `2 ^ 256`, where `d` is congruent to `1` modulo `2`
    */
    function inv256(uint256 d) private pure returns (uint256) { unchecked {
        // approximate the root of `f(x) = 1 / x - d` using the newton–raphson convergence method
        uint256 x = 1;
        for (uint256 i = 0; i < 8; ++i)
            x = unsafeMul(x, unsafeSub(2, unsafeMul(x, d))); // `x = x * (2 - x * d) mod 2 ^ 256`
        return x;
    }}
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"banana_","type":"address"},{"internalType":"address","name":"usdc_","type":"address"},{"internalType":"address","name":"twamm_","type":"address"},{"internalType":"address","name":"bananaDistributor_","type":"address"},{"internalType":"address","name":"keeper_","type":"address"},{"internalType":"uint256","name":"secondsOfEpoch_","type":"uint256"},{"internalType":"uint256","name":"initPrice","type":"uint256"},{"internalType":"uint256","name":"initReward","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"buyingRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burned","type":"uint256"}],"name":"BuybackExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPendingOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"NewPendingOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnAmount","type":"uint256"}],"name":"WithdrawAndBurn","type":"event"},{"inputs":[],"name":"acceptOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"banana","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bananaDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isStop","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keeper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBuyingRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastExecuteTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastOrderId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceT1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceT2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPriceT1","type":"uint256"},{"internalType":"uint256","name":"newPriceT2","type":"uint256"}],"name":"resetPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRewardT1","type":"uint256"},{"internalType":"uint256","name":"newRewardT2","type":"uint256"}],"name":"resetReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardT1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardT2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secondsOfEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secondsPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"setPendingOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twamm","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"endTime_","type":"uint256"}],"name":"updateEndTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"keeper_","type":"address"}],"name":"updateKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newExecuteTime","type":"uint256"}],"name":"updateLastExecuteTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPriceIndex","type":"uint256"}],"name":"updatePriceIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRewardIndex","type":"uint256"}],"name":"updateRewardIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSecondsOfEpoch","type":"uint256"}],"name":"updateSecondsOfEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSecondsPerBlock","type":"uint256"}],"name":"updateSecondsPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isStop_","type":"bool"}],"name":"updateStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdc","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"withdrawAndBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"withdrawUsdc","outputs":[],"stateMutability":"nonpayable","type":"function"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061021c5760003560e01c80639545022e11610125578063c3cafc6f116100ad578063cfea5d851161007c578063cfea5d8514610485578063e30c39781461048e578063e9ee2fa9146104a1578063ebbc4965146104aa578063f902055a146104b25761021c565b8063c3cafc6f1461042f578063c42069ec14610456578063cc7b326a14610469578063cd97cb451461047c5761021c565b8063aa168c5f116100f4578063aa168c5f146103da578063aced1661146103e3578063b39cc7b1146103f6578063b6a035a414610409578063bab4ce6b1461041c5761021c565b80639545022e1461039957806397779e1b146103ac57806397790217146103be578063a9ea1896146103d15761021c565b80635662ecc7116101a85780636ab3846b116101775780636ab3846b1461035857806377e811721461036b5780637a7d4937146103745780638460c6881461037d5780638da5cb5b146103865761021c565b80635662ecc7146103215780635cdc48f91461032a578063614619541461033d578063698ca7c2146103455761021c565b8063158ef93e116101ef578063158ef93e146102b857806319e072ef146102d55780633197cbb6146102e85780633e413bee146102f157806345f988a4146103185761021c565b80630dcc4b441461022157806310bd7ef614610236578063118f117f1461027a5780631406c88d14610291575b600080fd5b61023461022f366004612d33565b6104c5565b005b61025d7f000000000000000000000000efb66c23f6e0d178d8499744a7fe675ba32c69ca81565b6040516001600160a01b0390911681526020015b60405180910390f35b610283608d5481565b604051908152602001610271565b61025d7f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b881565b608f546102c59060ff1681565b6040519015158152602001610271565b6102346102e3366004612c64565b6104fd565b610283608e5481565b61025d7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b61028360855481565b610283608c5481565b610234610338366004612c2c565b610541565b610234610678565b610234610353366004612d63565b61119a565b610234610366366004612d33565b6111cf565b61028360875481565b610283608a5481565b61028360885481565b60005461025d906001600160a01b031681565b6102346103a7366004612d33565b6111fe565b608f546102c590610100900460ff1681565b6102346103cc366004612c2c565b6116cc565b61028360845481565b61028360865481565b60825461025d906001600160a01b031681565b610234610404366004612d33565b611718565b610234610417366004612d63565b611747565b61023461042a366004612d33565b61177c565b61025d7f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a9081565b610234610464366004612c2c565b6117ab565b610234610477366004612d33565b611886565b610283608b5481565b61028360835481565b60015461025d906001600160a01b031681565b61028360895481565b6102346118b5565b6102346104c0366004612d33565b6119a9565b6000546001600160a01b031633146104f85760405162461bcd60e51b81526004016104ef90612de0565b60405180910390fd5b608955565b6000546001600160a01b031633146105275760405162461bcd60e51b81526004016104ef90612de0565b608f80549115156101000261ff0019909216919091179055565b6000546001600160a01b0316331461056b5760405162461bcd60e51b81526004016104ef90612de0565b608f54610100900460ff166105ad5760405162461bcd60e51b815260206004820152600860248201526706e6f742073746f760c41b60448201526064016104ef565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb486001600160a01b0316906370a082319060240160206040518083038186803b15801561060f57600080fd5b505afa158015610623573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106479190612d4b565b90506106747f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4883836119d8565b5050565b608f54610100900460ff16156106ba5760405162461bcd60e51b8152602060048201526007602482015266069732073746f760cc1b60448201526064016104ef565b6082546001600160a01b031633146107025760405162461bcd60e51b815260206004820152600b60248201526a37b7363c9035b2b2b832b960a91b60448201526064016104ef565b608e5442106107395760405162461bcd60e51b8152602060048201526003602482015262195b9960ea1b60448201526064016104ef565b608b54608d546107499190612e10565b608d8190554210156107965760405162461bcd60e51b81526020600482015260166024820152756e6f7420726561636820657865637574652074696d6560501b60448201526064016104ef565b42608b54608d546107a79190612e10565b116107eb5760405162461bcd60e51b81526020600482015260146024820152736f766572206e6578742065706f63682074696d6560601b60448201526064016104ef565b6000600019608c5414610be657604051633567cb5160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811660048301527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a90811660248301526000917f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b890911690633567cb519060440160206040518083038186803b1580156108a657600080fd5b505afa1580156108ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108de9190612c48565b90506000816001600160a01b031663ec7dd7bb608c546040518263ffffffff1660e01b815260040161091291815260200190565b60c06040518083038186803b15801561092a57600080fd5b505afa15801561093e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109629190612c9c565b9050806020015143116109b75760405162461bcd60e51b815260206004820152601c60248201527f6e6f7420726561636820776974686472617761626c6520626c6f636b0000000060448201526064016104ef565b608c5460405163af6602b160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811660048301527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a908116602483015260448201929092524260648201527f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b89091169063af6602b190608401602060405180830381600087803b158015610a7557600080fd5b505af1158015610a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aad9190612d4b565b506040516370a0823160e01b81523060048201527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a906001600160a01b0316906370a082319060240160206040518083038186803b158015610b0d57600080fd5b505afa158015610b21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b459190612d4b565b604051630852cd8d60e31b8152600481018290529093507f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a906001600160a01b0316906342966c6890602401602060405180830381600087803b158015610baa57600080fd5b505af1158015610bbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be29190612c80565b5050505b60007f000000000000000000000000efb66c23f6e0d178d8499744a7fe675ba32c69ca6001600160a01b031663c9b171496040518163ffffffff1660e01b815260040160206040518083038186803b158015610c4157600080fd5b505afa158015610c55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c799190612d4b565b60865490915015610c8b576086546087555b6086819055604051638caa017160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811660048301527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a908116602483015260009182917f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b81690638caa017190604401604080518083038186803b158015610d3d57600080fd5b505afa158015610d51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d759190612d84565b90925090506000610d94836c0c9f2c9cd04674edea4000000084611b09565b60845490915015610da6576084546085555b80608481905550600042608b54608d54610dc09190612e10565b610dca9190612e67565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4816906370a082319060240160206040518083038186803b158015610e2f57600080fd5b505afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e679190612d4b565b608f5490915060009060ff16610e98575080610e838382612e28565b608355608f805460ff19166001179055610f1e565b600080610eae6085546084546088546064611bbe565b91509150600080610ec86086546087546089546064611bbe565b91509150610eef8282610ee88787608354611b099092919063ffffffff16565b9190611b09565b6083819055610efe9088612e48565b945085851115610f1957859450610f158786612e28565b6083555b505050505b60008111610f635760405162461bcd60e51b81526020600482015260126024820152710627579696e6720616d6f756e7420697320360741b60448201526064016104ef565b60405163095ea7b360e01b81526001600160a01b037f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b881166004830152602482018390527f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48169063095ea7b390604401602060405180830381600087803b158015610fed57600080fd5b505af1158015611001573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110259190612c80565b507f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b86001600160a01b031663cd743e3e7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb487f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a9084608a5460056110a79190612e48565b6110b19089612e28565b6040516001600160e01b031960e087901b1681526001600160a01b0394851660048201529390921660248401526044830152606482015242608482015260a401602060405180830381600087803b15801561110b57600080fd5b505af115801561111f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111439190612d4b565b608c8190556083546040805192835260208301849052820152606081018990527f42659a4aa613c1e350c764f0ff2be36a175ac2a1e4b77b8e1467d1fed32becc89060800160405180910390a15050505050505050565b6000546001600160a01b031633146111c45760405162461bcd60e51b81526004016104ef90612de0565b608491909155608555565b6000546001600160a01b031633146111f95760405162461bcd60e51b81526004016104ef90612de0565b608e55565b6000546001600160a01b031633146112285760405162461bcd60e51b81526004016104ef90612de0565b608f54610100900460ff1661126a5760405162461bcd60e51b815260206004820152600860248201526706e6f742073746f760c41b60448201526064016104ef565b604051633567cb5160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811660048301527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a90811660248301526000917f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b890911690633567cb519060440160206040518083038186803b15801561131857600080fd5b505afa15801561132c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113509190612c48565b60405163ec7dd7bb60e01b8152600481018490529091506000906001600160a01b0383169063ec7dd7bb9060240160c06040518083038186803b15801561139657600080fd5b505afa1580156113aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ce9190612c9c565b9050806020015143116114235760405162461bcd60e51b815260206004820152601c60248201527f6e6f7420726561636820776974686472617761626c6520626c6f636b0000000060448201526064016104ef565b60405163af6602b160e01b81526001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811660048301527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a9081166024830152604482018590524260648301527f000000000000000000000000cd43aba971bef65555d877657f83093ddfb885b8169063af6602b190608401602060405180830381600087803b1580156114db57600080fd5b505af11580156114ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115139190612d4b565b506040516370a0823160e01b81523060048201526000907f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a906001600160a01b0316906370a082319060240160206040518083038186803b15801561157657600080fd5b505afa15801561158a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ae9190612d4b565b9050600081116115f25760405162461bcd60e51b815260206004820152600f60248201526e3737ba3434b733903a3790313ab93760891b60448201526064016104ef565b604051630852cd8d60e31b8152600481018290527f0000000000000000000000002a1dca74419c2d304a3d359f428ee1a4e9324a906001600160a01b0316906342966c6890602401602060405180830381600087803b15801561165457600080fd5b505af1158015611668573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168c9190612c80565b5060408051858152602081018390527f321a70b1e7aa7f458835d8a34f15391640fc7007590907c1f65e02de099f2e4f910160405180910390a150505050565b6000546001600160a01b031633146116f65760405162461bcd60e51b81526004016104ef90612de0565b608280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146117425760405162461bcd60e51b81526004016104ef90612de0565b608d55565b6000546001600160a01b031633146117715760405162461bcd60e51b81526004016104ef90612de0565b608691909155608755565b6000546001600160a01b031633146117a65760405162461bcd60e51b81526004016104ef90612de0565b608855565b6000546001600160a01b031633146117d55760405162461bcd60e51b81526004016104ef90612de0565b6001546001600160a01b038281169116141561182a5760405162461bcd60e51b815260206004820152601460248201527313dddb98589b194e881053149150511657d4d15560621b60448201526064016104ef565b6001546040516001600160a01b038084169216907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146118b05760405162461bcd60e51b81526004016104ef90612de0565b608a55565b6001546001600160a01b0316331461190f5760405162461bcd60e51b815260206004820152601e60248201527f4f776e61626c653a20524551554952455f50454e44494e475f4f574e4552000060448201526064016104ef565b60008054600180546001600160a01b038082166001600160a01b03198086168217808855931690935560405193811694929391169184917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b23649190a36001546040516001600160a01b03918216918316907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b6000546001600160a01b031633146119d35760405162461bcd60e51b81526004016104ef90612de0565b608b55565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691611a349190612da7565b6000604051808303816000865af19150503d8060008114611a71576040519150601f19603f3d011682016040523d82523d6000602084013e611a76565b606091505b5091509150818015611aa0575080511580611aa0575080806020019051810190611aa09190612c80565b611b025760405162461bcd60e51b815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201526c185b9cd9995c8819985a5b1959609a1b60648201526084016104ef565b5050505050565b600080806000198587098587029250828110838203039150508060001415611b435760008411611b3857600080fd5b508290049050611bb7565b808411611b4f57600080fd5b600084868809851960019081018716968790049682860381900495909211909303600082900391909104909201919091029190911760038402600290811880860282030280860282030280860282030280860282030280860282030280860290910302029150505b9392505050565b600080848610611bea57611be1611bda6001607f1b8888611c16565b8585611c33565b91509150611c0d565b600080611c06611bff6001607f1b898b611c16565b8787611c33565b9450925050505b94509492505050565b6000611c2b611c26858585611c56565b611d45565b949350505050565b600080611c49611c44868686611c56565b611d7e565b915091505b935093915050565b6000806000611c658686611dd6565b915091508160001415611c9957838181611c8f57634e487b7160e01b600052601260045260246000fd5b0492505050611bb7565b8382101561021c576000611cae878787611e11565b9050600080611cbe858585611e3a565b915091508160001415611cf557868181611ce857634e487b7160e01b600052601260045260246000fd5b0495505050505050611bb7565b6000878103881690611d08848484611e5d565b90506000611d32838b81611d2c57634e487b7160e01b600052601260045260246000fd5b04611eb6565b919091029750611bb79650505050505050565b600070015bf0a8b1457695355fb8ac404e7a79e4821015611d7057611d6982611ede565b9050611d79565b611d69826122f2565b919050565b600080600160831b831015611da457611d968361239c565b91506001607f1b9050611dd1565b6000611daf846126f8565b9050611dc481607f0360ff1685901c82612804565b9250600160ff9091161b90505b915091565b6000806000611de58585612bb2565b9050848402808210611dfe579081900392509050611e0a565b60018183030393509150505b9250929050565b60008180611e2f57634e487b7160e01b600052601260045260246000fd5b838509949350505050565b600080828410611e505750839050818303611c4e565b6000198501838503611c49565b600080611e898380830381611e8257634e487b7160e01b600052601260045260246000fd5b0460010190565b9050828481611ea857634e487b7160e01b600052601260045260246000fd5b048186021795945050505050565b60006001815b6008811015611ed75783820260020382029150600101611ebc565b5092915050565b6000808080806fd3094c70f034de4b96ff7d5b6f99fcd98610611f21576001607e1b93909301926fd3094c70f034de4b96ff7d5b6f99fcd96001607f1b87020495505b6fa45af1e1f40c333b3de1db4dd55f29a88610611f5e576001607d1b93909301926fa45af1e1f40c333b3de1db4dd55f29a86001607f1b87020495505b6f910b022db7ae67ce76b441c27035c6a28610611f9b576001607c1b93909301926f910b022db7ae67ce76b441c27035c6a26001607f1b87020495505b6f88415abbe9a76bead8d00cf112e4d4a98610611fd8576001607b1b93909301926f88415abbe9a76bead8d00cf112e4d4a96001607f1b87020495505b6f84102b00893f64c705e841d5d4064bd48610612015576001607a1b93909301926f84102b00893f64c705e841d5d4064bd46001607f1b87020495505b6f8204055aaef1c8bd5c3259f4822735a3861061205257600160791b93909301926f8204055aaef1c8bd5c3259f4822735a36001607f1b87020495505b6f810100ab00222d861931c15e39b44e9a861061208f57600160781b93909301926f810100ab00222d861931c15e39b44e9a6001607f1b87020495505b6f808040155aabbbe9451521693554f73486106120cc57600160771b93909301926f808040155aabbbe9451521693554f7346001607f1b87020495505b6f7fffffffffffffffffffffffffffffff19860192508291506001607f1b828002049050600160801b83810383020493909301926001607f1b828202049150600160811b836faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0383028161214057634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600360801b836f999999999999999999999999999999990383028161218657634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600160821b836f92492492492492492492492492492492038302816121cc57634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600560801b836f8e38e38e38e38e38e38e38e38e38e38e0383028161221257634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600360811b836f8ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b0383028161225857634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600760801b836f89d89d89d89d89d89d89d89d89d89d890383028161229e57634e487b7160e01b600052601260045260246000fd5b0493909301926001607f1b828202049150600160831b836f88888888888888888888888888888888038302816122e457634e487b7160e01b600052601260045260246000fd5b049390930195945050505050565b600080600160801b83106123225760006123116001607f1b8504612bc1565b60ff1693841c936001607f1b029150505b6001607f1b83111561237057607f5b60ff81161561236e576001607f1b848002049350600160801b841061236557600193841c9360ff6000198301161b91909101905b60001901612331565b505b6f05b9de1d10bf4103d647b0955897ba806f03f80fe03f80fe03f80fe03f80fe03f88202049392505050565b60008080806001607c1b850691508190506001607f1b818002046710e1b3be415a00008102939093019290506001607f1b828202046705a0913f6b1e00008102939093019290506001607f1b82820204670168244fdac780008102939093019290506001607f1b82820204664807432bc180008102939093019290506001607f1b82820204660c0135dca040008102939093019290506001607f1b828202046601b707b1cdc0008102939093019290506001607f1b828202046536e0f639b8008102939093019290506001607f1b82820204650618fee9f8008102939093019290506001607f1b82820204649c197dcc008102939093019290506001607f1b82820204640e30dce4008102939093019290506001607f1b8282020464012ebd13008102939093019290506001607f1b828202046317499f008102939093019290506001607f1b828202046301a9d4808102939093019290506001607f1b82820204621c63808102939093019290506001607f1b828202046201c6388102939093019290506001607f1b82820204611ab88102939093019290506001607f1b8282020461017c8102939093019290506001607f1b8282020460148102939093019290506001607f1b828202049283019290506001607f1b826721c3677c82b400008504010192506001607c1b8516156125b85770018ebef9eac820ae8682b9793ac6d1e7767001c3d6a24ed82218787d624d3e5eba95f984020492505b6001607d1b8516156125ee577001368b2fc6f9609fe7aceb46aa619baed470018ebef9eac820ae8682b9793ac6d1e77884020492505b6001607e1b851615612623576fbc5ab1b16779be3575bd8f0520a9f21f7001368b2fc6f9609fe7aceb46aa619baed584020492505b6001607f1b851615612657576f454aaa8efe072e7f6ddbab84b40a55c96fbc5ab1b16779be3575bd8f0520a9f21e84020492505b600160801b85161561268b576f0960aadc109e7a3bf4578099615711ea6f454aaa8efe072e7f6ddbab84b40a55c584020492505b600160811b8516156126be576e2bf84208204f5977f9a8cf01fdce3d6f0960aadc109e7a3bf4578099615711d784020492505b600160821b8516156126ef576d03c6ab775dd0b95b4cbee7e65d116e2bf84208204f5977f9a8cf01fdc30784020492505b50909392505050565b60006020607f5b8060ff168260010160ff16101561275b576000600260ff848401160490508460028260ff166080811061274257634e487b7160e01b600052603260045260246000fd5b01541061275157809250612755565b8091505b506126ff565b8360028260ff166080811061278057634e487b7160e01b600052603260045260246000fd5b015410612790579150611d799050565b8360028360ff16608081106127b557634e487b7160e01b600052603260045260246000fd5b0154106127c457509050611d79565b60405162461bcd60e51b81526020600482015260156024820152740ccd2dcc8a0dee6d2e8d2dedc7440f0407c40dac2f605b1b60448201526064016104ef565b60008083905060008360ff16858302901c9150816f03442c4e6074a82f1797f72ac000000002810190508360ff16858302901c9150816f0116b96f757c380fb287fd0e4000000002810190508360ff16858302901c9150816e45ae5bdd5f0e03eca1ff439000000002810190508360ff16858302901c9150816e0defabf91302cd95b9ffda5000000002810190508360ff16858302901c9150816e02529ca9832b22439efff9b800000002810190508360ff16858302901c9150816d54f1cf12bd04e516b6da8800000002810190508360ff16858302901c9150816d0a9e39e257a09ca2d6db5100000002810190508360ff16858302901c9150816d012e066e7b839fa050c30900000002810190508360ff16858302901c9150816c1e33d7d926c329a1ad1a80000002810190508360ff16858302901c9150816c02bee513bdb4a6b19b5f80000002810190508360ff16858302901c9150816b3a9316fa79b88eccf2a0000002810190508360ff16858302901c9150816b048177ebe1fa81237520000002810190508360ff16858302901c9150816a5263fe90242dcbacf0000002810190508360ff16858302901c9150816a057e22099c030d9410000002810190508360ff16858302901c9150816957e22099c030d941000002810190508360ff16858302901c91508169052b6b5456997631000002810190508360ff16858302901c915081684985f67696bf74800002810190508360ff16858302901c9150816803dea12ea99e49800002810190508360ff16858302901c9150816731880f2214b6e00002810190508360ff16858302901c91508167025bcff56eb3600002810190508360ff16858302901c915081661b722e10ab100002810190508360ff16858302901c9150816601317c7007700002810190508360ff16858302901c915081650cba84aafa0002810190508360ff16858302901c9150816482573a0a0002810190508360ff16858302901c9150816405035ad90002810190508360ff16858302901c915081632f881b0002810190508360ff16858302901c9150816301b2934002810190508360ff16858302901c915081620efc4002810190508360ff16858302901c915081617fe002810190508360ff16858302901c91508161042002810190508360ff16858302901c915081602102810190508360ff16858302901c915081600102810190508360ff166001901b856f0688589cc0e9505e2f2fee55800000008381612ba657634e487b7160e01b600052601260045260246000fd5b04010195945050505050565b60006000198284099392505050565b600080610100831015612be9575b6001831115612be457600192831c9201612bcf565b612c1b565b60805b60ff811615611ed757600160ff82161b8410612c105760ff81169390931c92908117905b60011c607f16612bec565b92915050565b8051611d7981612e94565b600060208284031215612c3d578081fd5b8135611bb781612e94565b600060208284031215612c59578081fd5b8151611bb781612e94565b600060208284031215612c75578081fd5b8135611bb781612eac565b600060208284031215612c91578081fd5b8151611bb781612eac565b600060c08284031215612cad578081fd5b60405160c0810181811067ffffffffffffffff82111715612cdc57634e487b7160e01b83526041600452602483fd5b8060405250825181526020830151602082015260408301516040820152612d0560608401612c21565b6060820152612d1660808401612c21565b6080820152612d2760a08401612c21565b60a08201529392505050565b600060208284031215612d44578081fd5b5035919050565b600060208284031215612d5c578081fd5b5051919050565b60008060408385031215612d75578081fd5b50508035926020909101359150565b60008060408385031215612d96578182fd5b505080516020909101519092909150565b60008251815b81811015612dc75760208186018101518583015201612dad565b81811115612dd55782828501525b509190910192915050565b60208082526016908201527527bbb730b136329d102922a8aaa4a922afa7aba722a960511b604082015260600190565b60008219821115612e2357612e23612e7e565b500190565b600082612e4357634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615612e6257612e62612e7e565b500290565b600082821015612e7957612e79612e7e565b500390565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b0381168114612ea957600080fd5b50565b8015158114612ea957600080fdfea2646970667358221220b81f0d605fd02a2fe0f4b95fcb06708b034618edb8a98a54a3249507e1ac14de64736f6c63430008020033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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