Contract 0x3d09A80369071E6AC91634e0Bf889EE54Dd510C6

Contract Overview

Balance:
0 AVAX

AVAX Value:
$0.00

Token:
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x9c8c5640c3e3872b141644033938592edd2c176b601bb0ce11d2ea66f13d33c9Distribute203335132022-09-27 7:40:572 days 4 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.01996033 26
0xd001ac4ec6d62059b726509daac4f358d32ee652ad2cce1556e865c821cdf898Pre Distribute203335082022-09-27 7:40:472 days 4 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.008574098 26
0x0beaf777bf659ecff07c33729f9396fb792e7dad68c918d9a9ec7baeb75f960eDistribute201026602022-09-21 14:06:037 days 22 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0200459606 26.2
0xa6f6e83e02b8f4bdc14202a89b52cb2b225c0320c325bbca8bde82361a98f85cPre Distribute201026542022-09-21 14:05:497 days 22 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0086400526 26.2
0x24fd41a6c677eeb191d36ebcf5b4970b794dbe2868f7c2a9f18d87810cb18412Distribute198391262022-09-13 18:17:5815 days 17 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.020113871 26.2
0xb1ffb58dfeaeb2af4d814f2ef977deaa3cc479989e3a90aecfbe25b7751be6c6Pre Distribute198391222022-09-13 18:17:4815 days 18 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0081920326 26.2
0x1dafdee52fe6842799219cadc097cb5a90182a15afe91f8db4500163a910d1abDistribute196310782022-09-07 6:50:4522 days 5 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.020113871 26.2
0xa7515db3a5353c248bd9f77b52a906432fb0a28d675f83312fca79077a74c8b8Pre Distribute196310762022-09-07 6:50:2522 days 5 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0086400526 26.2
0x5ad71563ec16d4b97f3036b7d140cfd8ab3db7916890cc66594234417f4ff41bDistribute193711292022-08-31 19:54:3028 days 16 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0197525206 26.2
0x33584d64f49eaedc6caf76f9fb3ccbbec803e2771138927d453f3572e6575e89Pre Distribute193711252022-08-31 19:54:2228 days 16 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0088601326 26.2
0x7431841b7d62551200555ad3ca3712031e337430eafc8a175050aaff64363e27Vote193690222022-08-31 18:44:0628 days 17 hrs ago0x6fe797a05359c9d91b1f85d418e2ed4ea6c65a8f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.002699502 26.5
0xa0e772dec7fb2202e9fc03a8058377d7a726f3431f379d2957baf00ed868ca78Distribute190178732022-08-23 13:37:3636 days 22 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.020113871 26.2
0x710049bc8e4fb849e5624977aaf333f61693618b989c41303f084d2240cee8baPre Distribute190178482022-08-23 13:36:4636 days 22 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0086400526 26.2
0x520c01fb9fa1be2e56e7f18463c9022cd3bc88f6c740068aae1a3760fc20bf28Distribute187292182022-08-16 18:43:4243 days 17 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0199726006 26.2
0xa71202d8190d286abd3729b8b7b1cd5f197e1d954224bae5503eafcd79b14670Pre Distribute187292122022-08-16 18:43:3043 days 17 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0087867726 26.2
0x898e9b43a590bc007468ab4329db844a4d0ef435700ce015eb4719c698d78986Vote187266392022-08-16 17:15:4243 days 19 hrs ago0x6fe797a05359c9d91b1f85d418e2ed4ea6c65a8f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.001989302 26.5
0xb33a8e5e8ed62add6e0103cd7eeb856392cda513012b0f5b749bb4abcbba80aeDistribute183846962022-08-08 17:54:3251 days 18 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0201193206 26.2
0x872db51fae3f6bbba5e10518b973aa579d3653cb06b57b8a599d8a931c28febePre Distribute183846922022-08-08 17:54:2451 days 18 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0093002926 26.2
0x061f14b7c7d8232d840f51fe47271f2dcda40b68bd26f2f2b9342e604303d0ddVote183262732022-08-07 9:18:2453 days 2 hrs ago0x5da29f0ddf1a7570ddd27dde52d5136dc167ac80 IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0137818815 26.5
0xe7494dd1a92d6e4cde7ca40ee51fadb4c90c312706ba156afd4b5a6d28de1a13Vote182649502022-08-05 22:51:3354 days 13 hrs ago0x6fe797a05359c9d91b1f85d418e2ed4ea6c65a8f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.002699502 26.5
0x924c278dc8b8de717e1000eaa1461a6e3ca7ee57c76bb567e986746fe08530b0Vote181634512022-08-03 13:53:0356 days 22 hrs ago0x6fe797a05359c9d91b1f85d418e2ed4ea6c65a8f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.002699502 26.5
0x79511bd2451cbd9120d792032381707e54c076df6f5f13f88a9441e1f2a4a86fVote180919382022-08-01 21:23:1958 days 14 hrs ago0x0342bf051724c2697362a3b947e170b4bea63299 IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.002699502 26.5
0xd49bedeeb5622a5f6f0d1a7f88255141d5a53e2597bacc675165a87ebc42f45dDistribute180806252022-08-01 14:52:5258 days 21 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0200411922 26.2
0xbf75d3f308e5b47574a2f204d030ec4cb992acc69f71e5f12f0b05180e23f2eePre Distribute180806192022-08-01 14:52:3958 days 21 hrs ago0x096a46142c199c940ffebf34f0fe2f2d674fdb1f IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.0096749526 26.2
0xcff312edcebf03d2c7e10f7097a12b3f52486730f29a6a2e11227cf1bb471ba2Vote180292482022-07-31 9:18:3860 days 2 hrs ago0x0342bf051724c2697362a3b947e170b4bea63299 IN  0x3d09a80369071e6ac91634e0bf889ee54dd510c60 AVAX0.002699502 26.5
[ Download CSV Export 
Latest 9 internal transactions
Parent Txn Hash Block From To Value
0xab163a8c6cc5416960b7743b23a8220501588108c6920ec0f2f159764ef4f6ed173366562022-07-15 0:13:5576 days 12 hrs ago 0x3d09a80369071e6ac91634e0bf889ee54dd510c6  Contract Creation0 AVAX
0x0360108118e5981fcb808cb523ebb7ce1e2cc119307c3cc3aaebe54645831449163789262022-06-22 18:07:0998 days 18 hrs ago 0x3d09a80369071e6ac91634e0bf889ee54dd510c6  Contract Creation0 AVAX
0xde7b6696bcc8875949ca806cfe0ce0c30a48a634496945c44a0afe19739c2cc5163789202022-06-22 18:06:5898 days 18 hrs ago 0x3d09a80369071e6ac91634e0bf889ee54dd510c6  Contract Creation0 AVAX
0x86212c4d4779c5e4b265c28a66d6935833fe35fa55d084782c8eced241bc4954151616622022-05-25 14:35:25126 days 21 hrs ago 0x3d09a80369071e6ac91634e0bf889ee54dd510c6  Contract Creation0 AVAX
0x4244a7f462c5b725cb3b28eb52c5f0c3b263613c9c34f98d2d26b511809fc7e5151616582022-05-25 14:35:17126 days 21 hrs ago 0x3d09a80369071e6ac91634e0bf889ee54dd510c6  Contract Creation0 AVAX
0xec3ad97dd72affdb107f20247f4d7429781e47b6d7d8143ed36090e70f86547a151616432022-05-25 14:34:46126 days 21 hrs ago 0x3d09a80369071e6ac91634e0bf889ee54dd510c6  Contract Creation0 AVAX
0x732811485385ac1f82183ed5a8feeeea64bf0577dd169957aacfc41563a36580151616422022-05-25 14:34:44126 days 21 hrs ago 0x3d09a80369071e6ac91634e0bf889ee54dd510c6  Contract Creation0 AVAX
0x4ad05a7b3ac024de1d05bcb99e8a688110030bf38f1dd108a83753957557da73151616332022-05-25 14:34:26126 days 21 hrs ago 0x3d09a80369071e6ac91634e0bf889ee54dd510c6  Contract Creation0 AVAX
0xd99d157c465c4c5230473c7ae3819775c3015d10ff0bdc9651998eba99d01884150596542022-05-23 5:22:25129 days 6 hrs ago 0x3d09a80369071e6ac91634e0bf889ee54dd510c6  Contract Creation0 AVAX
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GaugeProxy

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at snowtrace.io on 2022-05-23
*/

// Sources flattened with hardhat v2.9.6 https://hardhat.org

// File contracts/libraries/ProtocolGovernance.sol

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

contract ProtocolGovernance {
    /// @notice address of the governance contract
    address public governance;
    address public pendingGovernance;

    /// @notice modifier to allow for easy gov only control over a function
    modifier onlyGovernance() {
        require(msg.sender == governance, "unauthorized sender (governance");
        _;
    }

    /// @notice Allows governance to change governance (for future upgradability)
    /// @param _governance new governance address to set
    function setGovernance(address _governance) external onlyGovernance {
        pendingGovernance = _governance;
    }

    /// @notice Allows pendingGovernance to accept their role as governance (protection pattern)
    function acceptGovernance() external {
        require(
            msg.sender == pendingGovernance,
            "acceptGovernance: !pendingGov"
        );
        governance = pendingGovernance;
    }
}


// File contracts/libraries/Strategist.sol


pragma solidity 0.8.9;

contract Strategist {
    /// @notice strategist address for the strategist contract
    address public strategist;
    address public pendingStrategist;

    /// @notice modifier to allow for easy gov only control over a function
    modifier onlyStrategist() {
        require(msg.sender == strategist, "unauthorized sender (strategist)");
        _;
    }

    /// @notice Allows strategist to change strategist (for future upgradability)
    /// @param _strategist new strategist address to set
    function setStrategist(address _strategist) external onlyStrategist {
        pendingStrategist = _strategist;
    }

    /// @notice Allows pendingStrategist to accept their role as strategist
    function acceptStrategist() external {
        require(
            msg.sender == pendingStrategist,
            "unauthorized sender (pendingStrategist)"
        );
        strategist = pendingStrategist;
    }
}


// File @openzeppelin/contracts/token/ERC20/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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


// File @openzeppelin/contracts/utils/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


// File @openzeppelin/contracts/token/ERC20/utils/[email protected]


// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;


/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}


// File @openzeppelin/contracts/security/[email protected]


// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}


// File @openzeppelin/contracts/utils/[email protected]


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}


// File @openzeppelin/contracts/access/[email protected]


// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}


// File contracts/AccruingStake.sol


pragma solidity 0.8.9;

/// @title A staking contract which accrues over time based on the amount staked
/// @author Auroter
/// @notice Allows you to lock tokens in exchange for distribution tokens
/// @notice Locks can be deposited into or closed
/// @dev Simply call stake(...) to deposit tokens
/// @dev Call getAccrued(user) / getTotalAccrued() = users share
contract AccruingStake is ReentrancyGuard, Ownable {
    using SafeERC20 for IERC20;

    // Info pertaining to staking contract
    address public stakedToken; // An ERC20 Token to be staked (i.e. Axial)
    string public name; // New asset after staking (i.e. veAxial)
    string public symbol; // New asset symbol after staking (i.e. veAXIAL)

    // Info pertaining to users
    uint256 private totalTokensLocked; // Total balance of tokens users have locked
    uint256 private totalTokensAccrued; // Total balance of accrued tokens currently awarded to users
    uint256 private lastUserIndexUpdated; // Index of the user whose accrual was most recently updated
    uint256 private timeStamp; // Last time Total Accrual was updated
    address[] private users; // An array containing all user addresses
    mapping(address => AccrueVe) private locks; // A mapping of each users tokens staked

    struct AccrueVe {
        uint256 accruedTokens; // Quantity of tokens awarded to the user at time of Timestamp
        uint256 stakedTokens; // Quantity of tokens the user has staked
        uint256 timeStamp; // Last time the accrual was updated
        uint256 userIndex; // Index of user, used to manage iteration
        bool initialized; // True if the user is staked
    }

    /// @notice Constructor
    /// @param _stakedToken Address of the token our users will deposit and lock in exchange for governance tokens
    /// @param _name Desired name of our governance token
    /// @param _symbol Desired symbol of our governance token
    /// @param _governance Address of wallet which will be given adminstrative access to this contract
    constructor(
        address _stakedToken,
        string memory _name,
        string memory _symbol,
        address _governance
    ) {
        transferOwnership(_governance);
        stakedToken = _stakedToken;
        name = _name;
        symbol = _symbol;
    }

    /// @notice Emitted when a user creates a new stake
    /// @param user Address of the user who staked
    /// @param amount Quantity of tokens deposited
    event userStaked(address indexed user, uint256 amount);

    /// @notice Emitted when a user adds to their stake
    /// @param user Address of the user who staked
    /// @param amount Quantity of tokens deposited
    event userRestaked(address indexed user, uint256 amount);

    /// @notice Emitted when a user withdraws their funds
    /// @param user Address of the user who withdrew
    /// @param amount Quantity of tokens withdrawn
    /// @param accrued Quantity of accrued tokens lost
    event userWithdrew(address indexed user, uint256 amount, uint256 accrued);

    /// @notice Get the number of tokens a user currently has staked
    /// @param _userAddr Address of any user to view the number of vested tokens they have not yet claimed
    /// @return Quantity of tokens which a user currently has staked
    function getStaked(address _userAddr) public view returns (uint256) {
        return locks[_userAddr].stakedTokens;
    }

    /// @notice Get the total number of tokens a user has accrued
    /// @param _userAddr Address of any user to view the number of vested tokens they have not yet claimed
    /// @return Quantity of tokens which a user has accrued over time
    /// @dev Use this function to get the numerator for a users share of the rewards pool
    function getAccrued(address _userAddr) public view returns (uint256) {
        //return Locks[_userAddr].AccruedTokens;
        return locks[_userAddr].accruedTokens + (locks[_userAddr].stakedTokens * (block.timestamp - locks[_userAddr].timeStamp));
    }

    /// @notice Get the total number of tokens accrued via this contract
    /// @return Quantity of all tokens awarded by this contract
    /// @dev Use this function to get the denominator for a users share of the rewards pool
    function getTotalAccrued() public view returns (uint256) {
        return totalTokensAccrued + (totalTokensLocked * (block.timestamp - timeStamp));
    }

    /// @notice Retrieve a list of all users who have ever staked
    /// @return An array of addresses of all users who have ever staked
    function getAllUsers() public view returns (address[] memory) {
        return users;
    }

    // Accrual is tokens locked * seconds
    /// @notice Update the accrual for a specific user
    /// @param _userAddr address of user to update
    /// @dev This synchronizes a users accrual when their deposit amount changes
    function _updateUsersAccrual(address _userAddr) private {
        AccrueVe storage lock = locks[_userAddr];
        uint256 blockTimestamp = block.timestamp;

        uint256 accrual = (blockTimestamp - lock.timeStamp) * lock.stakedTokens;

        lock.timeStamp = blockTimestamp;
        lock.accruedTokens += accrual;
    }

    /// @notice Update the total accrual for all users
    /// @dev This updates the value used as the denominator for a users accrual share
    /// @dev This must always be called before changing the amount of tokens deposited in this contract
    function _updateTotalAccrual() private {
        uint256 currentTime = block.timestamp;
        uint256 delta = currentTime - timeStamp;
        totalTokensAccrued += totalTokensLocked * delta;
        timeStamp = currentTime;
    }

    /// @notice Allow owner to reclaim tokens not matching the deposit token
    /// @notice Some users may have accidentally sent these to the contract
    /// @param _token Address of the non-deposit token
    /// @dev Always ensure the _token is legitimate before calling this
    /// @dev A bad token can mimic safetransfer or balanceof with a nocive function
    function ownerRemoveNonDepositToken(address _token) public nonReentrant onlyOwner {
        require(_token != stakedToken, "!invalid");
        uint256 balanceOfToken = IERC20(_token).balanceOf(address(this));
        require(balanceOfToken > 0, "!balance");
        IERC20(_token).safeTransfer(owner(), balanceOfToken);
    }

    /// @notice Transfers deposited tokens back to their original owner
    /// @notice This will reset the users accrual!
    /// @dev This could be called by the web application via a button or some other means
    function withdrawMyFunds() external nonReentrant {
        address userAddr = msg.sender;
        uint256 fundsToClaim = locks[userAddr].stakedTokens;

        require(fundsToClaim > 0, "!funds");
        IERC20(stakedToken).safeTransfer(userAddr, fundsToClaim);

        // decrement totals
        _updateTotalAccrual();
        uint256 tokensAccrued = getAccrued(userAddr);
        totalTokensLocked -= fundsToClaim;
        totalTokensAccrued -= tokensAccrued;

        // Broadcast withdrawal
        emit userWithdrew(userAddr, fundsToClaim, locks[userAddr].accruedTokens);

        locks[userAddr].stakedTokens = 0;
        locks[userAddr].accruedTokens = 0;
        locks[userAddr].initialized = false;

        // Fairly efficient way of removing user from list
        uint256 lastUsersIndex = users.length - 1;
        uint256 myIndex = locks[userAddr].userIndex;
        locks[users[lastUsersIndex]].userIndex = myIndex;
        users[myIndex] = users[lastUsersIndex];
        users.pop();
    }

    /// @notice Deposit tokens into the contract, adjusting accrual rate
    /// @param _amount Number of tokens to deposit
    function stake(uint256 _amount) external nonReentrant {
        require(_amount > 0, "!amount");

        address userAddr = msg.sender;

        // Receive the users tokens
        require(IERC20(stakedToken).balanceOf(userAddr) >= _amount, "!balance");
        require(IERC20(stakedToken).allowance(userAddr, address(this)) >= _amount, "!approved");
        IERC20(stakedToken).safeTransferFrom(userAddr, address(this), _amount);

        _updateTotalAccrual();
        totalTokensLocked += _amount;

        // Keep track of new users
        if (!locks[userAddr].initialized) {
            users.push(userAddr);
            locks[userAddr].initialized = true;
            locks[userAddr].timeStamp = block.timestamp; // begin accrual from time of initial deposit
            locks[userAddr].userIndex = users.length - 1;
            emit userStaked(userAddr, _amount);
        } else {
            _updateUsersAccrual(userAddr); // balance ledger before accrual rate is increased
            emit userRestaked(userAddr, _amount);
        }

        // Update balance
        locks[userAddr].stakedTokens += _amount;
    }
}


