Contract 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c

Contract Overview

Balance:
0 BNB
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x152a0ba221a34697e11852e686dca53bdafe8dd01746cb90cd4e6e3232c66c790x6080604087371672021-05-11 3:03:12135 days 21 hrs ago0x20000b9b01e93a39db9d286e9264eff7f2af16e9 IN  Contract Creation0 BNB0.01156941
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x685ca72d08c0fa9e4ae4056635832ee26cea6ca26735f66d6bf566b02fb804cc105252542021-07-12 10:44:0873 days 13 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x50f90eaf4a6e3a8c60c1aa5e42e142ee33e124ba1261c81945d191b31c9a9bbb93151152021-05-31 6:01:29115 days 18 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x35a13b0aa08592af721b7413b510aeb32583bfa04927828e617393acc895318c93151122021-05-31 6:01:20115 days 18 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x0aa38b706af1d27d12f918630386e4cd47708664650aca259e3fbb9029aa99dc93151092021-05-31 6:01:11115 days 18 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0xcdb42b518157caf306910665809d80189fcab0071ede49f9ea319e961c45e56a93151062021-05-31 6:01:02115 days 18 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x86c8370fe79fcd03cde9bf2943a50223a93ca17c8c256562590b0091b3b6b6c793151032021-05-31 6:00:53115 days 18 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0xeaffc0a0a61156905b14d2fad826ab206adf5a88efbafb5c3d4efb32486a46bf93139152021-05-31 5:01:29115 days 19 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0xc05324442b6d1e66105bd3528cb388635a9df865d8c45ae76fbb312ca5602db693139112021-05-31 5:01:17115 days 19 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0xcd53f6ae1b5e21d11c1aa8c0ee8bf3f00250aba59c80ee815203ae146107d2f993139092021-05-31 5:01:11115 days 19 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x3c9c82fd8d22ad47e0f10a88f13e947807f3b862b66d5d690518f010e939104593139062021-05-31 5:01:02115 days 19 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x7976ee4c5137ec517706274f43c03f498684c441a01db252487b405f9315c34393139022021-05-31 5:00:50115 days 19 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0xa9663597d3bdbcab70a7be83a1d9f328639c2f26ad179f4782f52e2e5cc5760b93127122021-05-31 4:01:20115 days 20 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x62a8efe602db88cf67b4d79347fc66b61c535757e5689ff1eceaa369461e8efd93127102021-05-31 4:01:14115 days 20 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x547a07f5969abffc095affafa04ae9eb7a36bb79283aec1c5ca94142615ccb1f93127072021-05-31 4:01:05115 days 20 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x0dedf43f56b452f604d247f6985d54b0a05fbdbbe6cfcf64a168ba1cd13738e293127052021-05-31 4:00:59115 days 20 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0xfc443c4284776dbf6a7abbfd621159daeaa2b4de2efddd602fe8e176a85859d393127032021-05-31 4:00:53115 days 20 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x7197eadae9e37730500d47f38d147592115d50d20486e8218f102775f7b2df0493115222021-05-31 3:01:50115 days 21 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0xa920c658f55e35ff3200f3bf34df05f94db821f92858e1c64eeb4f0a88a83d7d93115172021-05-31 3:01:35115 days 21 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x1a7e24d9f524877136492de642311ae0be5b4ba7b68219e1dc5318fd64f830a793115132021-05-31 3:01:23115 days 21 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x6af613639a765ebb786ba82b4d9076ee20fdfc1f497ccf31f70b4ff9f1710e2693115092021-05-31 3:01:11115 days 21 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x8efc8a3a2b7d422d07b2453583e6cfa0029620ee63d445acd1da6cbfd558601793115022021-05-31 3:00:50115 days 21 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0xd2ba1a475dac7bb9e8563b3b8c94f21056fc520ad97a2de5d1e6469a4298516593103162021-05-31 2:01:32115 days 22 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0xc06a3d784ef8a1af1cd12be844865e6db6f07cff50f92dda07daf72b4984bd8093103122021-05-31 2:01:20115 days 22 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0x8391987790477cbe7e8bc124d2460efb19cfdddff21c4e621076a622f779c49f93103092021-05-31 2:01:11115 days 22 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
0xf12e19ea040778cdbb4fe96a5294bcf7e27eddd2b4884065581fe589b4f0234493103072021-05-31 2:01:05115 days 22 hrs ago 0xcbf577017c2a05a3dd47541c95911e570f07d9b6 0xc1d1506cb8ea2efe217f2b2fe626749afd690e0c0 BNB
[ Download CSV Export 
Loading

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x604d30789bD7fB3d8068C3A922492de131c70602

Contract Name:
BSCPriceFeed

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at BscScan.com on 2021-02-23
*/

// File: @chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol

pragma solidity >=0.6.0;

interface AggregatorV3Interface {

  function decimals() external view returns (uint8);
  function description() external view returns (string memory);
  function version() external view returns (uint256);

  // getRoundData and latestRoundData should both raise "No data present"
  // if they do not have data to report, instead of returning unset values
  // which could be misinterpreted as actual reported values.
  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

}

// File: @openzeppelin/contracts-upgradeable/proxy/Initializable.sol

// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version


/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 * 
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
 * 
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function _isConstructor() private view returns (bool) {
        // extcodesize checks the size of the code stored in an address, and
        // address returns the current address. Since the code is still not
        // deployed when running a constructor, any checks on its code size will
        // yield zero, making it an effective way to detect if a contract is
        // under construction or not.
        address self = address(this);
        uint256 cs;
        // solhint-disable-next-line no-inline-assembly
        assembly { cs := extcodesize(self) }
        return cs == 0;
    }
}

