Token

Overview

Total Supply:
73,867,685.954816 N/A

Holders:
0 addresses

Transfers:
-

Contract:
0x88afdae1a9f58da3e68584421937e5f564a0135b0x88afdaE1a9F58Da3E68584421937E5F564A0135b

Decimals:
18

Social Profiles:
Not Available, Update ?

Loading
[ Download CSV Export  ] 
Loading
Loading

Click here to update the token ICO / general information
# Exchange Pair Price  24H Volume % Volume

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x78d4BFb3b50E5895932073DC5Eb4713eb532941B

Contract Name:
StakingRewards

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-11-03
*/

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

// File openzeppelin-contracts-legacy/GSN/[email protected]

// SPDX-License-Identifier: MIT


pragma solidity >=0.6.0 <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 GSN 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 payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}


// File openzeppelin-contracts-legacy/access/[email protected]

pragma solidity >=0.6.0 <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 () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view 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 {
        emit OwnershipTransferred(_owner, address(0));
        _owner = 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");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}


// File openzeppelin-contracts-legacy/math/[email protected]

pragma solidity >=0.6.0 <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, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}


// File openzeppelin-contracts-legacy/math/[email protected]

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @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) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @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 sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @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) {
        // 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 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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 mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}


// File openzeppelin-contracts-legacy/token/ERC20/[email protected]



pragma solidity >=0.6.0 <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 `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, 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-legacy/utils/[email protected]



pragma solidity >=0.6.2 <0.8.0;

/**
 * @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
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 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");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}


// File openzeppelin-contracts-legacy/token/ERC20/[email protected]



pragma solidity >=0.6.0 <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 SafeMath for uint256;
    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'
        // solhint-disable-next-line max-line-length
        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).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _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
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}


// File openzeppelin-contracts-legacy/utils/[email protected]



pragma solidity >=0.6.0 <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 () internal {
        _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 make 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 @pangolindex/exchange-contracts/contracts/pangolin-core/interfaces/[email protected]

pragma solidity >=0.5.0;

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

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
}


// File contracts/StakingRewards.sol

pragma solidity ^0.7.6;





// https://docs.synthetix.io/contracts/source/contracts/stakingrewards
contract StakingRewards is ReentrancyGuard, Ownable {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    /* ========== STATE VARIABLES ========== */

    IERC20 public rewardsToken;
    IERC20 public stakingToken;
    uint256 public periodFinish = 0;
    uint256 public rewardRate = 0;
    uint256 public rewardsDuration = 1 days;
    uint256 public lastUpdateTime;
    uint256 public rewardPerTokenStored;

    mapping(address => uint256) public userRewardPerTokenPaid;
    mapping(address => uint256) public rewards;

    uint256 private _totalSupply;
    mapping(address => uint256) private _balances;

    /* ========== CONSTRUCTOR ========== */

    constructor(
        address _rewardsToken,
        address _stakingToken
    ) public {
        rewardsToken = IERC20(_rewardsToken);
        stakingToken = IERC20(_stakingToken);
    }

    /* ========== VIEWS ========== */

    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) external view returns (uint256) {
        return _balances[account];
    }

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

    function rewardPerToken() public view returns (uint256) {
        if (_totalSupply == 0) {
            return rewardPerTokenStored;
        }
        return
            rewardPerTokenStored.add(
                lastTimeRewardApplicable().sub(lastUpdateTime).mul(rewardRate).mul(1e18).div(_totalSupply)
            );
    }

    function earned(address account) public view returns (uint256) {
        return _balances[account].mul(rewardPerToken().sub(userRewardPerTokenPaid[account])).div(1e18).add(rewards[account]);
    }

    function getRewardForDuration() external view returns (uint256) {
        return rewardRate.mul(rewardsDuration);
    }

    /* ========== MUTATIVE FUNCTIONS ========== */

    function stakeWithPermit(uint256 amount, uint deadline, uint8 v, bytes32 r, bytes32 s) external nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot stake 0");
        _totalSupply = _totalSupply.add(amount);
        _balances[msg.sender] = _balances[msg.sender].add(amount);

        // permit
        IPangolinERC20(address(stakingToken)).permit(msg.sender, address(this), amount, deadline, v, r, s);

        stakingToken.safeTransferFrom(msg.sender, address(this), amount);
        emit Staked(msg.sender, amount);
    }

    function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot stake 0");
        _totalSupply = _totalSupply.add(amount);
        _balances[msg.sender] = _balances[msg.sender].add(amount);
        stakingToken.safeTransferFrom(msg.sender, address(this), amount);
        emit Staked(msg.sender, amount);
    }

    function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot withdraw 0");
        _totalSupply = _totalSupply.sub(amount);
        _balances[msg.sender] = _balances[msg.sender].sub(amount);
        stakingToken.safeTransfer(msg.sender, amount);
        emit Withdrawn(msg.sender, amount);
    }

    function getReward() public nonReentrant updateReward(msg.sender) {
        uint256 reward = rewards[msg.sender];
        if (reward > 0) {
            rewards[msg.sender] = 0;
            rewardsToken.safeTransfer(msg.sender, reward);
            emit RewardPaid(msg.sender, reward);
        }
    }

    function exit() external {
        withdraw(_balances[msg.sender]);
        getReward();
    }

    /* ========== RESTRICTED FUNCTIONS ========== */

    // Always needs to update the balance of the contract when calling this method
    function notifyRewardAmount(uint256 reward) external onlyOwner updateReward(address(0)) {
        if (block.timestamp >= periodFinish) {
            rewardRate = reward.div(rewardsDuration);
        } else {
            uint256 remaining = periodFinish.sub(block.timestamp);
            uint256 leftover = remaining.mul(rewardRate);
            rewardRate = reward.add(leftover).div(rewardsDuration);
        }

        // 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.
        uint balance = rewardsToken.balanceOf(address(this));
        require(rewardRate <= balance.div(rewardsDuration), "Provided reward too high");

        lastUpdateTime = block.timestamp;
        periodFinish = block.timestamp.add(rewardsDuration);
        emit RewardAdded(reward);
    }

    // Added to support recovering LP Rewards from other systems such as BAL to be distributed to holders
    function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner nonReentrant {
        require(tokenAddress != address(stakingToken), "Cannot withdraw the staking token");
        IERC20(tokenAddress).safeTransfer(owner(), tokenAmount);
        emit Recovered(tokenAddress, tokenAmount);
    }

    function setRewardsDuration(uint256 _rewardsDuration) external onlyOwner {
        require(
            block.timestamp > periodFinish,
            "Previous rewards period must be complete before changing the duration for the new period"
        );
        require(_rewardsDuration > 0, "Reward duration can't be zero");
        rewardsDuration = _rewardsDuration;
        emit RewardsDurationUpdated(rewardsDuration);
    }

    /* ========== MODIFIERS ========== */

    modifier updateReward(address account) {
        rewardPerTokenStored = rewardPerToken();
        lastUpdateTime = lastTimeRewardApplicable();
        if (account != address(0)) {
            rewards[account] = earned(account);
            userRewardPerTokenPaid[account] = rewardPerTokenStored;
        }
        _;
    }

    /* ========== EVENTS ========== */

    event RewardAdded(uint256 reward);
    event Staked(address indexed user, uint256 amount);
    event Withdrawn(address indexed user, uint256 amount);
    event RewardPaid(address indexed user, uint256 reward);
    event RewardsDurationUpdated(uint256 newDuration);
    event Recovered(address token, uint256 amount);
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_rewardsToken","type":"address"},{"internalType":"address","name":"_stakingToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"RewardsDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardForDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_rewardsDuration","type":"uint256"}],"name":"setRewardsDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"stakeWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600060045560006005556201518060065534801561002157600080fd5b50604051611b8a380380611b8a8339818101604052604081101561004457600080fd5b5080516020909101516001600090815561005c6100db565b600180546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600280546001600160a01b039384166001600160a01b031991821617909155600380549290931691161790556100df565b3390565b611a9c806100ee6000396000f3fe608060405234801561001057600080fd5b50600436106101ad5760003560e01c80638980f11f116100ee578063cd3daf9d11610097578063e9fad8ee11610071578063e9fad8ee14610382578063ebe2b12b1461038a578063ecd9ba8214610392578063f2fde38b146103ca576101ad565b8063cd3daf9d1461036a578063d1af0c7d14610372578063df136d651461037a576101ad565b8063a694fc3a116100c8578063a694fc3a14610328578063c8f33c9114610345578063cc1a378f1461034d576101ad565b80638980f11f146102ce5780638b876347146102fa5780638da5cb5b14610320576101ad565b80633c6b16ab1161015b578063715018a611610135578063715018a61461029257806372f702f31461029a5780637b0a47ee146102be57806380faa57d146102c6576101ad565b80633c6b16ab146102475780633d18b9121461026457806370a082311461026c576101ad565b80631c1f78eb1161018c5780631c1f78eb146102185780632e1a7d4d14610220578063386a95251461023f576101ad565b80628cc262146101b25780630700037d146101ea57806318160ddd14610210575b600080fd5b6101d8600480360360208110156101c857600080fd5b50356001600160a01b03166103f0565b60408051918252519081900360200190f35b6101d86004803603602081101561020057600080fd5b50356001600160a01b031661046e565b6101d8610480565b6101d8610487565b61023d6004803603602081101561023657600080fd5b50356104a5565b005b6101d8610647565b61023d6004803603602081101561025d57600080fd5b503561064d565b61023d6108ba565b6101d86004803603602081101561028257600080fd5b50356001600160a01b03166109f1565b61023d610a0c565b6102a2610acd565b604080516001600160a01b039092168252519081900360200190f35b6101d8610adc565b6101d8610ae2565b61023d600480360360408110156102e457600080fd5b506001600160a01b038135169060200135610af0565b6101d86004803603602081101561031057600080fd5b50356001600160a01b0316610c6d565b6102a2610c7f565b61023d6004803603602081101561033e57600080fd5b5035610c8e565b6101d8610e31565b61023d6004803603602081101561036357600080fd5b5035610e37565b6101d8610f71565b6102a2610fbf565b6101d8610fce565b61023d610fd4565b6101d8610ff7565b61023d600480360360a08110156103a857600080fd5b5080359060208101359060ff6040820135169060608101359060800135610ffd565b61023d600480360360208110156103e057600080fd5b50356001600160a01b0316611248565b6001600160a01b0381166000908152600a60209081526040808320546009909252822054610468919061046290670de0b6b3a76400009061045c9061043d90610437610f71565b90611360565b6001600160a01b0388166000908152600c6020526040902054906113a9565b90611402565b90611444565b92915050565b600a6020526000908152604090205481565b600b545b90565b60006104a06006546005546113a990919063ffffffff16565b905090565b600260005414156104fd576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000553361050b610f71565b600855610516610ae2565b6007556001600160a01b0381161561055d57610531816103f0565b6001600160a01b0382166000908152600a60209081526040808320939093556008546009909152919020555b600082116105b2576040805162461bcd60e51b815260206004820152601160248201527f43616e6e6f742077697468647261772030000000000000000000000000000000604482015290519081900360640190fd5b600b546105bf9083611360565b600b55336000908152600c60205260409020546105dc9083611360565b336000818152600c6020526040902091909155600354610608916001600160a01b03909116908461149e565b60408051838152905133917f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5919081900360200190a250506001600055565b60065481565b610655611523565b6001546001600160a01b039081169116146106b7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60006106c1610f71565b6008556106cc610ae2565b6007556001600160a01b03811615610713576106e7816103f0565b6001600160a01b0382166000908152600a60209081526040808320939093556008546009909152919020555b60045442106107325760065461072a908390611402565b600555610775565b6004546000906107429042611360565b9050600061075b600554836113a990919063ffffffff16565b60065490915061076f9061045c8684611444565b60055550505b600254604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156107d957600080fd5b505afa1580156107ed573d6000803e3d6000fd5b505050506040513d602081101561080357600080fd5b5051600654909150610816908290611402565b600554111561086c576040805162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015290519081900360640190fd5b42600781905560065461087f9190611444565b6004556040805184815290517fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9181900360200190a1505050565b60026000541415610912576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260005533610920610f71565b60085561092b610ae2565b6007556001600160a01b0381161561097257610946816103f0565b6001600160a01b0382166000908152600a60209081526040808320939093556008546009909152919020555b336000908152600a602052604090205480156109e857336000818152600a60205260408120556002546109b1916001600160a01b03909116908361149e565b60408051828152905133917fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486919081900360200190a25b50506001600055565b6001600160a01b03166000908152600c602052604090205490565b610a14611523565b6001546001600160a01b03908116911614610a76576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36001805473ffffffffffffffffffffffffffffffffffffffff19169055565b6003546001600160a01b031681565b60055481565b60006104a042600454611527565b610af8611523565b6001546001600160a01b03908116911614610b5a576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60026000541415610bb2576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000556003546001600160a01b0383811691161415610c045760405162461bcd60e51b8152600401808060200182810382526021815260200180611a466021913960400191505060405180910390fd5b610c20610c0f610c7f565b6001600160a01b038416908361149e565b604080516001600160a01b03841681526020810183905281517f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa28929181900390910190a150506001600055565b60096020526000908152604090205481565b6001546001600160a01b031690565b60026000541415610ce6576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260005533610cf4610f71565b600855610cff610ae2565b6007556001600160a01b03811615610d4657610d1a816103f0565b6001600160a01b0382166000908152600a60209081526040808320939093556008546009909152919020555b60008211610d9b576040805162461bcd60e51b815260206004820152600e60248201527f43616e6e6f74207374616b652030000000000000000000000000000000000000604482015290519081900360640190fd5b600b54610da89083611444565b600b55336000908152600c6020526040902054610dc59083611444565b336000818152600c6020526040902091909155600354610df2916001600160a01b0390911690308561153d565b60408051838152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a250506001600055565b60075481565b610e3f611523565b6001546001600160a01b03908116911614610ea1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6004544211610ee15760405162461bcd60e51b81526004018080602001828103825260588152602001806119576058913960600191505060405180910390fd5b60008111610f36576040805162461bcd60e51b815260206004820152601d60248201527f526577617264206475726174696f6e2063616e2774206265207a65726f000000604482015290519081900360640190fd5b60068190556040805182815290517ffb46ca5a5e06d4540d6387b930a7c978bce0db5f449ec6b3f5d07c6e1d44f2d39181900360200190a150565b6000600b5460001415610f875750600854610484565b6104a0610fb6600b5461045c670de0b6b3a7640000610fb0600554610fb0600754610437610ae2565b906113a9565b60085490611444565b6002546001600160a01b031681565b60085481565b336000908152600c6020526040902054610fed906104a5565b610ff56108ba565b565b60045481565b60026000541415611055576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260005533611063610f71565b60085561106e610ae2565b6007556001600160a01b038116156110b557611089816103f0565b6001600160a01b0382166000908152600a60209081526040808320939093556008546009909152919020555b6000861161110a576040805162461bcd60e51b815260206004820152600e60248201527f43616e6e6f74207374616b652030000000000000000000000000000000000000604482015290519081900360640190fd5b600b546111179087611444565b600b55336000908152600c60205260409020546111349087611444565b336000818152600c60205260408082209390935560035483517fd505accf0000000000000000000000000000000000000000000000000000000081526004810193909352306024840152604483018a90526064830189905260ff8816608484015260a4830187905260c4830186905292516001600160a01b039093169263d505accf9260e480820193929182900301818387803b1580156111d457600080fd5b505af11580156111e8573d6000803e3d6000fd5b505060035461120592506001600160a01b0316905033308961153d565b60408051878152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a25050600160005550505050565b611250611523565b6001546001600160a01b039081169116146112b2576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166112f75760405162461bcd60e51b81526004018080602001828103825260268152602001806119af6026913960400191505060405180910390fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006113a283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506115cb565b9392505050565b6000826113b857506000610468565b828202828482816113c557fe5b04146113a25760405162461bcd60e51b81526004018080602001828103825260218152602001806119fb6021913960400191505060405180910390fd5b60006113a283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611662565b6000828201838110156113a2576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261151e9084906116c7565b505050565b3390565b600081831061153657816113a2565b5090919050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526115c59085906116c7565b50505050565b6000818484111561165a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561161f578181015183820152602001611607565b50505050905090810190601f16801561164c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836116b15760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561161f578181015183820152602001611607565b5060008385816116bd57fe5b0495945050505050565b600061171c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166117789092919063ffffffff16565b80519091501561151e5780806020019051602081101561173b57600080fd5b505161151e5760405162461bcd60e51b815260040180806020018281038252602a815260200180611a1c602a913960400191505060405180910390fd5b6060611787848460008561178f565b949350505050565b6060824710156117d05760405162461bcd60e51b81526004018080602001828103825260268152602001806119d56026913960400191505060405180910390fd5b6117d9856118ea565b61182a576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600080866001600160a01b031685876040518082805190602001908083835b602083106118685780518252601f199092019160209182019101611849565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146118ca576040519150601f19603f3d011682016040523d82523d6000602084013e6118cf565b606091505b50915091506118df8282866118f0565b979650505050505050565b3b151590565b606083156118ff5750816113a2565b82511561190f5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561161f57818101518382015260200161160756fe50726576696f7573207265776172647320706572696f64206d75737420626520636f6d706c657465206265666f7265206368616e67696e6720746865206475726174696f6e20666f7220746865206e657720706572696f644f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656443616e6e6f7420776974686472617720746865207374616b696e6720746f6b656ea26469706673582212206f44426a74f577b6d4f862ae02ec89c75f5c1bc3041e522f4a80381cfe10654964736f6c63430007060033000000000000000000000000340fe1d898eccaad394e2ba0fc1f93d27c7b717a00000000000000000000000060781c2586d68229fde47564546784ab3faca982

Deployed ByteCode Sourcemap

27455:6589:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29089:198;;;;;;;;;;;;;;;;-1:-1:-1;29089:198:0;-1:-1:-1;;;;;29089:198:0;;:::i;:::-;;;;;;;;;;;;;;;;27963:42;;;;;;;;;;;;;;;;-1:-1:-1;27963:42:0;-1:-1:-1;;;;;27963:42:0;;:::i;28391:93::-;;;:::i;29295:121::-;;;:::i;30420:357::-;;;;;;;;;;;;;;;;-1:-1:-1;30420:357:0;;:::i;:::-;;27773:39;;;:::i;31345:1069::-;;;;;;;;;;;;;;;;-1:-1:-1;31345:1069:0;;:::i;30785:307::-;;;:::i;28492:112::-;;;;;;;;;;;;;;;;-1:-1:-1;28492:112:0;-1:-1:-1;;;;;28492:112:0;;:::i;2860:148::-;;;:::i;27666:26::-;;;:::i;:::-;;;;-1:-1:-1;;;;;27666:26:0;;;;;;;;;;;;;;27737:29;;;:::i;28612:131::-;;;:::i;32529:317::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;32529:317:0;;;;;;;;:::i;27899:57::-;;;;;;;;;;;;;;;;-1:-1:-1;27899:57:0;-1:-1:-1;;;;;27899:57:0;;:::i;2218:79::-;;;:::i;30043:369::-;;;;;;;;;;;;;;;;-1:-1:-1;30043:369:0;;:::i;27819:29::-;;;:::i;32854:433::-;;;;;;;;;;;;;;;;-1:-1:-1;32854:433:0;;:::i;28751:330::-;;;:::i;27633:26::-;;;:::i;27855:35::-;;;:::i;31100:97::-;;;:::i;27699:31::-;;;:::i;29478:557::-;;;;;;;;;;;;;;;;-1:-1:-1;29478:557:0;;;;;;;;;;;;;;;;;;;;;;;;:::i;3163:244::-;;;;;;;;;;;;;;;;-1:-1:-1;3163:244:0;-1:-1:-1;;;;;3163:244:0;;:::i;29089:198::-;-1:-1:-1;;;;;29262:16:0;;29143:7;29262:16;;;:7;:16;;;;;;;;;29214:22;:31;;;;;;29170:109;;29262:16;29170:87;;29252:4;;29170:77;;29193:53;;:16;:14;:16::i;:::-;:20;;:53::i;:::-;-1:-1:-1;;;;;29170:18:0;;;;;;:9;:18;;;;;;;:22;:77::i;:::-;:81;;:87::i;:::-;:91;;:109::i;:::-;29163:116;29089:198;-1:-1:-1;;29089:198:0:o;27963:42::-;;;;;;;;;;;;;:::o;28391:93::-;28464:12;;28391:93;;:::o;29295:121::-;29350:7;29377:31;29392:15;;29377:10;;:14;;:31;;;;:::i;:::-;29370:38;;29295:121;:::o;30420:357::-;25073:1;25679:7;;:19;;25671:63;;;;;-1:-1:-1;;;25671:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;25073:1;25812:7;:18;30487:10:::1;33413:16;:14;:16::i;:::-;33390:20;:39:::0;33457:26:::1;:24;:26::i;:::-;33440:14;:43:::0;-1:-1:-1;;;;;33498:21:0;::::1;::::0;33494:157:::1;;33555:15;33562:7;33555:6;:15::i;:::-;-1:-1:-1::0;;;;;33536:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;33619:20:::1;::::0;33585:22:::1;:31:::0;;;;;;:54;33494:157:::1;30527:1:::2;30518:6;:10;30510:40;;;::::0;;-1:-1:-1;;;30510:40:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;30576:12;::::0;:24:::2;::::0;30593:6;30576:16:::2;:24::i;:::-;30561:12;:39:::0;30645:10:::2;30635:21;::::0;;;:9:::2;:21;::::0;;;;;:33:::2;::::0;30661:6;30635:25:::2;:33::i;:::-;30621:10;30611:21;::::0;;;:9:::2;:21;::::0;;;;:57;;;;30679:12:::2;::::0;:45:::2;::::0;-1:-1:-1;;;;;30679:12:0;;::::2;::::0;30717:6;30679:25:::2;:45::i;:::-;30740:29;::::0;;;;;;;30750:10:::2;::::0;30740:29:::2;::::0;;;;;::::2;::::0;;::::2;-1:-1:-1::0;;25029:1:0;25991:7;:22;30420:357::o;27773:39::-;;;;:::o;31345:1069::-;2440:12;:10;:12::i;:::-;2430:6;;-1:-1:-1;;;;;2430:6:0;;;:22;;;2422:67;;;;;-1:-1:-1;;;2422:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31429:1:::1;33413:16;:14;:16::i;:::-;33390:20;:39:::0;33457:26:::1;:24;:26::i;:::-;33440:14;:43:::0;-1:-1:-1;;;;;33498:21:0;::::1;::::0;33494:157:::1;;33555:15;33562:7;33555:6;:15::i;:::-;-1:-1:-1::0;;;;;33536:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;33619:20:::1;::::0;33585:22:::1;:31:::0;;;;;;:54;33494:157:::1;31467:12:::2;;31448:15;:31;31444:318;;31520:15;::::0;31509:27:::2;::::0;:6;;:10:::2;:27::i;:::-;31496:10;:40:::0;31444:318:::2;;;31589:12;::::0;31569:17:::2;::::0;31589:33:::2;::::0;31606:15:::2;31589:16;:33::i;:::-;31569:53;;31637:16;31656:25;31670:10;;31656:9;:13;;:25;;;;:::i;:::-;31734:15;::::0;31637:44;;-1:-1:-1;31709:41:0::2;::::0;:20:::2;:6:::0;31637:44;31709:10:::2;:20::i;:41::-;31696:10;:54:::0;-1:-1:-1;;31444:318:0::2;32137:12;::::0;:37:::2;::::0;;;;;32168:4:::2;32137:37;::::0;::::2;::::0;;;32122:12:::2;::::0;-1:-1:-1;;;;;32137:12:0::2;::::0;:22:::2;::::0;:37;;;;;::::2;::::0;;;;;;;;:12;:37;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;32137:37:0;32219:15:::2;::::0;32137:37;;-1:-1:-1;32207:28:0::2;::::0;32137:37;;32207:11:::2;:28::i;:::-;32193:10;;:42;;32185:79;;;::::0;;-1:-1:-1;;;32185:79:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;32294:15;32277:14;:32:::0;;;32355:15:::2;::::0;32335:36:::2;::::0;32294:15;32335:19:::2;:36::i;:::-;32320:12;:51:::0;32387:19:::2;::::0;;;;;;;::::2;::::0;;;;::::2;::::0;;::::2;33661:1;2500::::1;31345:1069:::0;:::o;30785:307::-;25073:1;25679:7;;:19;;25671:63;;;;;-1:-1:-1;;;25671:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;25073:1;25812:7;:18;30839:10:::1;33413:16;:14;:16::i;:::-;33390:20;:39:::0;33457:26:::1;:24;:26::i;:::-;33440:14;:43:::0;-1:-1:-1;;;;;33498:21:0;::::1;::::0;33494:157:::1;;33555:15;33562:7;33555:6;:15::i;:::-;-1:-1:-1::0;;;;;33536:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;33619:20:::1;::::0;33585:22:::1;:31:::0;;;;;;:54;33494:157:::1;30887:10:::2;30862:14;30879:19:::0;;;:7:::2;:19;::::0;;;;;30913:10;;30909:176:::2;;30948:10;30962:1;30940:19:::0;;;:7:::2;:19;::::0;;;;:23;30978:12:::2;::::0;:45:::2;::::0;-1:-1:-1;;;;;30978:12:0;;::::2;::::0;31016:6;30978:25:::2;:45::i;:::-;31043:30;::::0;;;;;;;31054:10:::2;::::0;31043:30:::2;::::0;;;;;::::2;::::0;;::::2;30909:176;-1:-1:-1::0;;25029:1:0;25991:7;:22;30785:307::o;28492:112::-;-1:-1:-1;;;;;28578:18:0;28551:7;28578:18;;;:9;:18;;;;;;;28492:112::o;2860:148::-;2440:12;:10;:12::i;:::-;2430:6;;-1:-1:-1;;;;;2430:6:0;;;:22;;;2422:67;;;;;-1:-1:-1;;;2422:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2951:6:::1;::::0;2930:40:::1;::::0;2967:1:::1;::::0;-1:-1:-1;;;;;2951:6:0::1;::::0;2930:40:::1;::::0;2967:1;;2930:40:::1;2981:6;:19:::0;;-1:-1:-1;;2981:19:0::1;::::0;;2860:148::o;27666:26::-;;;-1:-1:-1;;;;;27666:26:0;;:::o;27737:29::-;;;;:::o;28612:131::-;28669:7;28696:39;28705:15;28722:12;;28696:8;:39::i;32529:317::-;2440:12;:10;:12::i;:::-;2430:6;;-1:-1:-1;;;;;2430:6:0;;;:22;;;2422:67;;;;;-1:-1:-1;;;2422:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25073:1:::1;25679:7;;:19;;25671:63;;;::::0;;-1:-1:-1;;;25671:63:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;25073:1;25812:7;:18:::0;32669:12:::2;::::0;-1:-1:-1;;;;;32645:37:0;;::::2;32669:12:::0;::::2;32645:37;;32637:83;;;;-1:-1:-1::0;;;32637:83:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32731:55;32765:7;:5;:7::i;:::-;-1:-1:-1::0;;;;;32731:33:0;::::2;::::0;32774:11;32731:33:::2;:55::i;:::-;32802:36;::::0;;-1:-1:-1;;;;;32802:36:0;::::2;::::0;;::::2;::::0;::::2;::::0;;;;;::::2;::::0;;;;;;;;;::::2;-1:-1:-1::0;;25029:1:0::1;25991:7;:22:::0;32529:317::o;27899:57::-;;;;;;;;;;;;;:::o;2218:79::-;2283:6;;-1:-1:-1;;;;;2283:6:0;2218:79;:::o;30043:369::-;25073:1;25679:7;;:19;;25671:63;;;;;-1:-1:-1;;;25671:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;25073:1;25812:7;:18;30109:10:::1;33413:16;:14;:16::i;:::-;33390:20;:39:::0;33457:26:::1;:24;:26::i;:::-;33440:14;:43:::0;-1:-1:-1;;;;;33498:21:0;::::1;::::0;33494:157:::1;;33555:15;33562:7;33555:6;:15::i;:::-;-1:-1:-1::0;;;;;33536:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;33619:20:::1;::::0;33585:22:::1;:31:::0;;;;;;:54;33494:157:::1;30149:1:::2;30140:6;:10;30132:37;;;::::0;;-1:-1:-1;;;30132:37:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;30195:12;::::0;:24:::2;::::0;30212:6;30195:16:::2;:24::i;:::-;30180:12;:39:::0;30264:10:::2;30254:21;::::0;;;:9:::2;:21;::::0;;;;;:33:::2;::::0;30280:6;30254:25:::2;:33::i;:::-;30240:10;30230:21;::::0;;;:9:::2;:21;::::0;;;;:57;;;;30298:12:::2;::::0;:64:::2;::::0;-1:-1:-1;;;;;30298:12:0;;::::2;::::0;30348:4:::2;30355:6:::0;30298:29:::2;:64::i;:::-;30378:26;::::0;;;;;;;30385:10:::2;::::0;30378:26:::2;::::0;;;;;::::2;::::0;;::::2;-1:-1:-1::0;;25029:1:0;25991:7;:22;30043:369::o;27819:29::-;;;;:::o;32854:433::-;2440:12;:10;:12::i;:::-;2430:6;;-1:-1:-1;;;;;2430:6:0;;;:22;;;2422:67;;;;;-1:-1:-1;;;2422:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32978:12:::1;;32960:15;:30;32938:168;;;;-1:-1:-1::0;;;32938:168:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33144:1;33125:16;:20;33117:62;;;::::0;;-1:-1:-1;;;33117:62:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;33190:15;:34:::0;;;33240:39:::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;32854:433:::0;:::o;28751:330::-;28798:7;28822:12;;28838:1;28822:17;28818:77;;;-1:-1:-1;28863:20:0;;28856:27;;28818:77;28925:148;28968:90;29045:12;;28968:72;29035:4;28968:62;29019:10;;28968:46;28999:14;;28968:26;:24;:26::i;:46::-;:50;;:62::i;:90::-;28925:20;;;:24;:148::i;27633:26::-;;;-1:-1:-1;;;;;27633:26:0;;:::o;27855:35::-;;;;:::o;31100:97::-;31155:10;31145:21;;;;:9;:21;;;;;;31136:31;;:8;:31::i;:::-;31178:11;:9;:11::i;:::-;31100:97::o;27699:31::-;;;;:::o;29478:557::-;25073:1;25679:7;;:19;;25671:63;;;;;-1:-1:-1;;;25671:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;25073:1;25812:7;:18;29600:10:::1;33413:16;:14;:16::i;:::-;33390:20;:39:::0;33457:26:::1;:24;:26::i;:::-;33440:14;:43:::0;-1:-1:-1;;;;;33498:21:0;::::1;::::0;33494:157:::1;;33555:15;33562:7;33555:6;:15::i;:::-;-1:-1:-1::0;;;;;33536:16:0;::::1;;::::0;;;:7:::1;:16;::::0;;;;;;;:34;;;;33619:20:::1;::::0;33585:22:::1;:31:::0;;;;;;:54;33494:157:::1;29640:1:::2;29631:6;:10;29623:37;;;::::0;;-1:-1:-1;;;29623:37:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;29686:12;::::0;:24:::2;::::0;29703:6;29686:16:::2;:24::i;:::-;29671:12;:39:::0;29755:10:::2;29745:21;::::0;;;:9:::2;:21;::::0;;;;;:33:::2;::::0;29771:6;29745:25:::2;:33::i;:::-;29731:10;29721:21;::::0;;;:9:::2;:21;::::0;;;;;:57;;;;29833:12:::2;::::0;29810:98;;;;;::::2;::::0;::::2;::::0;;;;29875:4:::2;29810:98:::0;;;;;;;;;;;;;;;;::::2;::::0;::::2;::::0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;29833:12:0;;::::2;::::0;29810:44:::2;::::0;:98;;;;;29721:21;29810:98;;;;;;29721:21;29833:12;29810:98;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;29921:12:0::2;::::0;:64:::2;::::0;-1:-1:-1;;;;;;29921:12:0::2;::::0;-1:-1:-1;29951:10:0::2;29971:4;29978:6:::0;29921:29:::2;:64::i;:::-;30001:26;::::0;;;;;;;30008:10:::2;::::0;30001:26:::2;::::0;;;;;::::2;::::0;;::::2;-1:-1:-1::0;;25029:1:0;25991:7;:22;-1:-1:-1;;;;29478:557:0:o;3163:244::-;2440:12;:10;:12::i;:::-;2430:6;;-1:-1:-1;;;;;2430:6:0;;;:22;;;2422:67;;;;;-1:-1:-1;;;2422:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3252:22:0;::::1;3244:73;;;;-1:-1:-1::0;;;3244:73:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3354:6;::::0;3333:38:::1;::::0;-1:-1:-1;;;;;3333:38:0;;::::1;::::0;3354:6:::1;::::0;3333:38:::1;::::0;3354:6:::1;::::0;3333:38:::1;3382:6;:17:::0;;-1:-1:-1;;3382:17:0::1;-1:-1:-1::0;;;;;3382:17:0;;;::::1;::::0;;;::::1;::::0;;3163:244::o;5692:136::-;5750:7;5777:43;5781:1;5784;5777:43;;;;;;;;;;;;;;;;;:3;:43::i;:::-;5770:50;5692:136;-1:-1:-1;;;5692:136:0:o;6582:471::-;6640:7;6885:6;6881:47;;-1:-1:-1;6915:1:0;6908:8;;6881:47;6952:5;;;6956:1;6952;:5;:1;6976:5;;;;;:10;6968:56;;;;-1:-1:-1;;;6968:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7529:132;7587:7;7614:39;7618:1;7621;7614:39;;;;;;;;;;;;;;;;;:3;:39::i;5228:181::-;5286:7;5318:5;;;5342:6;;;;5334:46;;;;;-1:-1:-1;;;5334:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;20234:177;20344:58;;;-1:-1:-1;;;;;20344:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20367:23;20344:58;;;20317:86;;20337:5;;20317:19;:86::i;:::-;20234:177;;;:::o;743:106::-;831:10;743:106;:::o;3860:::-;3918:7;3949:1;3945;:5;:13;;3957:1;3945:13;;;-1:-1:-1;3953:1:0;;3860:106;-1:-1:-1;3860:106:0:o;20419:205::-;20547:68;;;-1:-1:-1;;;;;20547:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20570:27;20547:68;;;20520:96;;20540:5;;20520:19;:96::i;:::-;20419:205;;;;:::o;6131:192::-;6217:7;6253:12;6245:6;;;;6237:29;;;;-1:-1:-1;;;6237:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;6289:5:0;;;6131:192::o;8157:278::-;8243:7;8278:12;8271:5;8263:28;;;;-1:-1:-1;;;8263:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8302:9;8318:1;8314;:5;;;;;;;8157:278;-1:-1:-1;;;;;8157:278:0:o;22539:761::-;22963:23;22989:69;23017:4;22989:69;;;;;;;;;;;;;;;;;22997:5;-1:-1:-1;;;;;22989:27:0;;;:69;;;;;:::i;:::-;23073:17;;22963:95;;-1:-1:-1;23073:21:0;23069:224;;23215:10;23204:30;;;;;;;;;;;;;;;-1:-1:-1;23204:30:0;23196:85;;;;-1:-1:-1;;;23196:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16219:195;16322:12;16354:52;16376:6;16384:4;16390:1;16393:12;16354:21;:52::i;:::-;16347:59;16219:195;-1:-1:-1;;;;16219:195:0:o;17271:530::-;17398:12;17456:5;17431:21;:30;;17423:81;;;;-1:-1:-1;;;17423:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17523:18;17534:6;17523:10;:18::i;:::-;17515:60;;;;;-1:-1:-1;;;17515:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;17649:12;17663:23;17690:6;-1:-1:-1;;;;;17690:11:0;17710:5;17718:4;17690:33;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;17690:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17648:75;;;;17741:52;17759:7;17768:10;17780:12;17741:17;:52::i;:::-;17734:59;17271:530;-1:-1:-1;;;;;;;17271:530:0:o;13301:422::-;13668:20;13707:8;;;13301:422::o;18807:742::-;18922:12;18951:7;18947:595;;;-1:-1:-1;18982:10:0;18975:17;;18947:595;19096:17;;:21;19092:439;;19359:10;19353:17;19420:15;19407:10;19403:2;19399:19;19392:44;19307:148;19495:20;;-1:-1:-1;;;19495:20:0;;;;;;;;;;;;;;;;;19502:12;;19495:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Swarm Source

ipfs://6f44426a74f577b6d4f862ae02ec89c75f5c1bc3041e522f4a80381cfe106549
Loading