// File contracts/VestingStake.sol


pragma solidity 0.8.9;

/// @title A vesting style staking contract with extendable linear decay
/// @author Auroter
/// @notice Allows you to lock tokens in exchange for governance tokens
/// @notice Locks can be extended or deposited into
/// @notice Maximum deposit duration is two years (104 weeks)
/// @dev Simply call stake(...) to create initial lock or extend one that already exists for the user
contract VestingStake is ReentrancyGuard, Ownable {
    using SafeERC20 for IERC20;

    // Info pertaining to staking contract
    address public stakedToken; // An ERC20 Token to be staked (i.e. Axial)
    string public name; // New asset after staking (i.e. sAxial)
    string public symbol; // New asset symbol after staking (i.e. sAXIAL)
    uint256 private interpolationGranularity = 1e18; // Note: ERC20.decimals() is for display and does not affect arithmetic!

    // Info pertaining to users
    address[] private users; // An array containing all user addresses
    mapping(address => LockVe) private locks; // A mapping of each users lock
    mapping(address => uint256) private lockedFunds; // A mapping of each users total deposited funds
    mapping(address => uint256) private deferredFunds; // A mapping of vested funds the user wishes to leave unclaimed

    // Lock structure, only one of these is allowed per user
    // A DELTA can be derived as the degree of interpolation between the start/end block:
    // Delta = (end - now) / end - start
    // This can be used to determine how much of our staked token is unlocked:
    // currentAmountLocked = startingAmountLocked - (delta * startingAmountLocked)
    struct LockVe {
        uint256 startBlockTime;
        uint256 endBlockTime;
        uint256 startingAmountLocked;
        bool initialized;
    }

    /// @notice Constructor
    /// @param _stakedToken Address of the token our users will deposit and lock in exchange for governance tokens
    /// @param _name Desired name of our governance token
    /// @param _symbol Desired symbol of our governance token
    /// @param _governance Address of wallet which will be given adminstrative access to this contract
    constructor(
        address _stakedToken,
        string memory _name,
        string memory _symbol,
        address _governance
    ) {
        transferOwnership(_governance);
        stakedToken = _stakedToken;
        name = _name;
        symbol = _symbol;
    }

    /// @notice Emitted when a user stakes for the first time
    /// @param user Address of the user who staked
    /// @param amount Quantity of tokens staked
    /// @param duration Length in seconds of stake
    event userStaked(address indexed user, uint256 amount, uint256 duration);

    /// @notice Emitted when a user extends and/or deposits into their existing stake
    /// @param user Address of the user who staked
    /// @param amount New total quantity of tokens in stake
    /// @param duration New total length of stake
    event userExtended(address indexed user, uint256 amount, uint256 duration);

    /// @notice Emitted when a user claims outstanding vested balance
    /// @param user Address of the user who claimed
    /// @param amount Quantity of tokens claimed
    event userClaimed(address indexed user, uint256 amount);

    /// @notice Calculate the number of vested tokens a user has not claimed
    /// @param _userAddr Address of any user to view the number of vested tokens they have not yet claimed
    /// @return Quantity of tokens which have vested but are unclaimed by the specified user
    function getUnclaimed(address _userAddr) public view returns (uint256) {
        uint256 totalFundsDeposited = lockedFunds[_userAddr] + deferredFunds[_userAddr];
        uint256 currentBalance = getBalance(_userAddr);
        uint256 fundsToClaim = totalFundsDeposited - currentBalance;
        return fundsToClaim;
    }

    /// @notice Calculate the number of tokens a user still has locked
    /// @param _userAddr Address of any user to view the number of tokens they still have locked
    /// @return Quantity of tokens the user has locked
    function getBalance(address _userAddr) public view returns (uint256) {
        LockVe memory usersLock = locks[_userAddr];

        uint256 currentTimestamp = block.timestamp;
        uint256 balance = 0;

        if (usersLock.endBlockTime > currentTimestamp) {
            uint256 granularDelta = ((usersLock.endBlockTime - currentTimestamp) * interpolationGranularity) / (usersLock.endBlockTime - usersLock.startBlockTime);
            balance += (usersLock.startingAmountLocked * granularDelta) / interpolationGranularity;
        }
        return balance;
    }

    /// @notice This is an overload for getPower so that users can see the 'token' in their wallets
    function balanceOf(address _account) external view returns (uint256) {
        return getPower(_account);
    }

    /// @notice Calculate the number of governance tokens currently allocated to a user by this contract
    /// @param _userAddr Address of any user to view the number of governance tokens currently awarded to them
    /// @return Quantity of governance tokens allocated to the user
    function getPower(address _userAddr) public view returns (uint256) {
        LockVe memory usersLock = locks[_userAddr];

        uint256 currentTimestamp = block.timestamp;
        uint256 power = 0;

        if (usersLock.endBlockTime > currentTimestamp) {
            // let delta = elapsed / totalLocktinme
            // let startingPower = duration / 2 years
            // let power = delta * startingPower
            uint256 startingAmountAwarded = ((usersLock.endBlockTime - usersLock.startBlockTime) * usersLock.startingAmountLocked) / 104 weeks;
            uint256 granularDelta = ((usersLock.endBlockTime - currentTimestamp) * interpolationGranularity) / (usersLock.endBlockTime - usersLock.startBlockTime);
            power += (startingAmountAwarded * granularDelta) / interpolationGranularity;
        }
        return power;
    }

    /// @notice Retrieve a list of all users who have ever staked
    /// @return An array of addresses of all users who have ever staked
    function getAllUsers() public view returns (address[] memory) {
        return users;
    }

    /// @notice Check if a user has ever created a Lock in this contract
    /// @param _userAddr Address of any user to check
    /// @dev This may be used by the web application to determine if the UI says "Create Lock" or "Add to Lock"
    /// @return True if the user has ever created a lock
    function isUserLocked(address _userAddr) public view returns (bool) {
        LockVe memory usersLock = locks[_userAddr];
        return usersLock.initialized;
    }

    /// @notice View a users Lock
    /// @param _userAddr Address of any user to view all Locks they have ever created
    /// @dev This may be used by the web application for graphical illustration purposes
    /// @return Users Lock in the format of the LockVe struct
    function getLock(address _userAddr) public view returns (LockVe memory) {
        return locks[_userAddr];
    }

    /// @notice Allow owner to reclaim tokens not matching the deposit token
    /// @notice Some users may have accidentally sent these to the contract
    /// @param _token Address of the non-deposit token
    /// @dev Always ensure the _token is legitimate before calling this
    /// @dev A bad token can mimic safetransfer or balanceof with a nocive function
    function ownerRemoveNonDepositToken(address _token) public nonReentrant onlyOwner {
        require(_token != stakedToken, "!invalid");
        uint256 balanceOfToken = IERC20(_token).balanceOf(address(this));
        require(balanceOfToken > 0, "!balance");
        IERC20(_token).safeTransfer(owner(), balanceOfToken);
    }

    /// @notice Transfers vested tokens back to their original owner
    /// @notice It is up to the user to invoke this manually
    /// @dev This will need to be called by the web application via a button or some other means
    function claimMyFunds() external nonReentrant {
        address userAddr = msg.sender;
        uint256 totalFundsDeposited = lockedFunds[userAddr] + deferredFunds[userAddr];
        uint256 currentBalance = getBalance(userAddr);
        uint256 fundsToClaim = totalFundsDeposited - currentBalance;

        IERC20(stakedToken).safeTransfer(userAddr, fundsToClaim);

        lockedFunds[userAddr] = currentBalance;
        deferredFunds[userAddr] = 0;

        emit userClaimed(userAddr, fundsToClaim);
    }

    /// @notice Create/extend the duration of the invoking users lock and/or deposit additional tokens into it
    /// @param _duration Number of seconds the invoking user will extend their lock for
    /// @param _amount Number of additional tokens to deposit into the lock
    /// @param _deferUnclaimed If True, leaves any unclaimed vested balance in the staking contract
    function stake(uint256 _duration, uint256 _amount, bool _deferUnclaimed) public nonReentrant {
        require(_duration > 0 || _amount > 0, "null");

        // Retrieve lock the user may have already created
        address userAddr = msg.sender;
        LockVe memory usersLock = locks[userAddr];

        uint256 oldDurationRemaining = 0;

        // Keep track of new user or pre-existing lockout period
        if (!usersLock.initialized) {
            users.push(userAddr);
        } else if (block.timestamp < usersLock.endBlockTime) {
            oldDurationRemaining = usersLock.endBlockTime - block.timestamp;
        }

        require (oldDurationRemaining + _duration <= 104 weeks, ">2 years");

        // Receive the users tokens
        require(IERC20(stakedToken).balanceOf(userAddr) >= _amount, "!balance");
        require(IERC20(stakedToken).allowance(userAddr, address(this)) >= _amount, "!approved");
        IERC20(stakedToken).safeTransferFrom(userAddr,  address(this), _amount);

        // Account for balance / unclaimed funds
        uint256 totalFundsDeposited = lockedFunds[userAddr];
        uint256 oldBalance = getBalance(userAddr);
        uint256 fundsUnclaimed = totalFundsDeposited - oldBalance;
        if (!_deferUnclaimed) {
            fundsUnclaimed += deferredFunds[userAddr];
            IERC20(stakedToken).safeTransfer(userAddr, fundsUnclaimed);
            deferredFunds[userAddr] = 0;
            emit userClaimed(userAddr, fundsUnclaimed);
        } else {
            deferredFunds[userAddr] += fundsUnclaimed;
        }
        uint256 newTotalDeposit = oldBalance + _amount;

        // Update balance
        lockedFunds[userAddr] = newTotalDeposit;

        // Fill out updated LockVe struct
        LockVe memory newLock;
        newLock.startBlockTime = block.timestamp;
        newLock.endBlockTime = newLock.startBlockTime + _duration + oldDurationRemaining;
        newLock.startingAmountLocked = newTotalDeposit;
        newLock.initialized = true;
        locks[userAddr] = newLock;

        // Events
        if (oldDurationRemaining == 0) {
            emit userStaked(userAddr, newTotalDeposit, newLock.endBlockTime - newLock.startBlockTime);
        } else {
            emit userExtended(userAddr, newTotalDeposit, newLock.endBlockTime - newLock.startBlockTime);
        }
    }
}


// File contracts/interfaces/IMasterChef.sol

pragma solidity 0.8.9;
/// @title Master Chef V2(MCAV2) interface
/// @notice Interface for the MCAV2 contract that will control minting of AXIAL
interface IMasterChef {
    struct UserInfo {
        uint256 amount; // How many LP tokens the user has provided.
        uint256 rewardDebt; // Reward debt. See explanation below.
    }

    struct PoolInfo {
        IERC20 lpToken; // Address of LP token contract.
        uint256 allocPoint; // How many allocation points assigned to this pool. AXIALs to distribute per second.
        uint256 lastRewardTimestamp; // Last timestamp that AXIALs distribution occurs.
        uint256 accAxialPerShare; // Accumulated AXIALs per share, times 1e12. See below.
    }

    function poolInfo(uint256 pid) external view returns (IMasterChef.PoolInfo memory);

    function totalAllocPoint() external view returns (uint256);

    function axialPerSec() external view returns (uint256);

    function deposit(uint256 _pid, uint256 _amount) external;

    function devPercent() external view returns (uint256);

    function treasuryPercent() external view returns (uint256);

    function investorPercent() external view returns (uint256);

    function userInfo(uint256 pid, address addr) external view returns (uint256, uint256);

    function withdraw(uint256 pid, uint256 amount) external;
}


// File @openzeppelin/contracts/utils/math/[email protected]


// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}


// File @openzeppelin/contracts/token/ERC20/extensions/[email protected]


// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

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


// File @openzeppelin/contracts/token/ERC20/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;



/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, _allowances[owner][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = _allowances[owner][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
        }
        _balances[to] += amount;

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Spend `amount` form the allowance of `owner` toward `spender`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}


// File contracts/AxialDummyToken.sol

pragma solidity 0.8.9;
contract AxialDummyToken is ERC20("AxialDummyToken", "AXD") {
    using SafeMath for uint256;

    constructor() {
        _mint(msg.sender, 1e18);
    }
}


// File @openzeppelin/contracts/utils/math/[email protected]


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

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @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 / b + (a % b == 0 ? 0 : 1);
    }
}


// File contracts/Gauge.sol