// File: @openzeppelin/contracts-upgradeable/GSN/ContextUpgradeable.sol




/*
 * @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 ContextUpgradeable is Initializable {
    function __Context_init() internal initializer {
        __Context_init_unchained();
    }

    function __Context_init_unchained() internal initializer {
    }
    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;
    }
    uint256[50] private __gap;
}

// File: @openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol




/**
 * @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 OwnableUpgradeable is Initializable, ContextUpgradeable {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal initializer {
        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;
    }
    uint256[49] private __gap;
}

// File: @openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol



/**
 * @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 SafeMathUpgradeable {
    /**
     * @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: contracts/interface/IBSCPriceFeed.sol


interface IBSCPriceFeed {
    // get latest price
    function getPrice(bytes32 _priceFeedKey) external view returns (uint256);

    // get twap price depending on _period
    function getTwapPrice(bytes32 _priceFeedKey, uint256 _interval) external view returns (uint256);
}

// File: contracts/utils/DecimalMath.sol



/// @dev Implements simple fixed point math add, sub, mul and div operations.
/// @author Alberto Cuesta Cañada
library DecimalMath {
    using SafeMathUpgradeable for uint256;

    /// @dev Returns 1 in the fixed point representation, with `decimals` decimals.
    function unit(uint8 decimals) internal pure returns (uint256) {
        return 10**uint256(decimals);
    }

    /// @dev Adds x and y, assuming they are both fixed point with 18 decimals.
    function addd(uint256 x, uint256 y) internal pure returns (uint256) {
        return x.add(y);
    }

    /// @dev Subtracts y from x, assuming they are both fixed point with 18 decimals.
    function subd(uint256 x, uint256 y) internal pure returns (uint256) {
        return x.sub(y);
    }

    /// @dev Multiplies x and y, assuming they are both fixed point with 18 digits.
    function muld(uint256 x, uint256 y) internal pure returns (uint256) {
        return muld(x, y, 18);
    }

    /// @dev Multiplies x and y, assuming they are both fixed point with `decimals` digits.
    function muld(
        uint256 x,
        uint256 y,
        uint8 decimals
    ) internal pure returns (uint256) {
        return x.mul(y).div(unit(decimals));
    }

    /// @dev Divides x between y, assuming they are both fixed point with 18 digits.
    function divd(uint256 x, uint256 y) internal pure returns (uint256) {
        return divd(x, y, 18);
    }

    /// @dev Divides x between y, assuming they are both fixed point with `decimals` digits.
    function divd(
        uint256 x,
        uint256 y,
        uint8 decimals
    ) internal pure returns (uint256) {
        return x.mul(unit(decimals)).div(y);
    }
}

// File: contracts/utils/Decimal.sol




library Decimal {
    using DecimalMath for uint256;
    using SafeMathUpgradeable for uint256;

    struct decimal {
        uint256 d;
    }

    function zero() internal pure returns (decimal memory) {
        return decimal(0);
    }

    function one() internal pure returns (decimal memory) {
        return decimal(DecimalMath.unit(18));
    }

    function toUint(decimal memory x) internal pure returns (uint256) {
        return x.d;
    }

    function modD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        return decimal(x.d.mul(DecimalMath.unit(18)) % y.d);
    }

    function cmp(decimal memory x, decimal memory y) internal pure returns (int8) {
        if (x.d > y.d) {
            return 1;
        } else if (x.d < y.d) {
            return -1;
        }
        return 0;
    }

    /// @dev add two decimals
    function addD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.add(y.d);
        return t;
    }

    /// @dev subtract two decimals
    function subD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.sub(y.d);
        return t;
    }

    /// @dev multiple two decimals
    function mulD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.muld(y.d);
        return t;
    }

    /// @dev multiple a decimal by a uint256
    function mulScalar(decimal memory x, uint256 y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.mul(y);
        return t;
    }

    /// @dev divide two decimals
    function divD(decimal memory x, decimal memory y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.divd(y.d);
        return t;
    }

    /// @dev divide a decimal by a uint256
    function divScalar(decimal memory x, uint256 y) internal pure returns (decimal memory) {
        decimal memory t;
        t.d = x.d.div(y);
        return t;
    }
}

// File: contracts/BSCPriceFeed.sol







contract BSCPriceFeed is IBSCPriceFeed, OwnableUpgradeable {
    using SafeMathUpgradeable for uint256;
    using Decimal for Decimal.decimal;

    uint256 private constant TOKEN_DIGIT = 10**18;

    event AggregatorAdded(bytes32 currencyKey, address aggregator);
    event AggregatorRemoved(bytes32 currencyKey, address aggregator);

    // key by currency symbol, eg ETH
    mapping(bytes32 => AggregatorV3Interface) public priceFeedMap;
    bytes32[] public priceFeedKeys;

    //**********************************************************//
    //    Can not change the order of above state variables     //
    //**********************************************************//

    //◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤ add state variables below ◥◤◥◤◥◤◥◤◥◤◥◤◥◤◥◤//

    //◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣ add state variables above ◢◣◢◣◢◣◢◣◢◣◢◣◢◣◢◣//
    uint256[50] private __gap;

    //
    // FUNCTIONS
    //
    function initialize() public initializer {
        __Ownable_init();
    }

    function addAggregator(bytes32 _priceFeedKey, address _aggregator) external onlyOwner {
        requireNonEmptyAddress(_aggregator);
        if (address(priceFeedMap[_priceFeedKey]) == address(0)) {
            priceFeedKeys.push(_priceFeedKey);
        }
        priceFeedMap[_priceFeedKey] = AggregatorV3Interface(_aggregator);
        emit AggregatorAdded(_priceFeedKey, address(_aggregator));
    }

    function removeAggregator(bytes32 _priceFeedKey) external onlyOwner {
        address aggregator = address(priceFeedMap[_priceFeedKey]);
        requireNonEmptyAddress(aggregator);
        delete priceFeedMap[_priceFeedKey];

        uint256 length = priceFeedKeys.length;
        for (uint256 i; i < length; i++) {
            if (priceFeedKeys[i] == _priceFeedKey) {
                // if the removal item is the last one, just `pop`
                if (i != length - 1) {
                    priceFeedKeys[i] = priceFeedKeys[length - 1];
                }
                priceFeedKeys.pop();
                emit AggregatorRemoved(_priceFeedKey, aggregator);
                break;
            }
        }
    }

    function getAggregator(bytes32 _priceFeedKey) public view returns (AggregatorV3Interface) {
        return priceFeedMap[_priceFeedKey];
    }

    function getPrice(bytes32 _priceFeedKey) external view override returns (uint256) {
        require(isExistedKey(_priceFeedKey), "key not existed");
        AggregatorV3Interface aggregator = getAggregator(_priceFeedKey);

        (, int256 _price, , , ) = aggregator.latestRoundData();
        require(_price >= 0, "negative answer");
        uint8 decimals = aggregator.decimals();

        Decimal.decimal memory decimalPrice = Decimal.decimal(formatDecimals(uint256(_price), decimals));

        return decimalPrice.toUint();
    }

    function getLatestTimestamp(bytes32 _priceFeedKey) public view returns (uint256) {
        AggregatorV3Interface aggregator = getAggregator(_priceFeedKey);
        requireNonEmptyAddress(address(aggregator));

        (, , , uint256 timestamp, ) = aggregator.latestRoundData();

        return timestamp;
    }

    function getTwapPrice(bytes32 _priceFeedKey, uint256 _interval) external view override returns (uint256) {
        require(isExistedKey(_priceFeedKey), "key not existed");
        require(_interval != 0, "interval can't be 0");

        // ** We assume L1 and L2 timestamp will be very similar here **
        // 3 different timestamps, `previous`, `current`, `target`
        // `base` = now - _interval
        // `current` = current round timestamp from aggregator
        // `previous` = previous round timestamp form aggregator
        // now >= previous > current > = < base
        //
        //  while loop i = 0
        //  --+------+-----+-----+-----+-----+-----+
        //         base                 current  now(previous)
        //
        //  while loop i = 1
        //  --+------+-----+-----+-----+-----+-----+
        //         base           current previous now

        AggregatorV3Interface aggregator = getAggregator(_priceFeedKey);
        (uint80 roundId, int256 _price, , uint256 timestamp, ) = aggregator.latestRoundData();
        require(_price >= 0, "negative answer");
        uint8 decimals = aggregator.decimals();

        Decimal.decimal memory decimalPrice = Decimal.decimal(formatDecimals(uint256(_price), decimals));
        uint256 latestPrice = decimalPrice.toUint();

        require(roundId >= 0, "Not enough history");
        uint256 latestTimestamp = timestamp;
        uint256 baseTimestamp = block.timestamp.sub(_interval);
        // if latest updated timestamp is earlier than target timestamp, return the latest price.
        if (latestTimestamp < baseTimestamp || roundId == 0) {
            return latestPrice;
        }

        // rounds are like snapshots, latestRound means the latest price snapshot. follow chainlink naming
        uint256 cumulativeTime = block.timestamp.sub(latestTimestamp);
        uint256 previousTimestamp = latestTimestamp;
        uint256 weightedPrice = latestPrice.mul(cumulativeTime);
        while (true) {
            if (roundId == 0) {
                // if cumulative time is less than requested interval, return current twap price
                return weightedPrice.div(cumulativeTime);
            }

            roundId = roundId - 1;
            // get current round timestamp and price
            (, int256 _priceTemp, , uint256 currentTimestamp, ) = aggregator.getRoundData(roundId);
            require(_priceTemp >= 0, "negative answer");

            Decimal.decimal memory decimalPriceTemp = Decimal.decimal(formatDecimals(uint256(_priceTemp), decimals));
            uint256 price = decimalPriceTemp.toUint();

            // check if current round timestamp is earlier than target timestamp
            if (currentTimestamp <= baseTimestamp) {
                // weighted time period will be (target timestamp - previous timestamp). For example,
                // now is 1000, _interval is 100, then target timestamp is 900. If timestamp of current round is 970,
                // and timestamp of NEXT round is 880, then the weighted time period will be (970 - 900) = 70,
                // instead of (970 - 880)
                weightedPrice = weightedPrice.add(price.mul(previousTimestamp.sub(baseTimestamp)));
                break;
            }

            uint256 timeFraction = previousTimestamp.sub(currentTimestamp);
            weightedPrice = weightedPrice.add(price.mul(timeFraction));
            cumulativeTime = cumulativeTime.add(timeFraction);
            previousTimestamp = currentTimestamp;
        }
        return weightedPrice.div(_interval);
    }

    function isExistedKey(bytes32 _priceFeedKey) private view returns (bool) {
        uint256 length = priceFeedKeys.length;
        for (uint256 i; i < length; i++) {
            if (priceFeedKeys[i] == _priceFeedKey) {
                return true;
            }
        }
        return false;
    }

    function requireKeyExisted(bytes32 _key, bool _existed) private view {
        if (_existed) {
            require(isExistedKey(_key), "key not existed");
        } else {
            require(!isExistedKey(_key), "key existed");
        }
    }

    function requireNonEmptyAddress(address _addr) internal pure {
        require(_addr != address(0), "empty address");
    }

    function formatDecimals(uint256 _price, uint8 _decimals) internal pure returns (uint256) {
        return _price.mul(TOKEN_DIGIT).div(10**uint256(_decimals));
    }

    function getPriceFeedLength() public view returns (uint256 length) {
        return priceFeedKeys.length;
    }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"indexed":false,"internalType":"address","name":"aggregator","type":"address"}],"name":"AggregatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"indexed":false,"internalType":"address","name":"aggregator","type":"address"}],"name":"AggregatorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"bytes32","name":"_priceFeedKey","type":"bytes32"},{"internalType":"address","name":"_aggregator","type":"address"}],"name":"addAggregator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_priceFeedKey","type":"bytes32"}],"name":"getAggregator","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_priceFeedKey","type":"bytes32"}],"name":"getLatestTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_priceFeedKey","type":"bytes32"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPriceFeedLength","outputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_priceFeedKey","type":"bytes32"},{"internalType":"uint256","name":"_interval","type":"uint256"}],"name":"getTwapPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"priceFeedKeys","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"priceFeedMap","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_priceFeedKey","type":"bytes32"}],"name":"removeAggregator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b506113f9806100206000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c80634cea5ee81161008c5780638129fc1c116100665780638129fc1c146101ee5780638da5cb5b146101f6578063a2173df4146101fe578063f2fde38b14610221576100cf565b80634cea5ee8146101c1578063715018a6146101c95780637ad22632146101d1576100cf565b8063250742cc146100d45780632a0ab1dd1461010d5780632bed9e0c1461013c57806331d98b3f1461015b578063331b1816146101785780633f0e084f14610195575b600080fd5b6100f1600480360360208110156100ea57600080fd5b5035610247565b604080516001600160a01b039092168252519081900360200190f35b61012a6004803603602081101561012357600080fd5b5035610262565b60408051918252519081900360200190f35b6101596004803603602081101561015257600080fd5b5035610280565b005b61012a6004803603602081101561017157600080fd5b50356103fc565b6100f16004803603602081101561018e57600080fd5b50356105aa565b610159600480360360408110156101ab57600080fd5b50803590602001356001600160a01b03166105c5565b61012a6106e0565b6101596106e6565b61012a600480360360208110156101e757600080fd5b5035610788565b610159610811565b6100f16108bb565b61012a6004803603604081101561021457600080fd5b50803590602001356108ca565b6101596004803603602081101561023757600080fd5b50356001600160a01b0316610ce9565b6065602052600090815260409020546001600160a01b031681565b6066818154811061026f57fe5b600091825260209091200154905081565b610288610de2565b6033546001600160a01b039081169116146102d8576040805162461bcd60e51b815260206004820181905260248201526000805160206113a4833981519152604482015290519081900360640190fd5b6000818152606560205260409020546001600160a01b03166102f981610de6565b600082815260656020526040812080546001600160a01b0319169055606654905b818110156103f657836066828154811061033057fe5b906000526020600020015414156103ee57600182038114610380576066600183038154811061035b57fe5b90600052602060002001546066828154811061037357fe5b6000918252602090912001555b606680548061038b57fe5b600190038181906000526020600020016000905590557fec70e890fc7db7de4059b114c9093a1f41283d18ffcfbcac45566feea4d4f777848460405180838152602001826001600160a01b031681526020019250505060405180910390a16103f6565b60010161031a565b50505050565b600061040782610e31565b61044a576040805162461bcd60e51b815260206004820152600f60248201526e1ad95e481b9bdd08195e1a5cdd1959608a1b604482015290519081900360640190fd5b6000610455836105aa565b90506000816001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561049257600080fd5b505afa1580156104a6573d6000803e3d6000fd5b505050506040513d60a08110156104bc57600080fd5b50602001519050600081121561050b576040805162461bcd60e51b815260206004820152600f60248201526e3732b3b0ba34bb329030b739bbb2b960891b604482015290519081900360640190fd5b6000826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561054657600080fd5b505afa15801561055a573d6000803e3d6000fd5b505050506040513d602081101561057057600080fd5b5051905061057c61131b565b60405180602001604052806105918585610e7d565b9052905061059e81610ea8565b9450505050505b919050565b6000908152606560205260409020546001600160a01b031690565b6105cd610de2565b6033546001600160a01b0390811691161461061d576040805162461bcd60e51b815260206004820181905260248201526000805160206113a4833981519152604482015290519081900360640190fd5b61062681610de6565b6000828152606560205260409020546001600160a01b031661067857606680546001810182556000919091527f46501879b8ca8525e8c2fd519e2fbfcfa2ebea26501294aa02cbfcfb12e94354018290555b60008281526065602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518581529182015281517f0bcae573430f69c5361e5d76534d3f61d2d803958778680cd74be9dc6299bc63929181900390910190a15050565b60665490565b6106ee610de2565b6033546001600160a01b0390811691161461073e576040805162461bcd60e51b815260206004820181905260248201526000805160206113a4833981519152604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b600080610794836105aa565b905061079f81610de6565b6000816001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b1580156107da57600080fd5b505afa1580156107ee573d6000803e3d6000fd5b505050506040513d60a081101561080457600080fd5b5060600151949350505050565b600054610100900460ff168061082a575061082a610eac565b80610838575060005460ff16155b6108735760405162461bcd60e51b815260040180806020018281038252602e815260200180611355602e913960400191505060405180910390fd5b600054610100900460ff1615801561089e576000805460ff1961ff0019909116610100171660011790555b6108a6610eb2565b80156108b8576000805461ff00191690555b50565b6033546001600160a01b031690565b60006108d583610e31565b610918576040805162461bcd60e51b815260206004820152600f60248201526e1ad95e481b9bdd08195e1a5cdd1959608a1b604482015290519081900360640190fd5b81610960576040805162461bcd60e51b81526020600482015260136024820152720696e74657276616c2063616e2774206265203606c1b604482015290519081900360640190fd5b600061096b846105aa565b90506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b1580156109ab57600080fd5b505afa1580156109bf573d6000803e3d6000fd5b505050506040513d60a08110156109d557600080fd5b508051602082015160609092015190945090925090506000821215610a33576040805162461bcd60e51b815260206004820152600f60248201526e3732b3b0ba34bb329030b739bbb2b960891b604482015290519081900360640190fd5b6000846001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d6020811015610a9857600080fd5b50519050610aa461131b565b6040518060200160405280610ab98685610e7d565b905290506000610ac882610ea8565b9050836000610ad7428c610f4f565b905080821080610af1575069ffffffffffffffffffff8816155b15610b0757829950505050505050505050610ce3565b6000610b134284610f4f565b9050826000610b228684610f91565b90505b69ffffffffffffffffffff8b16610b5357610b408184610fea565b9c50505050505050505050505050610ce3565b60018b039a506000808d6001600160a01b0316639a6fc8f58e6040518263ffffffff1660e01b8152600401808269ffffffffffffffffffff16815260200191505060a06040518083038186803b158015610bac57600080fd5b505afa158015610bc0573d6000803e3d6000fd5b505050506040513d60a0811015610bd657600080fd5b50602081015160609091015190925090506000821215610c2f576040805162461bcd60e51b815260206004820152600f60248201526e3732b3b0ba34bb329030b739bbb2b960891b604482015290519081900360640190fd5b610c3761131b565b6040518060200160405280610c4c858e610e7d565b905290506000610c5b82610ea8565b9050878311610c8d57610c82610c7b610c74888b610f4f565b8390610f91565b869061102c565b945050505050610cca565b6000610c998785610f4f565b9050610caf610ca88383610f91565b879061102c565b9550610cbb888261102c565b97508396505050505050610b25565b610cd4818f610fea565b9c505050505050505050505050505b92915050565b610cf1610de2565b6033546001600160a01b03908116911614610d41576040805162461bcd60e51b815260206004820181905260248201526000805160206113a4833981519152604482015290519081900360640190fd5b6001600160a01b038116610d865760405162461bcd60e51b815260040180806020018281038252602681526020018061132f6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b6001600160a01b0381166108b8576040805162461bcd60e51b815260206004820152600d60248201526c656d707479206164647265737360981b604482015290519081900360640190fd5b606654600090815b81811015610e73578360668281548110610e4f57fe5b90600052602060002001541415610e6b576001925050506105a5565b600101610e39565b5060009392505050565b6000610ea160ff8316600a0a610e9b85670de0b6b3a7640000610f91565b90610fea565b9392505050565b5190565b303b1590565b600054610100900460ff1680610ecb5750610ecb610eac565b80610ed9575060005460ff16155b610f145760405162461bcd60e51b815260040180806020018281038252602e815260200180611355602e913960400191505060405180910390fd5b600054610100900460ff16158015610f3f576000805460ff1961ff0019909116610100171660011790555b610f47611086565b6108a6611126565b6000610ea183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061121f565b600082610fa057506000610ce3565b82820282848281610fad57fe5b0414610ea15760405162461bcd60e51b81526004018080602001828103825260218152602001806113836021913960400191505060405180910390fd5b6000610ea183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506112b6565b600082820183811015610ea1576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600054610100900460ff168061109f575061109f610eac565b806110ad575060005460ff16155b6110e85760405162461bcd60e51b815260040180806020018281038252602e815260200180611355602e913960400191505060405180910390fd5b600054610100900460ff161580156108a6576000805460ff1961ff00199091166101001716600117905580156108b8576000805461ff001916905550565b600054610100900460ff168061113f575061113f610eac565b8061114d575060005460ff16155b6111885760405162461bcd60e51b815260040180806020018281038252602e815260200180611355602e913960400191505060405180910390fd5b600054610100900460ff161580156111b3576000805460ff1961ff0019909116610100171660011790555b60006111bd610de2565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35080156108b8576000805461ff001916905550565b600081848411156112ae5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561127357818101518382015260200161125b565b50505050905090810190601f1680156112a05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836113055760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561127357818101518382015260200161125b565b50600083858161131157fe5b0495945050505050565b604051806020016040528060008152509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a26469706673582212209b3a3ca2ba4583cba604dc16bf1aba2b6c49d891188dad862c34b71f16d4e93464736f6c634300060c0033