pragma solidity 0.8.9;
contract Gauge is ProtocolGovernance, ReentrancyGuard {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    // ==================== External Dependencies ==================== //

    /// Token to allow boosting partner token rewards - VEAXIAL
    AccruingStake public immutable VEAXIAL;

    /// Token to be staked in return for primary rewards
    IERC20 public immutable poolToken;

    // ==================== Events ==================== //

    /// @notice emitted when a user stakes
    /// @param user The address of the user who staked
    /// @param amount the quantity of tokens the user staked
    event Staked(address indexed user, uint256 amount);

    /// @notice emitted when a user withdraws
    /// @param user The address of the user who withdrew
    /// @param amount The quantity of tokens the user withdrew
    event Withdrawn(address indexed user, uint256 amount);

    /// @notice emitted when a reward is claimed by a user
    /// @param user The address of the user who claimed the reward
    /// @param reward The quantity of tokens the user claimed
    /// @param token The address of the token the user claimed
    event RewardPaid(address indexed user, uint256 reward, address token);

    /// @notice emitted when the primary reward or partner rewards are added to the gauge
    /// @param reward the quantity of tokens added
    /// @param token the address of the reward token
    event RewardAdded(uint256 reward, address token);

    // ==================== State Variables ==================== //

    /// tokens to be distributed as a reward to stakers, 0 is primary reward and 1-... are partner rewards
    address[] public rewardTokens;

    /// contract responsible for distributing primary rewards (should be Gauge Proxy)
    address public gaugeProxy;

    /// Distribution interval for primary reward token
    uint256 public constant PRIMARY_REWARD_DURATION = 7 days;
    mapping(address => uint256) partnerRewardDurations;

    /// Used to keep track of reward token intervals
    // token => time
    mapping (address => uint256) public periodFinish;
    mapping (address => uint256) public lastUpdateTime;

    /// Rewards per second for each reward token
    mapping (address => uint256) public rewardRates;

    // token => amount
    mapping (address => uint256) public rewardPerTokenStored;

    /// @dev user => reward token => amount
    mapping(address => mapping (address => uint256)) public userRewardPerTokenPaid;

    /// @dev user => reward token => amount
    mapping(address => mapping (address => uint256)) public rewards;

    /// total supply of the primary reward token and partner reward tokens
    uint256 private _totalLPTokenSupply;

    uint256 totalBoost; // The sum of all users boost factors!

    /// user => LP token balance
    mapping(address => uint256) private _lpTokenBalances;

    /// user => boost factor
    mapping(address => uint256) public boostFactors;

    /// PARTNER STUFF:

    /// partner reward token => partner, used to determine permission for setting reward rates
    mapping(address => address) public tokenPartners;

    // ==================== Modifiers ==================== //

    // Affects all rewards
    modifier updateRewards(address account) {
        for (uint256 i = 0; i < rewardTokens.length; ++i) { // For each reward token
            address token = rewardTokens[i];
            rewardPerTokenStored[token] = rewardPerToken(token); // Update total rewards available for token
            lastUpdateTime[token] = lastTimeRewardApplicable(token);
            if (account != address(0)) {
                rewards[account][token] = earned(account, token); // Update users allocation out of total rewards for token
                userRewardPerTokenPaid[account][token] = rewardPerTokenStored[token]; // Keep track of what we have allocated so far for the user
            }
        }
        _; // execute function this modifier is attached to
        if (account != address(0)) {
            updateTotalBoostFactor(account); // update the total boost factor based on the users current status
        }
    }

    // Affects only one reward
    modifier updateReward(address account, uint256 tokenIndex) {
        require(tokenIndex < rewardTokens.length, "Invalid token index");
        address token = rewardTokens[tokenIndex];
        rewardPerTokenStored[token] = rewardPerToken(token);
        lastUpdateTime[token] = lastTimeRewardApplicable(token);
        if (account != address(0)) {
            rewards[account][token] = earned(account, token);
            userRewardPerTokenPaid[account][token] = rewardPerTokenStored[token];
        }
        _;
        if (account != address(0)) {
            updateTotalBoostFactor(account);
        }
    }

    modifier onlyDistribution() {
        require(msg.sender == gaugeProxy, "Gauge: not distribution contract");
        _;
    }

    modifier validAddress(address _rewardToken) {
        require(Address.isContract(_rewardToken), "Gauge: not a contract");
        _;
    }

    constructor(
        address _poolToken,
        address _owner,
        address _veAxial,
        address _primaryRewardToken
    ) {
        poolToken = IERC20(_poolToken);
        governance = _owner;
        VEAXIAL = AccruingStake(_veAxial);
        rewardTokens.push(_primaryRewardToken);
        gaugeProxy = msg.sender;
    }

    // ==================== Reward Token Logic ==================== //

    /// @notice adding a reward token to our array
    /// @param tokenAddress Reward token to be added to our rewardTokens array
    /// @param partnerAddress Address of partner who has permission to set the token reward rate
    function addRewardToken(address tokenAddress, address partnerAddress)
        public
        onlyGovernance
        validAddress(tokenAddress)
    {
        require(tokenPartners[tokenAddress] == address(0), "Token already in use");
        tokenPartners[tokenAddress] = partnerAddress; // certify partner with the authority to provide rewards for the token
        rewardTokens.push(tokenAddress); // add token to our list of reward token addresses
    }

    /// @notice returns the amount of reward tokens for the gauge
    function getNumRewardTokens() public view returns (uint256) {
        return rewardTokens.length;
    }

    function partnerDepositRewardTokens(address tokenAddress, uint256 amount, uint256 rewardPerSec) external updateRewards(address(0)) {
        require(tokenPartners[tokenAddress] == msg.sender, "You do not have the right.");
        require (rewardPerSec != 0, "Cannot set reward rate to 0");
        IERC20(tokenAddress).safeTransferFrom(msg.sender, address(this), amount);

        // Get balance in case there was some pending balance
        uint256 balance = IERC20(tokenAddress).balanceOf(address(this));

        uint duration = balance / rewardPerSec;

        lastUpdateTime[tokenAddress] = block.timestamp;
        periodFinish[tokenAddress] = block.timestamp.add(duration);
        rewardRates[tokenAddress] = rewardPerSec; // Just set the reward rate even if there is still pending balance
        emit RewardAdded(amount, tokenAddress);
    }

    /// @notice return how many of our reward tokens is the user receiving per lp token at the current point in time
    /// @dev (e.g. how many teddy or axial is received per AC4D token)
    function rewardPerToken(address token) public view returns (uint256) {
        if (_totalLPTokenSupply == 0 || totalBoost == 0) {
            return rewardPerTokenStored[token];
        }
        // x = rPTS + (lTRA - lUT) * rR * 1e18 / tB
        return rewardPerTokenStored[token] + 
        ((lastTimeRewardApplicable(token) - lastUpdateTime[token]) * rewardRates[token] * 1e18 /
        totalBoost);
    }

    /// @notice getting the reward to be received for primary tokens respective staking period
    function getRewardForDuration() external view returns (uint256)
    {
        address token = rewardTokens[0];
        return rewardRates[token].mul(PRIMARY_REWARD_DURATION);
    }

    /// @notice gets the amount of reward tokens that the user has earned
    function earned(address account, address token)
        public
        view
        returns (uint256)
    {
        // x = (bF * ( rPT - uRPTP ) / 1e18 ) + r
        return (boostFactors[account] * (rewardPerToken(token) - userRewardPerTokenPaid[account][token]) / 1e18) + rewards[account][token];
    }

    /// @notice This function is to allow us to update the gaugeProxy without resetting the old gauges.
    /// @dev this changes where it is receiving the axial tokens, as well as changes the governance
    function changeDistribution(address _distribution) external onlyGovernance {
        gaugeProxy = _distribution;
    }

    /// @notice total supply of our lp tokens in the gauge (e.g. AC4D tokens present)
    function totalSupply() external view returns (uint256) {
        return _totalLPTokenSupply;
    }

    /// @notice balance of lp tokens that user has in the gauge (e.g. amount of AC4D a user has)
    function balanceOf(address account) external view returns (uint256) {
        return _lpTokenBalances[account];
    }

    function lastTimeRewardApplicable(address token) public view returns (uint256) {
        return Math.min(block.timestamp, periodFinish[token]);
    }

    // returns the users share of the total LP supply * 1e18
    function userShare(address account) external view returns (uint256) {
        if (_totalLPTokenSupply == 0) return 0;
        return _lpTokenBalances[account] * 1e18 / _totalLPTokenSupply;
    }

    /// @notice returns boost factor for specified account
    function boostFactor(address account) public view returns (uint256) {
        uint256 _userBalanceInGauge = _lpTokenBalances[account];

        // Save some gas if this function is entered early
        if (_userBalanceInGauge == 0) {
            return 0;
        }

        // user / total = share
        uint256 usersVeAxialBalance = VEAXIAL.getAccrued(account);
        uint256 totalVeAxial = VEAXIAL.getTotalAccrued();

        // Don't divide by zero!
        uint256 denominator = _totalLPTokenSupply + totalVeAxial;
        if (denominator == 0) return 0;

        // Add users veAxial share to pool share ratio
        // If numerator and denominator are multiplicative, users will be punished for their relative veAxial balance
        uint256 numerator = (_lpTokenBalances[account] + usersVeAxialBalance) * 1e18;
        return numerator / denominator;
    }

    function updateTotalBoostFactor(address account) public {
        totalBoost -= boostFactors[account]; // Subtract users boost factor from total
        boostFactors[account] = boostFactor(account); // Update users boost factor
        totalBoost += boostFactors[account]; // Add new boost factor to total
    }

    /// @notice internal deposit function
    function _deposit(uint256 amount, address account)
        internal
        nonReentrant
        updateRewards(account)
    {
        require(amount > 0, "Cannot stake 0");
        poolToken.safeTransferFrom(account, address(this), amount);
        _totalLPTokenSupply = _totalLPTokenSupply.add(amount);
        _lpTokenBalances[account] = _lpTokenBalances[account].add(amount);
        emit Staked(account, amount);
    }

    /// @notice deposits all pool tokens to the gauge
    function depositAll() external {
        _deposit(poolToken.balanceOf(msg.sender), msg.sender);
    }

    /// @notice deposits specified amount of tokens into the gauge from msg.sender
    function deposit(uint256 amount) external {
        _deposit(amount, msg.sender);
    }

    /// @notice deposit specified amount of tokens into the gauge on behalf of specified account
    /// @param amount amount of tokens to be deposited
    /// @param account account to deposit from
    function depositFor(uint256 amount, address account) external {
        require(account != address(this), "!account"); // prevent inflation
        _deposit(amount, account);
    }

    /// @notice internal withdraw function
    function _withdraw(uint256 amount)
        internal
        nonReentrant
        updateRewards(msg.sender)
    {
        poolToken.safeTransfer(msg.sender, amount);
        require(amount > 0, "Cannot withdraw 0");
        _totalLPTokenSupply = _totalLPTokenSupply.sub(amount);
        _lpTokenBalances[msg.sender] = _lpTokenBalances[msg.sender].sub(amount);
        emit Withdrawn(msg.sender, amount);
    }

    /// @notice withdraws all pool tokens from the gauge
    function withdrawAll() external {
        _withdraw(_lpTokenBalances[msg.sender]);
    }

    /// @notice withdraw specified amount of primary pool tokens from the message senders balance
    function withdraw(uint256 amount) external {
        _withdraw(amount);
    }

    /// @notice get reward tokens from gauge
    function getReward(uint256 tokenIndex)
        public
        nonReentrant
        updateReward(msg.sender, tokenIndex)
    {
        address token = rewardTokens[tokenIndex];
        require(token != address(0), "Reward token does not exist");
        uint256 reward = rewards[msg.sender][token];
        if (reward > 0) {
            IERC20(token).safeTransfer(msg.sender, reward);
            rewards[msg.sender][token] = 0;
            emit RewardPaid(msg.sender, reward, token);
        }
    }

    /// @notice claims specific reward indices
    function getRewards(uint256[] calldata tokenIndices) public {
        for (uint256 i = 0; i < tokenIndices.length; ++i) {
            getReward(tokenIndices[i]);
        }
    }

    // /// @notice claims all rewards
    function getAllRewards() public {
        for (uint256 i = 0; i < rewardTokens.length; ++i) {
            getReward(i);
        }
    }

    /// @notice withdraw deposited pool tokens and claim reward tokens
    function exit() external {
        _withdraw(_lpTokenBalances[msg.sender]);
        getAllRewards();
    }

    /// @notice only called by the GaugeProxy and so only deals in the native token
    function notifyRewardAmount(uint256 reward)
        external
        onlyDistribution
        updateRewards(address(0))
    {
        address token = rewardTokens[0];
        IERC20(token).safeTransferFrom(
            gaugeProxy,
            address(this),
            reward
        );
        rewardRates[token] = reward.div(PRIMARY_REWARD_DURATION);

        // Ensure the provided reward amount is not more than the balance in the contract.
        // This keeps the reward rate in the right range, preventing overflows due to
        // very high values of rewardRate in the earned and rewardsPerToken functions;
        // Reward + leftover must be less than 2^256 / 10^18 to avoid overflow.
        uint256 balance = IERC20(token).balanceOf(address(this));
        require(
            rewardRates[token] <= balance.div(PRIMARY_REWARD_DURATION),
            "Provided reward too high"
        );

        lastUpdateTime[token] = block.timestamp;
        periodFinish[token] = block.timestamp.add(PRIMARY_REWARD_DURATION);
        emit RewardAdded(reward, token);
    }
}


// File contracts/GaugeProxy.sol

pragma solidity 0.8.9;
contract GaugeProxy is ProtocolGovernance {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    // ==================== External Dependencies ==================== //

    /// @notice Master Chef Axial V2 contract
    IMasterChef public MCAV2;

    /// @notice token for voting on Axial distribution to pools - SAXIAL
    VestingStake public immutable sAxial;

    /// @notice the Axial token contraxt
    IERC20 public immutable Axial;

    /// @notice dummy token required for masterchef deposits and withdrawals
    IERC20 public immutable axialDummyToken;

    /// @notice token to allow boosting rewards - VEAXIAL
    /// @dev This could be an address instead, as we do not use it other than passing the address to the Gauge constructor
    AccruingStake public immutable veAxial;

    // ==================== Token Voting Storage ==================== //

    /// @notice max time allowed to pass before distribution (6 hours)
    uint256 public constant DISTRIBUTION_DEADLINE = 21600;

    uint256 public pid = 0;
    uint256 public totalWeight;
    uint256 private lockedTotalWeight;
    uint256 private lockedBalance;
    uint256 private locktime;

    address[] internal _tokens;

    /// @dev token -> gauge
    mapping(address => address) public gauges;
    /// @dev token => gauge
    mapping(address => address) public deprecated;
    /// @dev token => weight
    mapping(address => uint256) public weights;
    /// @dev token => weight
    mapping(address => uint256) private lockedWeights;
    /// @dev msg.sender => token => votes
    mapping(address => mapping(address => uint256)) public votes;
    /// @dev msg.sender => token
    mapping(address => address[]) public tokenVote;
    /// @dev msg.sender => total voting weight of user
    mapping(address => uint256) public usedWeights;
    mapping(address => bool) public deployers;

    constructor(
        address _governance,
        address _axial,
        address _saxial,
        address _veaxial
    ) {
        governance = _governance;
        Axial = IERC20(_axial);
        sAxial = VestingStake(_saxial);
        veAxial = AccruingStake(_veaxial);
        axialDummyToken = new AxialDummyToken();
    }

    // ==================== Admin functions ==================== //

    /// @notice adds the specified address to the list of deployers
    /// @dev deployers can call distribute function
    function addDeployer(address _deployer) external onlyGovernance {
        deployers[_deployer] = true;
    }

    /// @notice removes the specified address from the list of deployers
    function removeDeployer(address _deployer) external onlyGovernance {
        deployers[_deployer] = false;
    }

    // ==================== Modifiers ==================== //

    /// @notice modifier to restrict functinos to governance or strategist roles
    modifier onlyBenevolent() {
        require(msg.sender == governance, "unauthorized sender");
        _;
    }

    // ==================== View functions ==================== //

    /// @notice returns the list of tokens that are currently being voted on
    function tokens() external view returns (address[] memory) {
        return _tokens;
    }

    /// @notice returns the gauge for the specifi(AccruingStake)
    function getGauge(address _token) external view returns (address) {
        return gauges[_token];
    }

    /// @notice returns the number of tokens currently being voted on
    function length() external view returns (uint256) {
        return _tokens.length;
    }

    // ==================== Voting Logic ==================== //

    /// @notice Vote with SAXIAL on a gauge, removing any previous votes
    /// @param _tokenVote: the array of tokens which will recieve tokens
    /// @param _weights: the weights to associate with the tokens listed in _tokenVote
    function vote(address[] calldata _tokenVote, uint256[] calldata _weights)
        external
    {
        require(
            _tokenVote.length == _weights.length,
            "weight/tokenvote length mismatch"
        );
        _vote(msg.sender, _tokenVote, _weights);
    }

    /// @notice internal voting function
    function _vote(
        address _owner,
        address[] memory _tokenVote,
        uint256[] memory _weights
    ) internal {
        // reset votes of the owner
        _reset(_owner);
        uint256 _tokenCnt = _tokenVote.length;
        uint256 _weight = sAxial.getPower(_owner);
        uint256 _totalVoteWeight = 0;
        uint256 _usedWeight = 0;

        for (uint256 i = 0; i < _tokenCnt; i++) {
            _totalVoteWeight = _totalVoteWeight.add(_weights[i]);
        }

        for (uint256 i = 0; i < _tokenCnt; i++) {
            address _token = _tokenVote[i];
            address _gauge = gauges[_token];
            // Calculate quantity of users SAXIAL to allocate for the gauge
            uint256 _tokenWeight = _weights[i].mul(_weight).div(
                _totalVoteWeight
            );

            if (_gauge != address(0x0)) {
                _usedWeight = _usedWeight.add(_tokenWeight);
                totalWeight = totalWeight.add(_tokenWeight);
                weights[_token] = weights[_token].add(_tokenWeight);
                tokenVote[_owner].push(_token);
                votes[_owner][_token] = _tokenWeight;
            }
        }
        usedWeights[_owner] = _usedWeight;
    }

    /// @notice Reset votes of msg.sender to 0
    function reset() external {
        _reset(msg.sender);
    }

    /// @notice Internal function to reset votes of the specified address to 0
    /// @param _owner address of owner of votes to be reset
    function _reset(address _owner) internal {
        // Get all tokens that the owner has voted on
        address[] storage _tokenVote = tokenVote[_owner];
        uint256 _tokenVoteCnt = _tokenVote.length;

        for (uint256 i = 0; i < _tokenVoteCnt; i++) {
            address _token = _tokenVote[i];
            // Get the amount of SAXIAL this user allocated for this specific token
            uint256 _votes = votes[_owner][_token];

            if (_votes > 0) {
                totalWeight = totalWeight.sub(_votes);
                weights[_token] = weights[_token].sub(_votes);

                votes[_owner][_token] = 0;
            }
        }

        delete tokenVote[_owner];
    }

    /// @notice Adjust _owner's votes according to latest _owner's SAXIAL balance
    function poke(address _owner) public {
        address[] memory _tokenVote = tokenVote[_owner];
        uint256 _tokenCnt = _tokenVote.length;
        uint256[] memory _weights = new uint256[](_tokenCnt);

        for (uint256 i = 0; i < _tokenCnt; i++) {
            _weights[i] = votes[_owner][_tokenVote[i]];
        }

        // _weights no longer total 100 like with the front-end
        // But we will minimize gas by not converting
        _vote(_owner, _tokenVote, _weights);
    }

    // ==================== Gauge Logic ==================== //

    /// @notice Add new token gauge
    function addGauge(address _token) external onlyBenevolent {
        require(gauges[_token] == address(0x0), "exists");
        gauges[_token] = address(
            new Gauge(_token, governance, address(veAxial), address(Axial))
        );
        _tokens.push(_token);
    }

    /// @notice Deprecate existing gauge
    function deprecateGauge(address _token) external onlyBenevolent {
        require(gauges[_token] != address(0x0), "does not exist");
        deprecated[_token] = gauges[_token];
        delete gauges[_token];
    }

    /// @notice Bring Deprecated gauge back into use
    function renewGauge(address _token) external onlyBenevolent {
        require(gauges[_token] == address(0x0), "exists");
        require(deprecated[_token] != address(0x0), "not deprecated");
        gauges[_token] = deprecated[_token];
        delete deprecated[_token];
    }

    /// @notice Add existing gauge
    function migrateGauge(address _gauge, address _token)
        external
        onlyBenevolent
    {
        require(gauges[_token] == address(0x0), "exists");
        gauges[_token] = _gauge;
        _tokens.push(_token);
    }

    // ==================== MCAV2 Logic ==================== //

    /// @notice Sets new MCAV2 address.  Useful for debugging.
    function setMasterChef(address _masterChef) external onlyGovernance {
        //MCAV2 = IMasterChefAxialV3(_masterChef);
        MCAV2 = IMasterChef(_masterChef);
        pid = 0;
        //pid = UINT256_MAX;
    }

    /// @notice Sets MCAV2 PID
    function setPID(uint256 _pid) external onlyGovernance {
        //require(pid == UINT256_MAX, "pid has already been set");
        // require(_pid < UINT256_MAX, "invalid pid");
        require(pid == 0, "pid has already been set");
        require(_pid != 0, "invalid pid");
        pid = _pid;
    }

    /// @notice Deposits Axial dummy token into MCAV2
    function depositDummyToken() public {
        require(pid != 0, "pid not initialized");
        uint256 _balance = axialDummyToken.balanceOf(address(this));
        axialDummyToken.safeApprove(address(MCAV2), 0);
        axialDummyToken.safeApprove(address(MCAV2), _balance);
        MCAV2.deposit(pid, _balance);
    }

    /// @notice Collects AXIAL from MCAV2 for distribution
    function collect() public {
        (uint256 _locked, ) = MCAV2.userInfo(pid, address(this));
        MCAV2.withdraw(pid, _locked);
        depositDummyToken();
    }

    // ==================== Distribution Logic ==================== //

    /// @notice collect AXIAL and update lock information
    function preDistribute() external {
        require(
            deployers[msg.sender] || msg.sender == governance,
            "unauthorized sender"
        );
        lockedTotalWeight = totalWeight;
        for (uint256 i = 0; i < _tokens.length; i++) {
            lockedWeights[_tokens[i]] = weights[_tokens[i]];
        }
        collect();
        lockedBalance = Axial.balanceOf(address(this));
        locktime = block.timestamp;
    }

    /// @notice Distribute tokens to gauges
    function distribute(uint256 _start, uint256 _end) external {
        require(
            deployers[msg.sender] || msg.sender == governance,
            "unauthorized sender"
        );
        require(_start < _end, "bad _start");
        require(_end <= _tokens.length, "bad _end");
        require(
            locktime + DISTRIBUTION_DEADLINE >= block.timestamp,
            "lock expired"
        );
        if (lockedBalance > 0 && lockedTotalWeight > 0) {
            for (uint256 i = _start; i < _end; i++) {
                address _token = _tokens[i];
                address _gauge = gauges[_token];
                uint256 _reward = lockedBalance.mul(lockedWeights[_token]).div(
                    totalWeight
                );
                if (_reward > 0) {
                    Axial.safeApprove(_gauge, 0);
                    Axial.safeApprove(_gauge, _reward);
                    Gauge(_gauge).notifyRewardAmount(_reward);
                }
            }
        }
    }
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_axial","type":"address"},{"internalType":"address","name":"_saxial","type":"address"},{"internalType":"address","name":"_veaxial","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Axial","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISTRIBUTION_DEADLINE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MCAV2","outputs":[{"internalType":"contract IMasterChef","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_deployer","type":"address"}],"name":"addDeployer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"addGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"axialDummyToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collect","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deployers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositDummyToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"deprecateGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deprecated","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gauges","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"length","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"migrateGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pendingGovernance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"poke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"preDistribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_deployer","type":"address"}],"name":"removeDeployer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"renewGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sAxial","outputs":[{"internalType":"contract VestingStake","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_governance","type":"address"}],"name":"setGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_masterChef","type":"address"}],"name":"setMasterChef","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"setPID","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenVote","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"usedWeights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"veAxial","outputs":[{"internalType":"contract AccruingStake","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokenVote","type":"address[]"},{"internalType":"uint256[]","name":"_weights","type":"uint256[]"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"votes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"weights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

61010060405260006003553480156200001757600080fd5b50604051620053a4380380620053a48339810160408190526200003a91620000d9565b600080546001600160a01b0319166001600160a01b038681169190911790915583811660a052828116608052811660e0526040516200007990620000ae565b604051809103906000f08015801562000096573d6000803e3d6000fd5b506001600160a01b031660c052506200013692505050565b610b77806200482d83390190565b80516001600160a01b0381168114620000d457600080fd5b919050565b60008060008060808587031215620000f057600080fd5b620000fb85620000bc565b93506200010b60208601620000bc565b92506200011b60408601620000bc565b91506200012b60608601620000bc565b905092959194509250565b60805160a05160c05160e05161467e620001af600039600081816106100152610f6301526000818161058801528181611163015281816111fe015261123b01526000818161029501528181610a0b01528181610a4201528181610ce20152610f850152600081816105140152611716015261467e6000f3fe60806040523480156200001157600080fd5b5060043610620002545760003560e01c8063a7cac8461162000149578063d826f88f11620000c7578063f2a1a8ed1162000086578063f2a1a8ed14620005b4578063f315df8614620005cb578063f39c38a014620005e2578063f40485a214620005f6578063fcd5189b146200060a57600080fd5b8063d826f88f1462000564578063e07a3c98146200056e578063e52253811462000578578063ed4355b81462000582578063f106845414620005aa57600080fd5b8063b1c6f0e91162000114578063b1c6f0e9146200049c578063b9a09fd514620004cb578063bdcf150814620004f7578063ca3e3c03146200050e578063cad1b906146200053657600080fd5b8063a7cac8461462000441578063ab033ea91462000464578063ae495365146200047b578063b1a997ac146200048557600080fd5b80637625391a11620001d75780638d06051911620001a25780638d06051914620003d957806396c82e5714620003f05780639d63848a14620003fa5780639da882ac1462000413578063a2d9f4dc146200042a57600080fd5b80637625391a146200038a5780637b66665314620003a15780638283639114620003b8578063880f403914620003c257600080fd5b8063266f803a1162000224578063266f803a14620002e55780635aa6e67514620003115780636848c2bd14620003255780636a2385e8146200033c5780636f816a20146200037357600080fd5b80622f8de4146200025957806303e9f23b146200028f5780631f7b6d3214620002d0578063238efcbc14620002d9575b600080fd5b6200027c6200026a36600462001eea565b600f6020526000908152604090205481565b6040519081526020015b60405180910390f35b620002b77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200162000286565b6008546200027c565b620002e362000632565b005b620002b7620002f636600462001eea565b600a602052600090815260409020546001600160a01b031681565b600054620002b7906001600160a01b031681565b620002e36200033636600462001eea565b620006b6565b620003626200034d36600462001eea565b60106020526000908152604090205460ff1681565b604051901515815260200162000286565b620002e36200038436600462001f57565b62000783565b620002e36200039b36600462001fca565b6200084a565b620002e3620003b236600462001fed565b62000ae6565b620002e362000bb9565b620002e3620003d336600462001eea565b62000d71565b620002e3620003ea36600462002025565b62000dc2565b6200027c60045481565b6200040462000e83565b6040516200028691906200203f565b620002e36200042436600462001eea565b62000ee7565b620002e36200043b36600462001eea565b62001061565b6200027c6200045236600462001eea565b600b6020526000908152604090205481565b620002e36200047536600462001eea565b620010b5565b620002e362001104565b620002e36200049636600462001eea565b620012d9565b620002b7620004ad36600462001eea565b6001600160a01b039081166000908152600960205260409020541690565b620002b7620004dc36600462001eea565b6009602052600090815260409020546001600160a01b031681565b620002e36200050836600462001eea565b62001447565b620002b77f000000000000000000000000000000000000000000000000000000000000000081565b6200027c6200054736600462001fed565b600d60209081526000928352604080842090915290825290205481565b620002e36200154f565b6200027c61546081565b620002e36200155c565b620002b77f000000000000000000000000000000000000000000000000000000000000000081565b6200027c60035481565b620002b7620005c53660046200208e565b62001660565b620002e3620005dc36600462001eea565b62001699565b600154620002b7906001600160a01b031681565b600254620002b7906001600160a01b031681565b620002b77f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b03163314620006925760405162461bcd60e51b815260206004820152601d60248201527f616363657074476f7665726e616e63653a202170656e64696e67476f7600000060448201526064015b60405180910390fd5b600154600080546001600160a01b0319166001600160a01b03909216919091179055565b6000546001600160a01b03163314620006e35760405162461bcd60e51b81526004016200068990620020bb565b6001600160a01b03818116600090815260096020526040902054166200073d5760405162461bcd60e51b815260206004820152600e60248201526d191bd95cc81b9bdd08195e1a5cdd60921b604482015260640162000689565b6001600160a01b0390811660009081526009602081815260408084208054600a8452919094208054919095166001600160a01b0319918216179094555280549091169055565b828114620007d45760405162461bcd60e51b815260206004820181905260248201527f7765696768742f746f6b656e766f7465206c656e677468206d69736d61746368604482015260640162000689565b620008443385858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250620016e792505050565b50505050565b3360009081526010602052604090205460ff16806200087357506000546001600160a01b031633145b620008925760405162461bcd60e51b81526004016200068990620020bb565b808210620008d05760405162461bcd60e51b815260206004820152600a6024820152691898590817dcdd185c9d60b21b604482015260640162000689565b6008548111156200090f5760405162461bcd60e51b81526020600482015260086024820152671898590817d95b9960c21b604482015260640162000689565b42615460600754620009229190620020fe565b1015620009615760405162461bcd60e51b815260206004820152600c60248201526b1b1bd8dac8195e1c1a5c995960a21b604482015260640162000689565b60006006541180156200097657506000600554115b1562000ae257815b8181101562000ae0576000600882815481106200099f576200099f62002119565b60009182526020808320909101546001600160a01b0390811680845260098352604080852054600454600c9095529085205460065492965092169392620009f4929091620009ed9162001970565b9062001985565b9050801562000ac75762000a346001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683600062001993565b62000a6a6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016838362001993565b604051633c6b16ab60e01b8152600481018290526001600160a01b03831690633c6b16ab90602401600060405180830381600087803b15801562000aad57600080fd5b505af115801562000ac2573d6000803e3d6000fd5b505050505b505050808062000ad7906200212f565b9150506200097e565b505b5050565b6000546001600160a01b0316331462000b135760405162461bcd60e51b81526004016200068990620020bb565b6001600160a01b03818116600090815260096020526040902054161562000b4e5760405162461bcd60e51b815260040162000689906200214d565b6001600160a01b0390811660008181526009602052604081208054939094166001600160a01b0319938416179093556008805460018101825593527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee390920180549091169091179055565b3360009081526010602052604090205460ff168062000be257506000546001600160a01b031633145b62000c015760405162461bcd60e51b81526004016200068990620020bb565b60045460055560005b60085481101562000cc257600b60006008838154811062000c2f5762000c2f62002119565b9060005260206000200160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002054600c60006008848154811062000c885762000c8862002119565b60009182526020808320909101546001600160a01b031683528201929092526040019020558062000cb9816200212f565b91505062000c0a565b5062000ccd6200155c565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801562000d2d57600080fd5b505afa15801562000d42573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000d6891906200216d565b60065542600755565b6000546001600160a01b0316331462000d9e5760405162461bcd60e51b8152600401620006899062002187565b6001600160a01b03166000908152601060205260409020805460ff19166001179055565b6000546001600160a01b0316331462000def5760405162461bcd60e51b8152600401620006899062002187565b6003541562000e415760405162461bcd60e51b815260206004820152601860248201527f7069642068617320616c7265616479206265656e207365740000000000000000604482015260640162000689565b8062000e7e5760405162461bcd60e51b815260206004820152600b60248201526a1a5b9d985b1a59081c1a5960aa1b604482015260640162000689565b600355565b6060600880548060200260200160405190810160405280929190818152602001828054801562000edd57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162000ebe575b5050505050905090565b6000546001600160a01b0316331462000f145760405162461bcd60e51b81526004016200068990620020bb565b6001600160a01b03818116600090815260096020526040902054161562000f4f5760405162461bcd60e51b815260040162000689906200214d565b60005460405182916001600160a01b0316907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009062000fb09062001e8a565b6001600160a01b039485168152928416602084015290831660408301529091166060820152608001604051809103906000f08015801562000ff5573d6000803e3d6000fd5b506001600160a01b0391821660008181526009602052604081208054939094166001600160a01b0319938416179093556008805460018101825593527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee390920180549091169091179055565b6000546001600160a01b031633146200108e5760405162461bcd60e51b8152600401620006899062002187565b600280546001600160a01b0319166001600160a01b03929092169190911790556000600355565b6000546001600160a01b03163314620010e25760405162461bcd60e51b8152600401620006899062002187565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6003546200114b5760405162461bcd60e51b81526020600482015260136024820152721c1a59081b9bdd081a5b9a5d1a585b1a5e9959606a1b604482015260640162000689565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b158015620011ae57600080fd5b505afa158015620011c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011e991906200216d565b60025490915062001229906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169116600062001993565b60025462001265906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691168362001993565b600254600354604051631c57762b60e31b81526001600160a01b039092169163e2bbb15891620012a2918590600401918252602082015260400190565b600060405180830381600087803b158015620012bd57600080fd5b505af1158015620012d2573d6000803e3d6000fd5b5050505050565b6001600160a01b0381166000908152600e60209081526040808320805482518185028101850190935280835291929091908301828280156200134557602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162001326575b5050505050905060008151905060008167ffffffffffffffff811115620013705762001370620021be565b6040519080825280602002602001820160405280156200139a578160200160208202803683370190505b50905060005b8281101562001439576001600160a01b0385166000908152600d602052604081208551909190869084908110620013db57620013db62002119565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205482828151811062001419576200141962002119565b60209081029190910101528062001430816200212f565b915050620013a0565b5062000844848483620016e7565b6000546001600160a01b03163314620014745760405162461bcd60e51b81526004016200068990620020bb565b6001600160a01b038181166000908152600960205260409020541615620014af5760405162461bcd60e51b815260040162000689906200214d565b6001600160a01b038181166000908152600a602052604090205416620015095760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd0819195c1c9958d85d195960921b604482015260640162000689565b6001600160a01b039081166000908152600a60208181526040808420805460098452919094208054919095166001600160a01b0319918216179094555280549091169055565b6200155a3362001ae2565b565b6002546003546040516393f1a40b60e01b815260048101919091523060248201526000916001600160a01b0316906393f1a40b90604401604080518083038186803b158015620015ab57600080fd5b505afa158015620015c0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015e69190620021d4565b50600254600354604051630441a3e760e41b81526004810191909152602481018390529192506001600160a01b03169063441a3e7090604401600060405180830381600087803b1580156200163a57600080fd5b505af11580156200164f573d6000803e3d6000fd5b505050506200165d62001104565b50565b600e60205281600052604060002081815481106200167d57600080fd5b6000918252602090912001546001600160a01b03169150829050565b6000546001600160a01b03163314620016c65760405162461bcd60e51b8152600401620006899062002187565b6001600160a01b03166000908152601060205260409020805460ff19169055565b620016f28362001ae2565b8151604051631776451f60e21b81526001600160a01b0385811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690635dd9147c9060240160206040518083038186803b1580156200175b57600080fd5b505afa15801562001770573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200179691906200216d565b905060008060005b84811015620017ef57620017d8868281518110620017c057620017c062002119565b60200260200101518462001c0390919063ffffffff16565b925080620017e6816200212f565b9150506200179e565b5060005b848110156200194b57600087828151811062001813576200181362002119565b6020908102919091018101516001600160a01b038082166000908152600990935260408320548a519294501691906200187b908790620009ed908a908d908990811062001864576200186462002119565b60200260200101516200197090919063ffffffff16565b90506001600160a01b03821615620019325762001899858262001c03565b600454909550620018ab908262001c03565b6004556001600160a01b0383166000908152600b6020526040902054620018d3908262001c03565b6001600160a01b038085166000818152600b6020908152604080832095909555928f16808252600e845284822080546001810182559083528483200180546001600160a01b031916841790558152600d83528381209181529152208190555b505050808062001942906200212f565b915050620017f3565b506001600160a01b039096166000908152600f60205260409020959095555050505050565b60006200197e8284620021f9565b9392505050565b60006200197e82846200221b565b80158062001a215750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015620019e457600080fd5b505afa158015620019f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001a1f91906200216d565b155b62001a8e5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840162000689565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905262000ae090849062001c11565b6001600160a01b0381166000908152600e60205260408120805490915b8181101562001bdf57600083828154811062001b1f5762001b1f62002119565b60009182526020808320909101546001600160a01b038881168452600d8352604080852091909216808552925290912054909150801562001bc75760045462001b69908262001cea565b6004556001600160a01b0382166000908152600b602052604090205462001b91908262001cea565b6001600160a01b038084166000818152600b6020908152604080832095909555928a168152600d83528381209181529152908120555b5050808062001bd6906200212f565b91505062001aff565b506001600160a01b0383166000908152600e6020526040812062000ae09162001e98565b60006200197e8284620020fe565b600062001c68826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662001cf89092919063ffffffff16565b80519091501562000ae0578080602001905181019062001c8991906200223e565b62000ae05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000689565b60006200197e828462002262565b606062001d09848460008562001d11565b949350505050565b60608247101562001d745760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000689565b6001600160a01b0385163b62001dcd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000689565b600080866001600160a01b0316858760405162001deb9190620022ab565b60006040518083038185875af1925050503d806000811462001e2a576040519150601f19603f3d011682016040523d82523d6000602084013e62001e2f565b606091505b509150915062001e4182828662001e4c565b979650505050505050565b6060831562001e5d5750816200197e565b82511562001e6e5782518084602001fd5b8160405162461bcd60e51b8152600401620006899190620022c9565b61234a80620022ff83390190565b50805460008255906000526020600020908101906200165d91905b8082111562001ec9576000815560010162001eb3565b5090565b80356001600160a01b038116811462001ee557600080fd5b919050565b60006020828403121562001efd57600080fd5b6200197e8262001ecd565b60008083601f84011262001f1b57600080fd5b50813567ffffffffffffffff81111562001f3457600080fd5b6020830191508360208260051b850101111562001f5057600080fd5b9250929050565b6000806000806040858703121562001f6e57600080fd5b843567ffffffffffffffff8082111562001f8757600080fd5b62001f958883890162001f08565b9096509450602087013591508082111562001faf57600080fd5b5062001fbe8782880162001f08565b95989497509550505050565b6000806040838503121562001fde57600080fd5b50508035926020909101359150565b600080604083850312156200200157600080fd5b6200200c8362001ecd565b91506200201c6020840162001ecd565b90509250929050565b6000602082840312156200203857600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015620020825783516001600160a01b0316835292840192918401916001016200205b565b50909695505050505050565b60008060408385031215620020a257600080fd5b620020ad8362001ecd565b946020939093013593505050565b6020808252601390820152723ab730baba3437b934bd32b21039b2b73232b960691b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008219821115620021145762002114620020e8565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620021465762002146620020e8565b5060010190565b60208082526006908201526565786973747360d01b604082015260600190565b6000602082840312156200218057600080fd5b5051919050565b6020808252601f908201527f756e617574686f72697a65642073656e6465722028676f7665726e616e636500604082015260600190565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215620021e857600080fd5b505080516020909101519092909150565b6000816000190483118215151615620022165762002216620020e8565b500290565b6000826200223957634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156200225157600080fd5b815180151581146200197e57600080fd5b600082821015620022775762002277620020e8565b500390565b60005b83811015620022995781810151838201526020016200227f565b83811115620008445750506000910152565b60008251620022bf8184602087016200227c565b9190910192915050565b6020815260008251806020840152620022ea8160408501602087016200227c565b601f01601f1916919091016040019291505056fe60c06040523480156200001157600080fd5b506040516200234a3803806200234a8339810160408190526200003491620000d0565b600160028190556001600160a01b0394851660a052600080549486166001600160a01b03199586161781559285166080526003805491820181559092527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9091018054919093169082161790915560048054909116331790556200012d565b80516001600160a01b0381168114620000cb57600080fd5b919050565b60008060008060808587031215620000e757600080fd5b620000f285620000b3565b93506200010260208601620000b3565b92506200011260408601620000b3565b91506200012260608601620000b3565b905092959194509250565b60805160a0516121d4620001766000396000818161051201528181611552015281816118850152611aec01526000818161045f015281816113ac015261142e01526121d46000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c806370fbc10a1161013b578063ca1c9b75116100b8578063e70b9e271161007c578063e70b9e2714610566578063e9fad8ee14610591578063f122977714610599578063f39c38a0146105ac578063f4901772146105bf57600080fd5b8063ca1c9b75146104fa578063cbdf382c1461050d578063da09d19d14610534578063de5f626814610554578063e35c1e271461055c57600080fd5b80639ce43f90116100ff5780639ce43f9014610481578063a500fa4b146104a1578063ab033ea9146104c1578063b67c6024146104d4578063b6b55f25146104e757600080fd5b806370fbc10a14610419578063789ef0e01461042c5780637bb7bed11461043f578063853828b6146104525780638ebdcfc61461045a57600080fd5b80633c6b16ab116101c95780635aa6e6751161018d5780635aa6e6751461038c57806362b009d91461039f578063638634ee146103b25780637035ab98146103c557806370a08231146103f057600080fd5b80633c6b16ab146103365780633c6f778c146103495780633d3b2603146103515780633d5ba7c61461037157806345b35f561461038457600080fd5b806323cb23901161021057806323cb23901461029c5780632ce9aead146102af5780632e1a7d4d146102cf578063348701dc146102e257806336efd16f1461032357600080fd5b806318160ddd1461024d5780631c1f78eb146102645780631c4b774b1461026c578063211dc32d14610281578063238efcbc14610294575b600080fd5b600c545b6040519081526020015b60405180910390f35b6102516105d2565b61027f61027a366004611e75565b610624565b005b61025161028f366004611eaa565b6108aa565b61027f610942565b61027f6102aa366004611eaa565b6109c0565b6102516102bd366004611edd565b60076020526000908152604090205481565b61027f6102dd366004611e75565b610b03565b61030b6102f0366004611edd565b6010602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161025b565b61027f610331366004611ef8565b610b0f565b61027f610344366004611e75565b610b61565b600354610251565b61025161035f366004611edd565b60086020526000908152604090205481565b61027f61037f366004611edd565b610e8c565b61027f610efc565b60005461030b906001600160a01b031681565b61027f6103ad366004611edd565b610f22565b6102516103c0366004611edd565b610f6e565b6102516103d3366004611eaa565b600a60209081526000928352604080842090915290825290205481565b6102516103fe366004611edd565b6001600160a01b03166000908152600e602052604090205490565b61027f610427366004611f1b565b610f98565b61025161043a366004611edd565b611285565b61030b61044d366004611e75565b6112d2565b61027f6112fc565b61030b7f000000000000000000000000000000000000000000000000000000000000000081565b61025161048f366004611edd565b60096020526000908152604090205481565b6102516104af366004611edd565b600f6020526000908152604090205481565b61027f6104cf366004611edd565b611317565b6102516104e2366004611edd565b611363565b61027f6104f5366004611e75565b61152f565b60045461030b906001600160a01b031681565b61030b7f000000000000000000000000000000000000000000000000000000000000000081565b610251610542366004611edd565b60066020526000908152604090205481565b61027f611539565b61025162093a8081565b610251610574366004611eaa565b600b60209081526000928352604080842090915290825290205481565b61027f6115da565b6102516105a7366004611edd565b6115fb565b60015461030b906001600160a01b031681565b61027f6105cd366004611f4e565b6116b3565b60008060036000815481106105e9576105e9611fc3565b60009182526020808320909101546001600160a01b0316808352600890915260409091205490915061061e9062093a806116f4565b91505090565b60028054141561064f5760405162461bcd60e51b815260040161064690611fd9565b60405180910390fd5b6002805560035433908290811061069e5760405162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e8ded6cadc40d2dcc8caf606b1b6044820152606401610646565b6000600382815481106106b3576106b3611fc3565b6000918252602090912001546001600160a01b031690506106d3816115fb565b6001600160a01b0382166000908152600960205260409020556106f581610f6e565b6001600160a01b0380831660009081526007602052604090209190915583161561076d5761072383826108aa565b6001600160a01b038085166000818152600b60209081526040808320948716808452948252808320959095556009815284822054928252600a815284822093825292909252919020555b60006003858154811061078257610782611fc3565b6000918252602090912001546001600160a01b03169050806107e65760405162461bcd60e51b815260206004820152601b60248201527f52657761726420746f6b656e20646f6573206e6f7420657869737400000000006044820152606401610646565b336000908152600b602090815260408083206001600160a01b03851684529091529020548015610885576108246001600160a01b0383163383611700565b336000818152600b602090815260408083206001600160a01b038716808552908352818420939093558051858152918201929092527f8e0d3fa908fd7ee819155b3ce71e292b601bbeb0cd00d7758b9d226a523cb827910160405180910390a25b50506001600160a01b0383161561089f5761089f83610e8c565b505060016002555050565b6001600160a01b038083166000818152600b6020908152604080832094861680845294825280832054938352600a825280832094835293905291822054670de0b6b3a7640000906108fa856115fb565b6109049190612026565b6001600160a01b0386166000908152600f6020526040902054610927919061203d565b610931919061205c565b61093b919061207e565b9392505050565b6001546001600160a01b0316331461099c5760405162461bcd60e51b815260206004820152601d60248201527f616363657074476f7665726e616e63653a202170656e64696e67476f760000006044820152606401610646565b600154600080546001600160a01b0319166001600160a01b03909216919091179055565b6000546001600160a01b031633146109ea5760405162461bcd60e51b815260040161064690612096565b816001600160a01b0381163b610a3a5760405162461bcd60e51b815260206004820152601560248201527411d85d59d94e881b9bdd08184818dbdb9d1c9858dd605a1b6044820152606401610646565b6001600160a01b038381166000908152601060205260409020541615610a995760405162461bcd60e51b8152602060048201526014602482015273546f6b656e20616c726561647920696e2075736560601b6044820152606401610646565b506001600160a01b0391821660008181526010602052604081208054949093166001600160a01b0319948516179092556003805460018101825592527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9091018054909216179055565b610b0c81611763565b50565b6001600160a01b038116301415610b535760405162461bcd60e51b8152602060048201526008602482015267085858d8dbdd5b9d60c21b6044820152606401610646565b610b5d8282611989565b5050565b6004546001600160a01b03163314610bbb5760405162461bcd60e51b815260206004820181905260248201527f47617567653a206e6f7420646973747269627574696f6e20636f6e74726163746044820152606401610646565b6000805b600354811015610ca957600060038281548110610bde57610bde611fc3565b6000918252602090912001546001600160a01b03169050610bfe816115fb565b6001600160a01b038216600090815260096020526040902055610c2081610f6e565b6001600160a01b03808316600090815260076020526040902091909155831615610c9857610c4e83826108aa565b6001600160a01b038085166000818152600b60209081526040808320948716808452948252808320959095556009815284822054928252600a815284822093825292909252919020555b50610ca2816120cd565b9050610bbf565b5060006003600081548110610cc057610cc0611fc3565b6000918252602090912001546004546001600160a01b039182169250610cea918391163086611bc0565b610cf78362093a80611bf8565b6001600160a01b0382166000818152600860205260408082209390935591516370a0823160e01b81523060048201526370a082319060240160206040518083038186803b158015610d4757600080fd5b505afa158015610d5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7f91906120e8565b9050610d8e8162093a80611bf8565b6001600160a01b0383166000908152600860205260409020541115610df55760405162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f206869676800000000000000006044820152606401610646565b6001600160a01b03821660009081526007602052604090204290819055610e1f9062093a80611c04565b6001600160a01b038316600081815260066020908152604091829020939093558051878152928301919091527ffb5edb6eb340a01f6a67189edc978df97841c43752c212fc85995ea230017635910160405180910390a150506001600160a01b03811615610b5d57610b5d815b6001600160a01b0381166000908152600f6020526040812054600d805491929091610eb8908490612026565b90915550610ec7905081611363565b6001600160a01b0382166000908152600f60205260408120829055600d8054909190610ef490849061207e565b909155505050565b60005b600354811015610b0c57610f1281610624565b610f1b816120cd565b9050610eff565b6000546001600160a01b03163314610f4c5760405162461bcd60e51b815260040161064690612096565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038116600090815260066020526040812054610f92904290611c10565b92915050565b6000805b60035481101561108657600060038281548110610fbb57610fbb611fc3565b6000918252602090912001546001600160a01b03169050610fdb816115fb565b6001600160a01b038216600090815260096020526040902055610ffd81610f6e565b6001600160a01b038083166000908152600760205260409020919091558316156110755761102b83826108aa565b6001600160a01b038085166000818152600b60209081526040808320948716808452948252808320959095556009815284822054928252600a815284822093825292909252919020555b5061107f816120cd565b9050610f9c565b506001600160a01b038481166000908152601060205260409020541633146110f05760405162461bcd60e51b815260206004820152601a60248201527f596f7520646f206e6f742068617665207468652072696768742e0000000000006044820152606401610646565b8161113d5760405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f742073657420726577617264207261746520746f203000000000006044820152606401610646565b6111526001600160a01b038516333086611bc0565b6040516370a0823160e01b81523060048201526000906001600160a01b038616906370a082319060240160206040518083038186803b15801561119457600080fd5b505afa1580156111a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111cc91906120e8565b905060006111da848361205c565b6001600160a01b038716600090815260076020526040902042908190559091506112049082611c04565b6001600160a01b03871660008181526006602090815260408083209490945560088152908390208790558251888152908101919091527ffb5edb6eb340a01f6a67189edc978df97841c43752c212fc85995ea230017635910160405180910390a150506001600160a01b0381161561127f5761127f81610e8c565b50505050565b6000600c546000141561129a57506000919050565b600c546001600160a01b0383166000908152600e60205260409020546112c890670de0b6b3a764000061203d565b610f92919061205c565b600381815481106112e257600080fd5b6000918252602090912001546001600160a01b0316905081565b336000908152600e602052604090205461131590611763565b565b6000546001600160a01b031633146113415760405162461bcd60e51b815260040161064690612096565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166000908152600e60205260408120548061138a5750600092915050565b604051639869e13760e01b81526001600160a01b0384811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690639869e1379060240160206040518083038186803b1580156113f057600080fd5b505afa158015611404573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142891906120e8565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7812b7f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561148557600080fd5b505afa158015611499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114bd91906120e8565b9050600081600c546114cf919061207e565b9050806114e25750600095945050505050565b6001600160a01b0386166000908152600e602052604081205461150690859061207e565b61151890670de0b6b3a764000061203d565b9050611524828261205c565b979650505050505050565b610b0c8133611989565b6040516370a0823160e01b8152336004820152611315907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561159c57600080fd5b505afa1580156115b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d491906120e8565b33611989565b336000908152600e60205260409020546115f390611763565b611315610efc565b6000600c546000148061160e5750600d54155b1561162f57506001600160a01b031660009081526009602052604090205490565b600d546001600160a01b03831660009081526008602090815260408083205460079092529091205461166085610f6e565b61166a9190612026565b611674919061203d565b61168690670de0b6b3a764000061203d565b611690919061205c565b6001600160a01b038316600090815260096020526040902054610f92919061207e565b60005b818110156116ef576116df8383838181106116d3576116d3611fc3565b90506020020135610624565b6116e8816120cd565b90506116b6565b505050565b600061093b828461203d565b6040516001600160a01b0383166024820152604481018290526116ef90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c26565b6002805414156117855760405162461bcd60e51b815260040161064690611fd9565b600280553360005b600354811015611877576000600382815481106117ac576117ac611fc3565b6000918252602090912001546001600160a01b031690506117cc816115fb565b6001600160a01b0382166000908152600960205260409020556117ee81610f6e565b6001600160a01b038083166000908152600760205260409020919091558316156118665761181c83826108aa565b6001600160a01b038085166000818152600b60209081526040808320948716808452948252808320959095556009815284822054928252600a815284822093825292909252919020555b50611870816120cd565b905061178d565b506118ac6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163384611700565b600082116118f05760405162461bcd60e51b8152602060048201526011602482015270043616e6e6f74207769746864726177203607c1b6044820152606401610646565b600c546118fd9083611cf8565b600c55336000908152600e602052604090205461191a9083611cf8565b336000818152600e6020526040908190209290925590517f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5906119609085815260200190565b60405180910390a26001600160a01b038116156119805761198081610e8c565b50506001600255565b6002805414156119ab5760405162461bcd60e51b815260040161064690611fd9565b600280558060005b600354811015611a9d576000600382815481106119d2576119d2611fc3565b6000918252602090912001546001600160a01b031690506119f2816115fb565b6001600160a01b038216600090815260096020526040902055611a1481610f6e565b6001600160a01b03808316600090815260076020526040902091909155831615611a8c57611a4283826108aa565b6001600160a01b038085166000818152600b60209081526040808320948716808452948252808320959095556009815284822054928252600a815284822093825292909252919020555b50611a96816120cd565b90506119b3565b5060008311611adf5760405162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b6044820152606401610646565b611b146001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016833086611bc0565b600c54611b219084611c04565b600c556001600160a01b0382166000908152600e6020526040902054611b479084611c04565b6001600160a01b0383166000818152600e6020526040908190209290925590517f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d90611b969086815260200190565b60405180910390a26001600160a01b03811615611bb657611bb681610e8c565b5050600160025550565b6040516001600160a01b038085166024830152831660448201526064810182905261127f9085906323b872dd60e01b9060840161172c565b600061093b828461205c565b600061093b828461207e565b6000818310611c1f578161093b565b5090919050565b6000611c7b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611d049092919063ffffffff16565b8051909150156116ef5780806020019051810190611c999190612101565b6116ef5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610646565b600061093b8284612026565b6060611d138484600085611d1b565b949350505050565b606082471015611d7c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610646565b6001600160a01b0385163b611dd35760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610646565b600080866001600160a01b03168587604051611def919061214f565b60006040518083038185875af1925050503d8060008114611e2c576040519150601f19603f3d011682016040523d82523d6000602084013e611e31565b606091505b509150915061152482828660608315611e4b57508161093b565b825115611e5b5782518084602001fd5b8160405162461bcd60e51b8152600401610646919061216b565b600060208284031215611e8757600080fd5b5035919050565b80356001600160a01b0381168114611ea557600080fd5b919050565b60008060408385031215611ebd57600080fd5b611ec683611e8e565b9150611ed460208401611e8e565b90509250929050565b600060208284031215611eef57600080fd5b61093b82611e8e565b60008060408385031215611f0b57600080fd5b82359150611ed460208401611e8e565b600080600060608486031215611f3057600080fd5b611f3984611e8e565b95602085013595506040909401359392505050565b60008060208385031215611f6157600080fd5b823567ffffffffffffffff80821115611f7957600080fd5b818501915085601f830112611f8d57600080fd5b813581811115611f9c57600080fd5b8660208260051b8501011115611fb157600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052603260045260246000fd5b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008282101561203857612038612010565b500390565b600081600019048311821515161561205757612057612010565b500290565b60008261207957634e487b7160e01b600052601260045260246000fd5b500490565b6000821982111561209157612091612010565b500190565b6020808252601f908201527f756e617574686f72697a65642073656e6465722028676f7665726e616e636500604082015260600190565b60006000198214156120e1576120e1612010565b5060010190565b6000602082840312156120fa57600080fd5b5051919050565b60006020828403121561211357600080fd5b8151801515811461093b57600080fd5b60005b8381101561213e578181015183820152602001612126565b8381111561127f5750506000910152565b60008251612161818460208701612123565b9190910192915050565b602081526000825180602084015261218a816040850160208701612123565b601f01601f1916919091016040019291505056fea26469706673582212203059959448c651613588d1add1c6332e4d36adca126c9c049063a5d16117f2af64736f6c63430008090033a2646970667358221220c8562d175adeb730a281afd9128b83b86c38026884dd91a0228281f2c154209b64736f6c6343000809003360806040523480156200001157600080fd5b506040518060400160405280600f81526020016e20bc34b0b6223ab6b6bcaa37b5b2b760891b8152506040518060400160405280600381526020016210561160ea1b81525081600390805190602001906200006e9291906200018f565b508051620000849060049060208401906200018f565b505050620000a133670de0b6b3a7640000620000a760201b60201c565b62000299565b6001600160a01b038216620001025760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b806002600082825462000116919062000235565b90915550506001600160a01b038216600090815260208190526040812080548392906200014590849062000235565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b8280546200019d906200025c565b90600052602060002090601f016020900481019282620001c157600085556200020c565b82601f10620001dc57805160ff19168380011785556200020c565b828001600101855582156200020c579182015b828111156200020c578251825591602001919060010190620001ef565b506200021a9291506200021e565b5090565b5b808211156200021a57600081556001016200021f565b600082198211156200025757634e487b7160e01b600052601160045260246000fd5b500190565b600181811c908216806200027157607f821691505b602082108114156200029357634e487b7160e01b600052602260045260246000fd5b50919050565b6108ce80620002a96000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461012357806370a082311461013657806395d89b411461015f578063a457c2d714610167578063a9059cbb1461017a578063dd62ed3e1461018d57600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610101578063313ce56714610114575b600080fd5b6100b66101c6565b6040516100c3919061070b565b60405180910390f35b6100df6100da36600461077c565b610258565b60405190151581526020016100c3565b6002545b6040519081526020016100c3565b6100df61010f3660046107a6565b610270565b604051601281526020016100c3565b6100df61013136600461077c565b610294565b6100f36101443660046107e2565b6001600160a01b031660009081526020819052604090205490565b6100b66102d3565b6100df61017536600461077c565b6102e2565b6100df61018836600461077c565b610379565b6100f361019b366004610804565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600380546101d590610837565b80601f016020809104026020016040519081016040528092919081815260200182805461020190610837565b801561024e5780601f106102235761010080835404028352916020019161024e565b820191906000526020600020905b81548152906001019060200180831161023157829003601f168201915b5050505050905090565b600033610266818585610387565b5060019392505050565b60003361027e8582856104ab565b61028985858561053d565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061026690829086906102ce908790610872565b610387565b6060600480546101d590610837565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091908381101561036c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102898286868403610387565b60003361026681858561053d565b6001600160a01b0383166103e95760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610363565b6001600160a01b03821661044a5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610363565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610537578181101561052a5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610363565b6105378484848403610387565b50505050565b6001600160a01b0383166105a15760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610363565b6001600160a01b0382166106035760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610363565b6001600160a01b0383166000908152602081905260409020548181101561067b5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610363565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906106b2908490610872565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516106fe91815260200190565b60405180910390a3610537565b600060208083528351808285015260005b818110156107385785810183015185820160400152820161071c565b8181111561074a576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b038116811461077757600080fd5b919050565b6000806040838503121561078f57600080fd5b61079883610760565b946020939093013593505050565b6000806000606084860312156107bb57600080fd5b6107c484610760565b92506107d260208501610760565b9150604084013590509250925092565b6000602082840312156107f457600080fd5b6107fd82610760565b9392505050565b6000806040838503121561081757600080fd5b61082083610760565b915061082e60208401610760565b90509250929050565b600181811c9082168061084b57607f821691505b6020821081141561086c57634e487b7160e01b600052602260045260246000fd5b50919050565b6000821982111561089357634e487b7160e01b600052601160045260246000fd5b50019056fea264697066735822122038eba5f99e5e6b1a7e5dd4cf59cd61df98570c7f1e5bf74ab77d59f0cb64106464736f6c634300080900330000000000000000000000004980ad7ccb304f7d3c5053aa1131ed1edaf48809000000000000000000000000cf8419a615c57511807236751c0af38db4ba3351000000000000000000000000ed7f93c8fd3b96b53c924f601b3948175d2820d80000000000000000000000003f563f7efc6dc55adfc1b64bc6bd4bc5f394c4b2

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

0000000000000000000000004980AD7cCB304f7d3c5053Aa1131eD1EDaf48809000000000000000000000000cF8419A615c57511807236751c0AF38Db4ba3351000000000000000000000000ed7f93C8FD3B96B53c924F601B3948175D2820D80000000000000000000000003f563F7efc6dC55adFc1B64BC6Bd4bC5F394c4b2

-----Decoded View---------------
Arg [0] : _governance (address): 0x4980ad7ccb304f7d3c5053aa1131ed1edaf48809
Arg [1] : _axial (address): 0xcf8419a615c57511807236751c0af38db4ba3351
Arg [2] : _saxial (address): 0xed7f93c8fd3b96b53c924f601b3948175d2820d8
Arg [3] : _veaxial (address): 0x3f563f7efc6dc55adfc1b64bc6bd4bc5f394c4b2

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000004980AD7cCB304f7d3c5053Aa1131eD1EDaf48809
Arg [1] : 000000000000000000000000cF8419A615c57511807236751c0AF38Db4ba3351
Arg [2] : 000000000000000000000000ed7f93C8FD3B96B53c924F601B3948175D2820D8
Arg [3] : 0000000000000000000000003f563F7efc6dC55adFc1B64BC6Bd4bC5F394c4b2


Deployed ByteCode Sourcemap

83714:11398:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85535:46;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;529:25:1;;;517:2;502:18;85535:46:0;;;;;;;;84149:29;;;;;;;;-1:-1:-1;;;;;743:32:1;;;725:51;;713:2;698:18;84149:29:0;565:217:1;87258:90:0;87326:7;:14;87258:90;;912:207;;;:::i;:::-;;85065:45;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;85065:45:0;;;264:25;;;;;-1:-1:-1;;;;;264:25:0;;;91270:218;;;;;;:::i;:::-;;:::i;85588:41::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1160:14:1;;1153:22;1135:41;;1123:2;1108:18;85588:41:0;995:187:1;87660:284:0;;;;;;:::i;:::-;;:::i;94091:1018::-;;;;;;:::i;:::-;;:::i;91876:234::-;;;;;;:::i;:::-;;:::i;93582:456::-;;;:::i;86177:110::-;;;;;;:::i;:::-;;:::i;92508:307::-;;;;;;:::i;:::-;;:::i;84782:26::-;;;;;;86907:92;;;:::i;:::-;;;;;;;:::i;90939:281::-;;;;;;:::i;:::-;;:::i;92249:219::-;;;;;;:::i;:::-;;:::i;85147:42::-;;;;;;:::i;:::-;;;;;;;;;;;;;;688:118;;;;;;:::i;:::-;;:::i;92878:325::-;;;:::i;90324:503::-;;;;;;:::i;:::-;;:::i;87073:106::-;;;;;;:::i;:::-;-1:-1:-1;;;;;87157:14:0;;;87130:7;87157:14;;;:6;:14;;;;;;;;87073:106;84988:41;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;84988:41:0;;;91550:282;;;;;;:::i;:::-;;:::i;84062:36::-;;;;;85325:60;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;89304:63;;;:::i;84691:53::-;;84739:5;84691:53;;93271:170;;;:::i;84265:39::-;;;;;84753:22;;;;;;85426:46;;;;;;:::i;:::-;;:::i;86369:114::-;;;;;;:::i;:::-;;:::i;296:32::-;;;;;-1:-1:-1;;;;;296:32:0;;;83955:24;;;;;-1:-1:-1;;;;;83955:24:0;;;84496:38;;;;;912:207;996:17;;-1:-1:-1;;;;;996:17:0;982:10;:31;960:110;;;;-1:-1:-1;;;960:110:0;;4851:2:1;960:110:0;;;4833:21:1;4890:2;4870:18;;;4863:30;4929:31;4909:18;;;4902:59;4978:18;;960:110:0;;;;;;;;;1094:17;;;1081:30;;-1:-1:-1;;;;;;1081:30:0;-1:-1:-1;;;;;1094:17:0;;;1081:30;;;;;;912:207::o;91270:218::-;86697:10;;-1:-1:-1;;;;;86697:10:0;86683;:24;86675:56;;;;-1:-1:-1;;;86675:56:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;91353:14:0;;::::1;91379:3;91353:14:::0;;;:6:::1;:14;::::0;;;;;::::1;91345:57;;;::::0;-1:-1:-1;;;91345:57:0;;5557:2:1;91345:57:0::1;::::0;::::1;5539:21:1::0;5596:2;5576:18;;;5569:30;-1:-1:-1;;;5615:18:1;;;5608:44;5669:18;;91345:57:0::1;5355:338:1::0;91345:57:0::1;-1:-1:-1::0;;;;;91434:14:0;;::::1;;::::0;;;:6:::1;:14;::::0;;;;;;;;;91413:10:::1;:18:::0;;;;;;:35;;91434:14;;;::::1;-1:-1:-1::0;;;;;;91413:35:0;;::::1;;::::0;;;91466:14;91459:21;;;;::::1;::::0;;91270:218::o;87660:284::-;87790:36;;;87768:118;;;;-1:-1:-1;;;87768:118:0;;5900:2:1;87768:118:0;;;5882:21:1;;;5919:18;;;5912:30;5978:34;5958:18;;;5951:62;6030:18;;87768:118:0;5698:356:1;87768:118:0;87897:39;87903:10;87915;;87897:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;87897:39:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;87927:8:0;;-1:-1:-1;87927:8:0;;;;87897:39;;;87927:8;;87897:39;87927:8;87897:39;;;;;;;;;-1:-1:-1;87897:5:0;;-1:-1:-1;;;87897:39:0:i;:::-;87660:284;;;;:::o;94091:1018::-;94193:10;94183:21;;;;:9;:21;;;;;;;;;:49;;-1:-1:-1;94222:10:0;;-1:-1:-1;;;;;94222:10:0;94208;:24;94183:49;94161:118;;;;-1:-1:-1;;;94161:118:0;;;;;;;:::i;:::-;94307:4;94298:6;:13;94290:36;;;;-1:-1:-1;;;94290:36:0;;6261:2:1;94290:36:0;;;6243:21:1;6300:2;6280:18;;;6273:30;-1:-1:-1;;;6319:18:1;;;6312:40;6369:18;;94290:36:0;6059:334:1;94290:36:0;94353:7;:14;94345:22;;;94337:43;;;;-1:-1:-1;;;94337:43:0;;6600:2:1;94337:43:0;;;6582:21:1;6639:1;6619:18;;;6612:29;-1:-1:-1;;;6657:18:1;;;6650:38;6705:18;;94337:43:0;6398:331:1;94337:43:0;94449:15;84739:5;94413:8;;:32;;;;:::i;:::-;:51;;94391:113;;;;-1:-1:-1;;;94391:113:0;;7201:2:1;94391:113:0;;;7183:21:1;7240:2;7220:18;;;7213:30;-1:-1:-1;;;7259:18:1;;;7252:42;7311:18;;94391:113:0;6999:336:1;94391:113:0;94535:1;94519:13;;:17;:42;;;;;94560:1;94540:17;;:21;94519:42;94515:587;;;94595:6;94578:513;94607:4;94603:1;:8;94578:513;;;94637:14;94654:7;94662:1;94654:10;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;94654:10:0;;;94700:14;;;:6;:14;;;;;;;94818:11;;94769:13;:21;;;;;;;94751:13;;94654:10;;-1:-1:-1;94700:14:0;;;94654:10;94751:97;;94818:11;;94751:40;;:17;:40::i;:::-;:44;;:97::i;:::-;94733:115;-1:-1:-1;94871:11:0;;94867:209;;94907:28;-1:-1:-1;;;;;94907:5:0;:17;94925:6;94933:1;94907:17;:28::i;:::-;94958:34;-1:-1:-1;;;;;94958:5:0;:17;94976:6;94984:7;94958:17;:34::i;:::-;95015:41;;-1:-1:-1;;;95015:41:0;;;;;529:25:1;;;-1:-1:-1;;;;;95015:32:0;;;;;502:18:1;;95015:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94867:209;94618:473;;;94613:3;;;;;:::i;:::-;;;;94578:513;;;;94515:587;94091:1018;;:::o;91876:234::-;86697:10;;-1:-1:-1;;;;;86697:10:0;86683;:24;86675:56;;;;-1:-1:-1;;;86675:56:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;91996:14:0;;::::1;92022:3;91996:14:::0;;;:6:::1;:14;::::0;;;;;::::1;:30:::0;91988:49:::1;;;;-1:-1:-1::0;;;91988:49:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;92048:14:0;;::::1;;::::0;;;:6:::1;:14;::::0;;;;:23;;;;;::::1;-1:-1:-1::0;;;;;;92048:23:0;;::::1;;::::0;;;92082:7:::1;:20:::0;;92048:23;92082:20;::::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;91876:234::o;93582:456::-;93659:10;93649:21;;;;:9;:21;;;;;;;;;:49;;-1:-1:-1;93688:10:0;;-1:-1:-1;;;;;93688:10:0;93674;:24;93649:49;93627:118;;;;-1:-1:-1;;;93627:118:0;;;;;;;:::i;:::-;93776:11;;93756:17;:31;-1:-1:-1;93798:119:0;93822:7;:14;93818:18;;93798:119;;;93886:7;:19;93894:7;93902:1;93894:10;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;93894:10:0;-1:-1:-1;;;;;93886:19:0;-1:-1:-1;;;;;93886:19:0;;;;;;;;;;;;;93858:13;:25;93872:7;93880:1;93872:10;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;93872:10:0;93858:25;;;;;;;;;;;;:47;93838:3;;;;:::i;:::-;;;;93798:119;;;;93927:9;:7;:9::i;:::-;93963:30;;-1:-1:-1;;;93963:30:0;;93987:4;93963:30;;;725:51:1;93963:5:0;-1:-1:-1;;;;;93963:15:0;;;;698:18:1;;93963:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93947:13;:46;94015:15;94004:8;:26;93582:456::o;86177:110::-;473:10;;-1:-1:-1;;;;;473:10:0;459;:24;451:68;;;;-1:-1:-1;;;451:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;86252:20:0::1;;::::0;;;:9:::1;:20;::::0;;;;:27;;-1:-1:-1;;86252:27:0::1;86275:4;86252:27;::::0;;86177:110::o;92508:307::-;473:10;;-1:-1:-1;;;;;473:10:0;459;:24;451:68;;;;-1:-1:-1;;;451:68:0;;;;;;;:::i;:::-;92705:3:::1;::::0;:8;92697:45:::1;;;::::0;-1:-1:-1;;;92697:45:0;;8697:2:1;92697:45:0::1;::::0;::::1;8679:21:1::0;8736:2;8716:18;;;8709:30;8775:26;8755:18;;;8748:54;8819:18;;92697:45:0::1;8495:348:1::0;92697:45:0::1;92761:9:::0;92753:33:::1;;;::::0;-1:-1:-1;;;92753:33:0;;9050:2:1;92753:33:0::1;::::0;::::1;9032:21:1::0;9089:2;9069:18;;;9062:30;-1:-1:-1;;;9108:18:1;;;9101:41;9159:18;;92753:33:0::1;8848:335:1::0;92753:33:0::1;92797:3;:10:::0;92508:307::o;86907:92::-;86948:16;86984:7;86977:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;86977:14:0;;;;;;;;;;;;;;;;;;;;;;;86907:92;:::o;90939:281::-;86697:10;;-1:-1:-1;;;;;86697:10:0;86683;:24;86675:56;;;;-1:-1:-1;;;86675:56:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;91016:14:0;;::::1;91042:3;91016:14:::0;;;:6:::1;:14;::::0;;;;;::::1;:30:::0;91008:49:::1;;;;-1:-1:-1::0;;;91008:49:0::1;;;;;;;:::i;:::-;91125:10;::::0;91107:63:::1;::::0;91117:6;;-1:-1:-1;;;;;91125:10:0::1;::::0;91145:7:::1;::::0;91163:5:::1;::::0;91107:63:::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;;;;;9475:15:1;;;9457:34;;9527:15;;;9522:2;9507:18;;9500:43;9579:15;;;9574:2;9559:18;;9552:43;9631:15;;;9626:2;9611:18;;9604:43;9406:3;9391:19;91107:63:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;;;;;91068:14:0;;::::1;;::::0;;;:6:::1;:14;::::0;;;;:113;;;;;::::1;-1:-1:-1::0;;;;;;91068:113:0;;::::1;;::::0;;;91192:7:::1;:20:::0;;91068:113;91192:20;::::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;90939:281::o;92249:219::-;473:10;;-1:-1:-1;;;;;473:10:0;459;:24;451:68;;;;-1:-1:-1;;;451:68:0;;;;;;;:::i;:::-;92380:5:::1;:32:::0;;-1:-1:-1;;;;;;92380:32:0::1;-1:-1:-1::0;;;;;92380:32:0;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;92423:3:0::1;:7:::0;92249:219::o;688:118::-;473:10;;-1:-1:-1;;;;;473:10:0;459;:24;451:68;;;;-1:-1:-1;;;451:68:0;;;;;;;:::i;:::-;767:17:::1;:31:::0;;-1:-1:-1;;;;;;767:31:0::1;-1:-1:-1::0;;;;;767:31:0;;;::::1;::::0;;;::::1;::::0;;688:118::o;92878:325::-;92933:3;;92925:40;;;;-1:-1:-1;;;92925:40:0;;9860:2:1;92925:40:0;;;9842:21:1;9899:2;9879:18;;;9872:30;-1:-1:-1;;;9918:18:1;;;9911:49;9977:18;;92925:40:0;9658:343:1;92925:40:0;92995;;-1:-1:-1;;;92995:40:0;;93029:4;92995:40;;;725:51:1;92976:16:0;;92995:15;-1:-1:-1;;;;;92995:25:0;;;;698:18:1;;92995:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;93082:5;;92976:59;;-1:-1:-1;93046:46:0;;-1:-1:-1;;;;;93046:15:0;:27;;;93082:5;;93046:27;:46::i;:::-;93139:5;;93103:53;;-1:-1:-1;;;;;93103:15:0;:27;;;93139:5;93147:8;93103:27;:53::i;:::-;93167:5;;93181:3;;93167:28;;-1:-1:-1;;;93167:28:0;;-1:-1:-1;;;;;93167:5:0;;;;:13;;:28;;93186:8;;93167:28;;10180:25:1;;;10236:2;10221:18;;10214:34;10168:2;10153:18;;10006:248;93167:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92914:289;92878:325::o;90324:503::-;-1:-1:-1;;;;;90402:17:0;;90372:27;90402:17;;;:9;:17;;;;;;;;90372:47;;;;;;;;;;;;;;;;;;;90402:17;;90372:47;;;90402:17;90372:47;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;90372:47:0;;;;;;;;;;;;;;;;;;;;;;;90430:17;90450:10;:17;90430:37;;90478:25;90520:9;90506:24;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;90506:24:0;;90478:52;;90548:9;90543:109;90567:9;90563:1;:13;90543:109;;;-1:-1:-1;;;;;90612:13:0;;;;;;:5;:13;;;;;90626;;90612;;;90626:10;;90637:1;;90626:13;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;90612:28:0;-1:-1:-1;;;;;90612:28:0;;;;;;;;;;;;;90598:8;90607:1;90598:11;;;;;;;;:::i;:::-;;;;;;;;;;:42;90578:3;;;;:::i;:::-;;;;90543:109;;;;90784:35;90790:6;90798:10;90810:8;90784:5;:35::i;91550:282::-;86697:10;;-1:-1:-1;;;;;86697:10:0;86683;:24;86675:56;;;;-1:-1:-1;;;86675:56:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;91629:14:0;;::::1;91655:3;91629:14:::0;;;:6:::1;:14;::::0;;;;;::::1;:30:::0;91621:49:::1;;;;-1:-1:-1::0;;;91621:49:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;91689:18:0;;::::1;91719:3;91689:18:::0;;;:10:::1;:18;::::0;;;;;::::1;91681:61;;;::::0;-1:-1:-1;;;91681:61:0;;10593:2:1;91681:61:0::1;::::0;::::1;10575:21:1::0;10632:2;10612:18;;;10605:30;-1:-1:-1;;;10651:18:1;;;10644:44;10705:18;;91681:61:0::1;10391:338:1::0;91681:61:0::1;-1:-1:-1::0;;;;;91770:18:0;;::::1;;::::0;;;:10:::1;:18;::::0;;;;;;;;;91753:6:::1;:14:::0;;;;;;:35;;91770:18;;;::::1;-1:-1:-1::0;;;;;;91753:35:0;;::::1;;::::0;;;91806:18;91799:25;;;;::::1;::::0;;91550:282::o;89304:63::-;89341:18;89348:10;89341:6;:18::i;:::-;89304:63::o;93271:170::-;93330:5;;93345:3;;93330:34;;-1:-1:-1;;;93330:34:0;;;;;10908:25:1;;;;93358:4:0;10949:18:1;;;10942:60;93309:15:0;;-1:-1:-1;;;;;93330:5:0;;:14;;10881:18:1;;93330:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;93375:5:0;;93390:3;;93375:28;;-1:-1:-1;;;93375:28:0;;;;;10180:25:1;;;;10221:18;;;10214:34;;;93308:56:0;;-1:-1:-1;;;;;;93375:5:0;;:14;;10153:18:1;;93375:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93414:19;:17;:19::i;:::-;93297:144;93271:170::o;85426:46::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;85426:46:0;;-1:-1:-1;85426:46:0;;-1:-1:-1;85426:46:0:o;86369:114::-;473:10;;-1:-1:-1;;;;;473:10:0;459;:24;451:68;;;;-1:-1:-1;;;451:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;86447:20:0::1;86470:5;86447:20:::0;;;:9:::1;:20;::::0;;;;:28;;-1:-1:-1;;86447:28:0::1;::::0;;86369:114::o;87994:1254::-;88172:14;88179:6;88172;:14::i;:::-;88217:17;;88263:23;;-1:-1:-1;;;88263:23:0;;-1:-1:-1;;;;;743:32:1;;;88263:23:0;;;725:51:1;88197:17:0;;88263:6;:15;;;;;;698:18:1;;88263:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;88245:41;;88297:24;88336:19;88377:9;88372:119;88396:9;88392:1;:13;88372:119;;;88446:33;88467:8;88476:1;88467:11;;;;;;;;:::i;:::-;;;;;;;88446:16;:20;;:33;;;;:::i;:::-;88427:52;-1:-1:-1;88407:3:0;;;;:::i;:::-;;;;88372:119;;;;88508:9;88503:694;88527:9;88523:1;:13;88503:694;;;88558:14;88575:10;88586:1;88575:13;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;88620:14:0;;;88603;88620;;;:6;:14;;;;;;;88749:11;;88575:13;;-1:-1:-1;88620:14:0;;88603;88749:78;;88796:16;;88749:24;;88765:7;;88749:8;;88758:1;;88749:11;;;;;;:::i;:::-;;;;;;;:15;;:24;;;;:::i;:78::-;88726:101;-1:-1:-1;;;;;;88848:22:0;;;88844:342;;88905:29;:11;88921:12;88905:15;:29::i;:::-;88967:11;;88891:43;;-1:-1:-1;88967:29:0;;88983:12;88967:15;:29::i;:::-;88953:11;:43;-1:-1:-1;;;;;89033:15:0;;;;;;:7;:15;;;;;;:33;;89053:12;89033:19;:33::i;:::-;-1:-1:-1;;;;;89015:15:0;;;;;;;:7;:15;;;;;;;;:51;;;;89085:17;;;;;;:9;:17;;;;;:30;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;89085:30:0;;;;;89134:13;;:5;:13;;;;;:21;;;;;;:36;;;88844:342;88543:654;;;88538:3;;;;;:::i;:::-;;;;88503:694;;;-1:-1:-1;;;;;;89207:19:0;;;;;;;:11;:19;;;;;:33;;;;-1:-1:-1;;;;;87994:1254:0:o;49410:98::-;49468:7;49495:5;49499:1;49495;:5;:::i;:::-;49488:12;49410:98;-1:-1:-1;;;49410:98:0:o;49809:::-;49867:7;49894:5;49898:1;49894;:5;:::i;14982:616::-;15346:10;;;15345:62;;-1:-1:-1;15362:39:0;;-1:-1:-1;;;15362:39:0;;15386:4;15362:39;;;11870:34:1;-1:-1:-1;;;;;11940:15:1;;;11920:18;;;11913:43;15362:15:0;;;;;11805:18:1;;15362:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;15345:62;15323:166;;;;-1:-1:-1;;;15323:166:0;;12169:2:1;15323:166:0;;;12151:21:1;12208:2;12188:18;;;12181:30;12247:34;12227:18;;;12220:62;-1:-1:-1;;;12298:18:1;;;12291:52;12360:19;;15323:166:0;11967:418:1;15323:166:0;15527:62;;;-1:-1:-1;;;;;12582:32:1;;15527:62:0;;;12564:51:1;12631:18;;;;12624:34;;;15527:62:0;;;;;;;;;;12537:18:1;;;;15527:62:0;;;;;;;;-1:-1:-1;;;;;15527:62:0;-1:-1:-1;;;15527:62:0;;;15500:90;;15520:5;;15500:19;:90::i;89516:717::-;-1:-1:-1;;;;;89654:17:0;;89623:28;89654:17;;;:9;:17;;;;;89706;;89654;;89736:453;89760:13;89756:1;:17;89736:453;;;89795:14;89812:10;89823:1;89812:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;89942:13:0;;;;;:5;:13;;;;;;89812;;;;89942:21;;;;;;;;;89812:13;;-1:-1:-1;89984:10:0;;89980:198;;90029:11;;:23;;90045:6;90029:15;:23::i;:::-;90015:11;:37;-1:-1:-1;;;;;90089:15:0;;;;;;:7;:15;;;;;;:27;;90109:6;90089:19;:27::i;:::-;-1:-1:-1;;;;;90071:15:0;;;;;;;:7;:15;;;;;;;;:45;;;;90137:13;;;;;:5;:13;;;;;:21;;;;;;;;:25;89980:198;89780:409;;89775:3;;;;;:::i;:::-;;;;89736:453;;;-1:-1:-1;;;;;;90208:17:0;;;;;;:9;:17;;;;;90201:24;;;:::i;48672:98::-;48730:7;48757:5;48761:1;48757;:5;:::i;16819:716::-;17243:23;17269:69;17297:4;17269:69;;;;;;;;;;;;;;;;;17277:5;-1:-1:-1;;;;;17269:27:0;;;:69;;;;;:::i;:::-;17353:17;;17243:95;;-1:-1:-1;17353:21:0;17349:179;;17450:10;17439:30;;;;;;;;;;;;:::i;:::-;17431:85;;;;-1:-1:-1;;;17431:85:0;;13153:2:1;17431:85:0;;;13135:21:1;13192:2;13172:18;;;13165:30;13231:34;13211:18;;;13204:62;-1:-1:-1;;;13282:18:1;;;13275:40;13332:19;;17431:85:0;12951:406:1;49053:98:0;49111:7;49138:5;49142:1;49138;:5;:::i;9018:229::-;9155:12;9187:52;9209:6;9217:4;9223:1;9226:12;9187:21;:52::i;:::-;9180:59;9018:229;-1:-1:-1;;;;9018:229:0:o;10138:510::-;10308:12;10366:5;10341:21;:30;;10333:81;;;;-1:-1:-1;;;10333:81:0;;13694:2:1;10333:81:0;;;13676:21:1;13733:2;13713:18;;;13706:30;13772:34;13752:18;;;13745:62;-1:-1:-1;;;13823:18:1;;;13816:36;13869:19;;10333:81:0;13492:402:1;10333:81:0;-1:-1:-1;;;;;6568:19:0;;;10425:60;;;;-1:-1:-1;;;10425:60:0;;14101:2:1;10425:60:0;;;14083:21:1;14140:2;14120:18;;;14113:30;14179:31;14159:18;;;14152:59;14228:18;;10425:60:0;13899:353:1;10425:60:0;10499:12;10513:23;10540:6;-1:-1:-1;;;;;10540:11:0;10559:5;10566:4;10540:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10498:73;;;;10589:51;10606:7;10615:10;10627:12;10589:16;:51::i;:::-;10582:58;10138:510;-1:-1:-1;;;;;;;10138:510:0:o;12824:712::-;12974:12;13003:7;12999:530;;;-1:-1:-1;13034:10:0;13027:17;;12999:530;13148:17;;:21;13144:374;;13346:10;13340:17;13407:15;13394:10;13390:2;13386:19;13379:44;13144:374;13489:12;13482:20;;-1:-1:-1;;;13482:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:173:1:-;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:186::-;251:6;304:2;292:9;283:7;279:23;275:32;272:52;;;320:1;317;310:12;272:52;343:29;362:9;343:29;:::i;1187:367::-;1250:8;1260:6;1314:3;1307:4;1299:6;1295:17;1291:27;1281:55;;1332:1;1329;1322:12;1281:55;-1:-1:-1;1355:20:1;;1398:18;1387:30;;1384:50;;;1430:1;1427;1420:12;1384:50;1467:4;1459:6;1455:17;1443:29;;1527:3;1520:4;1510:6;1507:1;1503:14;1495:6;1491:27;1487:38;1484:47;1481:67;;;1544:1;1541;1534:12;1481:67;1187:367;;;;;:::o;1559:773::-;1681:6;1689;1697;1705;1758:2;1746:9;1737:7;1733:23;1729:32;1726:52;;;1774:1;1771;1764:12;1726:52;1814:9;1801:23;1843:18;1884:2;1876:6;1873:14;1870:34;;;1900:1;1897;1890:12;1870:34;1939:70;2001:7;1992:6;1981:9;1977:22;1939:70;:::i;:::-;2028:8;;-1:-1:-1;1913:96:1;-1:-1:-1;2116:2:1;2101:18;;2088:32;;-1:-1:-1;2132:16:1;;;2129:36;;;2161:1;2158;2151:12;2129:36;;2200:72;2264:7;2253:8;2242:9;2238:24;2200:72;:::i;:::-;1559:773;;;;-1:-1:-1;2291:8:1;-1:-1:-1;;;;1559:773:1:o;2337:248::-;2405:6;2413;2466:2;2454:9;2445:7;2441:23;2437:32;2434:52;;;2482:1;2479;2472:12;2434:52;-1:-1:-1;;2505:23:1;;;2575:2;2560:18;;;2547:32;;-1:-1:-1;2337:248:1:o;2590:260::-;2658:6;2666;2719:2;2707:9;2698:7;2694:23;2690:32;2687:52;;;2735:1;2732;2725:12;2687:52;2758:29;2777:9;2758:29;:::i;:::-;2748:39;;2806:38;2840:2;2829:9;2825:18;2806:38;:::i;:::-;2796:48;;2590:260;;;;;:::o;2855:180::-;2914:6;2967:2;2955:9;2946:7;2942:23;2938:32;2935:52;;;2983:1;2980;2973:12;2935:52;-1:-1:-1;3006:23:1;;2855:180;-1:-1:-1;2855:180:1:o;3040:658::-;3211:2;3263:21;;;3333:13;;3236:18;;;3355:22;;;3182:4;;3211:2;3434:15;;;;3408:2;3393:18;;;3182:4;3477:195;3491:6;3488:1;3485:13;3477:195;;;3556:13;;-1:-1:-1;;;;;3552:39:1;3540:52;;3647:15;;;;3612:12;;;;3588:1;3506:9;3477:195;;;-1:-1:-1;3689:3:1;;3040:658;-1:-1:-1;;;;;;3040:658:1:o;3932:254::-;4000:6;4008;4061:2;4049:9;4040:7;4036:23;4032:32;4029:52;;;4077:1;4074;4067:12;4029:52;4100:29;4119:9;4100:29;:::i;:::-;4090:39;4176:2;4161:18;;;;4148:32;;-1:-1:-1;;;3932:254:1:o;5007:343::-;5209:2;5191:21;;;5248:2;5228:18;;;5221:30;-1:-1:-1;;;5282:2:1;5267:18;;5260:49;5341:2;5326:18;;5007:343::o;6734:127::-;6795:10;6790:3;6786:20;6783:1;6776:31;6826:4;6823:1;6816:15;6850:4;6847:1;6840:15;6866:128;6906:3;6937:1;6933:6;6930:1;6927:13;6924:39;;;6943:18;;:::i;:::-;-1:-1:-1;6979:9:1;;6866:128::o;7340:127::-;7401:10;7396:3;7392:20;7389:1;7382:31;7432:4;7429:1;7422:15;7456:4;7453:1;7446:15;7472:135;7511:3;-1:-1:-1;;7532:17:1;;7529:43;;;7552:18;;:::i;:::-;-1:-1:-1;7599:1:1;7588:13;;7472:135::o;7612:329::-;7814:2;7796:21;;;7853:1;7833:18;;;7826:29;-1:-1:-1;;;7886:2:1;7871:18;;7864:36;7932:2;7917:18;;7612:329::o;7946:184::-;8016:6;8069:2;8057:9;8048:7;8044:23;8040:32;8037:52;;;8085:1;8082;8075:12;8037:52;-1:-1:-1;8108:16:1;;7946:184;-1:-1:-1;7946:184:1:o;8135:355::-;8337:2;8319:21;;;8376:2;8356:18;;;8349:30;8415:33;8410:2;8395:18;;8388:61;8481:2;8466:18;;8135:355::o;10259:127::-;10320:10;10315:3;10311:20;10308:1;10301:31;10351:4;10348:1;10341:15;10375:4;10372:1;10365:15;11013:245;11092:6;11100;11153:2;11141:9;11132:7;11128:23;11124:32;11121:52;;;11169:1;11166;11159:12;11121:52;-1:-1:-1;;11192:16:1;;11248:2;11233:18;;;11227:25;11192:16;;11227:25;;-1:-1:-1;11013:245:1:o;11263:168::-;11303:7;11369:1;11365;11361:6;11357:14;11354:1;11351:21;11346:1;11339:9;11332:17;11328:45;11325:71;;;11376:18;;:::i;:::-;-1:-1:-1;11416:9:1;;11263:168::o;11436:217::-;11476:1;11502;11492:132;;11546:10;11541:3;11537:20;11534:1;11527:31;11581:4;11578:1;11571:15;11609:4;11606:1;11599:15;11492:132;-1:-1:-1;11638:9:1;;11436:217::o;12669:277::-;12736:6;12789:2;12777:9;12768:7;12764:23;12760:32;12757:52;;;12805:1;12802;12795:12;12757:52;12837:9;12831:16;12890:5;12883:13;12876:21;12869:5;12866:32;12856:60;;12912:1;12909;12902:12;13362:125;13402:4;13430:1;13427;13424:8;13421:34;;;13435:18;;:::i;:::-;-1:-1:-1;13472:9:1;;13362:125::o;14257:258::-;14329:1;14339:113;14353:6;14350:1;14347:13;14339:113;;;14429:11;;;14423:18;14410:11;;;14403:39;14375:2;14368:10;14339:113;;;14470:6;14467:1;14464:13;14461:48;;;-1:-1:-1;;14505:1:1;14487:16;;14480:27;14257:258::o;14520:274::-;14649:3;14687:6;14681:13;14703:53;14749:6;14744:3;14737:4;14729:6;14725:17;14703:53;:::i;:::-;14772:16;;;;;14520:274;-1:-1:-1;;14520:274:1:o;14799:383::-;14948:2;14937:9;14930:21;14911:4;14980:6;14974:13;15023:6;15018:2;15007:9;15003:18;14996:34;15039:66;15098:6;15093:2;15082:9;15078:18;15073:2;15065:6;15061:15;15039:66;:::i;:::-;15166:2;15145:15;-1:-1:-1;;15141:29:1;15126:45;;;;15173:2;15122:54;;14799:383;-1:-1:-1;;14799:383:1:o

Swarm Source

ipfs://38eba5f99e5e6b1a7e5dd4cf59cd61df98570c7f1e5bf74ab77d59f0cb641064
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.