Deployed ByteCode Sourcemap

17089:7964:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17476:61;;;;;;;;;;;;;;;;-1:-1:-1;17476:61:0;;:::i;:::-;;;;-1:-1:-1;;;;;17476:61:0;;;;;;;;;;;;;;17544:30;;;;;;;;;;;;;;;;-1:-1:-1;17544:30:0;;:::i;:::-;;;;;;;;;;;;;;;;18626:732;;;;;;;;;;;;;;;;-1:-1:-1;18626:732:0;;:::i;:::-;;19517:546;;;;;;;;;;;;;;;;-1:-1:-1;19517:546:0;;:::i;19366:143::-;;;;;;;;;;;;;;;;-1:-1:-1;19366:143:0;;:::i;18209:409::-;;;;;;;;;;;;;;;;-1:-1:-1;18209:409:0;;;;;;-1:-1:-1;;;;;18209:409:0;;:::i;24937:113::-;;;:::i;6731:148::-;;;:::i;20071:317::-;;;;;;;;;;;;;;;;-1:-1:-1;20071:317:0;;:::i;18125:76::-;;;:::i;6089:79::-;;;:::i;20396:3654::-;;;;;;;;;;;;;;;;-1:-1:-1;20396:3654:0;;;;;;;:::i;7034:244::-;;;;;;;;;;;;;;;;-1:-1:-1;7034:244:0;-1:-1:-1;;;;;7034:244:0;;:::i;17476:61::-;;;;;;;;;;;;-1:-1:-1;;;;;17476:61:0;;:::o;17544:30::-;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;17544:30:0;:::o;18626:732::-;6311:12;:10;:12::i;:::-;6301:6;;-1:-1:-1;;;;;6301:6:0;;;:22;;;6293:67;;;;;-1:-1:-1;;;6293:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;6293:67:0;;;;;;;;;;;;;;;18705:18:::1;18734:27:::0;;;:12:::1;:27;::::0;;;;;-1:-1:-1;;;;;18734:27:0::1;18773:34;18734:27:::0;18773:22:::1;:34::i;:::-;18825:27;::::0;;;:12:::1;:27;::::0;;;;18818:34;;-1:-1:-1;;;;;;18818:34:0::1;::::0;;18882:13:::1;:20:::0;;18913:438:::1;18933:6;18929:1;:10;18913:438;;;18985:13;18965;18979:1;18965:16;;;;;;;;;;;;;;;;:33;18961:379;;;19105:1;19096:6;:10;19091:1;:15;19087:108;;19150:13;19173:1;19164:6;:10;19150:25;;;;;;;;;;;;;;;;19131:13;19145:1;19131:16;;;;;;;;;::::0;;;::::1;::::0;;;::::1;:44:::0;19087:108:::1;19213:13;:19;;;;;;;;;;;;;;;;;;;;;;;;19256:44;19274:13;19289:10;19256:44;;;;;;;;;-1:-1:-1::0;;;;;19256:44:0::1;;;;;;;;;;;;;;;;19319:5;;18961:379;18941:3;;18913:438;;;;6371:1;;18626:732:::0;:::o;19517:546::-;19590:7;19618:27;19631:13;19618:12;:27::i;:::-;19610:55;;;;;-1:-1:-1;;;19610:55:0;;;;;;;;;;;;-1:-1:-1;;;19610:55:0;;;;;;;;;;;;;;;19676:32;19711:28;19725:13;19711;:28::i;:::-;19676:63;;19755:13;19778:10;-1:-1:-1;;;;;19778:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;19778:28:0;;;;-1:-1:-1;19835:1:0;19825:11;;;19817:39;;;;;-1:-1:-1;;;19817:39:0;;;;;;;;;;;;-1:-1:-1;;;19817:39:0;;;;;;;;;;;;;;;19867:14;19884:10;-1:-1:-1;;;;;19884:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;19884:21:0;;-1:-1:-1;19918:35:0;;:::i;:::-;19956:58;;;;;;;;19972:41;19995:6;20004:8;19972:14;:41::i;:::-;19956:58;;19918:96;-1:-1:-1;20034:21:0;19918:96;20034:19;:21::i;:::-;20027:28;;;;;;19517:546;;;;:::o;19366:143::-;19433:21;19474:27;;;:12;:27;;;;;;-1:-1:-1;;;;;19474:27:0;;19366:143::o;18209:409::-;6311:12;:10;:12::i;:::-;6301:6;;-1:-1:-1;;;;;6301:6:0;;;:22;;;6293:67;;;;;-1:-1:-1;;;6293:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;6293:67:0;;;;;;;;;;;;;;;18306:35:::1;18329:11;18306:22;:35::i;:::-;18404:1;18364:27:::0;;;:12:::1;:27;::::0;;;;;-1:-1:-1;;;;;18364:27:0::1;18352:116;;18423:13;:33:::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;18423:33:0;;;;;::::1;::::0;;;18352:116:::1;18478:27;::::0;;;:12:::1;:27;::::0;;;;;;;;:64;;-1:-1:-1;;;;;;18478:64:0::1;-1:-1:-1::0;;;;;18478:64:0;::::1;::::0;;::::1;::::0;;;18558:52;;;;;;;::::1;::::0;;;::::1;::::0;;;;;;;;;::::1;18209:409:::0;;:::o;24937:113::-;25022:13;:20;24937:113;:::o;6731:148::-;6311:12;:10;:12::i;:::-;6301:6;;-1:-1:-1;;;;;6301:6:0;;;:22;;;6293:67;;;;;-1:-1:-1;;;6293:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;6293:67:0;;;;;;;;;;;;;;;6822:6:::1;::::0;6801:40:::1;::::0;6838:1:::1;::::0;-1:-1:-1;;;;;6822:6:0::1;::::0;6801:40:::1;::::0;6838:1;;6801:40:::1;6852:6;:19:::0;;-1:-1:-1;;;;;;6852:19:0::1;::::0;;6731:148::o;20071:317::-;20143:7;20163:32;20198:28;20212:13;20198;:28::i;:::-;20163:63;;20237:43;20268:10;20237:22;:43::i;:::-;20300:17;20323:10;-1:-1:-1;;;;;20323:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20323:28:0;;;;20071:317;-1:-1:-1;;;;20071:317:0:o;18125:76::-;2505:13;;;;;;;;:33;;;2522:16;:14;:16::i;:::-;2505:50;;;-1:-1:-1;2543:12:0;;;;2542:13;2505:50;2497:109;;;;-1:-1:-1;;;2497:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2619:19;2642:13;;;;;;2641:14;2666:101;;;;2701:13;:20;;-1:-1:-1;;;;2701:20:0;;;;;2736:19;2717:4;2736:19;;;2666:101;18177:16:::1;:14;:16::i;:::-;2797:14:::0;2793:68;;;2844:5;2828:21;;-1:-1:-1;;2828:21:0;;;2793:68;18125:76;:::o;6089:79::-;6154:6;;-1:-1:-1;;;;;6154:6:0;6089:79;:::o;20396:3654::-;20492:7;20520:27;20533:13;20520:12;:27::i;:::-;20512:55;;;;;-1:-1:-1;;;20512:55:0;;;;;;;;;;;;-1:-1:-1;;;20512:55:0;;;;;;;;;;;;;;;20586:14;20578:46;;;;;-1:-1:-1;;;20578:46:0;;;;;;;;;;;;-1:-1:-1;;;20578:46:0;;;;;;;;;;;;;;;21309:32;21344:28;21358:13;21344;:28::i;:::-;21309:63;;21384:14;21400:13;21417:17;21440:10;-1:-1:-1;;;;;21440:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21440:28:0;;;;;;;;;;;;;-1:-1:-1;21440:28:0;;-1:-1:-1;21440:28:0;-1:-1:-1;21497:1:0;21487:11;;;21479:39;;;;;-1:-1:-1;;;21479:39:0;;;;;;;;;;;;-1:-1:-1;;;21479:39:0;;;;;;;;;;;;;;;21529:14;21546:10;-1:-1:-1;;;;;21546:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;21546:21:0;;-1:-1:-1;21580:35:0;;:::i;:::-;21618:58;;;;;;;;21634:41;21657:6;21666:8;21634:14;:41::i;:::-;21618:58;;21580:96;-1:-1:-1;21687:19:0;21709:21;21580:96;21709:19;:21::i;:::-;21687:43;-1:-1:-1;21823:9:0;21797:23;21867:30;:15;21887:9;21867:19;:30::i;:::-;21843:54;;22029:13;22011:15;:31;:47;;;-1:-1:-1;22046:12:0;;;;22011:47;22007:98;;;22082:11;22075:18;;;;;;;;;;;;;22007:98;22225:22;22250:36;:15;22270;22250:19;:36::i;:::-;22225:61;-1:-1:-1;22325:15:0;22297:25;22375:31;:11;22225:61;22375:15;:31::i;:::-;22351:55;;22417:1580;22449:12;;;22445:191;;22587:33;:13;22605:14;22587:17;:33::i;:::-;22580:40;;;;;;;;;;;;;;;;22445:191;22672:1;22662:7;:11;22652:21;;22745:17;22766:24;22796:10;-1:-1:-1;;;;;22796:23:0;;22820:7;22796:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;22796:32:0;;;;;;;;;;;-1:-1:-1;22796:32:0;-1:-1:-1;22865:1:0;22851:15;;;22843:43;;;;;-1:-1:-1;;;22843:43:0;;;;;;;;;;;;-1:-1:-1;;;22843:43:0;;;;;;;;;;;;;;;22903:39;;:::i;:::-;22945:62;;;;;;;;22961:45;22984:10;22997:8;22961:14;:45::i;:::-;22945:62;;22903:104;-1:-1:-1;23022:13:0;23038:25;22903:104;23038:23;:25::i;:::-;23022:41;;23186:13;23166:16;:33;23162:557;;23613:66;23631:47;23641:36;:17;23663:13;23641:21;:36::i;:::-;23631:5;;:9;:47::i;:::-;23613:13;;:17;:66::i;:::-;23597:82;;23698:5;;;;;;23162:557;23735:20;23758:39;:17;23780:16;23758:21;:39::i;:::-;23735:62;-1:-1:-1;23828:42:0;23846:23;:5;23735:62;23846:9;:23::i;:::-;23828:13;;:17;:42::i;:::-;23812:58;-1:-1:-1;23902:32:0;:14;23921:12;23902:18;:32::i;:::-;23885:49;;23969:16;23949:36;;22417:1580;;;;;;;;24014:28;:13;24032:9;24014:17;:28::i;:::-;24007:35;;;;;;;;;;;;;;20396:3654;;;;;:::o;7034:244::-;6311:12;:10;:12::i;:::-;6301:6;;-1:-1:-1;;;;;6301:6:0;;;:22;;;6293:67;;;;;-1:-1:-1;;;6293:67:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;6293:67:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;7123:22:0;::::1;7115:73;;;;-1:-1:-1::0;;;7115:73:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7225:6;::::0;7204:38:::1;::::0;-1:-1:-1;;;;;7204:38:0;;::::1;::::0;7225:6:::1;::::0;7204:38:::1;::::0;7225:6:::1;::::0;7204:38:::1;7253:6;:17:::0;;-1:-1:-1;;;;;;7253:17:0::1;-1:-1:-1::0;;;;;7253:17:0;;;::::1;::::0;;;::::1;::::0;;7034:244::o;4395:106::-;4483:10;4395:106;:::o;24630:125::-;-1:-1:-1;;;;;24710:19:0;;24702:45;;;;;-1:-1:-1;;;24702:45:0;;;;;;;;;;;;-1:-1:-1;;;24702:45:0;;;;;;;;;;;;;;24058:306;24159:13;:20;24125:4;;;24190:144;24210:6;24206:1;:10;24190:144;;;24262:13;24242;24256:1;24242:16;;;;;;;;;;;;;;;;:33;24238:85;;;24303:4;24296:11;;;;;;24238:85;24218:3;;24190:144;;;-1:-1:-1;24351:5:0;;24058:306;-1:-1:-1;;;24058:306:0:o;24763:166::-;24843:7;24870:51;24902:18;;;24898:2;:22;24870:23;:6;17280;24870:10;:23::i;:::-;:27;;:51::i;:::-;24863:58;24763:166;-1:-1:-1;;;24763:166:0:o;15238:95::-;15322:3;;15238:95::o;2961:604::-;3403:4;3514:17;3550:7;2961:604;:::o;5675:129::-;2505:13;;;;;;;;:33;;;2522:16;:14;:16::i;:::-;2505:50;;;-1:-1:-1;2543:12:0;;;;2542:13;2505:50;2497:109;;;;-1:-1:-1;;;2497:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2619:19;2642:13;;;;;;2641:14;2666:101;;;;2701:13;:20;;-1:-1:-1;;;;2701:20:0;;;;;2736:19;2717:4;2736:19;;;2666:101;5733:26:::1;:24;:26::i;:::-;5770;:24;:26::i;8713:136::-:0;8771:7;8798:43;8802:1;8805;8798:43;;;;;;;;;;;;;;;;;:3;:43::i;9603:471::-;9661:7;9906:6;9902:47;;-1:-1:-1;9936:1:0;9929:8;;9902:47;9973:5;;;9977:1;9973;:5;:1;9997:5;;;;;:10;9989:56;;;;-1:-1:-1;;;9989:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10550:132;10608:7;10635:39;10639:1;10642;10635:39;;;;;;;;;;;;;;;;;:3;:39::i;8249:181::-;8307:7;8339:5;;;8363:6;;;;8355:46;;;;;-1:-1:-1;;;8355:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;4324:65;2505:13;;;;;;;;:33;;;2522:16;:14;:16::i;:::-;2505:50;;;-1:-1:-1;2543:12:0;;;;2542:13;2505:50;2497:109;;;;-1:-1:-1;;;2497:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2619:19;2642:13;;;;;;2641:14;2666:101;;;;2701:13;:20;;-1:-1:-1;;;;2701:20:0;;;;;2736:19;2717:4;2736:19;;;2797:14;2793:68;;;2844:5;2828:21;;-1:-1:-1;;2828:21:0;;;4324:65;:::o;5812:196::-;2505:13;;;;;;;;:33;;;2522:16;:14;:16::i;:::-;2505:50;;;-1:-1:-1;2543:12:0;;;;2542:13;2505:50;2497:109;;;;-1:-1:-1;;;2497:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2619:19;2642:13;;;;;;2641:14;2666:101;;;;2701:13;:20;;-1:-1:-1;;;;2701:20:0;;;;;2736:19;2717:4;2736:19;;;2666:101;5880:17:::1;5900:12;:10;:12::i;:::-;5923:6;:18:::0;;-1:-1:-1;;;;;;5923:18:0::1;-1:-1:-1::0;;;;;5923:18:0;::::1;::::0;;::::1;::::0;;;5957:43:::1;::::0;5923:18;;-1:-1:-1;5923:18:0;-1:-1:-1;;5957:43:0::1;::::0;-1:-1:-1;;5957:43:0::1;2779:1;2797:14:::0;2793:68;;;2844:5;2828:21;;-1:-1:-1;;2828:21:0;;;5812:196;:::o;9152:192::-;9238:7;9274:12;9266:6;;;;9258:29;;;;-1:-1:-1;;;9258:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;9310:5:0;;;9152:192::o;11178:278::-;11264:7;11299:12;11292:5;11284:28;;;;-1:-1:-1;;;11284:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11323:9;11339:1;11335;:5;;;;;;;11178:278;-1:-1:-1;;;;;11178:278:0:o;-1:-1:-1:-;;;;;;;;;;;;;;:::o

Swarm Source

ipfs://9b3a3ca2ba4583cba604dc16bf1aba2b6c49d891188dad862c34b71f16d4e934
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading