ETH Price: $3,416.92 (+0.76%)
Gas: 57 Gwei

Contract

0xC000d75D4221Ba9D7A788C81DCc0A4714B4aE9e5
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Add Asset169912682023-04-06 18:17:23330 days ago1680805043IN
0xC000d75D...14B4aE9e5
0 ETH0.010008729.01082037
Set Exposure Of ...168767952023-03-21 15:06:47347 days ago1679411207IN
0xC000d75D...14B4aE9e5
0 ETH0.0010271333.36598469
Set Exposure Of ...168767952023-03-21 15:06:47347 days ago1679411207IN
0xC000d75D...14B4aE9e5
0 ETH0.0010275333.36598469
Set Exposure Of ...168767942023-03-21 15:06:23347 days ago1679411183IN
0xC000d75D...14B4aE9e5
0 ETH0.0010321633.56854383
Set Exposure Of ...168767932023-03-21 15:06:11347 days ago1679411171IN
0xC000d75D...14B4aE9e5
0 ETH0.0010249933.32223931
Set Exposure Of ...168767922023-03-21 15:05:59347 days ago1679411159IN
0xC000d75D...14B4aE9e5
0 ETH0.0009475130.80343975
Set Exposure Of ...168767902023-03-21 15:05:35347 days ago1679411135IN
0xC000d75D...14B4aE9e5
0 ETH0.0010658534.62382015
Set Exposure Of ...168767892023-03-21 15:05:23347 days ago1679411123IN
0xC000d75D...14B4aE9e5
0 ETH0.0010673634.65926692
Set Exposure Of ...168767882023-03-21 15:05:11347 days ago1679411111IN
0xC000d75D...14B4aE9e5
0 ETH0.0010668934.63059511
Set Exposure Of ...168767872023-03-21 15:04:59347 days ago1679411099IN
0xC000d75D...14B4aE9e5
0 ETH0.0011023535.79547394
Set Exposure Of ...168767842023-03-21 15:04:11347 days ago1679411051IN
0xC000d75D...14B4aE9e5
0 ETH0.0009868632.04524676
Set Exposure Of ...168767792023-03-21 15:03:11347 days ago1679410991IN
0xC000d75D...14B4aE9e5
0 ETH0.001018733.07912463
Set Exposure Of ...168767792023-03-21 15:03:11347 days ago1679410991IN
0xC000d75D...14B4aE9e5
0 ETH0.001018733.07912463
Add Asset168296972023-03-15 0:17:47353 days ago1678839467IN
0xC000d75D...14B4aE9e5
0 ETH0.0111304931.59371178
Add Asset168296972023-03-15 0:17:47353 days ago1678839467IN
0xC000d75D...14B4aE9e5
0 ETH0.0100165631.59371178
Add Asset168296222023-03-15 0:02:35353 days ago1678838555IN
0xC000d75D...14B4aE9e5
0 ETH0.0103837230.08423376
Add Asset168296222023-03-15 0:02:35353 days ago1678838555IN
0xC000d75D...14B4aE9e5
0 ETH0.0095391930.08423376
Add Asset168296222023-03-15 0:02:35353 days ago1678838555IN
0xC000d75D...14B4aE9e5
0 ETH0.009755230.08423376
Add Asset168296222023-03-15 0:02:35353 days ago1678838555IN
0xC000d75D...14B4aE9e5
0 ETH0.0094763530.08423376
Add Asset168296222023-03-15 0:02:35353 days ago1678838555IN
0xC000d75D...14B4aE9e5
0 ETH0.009700930.08423376
Add Asset168296222023-03-15 0:02:35353 days ago1678838555IN
0xC000d75D...14B4aE9e5
0 ETH0.009472530.08423376
Add Asset168296222023-03-15 0:02:35353 days ago1678838555IN
0xC000d75D...14B4aE9e5
0 ETH0.0094743930.08423376
Add Asset168296222023-03-15 0:02:35353 days ago1678838555IN
0xC000d75D...14B4aE9e5
0 ETH0.0094750530.08423376
Add Asset168296222023-03-15 0:02:35353 days ago1678838555IN
0xC000d75D...14B4aE9e5
0 ETH0.0094716930.08423376
Add Asset168296222023-03-15 0:02:35353 days ago1678838555IN
0xC000d75D...14B4aE9e5
0 ETH0.0105774330.08423376
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
StandardERC20PricingModule

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 4 of 10 : StandardERC20PricingModule.sol
/**
 * Created by Pragma Labs
 * SPDX-License-Identifier: BUSL-1.1
 */
pragma solidity ^0.8.13;

import { PricingModule, IPricingModule } from "./AbstractPricingModule.sol";
import { IOraclesHub } from "./interfaces/IOraclesHub.sol";
import { IMainRegistry } from "./interfaces/IMainRegistry.sol";
import { IERC20 } from "../interfaces/IERC20.sol";
import { FixedPointMathLib } from "lib/solmate/src/utils/FixedPointMathLib.sol";
import { IStandardERC20PricingModule } from "./interfaces/IStandardERC20PricingModule.sol";

/**
 * @title Pricing Module for Standard ERC20 tokens.
 * @author Pragma Labs
 * @notice The pricing logic and basic information for ERC20 tokens for which a direct price feed exists.
 * @dev No end-user should directly interact with the StandardERC20PricingModule, only the Main-registry,
 * Oracle-Hub or the contract owner.
 */
contract StandardERC20PricingModule is PricingModule, IStandardERC20PricingModule {
    using FixedPointMathLib for uint256;

    /* //////////////////////////////////////////////////////////////
                                STORAGE
    ////////////////////////////////////////////////////////////// */

    // Map asset => assetInformation.
    mapping(address => AssetInformation) public assetToInformation;

    // Struct with additional information for a specific asset.
    struct AssetInformation {
        uint64 assetUnit; // The unit of the asset, equal to 10^decimals.
        address[] oracles; // Array of contract addresses of oracles.
    }

    /* //////////////////////////////////////////////////////////////
                                CONSTRUCTOR
    ////////////////////////////////////////////////////////////// */

    /**
     * @param mainRegistry_ The contract address of the MainRegistry.
     * @param oracleHub_ The contract address of the OracleHub.
     * @param assetType_ Identifier for the token standard of the asset.
     * 0 = ERC20.
     * 1 = ERC721.
     * 2 = ERC1155.
     */
    constructor(address mainRegistry_, address oracleHub_, uint256 assetType_)
        PricingModule(mainRegistry_, oracleHub_, assetType_, msg.sender)
    { }

    /*///////////////////////////////////////////////////////////////
                        ASSET MANAGEMENT
    ///////////////////////////////////////////////////////////////*/

    /**
     * @notice Adds a new asset to the StandardERC20PricingModule.
     * @param asset The contract address of the asset.
     * @param oracles An array of contract addresses of oracles, to price the asset in USD.
     * @param riskVars An array of RiskVarInput structs.
     * @param maxExposure The maximum protocol wide exposure to the asset.
     * @dev Assets can't have more than 18 decimals.
     * @dev The asset slot in the RiskVarInput struct can be any value as it is not used in this function.
     * @dev If no risk variables are provided, the asset is added with the risk variables set by default to zero,
     * resulting in the asset being valued at 0.
     * @dev Risk variables are variables with 2 decimals precision.
     */
    function addAsset(address asset, address[] calldata oracles, RiskVarInput[] calldata riskVars, uint128 maxExposure)
        external
        onlyOwner
    {
        require(!inPricingModule[asset], "PM20_AA: already added");
        // View function, reverts in OracleHub if sequence is not correct.
        IOraclesHub(oracleHub).checkOracleSequence(oracles, asset);

        inPricingModule[asset] = true;
        assetsInPricingModule.push(asset);

        uint256 assetUnit = 10 ** IERC20(asset).decimals();
        require(assetUnit <= 1e18, "PM20_AA: Maximal 18 decimals");

        // Can safely cast to uint64, we previously checked it is smaller than 10e18.
        assetToInformation[asset].assetUnit = uint64(assetUnit);
        assetToInformation[asset].oracles = oracles;
        _setRiskVariablesForAsset(asset, riskVars);

        exposure[asset].maxExposure = maxExposure;

        emit MaxExposureSet(asset, maxExposure);

        // Will revert in MainRegistry if asset can't be added.
        IMainRegistry(mainRegistry).addAsset(asset, assetType);
    }

    /**
     * @notice Sets a new oracle sequence in the case one of the current oracles is decommissioned.
     * @param asset The contract address of the asset.
     * @param newOracles An array of contract addresses of oracles, to price the asset in USD.
     * @param decommissionedOracle The contract address of the decommissioned oracle.
     */
    function setOracles(address asset, address[] calldata newOracles, address decommissionedOracle)
        external
        onlyOwner
    {
        // If asset is not added to the Pricing Module, oldOracles will have length 0,
        // in this case the for loop will be skipped and the function will revert.
        address[] memory oldOracles = assetToInformation[asset].oracles;
        uint256 oraclesLength = oldOracles.length;
        for (uint256 i; i < oraclesLength;) {
            if (oldOracles[i] == decommissionedOracle) {
                require(!IOraclesHub(oracleHub).isActive(oldOracles[i]), "PM20_SO: Oracle still active");
                // View function, reverts in OracleHub if sequence is not correct.
                IOraclesHub(oracleHub).checkOracleSequence(newOracles, asset);
                assetToInformation[asset].oracles = newOracles;
                return;
            }
            unchecked {
                ++i;
            }
        }
        // We only arrive in tis state if length of oldOracles was zero, or decommissionedOracle was not in the oldOracles array.
        // -> reverts.
        revert("PM20_SO: Unknown Oracle");
    }

    /**
     * @notice Returns the asset information of an asset.
     * @param asset The contract address of the asset.
     * @return assetUnit The unit (10^decimals) of the asset.
     * @return oracles An array of contract addresses of oracles, to price the asset in USD.
     */
    function getAssetInformation(address asset) external view returns (uint64, address[] memory) {
        return (assetToInformation[asset].assetUnit, assetToInformation[asset].oracles);
    }

    /*///////////////////////////////////////////////////////////////
                          PRICING LOGIC
    ///////////////////////////////////////////////////////////////*/

    /**
     * @notice Returns the value of a certain asset, denominated in USD or in another BaseCurrency.
     * @param getValueInput A Struct with the input variables (avoid stack to deep).
     * - asset: The contract address of the asset.
     * - assetId: Since ERC20 tokens have no Id, the Id should be set to 0.
     * - assetAmount: The amount of assets.
     * - baseCurrency: The BaseCurrency in which the value is ideally denominated.
     * @return valueInUsd The value of the asset denominated in USD, with 18 Decimals precision.
     * @return valueInBaseCurrency The value of the asset denominated in a BaseCurrency different from USD, with 18 Decimals precision.
     * @return collateralFactor The collateral factor of the asset for a given baseCurrency, with 2 decimals precision.
     * @return liquidationFactor The liquidation factor of the asset for a given baseCurrency, with 2 decimals precision.
     * @dev If the OracleHub returns the rate in a baseCurrency different from USD, the StandardERC20PricingModule will return
     * the value of the asset in the same BaseCurrency. If the Oracle-Hub returns the rate in USD, the StandardERC20PricingModule
     * will return the value of the asset in USD.
     * Only one of the two values can be different from 0.
     * @dev Function will overflow when assetAmount * Rate * 10**(18 - rateDecimals) > MAXUINT256
     * @dev If the asset is not added to PricingModule, this function will return value 0 without throwing an error.
     * However no check in StandardERC20PricingModule is necessary, since the check if the asset is allow listed (and hence added to PricingModule)
     * is already done in the MainRegistry.
     */
    function getValue(IPricingModule.GetValueInput memory getValueInput)
        public
        view
        override
        returns (uint256 valueInUsd, uint256 valueInBaseCurrency, uint256 collateralFactor, uint256 liquidationFactor)
    {
        uint256 rateInUsd;
        uint256 rateInBaseCurrency;

        (rateInUsd, rateInBaseCurrency) =
            IOraclesHub(oracleHub).getRate(assetToInformation[getValueInput.asset].oracles, getValueInput.baseCurrency);

        if (rateInBaseCurrency > 0) {
            valueInBaseCurrency = (getValueInput.assetAmount).mulDivDown(
                rateInBaseCurrency, assetToInformation[getValueInput.asset].assetUnit
            );
        } else {
            valueInUsd =
                (getValueInput.assetAmount).mulDivDown(rateInUsd, assetToInformation[getValueInput.asset].assetUnit);
        }

        collateralFactor = assetRiskVars[getValueInput.asset][getValueInput.baseCurrency].collateralFactor;
        liquidationFactor = assetRiskVars[getValueInput.asset][getValueInput.baseCurrency].liquidationFactor;
    }
}

File 2 of 10 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

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

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

File 3 of 10 : FixedPointMathLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*//////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    uint256 internal constant MAX_UINT256 = 2**256 - 1;

    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*//////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // Divide x * y by the denominator.
            z := div(mul(x, y), denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // If x * y modulo the denominator is strictly greater than 0,
            // 1 is added to round up the division of x * y by the denominator.
            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            let y := x // We start y at x, which will help us make our initial estimate.

            z := 181 // The "correct" value is 1, but this saves a multiplication later.

            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.

            // We check y >= 2^(k + 8) but shift right by k bits
            // each branch to ensure that if x >= 256, then y >= 256.
            if iszero(lt(y, 0x10000000000000000000000000000000000)) {
                y := shr(128, y)
                z := shl(64, z)
            }
            if iszero(lt(y, 0x1000000000000000000)) {
                y := shr(64, y)
                z := shl(32, z)
            }
            if iszero(lt(y, 0x10000000000)) {
                y := shr(32, y)
                z := shl(16, z)
            }
            if iszero(lt(y, 0x1000000)) {
                y := shr(16, y)
                z := shl(8, z)
            }

            // Goal was to get z*z*y within a small factor of x. More iterations could
            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).
            // We ensured y >= 256 so that the relative difference between y and y+1 is small.
            // That's not possible if x < 256 but we can just verify those cases exhaustively.

            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.
            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.

            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range
            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.

            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate
            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.

            // There is no overflow risk here since y < 2^136 after the first branch above.
            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.

            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // If x+1 is a perfect square, the Babylonian method cycles between
            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.
            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.
            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.
            z := sub(z, lt(div(x, z), z))
        }
    }

    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Mod x by y. Note this will return
            // 0 instead of reverting if y is zero.
            z := mod(x, y)
        }
    }

    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Divide x by y. Note this will return
            // 0 instead of reverting if y is zero.
            r := div(x, y)
        }
    }

    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Add 1 to x * y if x % y > 0. Note this will
            // return 0 instead of reverting if y is zero.
            z := add(gt(mod(x, y), 0), div(x, y))
        }
    }
}

File 4 of 10 : AbstractPricingModule.sol
/**
 * Created by Pragma Labs
 * SPDX-License-Identifier: BUSL-1.1
 */
pragma solidity ^0.8.13;

import { IOraclesHub } from "./interfaces/IOraclesHub.sol";
import { IMainRegistry } from "./interfaces/IMainRegistry.sol";
import { IPricingModule } from "../interfaces/IPricingModule.sol";
import { RiskConstants } from "../utils/RiskConstants.sol";
import { Owned } from "lib/solmate/src/auth/Owned.sol";
import { IPricingModule } from "../interfaces/IPricingModule.sol";

/**
 * @title Abstract Pricing Module
 * @author Pragma Labs
 * @notice Abstract contract with the minimal implementation of a Pricing Module.
 * @dev No end-user should directly interact with Pricing Module, only the Main Registry, Oracle-Hub
 * or the contract owner.
 */
abstract contract PricingModule is Owned, IPricingModule {
    /* //////////////////////////////////////////////////////////////
                                STORAGE
    ////////////////////////////////////////////////////////////// */

    // The contract address of the MainRegistry.
    address public immutable mainRegistry;
    // The contract address of the OracleHub.
    address public immutable oracleHub;
    // Identifier for the token standard of the asset.
    uint256 public immutable assetType;
    // The address of the riskManager.
    address public riskManager;

    // Array with all the contract addresses of assets added to the Pricing Module.
    address[] public assetsInPricingModule;

    // Map asset => flag.
    mapping(address => bool) public inPricingModule;
    // Map asset => exposureInformation.
    mapping(address => Exposure) public exposure;
    // Map asset => baseCurrencyIdentifier => riskVariables.
    mapping(address => mapping(uint256 => RiskVars)) public assetRiskVars;

    // Struct with information about the exposure of a specific asset.
    struct Exposure {
        uint128 maxExposure; // The maximum protocol wide exposure to an asset.
        uint128 exposure; // The actual protocol wide exposure to an asset.
    }

    // Struct with the risk variables of a specific asset for a specific baseCurrency.
    struct RiskVars {
        uint16 collateralFactor; // The collateral factor, 2 decimals precision.
        uint16 liquidationFactor; // The liquidation factor, 2 decimals precision.
    }

    // Struct with the input variables for the function setBatchRiskVariables().
    struct RiskVarInput {
        address asset; // The contract address of an asset.
        uint8 baseCurrency; // An identifier (uint256) of a BaseCurrency.
        uint16 collateralFactor; // The collateral factor, 2 decimals precision.
        uint16 liquidationFactor; // The liquidation factor, 2 decimals precision.
    }

    /* //////////////////////////////////////////////////////////////
                                EVENTS
    ////////////////////////////////////////////////////////////// */

    event RiskManagerUpdated(address riskManager);
    event RiskVariablesSet(
        address indexed asset, uint8 indexed baseCurrencyId, uint16 collateralFactor, uint16 liquidationFactor
    );
    event MaxExposureSet(address indexed asset, uint128 maxExposure);

    /* //////////////////////////////////////////////////////////////
                                MODIFIERS
    ////////////////////////////////////////////////////////////// */

    modifier onlyRiskManager() {
        require(msg.sender == riskManager, "APM: ONLY_RISK_MANAGER");
        _;
    }

    modifier onlyMainReg() {
        require(msg.sender == mainRegistry, "APM: ONLY_MAIN_REGISTRY");
        _;
    }

    /* //////////////////////////////////////////////////////////////
                                CONSTRUCTOR
    ////////////////////////////////////////////////////////////// */

    /**
     * @param mainRegistry_ The contract address of the MainRegistry.
     * @param oracleHub_ The contract address of the OracleHub.
     * @param assetType_ Identifier for the token standard of the asset.
     * 0 = ERC20.
     * 1 = ERC721.
     * 2 = ERC1155.
     * @param riskManager_ The address of the Risk Manager.
     */
    constructor(address mainRegistry_, address oracleHub_, uint256 assetType_, address riskManager_)
        Owned(msg.sender)
    {
        mainRegistry = mainRegistry_;
        oracleHub = oracleHub_;
        assetType = assetType_;
        riskManager = riskManager_;

        emit RiskManagerUpdated(riskManager_);
    }

    /*///////////////////////////////////////////////////////////////
                    RISK MANAGER MANAGEMENT
    ///////////////////////////////////////////////////////////////*/
    /**
     * @notice Sets a new Risk Manager.
     * @param riskManager_ The address of the new Risk Manager.
     */
    function setRiskManager(address riskManager_) external onlyOwner {
        riskManager = riskManager_;

        emit RiskManagerUpdated(riskManager_);
    }

    /*///////////////////////////////////////////////////////////////
                        WHITE LIST MANAGEMENT
    ///////////////////////////////////////////////////////////////*/

    /**
     * @notice Checks for a token address and the corresponding Id if it is white-listed.
     * @param asset The contract address of the asset.
     * param assetId The Id of the asset.
     * @return A boolean, indicating if the asset is whitelisted.
     * @dev For assets without Id (ERC20, ERC4626...), the Id should be set to 0.
     */
    function isAllowListed(address asset, uint256) public view virtual returns (bool) {
        return exposure[asset].maxExposure != 0;
    }

    /*///////////////////////////////////////////////////////////////
                          PRICING LOGIC
    ///////////////////////////////////////////////////////////////*/

    /**
     * @notice Returns the value of a certain asset, denominated in USD or in another BaseCurrency.
     * @dev The value of the asset can be denominated in:
     * - USD.
     * - A given BaseCurrency, different from USD.
     * - A combination of USD and a given BaseCurrency, different from USD (will be very exceptional,
     * but theoretically possible for eg. a UNI V2 LP position of two underlying assets,
     * one denominated in USD and the other one in the BaseCurrency different from USD).
     */
    function getValue(GetValueInput memory) public view virtual returns (uint256, uint256, uint256, uint256) { }

    /*///////////////////////////////////////////////////////////////
                    RISK VARIABLES MANAGEMENT
    ///////////////////////////////////////////////////////////////*/

    /**
     * @notice Returns the risk variables of an asset.
     * @param asset The contract address of the asset.
     * @param baseCurrency An identifier (uint256) of the BaseCurrency.
     * @return collateralFactor The collateral factor of the asset for a given baseCurrency, 2 decimals precision.
     * @return liquidationFactor The liquidation factor of the asset for a given baseCurrency, 2 decimals precision.
     */
    function getRiskVariables(address asset, uint256 baseCurrency) public view virtual returns (uint16, uint16) {
        return
            (assetRiskVars[asset][baseCurrency].collateralFactor, assetRiskVars[asset][baseCurrency].liquidationFactor);
    }

    /**
     * @notice Sets a batch of risk variables for a batch of assets.
     * @param riskVarInputs An array of RiskVarInput structs.
     * @dev Risk variables have 2 decimals precision.
     * @dev Can only be called by the Risk Manager, which can be different from the owner.
     */
    function setBatchRiskVariables(RiskVarInput[] memory riskVarInputs) public virtual onlyRiskManager {
        uint256 baseCurrencyCounter = IMainRegistry(mainRegistry).baseCurrencyCounter();
        uint256 riskVarInputsLength = riskVarInputs.length;

        for (uint256 i; i < riskVarInputsLength;) {
            require(riskVarInputs[i].baseCurrency < baseCurrencyCounter, "APM_SBRV: BaseCur. not in limits");

            _setRiskVariables(
                riskVarInputs[i].asset,
                riskVarInputs[i].baseCurrency,
                RiskVars({
                    collateralFactor: riskVarInputs[i].collateralFactor,
                    liquidationFactor: riskVarInputs[i].liquidationFactor
                })
            );

            unchecked {
                ++i;
            }
        }
    }

    /**
     * @notice Sets a batch of risk variables for a specific asset.
     * @param asset The contract address of the asset.
     * @param riskVarInputs An array of RiskVarInput structs.
     * @dev Risk variables have 2 decimals precision.
     * @dev The asset slot in the RiskVarInput struct is ignored for this function.
     */
    function _setRiskVariablesForAsset(address asset, RiskVarInput[] memory riskVarInputs) internal virtual {
        uint256 baseCurrencyCounter = IMainRegistry(mainRegistry).baseCurrencyCounter();
        uint256 riskVarInputsLength = riskVarInputs.length;

        for (uint256 i; i < riskVarInputsLength;) {
            require(baseCurrencyCounter > riskVarInputs[i].baseCurrency, "APM_SRVFA: BaseCur not in limits");
            _setRiskVariables(
                asset,
                riskVarInputs[i].baseCurrency,
                RiskVars({
                    collateralFactor: riskVarInputs[i].collateralFactor,
                    liquidationFactor: riskVarInputs[i].liquidationFactor
                })
            );

            unchecked {
                ++i;
            }
        }
    }

    /**
     * @notice Sets a single pair of risk variables.
     * @param asset The contract address of the asset.
     * @param baseCurrency An identifier (uint256) of the BaseCurrency.
     * @param riskVars A struct with the risk variables.
     * @dev Risk variables have 2 decimals precision.
     */
    function _setRiskVariables(address asset, uint256 baseCurrency, RiskVars memory riskVars) internal virtual {
        require(riskVars.collateralFactor <= RiskConstants.MAX_COLLATERAL_FACTOR, "APM_SRV: Coll.Fact not in limits");
        require(riskVars.liquidationFactor <= RiskConstants.MAX_LIQUIDATION_FACTOR, "APM_SRV: Liq.Fact not in limits");

        assetRiskVars[asset][baseCurrency] = riskVars;

        emit RiskVariablesSet(asset, uint8(baseCurrency), riskVars.collateralFactor, riskVars.liquidationFactor);
    }

    /**
     * @notice Sets the maximum exposure for an asset.
     * @param asset The contract address of the asset.
     * @param maxExposure The maximum protocol wide exposure to the asset.
     * @dev Can only be called by the Risk Manager, which can be different from the owner.
     */
    function setExposureOfAsset(address asset, uint256 maxExposure) public virtual onlyRiskManager {
        require(maxExposure <= type(uint128).max, "APM_SEA: Max Exp. not in limits");
        exposure[asset].maxExposure = uint128(maxExposure);

        emit MaxExposureSet(asset, uint128(maxExposure));
    }

    /**
     * @notice Processes the deposit of an asset.
     * param vault The contract address of the Vault where the asset is transferred to.
     * @param asset The contract address of the asset.
     * param assetId The Id of the asset.
     * @param amount The amount of tokens.
     * @dev Unsafe cast to uint128, it is assumed no more than 10**(20+decimals) tokens can be deposited.
     */
    function processDeposit(address, address asset, uint256, uint256 amount) external virtual onlyMainReg {
        require(
            exposure[asset].exposure + uint128(amount) <= exposure[asset].maxExposure, "APM_PD: Exposure not in limits"
        );
        exposure[asset].exposure += uint128(amount);
    }

    /**
     * @notice Processes the withdrawal an asset.
     * param vault The address of the vault where the asset is withdrawn from
     * @param asset The contract address of the asset.
     * param assetId The Id of the asset.
     * @param amount The amount of tokens.
     * @dev Unsafe cast to uint128, it is assumed no more than 10**(20+decimals) tokens will ever be deposited.
     */
    function processWithdrawal(address, address asset, uint256, uint256 amount) external virtual onlyMainReg {
        exposure[asset].exposure -= uint128(amount);
    }
}

File 5 of 10 : IMainRegistry.sol
/**
 * Created by Pragma Labs
 * SPDX-License-Identifier: MIT
 */
pragma solidity ^0.8.13;

interface IMainRegistry {
    /**
     * @notice Returns the number of baseCurrencies.
     * @return Counter for the number of baseCurrencies in use.
     */
    function baseCurrencyCounter() external view returns (uint256);

    /**
     * @notice Adds a new asset to the Main Registry.
     * @param asset The contract address of the asset.
     * @param assetType Identifier for the type of the asset:
     * 0 = ERC20.
     * 1 = ERC721.
     * 2 = ERC1155.
     */
    function addAsset(address asset, uint256 assetType) external;
}

File 6 of 10 : IOraclesHub.sol
/**
 * Created by Pragma Labs
 * SPDX-License-Identifier: MIT
 */
pragma solidity ^0.8.13;

interface IOraclesHub {
    /**
     * @notice Verifies whether a sequence of oracles complies with a predetermined set of criteria.
     * @param oracles Array of contract addresses of oracles.
     * @param asset The contract address of the base-asset.
     */
    function checkOracleSequence(address[] memory oracles, address asset) external view;

    /**
     * @notice Returns the state of an oracle.
     * @param oracle The contract address of the oracle to be checked.
     * @return boolean indicating if the oracle is active or not.
     */
    function isActive(address oracle) external view returns (bool);

    /**
     * @notice Returns the rate of a certain asset, denominated in USD or in another BaseCurrency.
     * @param oracles Array of contract addresses of oracles.
     * @param baseCurrency The BaseCurrency in which the rate is ideally expressed.
     * @return rateInUsd The rate of the asset denominated in USD, with 18 Decimals precision.
     * @return rateInBaseCurrency The rate of the asset denominated in a BaseCurrency different from USD, with 18 Decimals precision.
     */
    function getRate(address[] memory oracles, uint256 baseCurrency) external view returns (uint256, uint256);
}

File 7 of 10 : IStandardERC20PricingModule.sol
/**
 * Created by Pragma Labs
 * SPDX-License-Identifier: MIT
 */
pragma solidity ^0.8.13;

interface IStandardERC20PricingModule {
    /**
     * @notice Returns the asset information of an asset.
     * @param asset The contract address of the asset.
     * @return assetUnit The unit (10^decimals) of the asset.
     * @return oracles An array of contract addresses of oracles, to price the asset in USD.
     */
    function getAssetInformation(address asset) external view returns (uint64, address[] memory);
}

File 8 of 10 : IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

interface IERC20 {
    function transferFrom(address from, address to, uint256 amount) external returns (bool);

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

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

    function decimals() external view returns (uint256);
}

File 9 of 10 : IPricingModule.sol
/**
 * Created by Pragma Labs
 * SPDX-License-Identifier: MIT
 */
pragma solidity ^0.8.13;

interface IPricingModule {
    // A Struct with the input variables for the function getValue() (avoid stack to deep).
    struct GetValueInput {
        address asset; // The contract address of the asset.
        uint256 assetId; // The Id of the asset.
        uint256 assetAmount; // The amount of assets.
        uint256 baseCurrency; // Identifier of the BaseCurrency in which the value is ideally denominated.
    }

    /**
     * @notice Returns the value of a certain asset, denominated in USD or in another BaseCurrency.
     * @param input A Struct with the input variables (avoid stack to deep).
     * @return valueInUsd The value of the asset denominated in USD, with 18 Decimals precision.
     * @return valueInBaseCurrency The value of the asset denominated in a BaseCurrency different from USD, with 18 Decimals precision.
     * @return collateralFactor The collateral factor of the asset for a given baseCurrency, with 2 decimals precision.
     * @return liquidationFactor liquidationFactor The liquidation factor of the asset for a given baseCurrency, with 2 decimals precision.
     */
    function getValue(GetValueInput memory input) external view returns (uint256, uint256, uint256, uint256);

    /**
     * @notice Returns the risk variables of an asset.
     * @param asset The contract address of the asset.
     * @param baseCurrency An identifier (uint256) of the BaseCurrency.
     * @return collateralFactor The collateral factor of the asset for a given baseCurrency, 2 decimals precision.
     * @return liquidationFactor The liquidation factor of the asset for a given baseCurrency, 2 decimals precision.
     */
    function getRiskVariables(address asset, uint256 baseCurrency) external view returns (uint16, uint16);

    /**
     * @notice Processes the deposit of an asset.
     * @param vault The contract address of the Vault where the asset is transferred to.
     * @param asset The contract address of the asset.
     * @param id The Id of the asset.
     * @param amount The amount of tokens.
     */
    function processDeposit(address vault, address asset, uint256 id, uint256 amount) external;

    /**
     * @notice Processes the withdrawal an asset.
     * @param vault The address of the vault where the asset is withdrawn from
     * @param asset The contract address of the asset.
     * @param id The Id of the asset.
     * @param amount The amount of tokens.
     */
    function processWithdrawal(address vault, address asset, uint256 id, uint256 amount) external;
}

File 10 of 10 : RiskConstants.sol
/**
 * Created by Pragma Labs
 * SPDX-License-Identifier: MIT
 */

pragma solidity ^0.8.13;

library RiskConstants {
    // Math
    uint16 public constant RISK_VARIABLES_UNIT = 100;

    uint16 public constant MIN_COLLATERAL_FACTOR = 0;
    uint16 public constant MIN_LIQUIDATION_FACTOR = 0;

    uint16 public constant MAX_COLLATERAL_FACTOR = 100;
    uint16 public constant MAX_LIQUIDATION_FACTOR = 100;

    uint16 public constant DEFAULT_COLLATERAL_FACTOR = 50;
    uint16 public constant DEFAULT_LIQUIDATION_FACTOR = 90;
}

Settings
{
  "remappings": [
    "arcadia-lending/=lib/arcadia-lending/",
    "ds-test/=lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "solmate/=lib/solmate/src/",
    "v2-periphery/=lib/v2-periphery/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"mainRegistry_","type":"address"},{"internalType":"address","name":"oracleHub_","type":"address"},{"internalType":"uint256","name":"assetType_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint128","name":"maxExposure","type":"uint128"}],"name":"MaxExposureSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"riskManager","type":"address"}],"name":"RiskManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"uint8","name":"baseCurrencyId","type":"uint8"},{"indexed":false,"internalType":"uint16","name":"collateralFactor","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"liquidationFactor","type":"uint16"}],"name":"RiskVariablesSet","type":"event"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address[]","name":"oracles","type":"address[]"},{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint8","name":"baseCurrency","type":"uint8"},{"internalType":"uint16","name":"collateralFactor","type":"uint16"},{"internalType":"uint16","name":"liquidationFactor","type":"uint16"}],"internalType":"struct PricingModule.RiskVarInput[]","name":"riskVars","type":"tuple[]"},{"internalType":"uint128","name":"maxExposure","type":"uint128"}],"name":"addAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"assetRiskVars","outputs":[{"internalType":"uint16","name":"collateralFactor","type":"uint16"},{"internalType":"uint16","name":"liquidationFactor","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assetToInformation","outputs":[{"internalType":"uint64","name":"assetUnit","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"assetsInPricingModule","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"exposure","outputs":[{"internalType":"uint128","name":"maxExposure","type":"uint128"},{"internalType":"uint128","name":"exposure","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getAssetInformation","outputs":[{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"baseCurrency","type":"uint256"}],"name":"getRiskVariables","outputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"assetId","type":"uint256"},{"internalType":"uint256","name":"assetAmount","type":"uint256"},{"internalType":"uint256","name":"baseCurrency","type":"uint256"}],"internalType":"struct IPricingModule.GetValueInput","name":"getValueInput","type":"tuple"}],"name":"getValue","outputs":[{"internalType":"uint256","name":"valueInUsd","type":"uint256"},{"internalType":"uint256","name":"valueInBaseCurrency","type":"uint256"},{"internalType":"uint256","name":"collateralFactor","type":"uint256"},{"internalType":"uint256","name":"liquidationFactor","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"inPricingModule","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"isAllowListed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleHub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"processDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"processWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"riskManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint8","name":"baseCurrency","type":"uint8"},{"internalType":"uint16","name":"collateralFactor","type":"uint16"},{"internalType":"uint16","name":"liquidationFactor","type":"uint16"}],"internalType":"struct PricingModule.RiskVarInput[]","name":"riskVarInputs","type":"tuple[]"}],"name":"setBatchRiskVariables","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"maxExposure","type":"uint256"}],"name":"setExposureOfAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address[]","name":"newOracles","type":"address[]"},{"internalType":"address","name":"decommissionedOracle","type":"address"}],"name":"setOracles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"riskManager_","type":"address"}],"name":"setRiskManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e06040523480156200001157600080fd5b50604051620020443803806200204483398101604081905262000034916200010a565b600080546001600160a01b031916339081178255604051859285928592909182918291907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160a01b0384811660805283811660a05260c0839052600180546001600160a01b03191691831691821790556040519081527f6d9a586ef7be36e9ed3db326a9c62cce6c939c7ddae2c48f8f35562dce4fcd729060200160405180910390a1505050505050506200014b565b80516001600160a01b03811681146200010557600080fd5b919050565b6000806000606084860312156200012057600080fd5b6200012b84620000ed565b92506200013b60208501620000ed565b9150604084015190509250925092565b60805160a05160c051611e83620001c1600039600081816101ed0152610aca0152600081816102eb0152818161045b0152818161081901528181610c360152610d4d01526000818161024d015281816105fc01528181610af001528181610e470152818161124d01526114140152611e836000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c80638ac4dbd0116100b8578063f2fde38b1161007c578063f2fde38b146103d0578063f3267a0b146103e3578063f74ed6de146103f6578063f782114414610409578063fa3a3d171461042a578063ffb29ecc1461043d57600080fd5b80638ac4dbd0146103205780638da5cb5b14610333578063b8eed0a714610346578063c4ff580314610369578063c7cc2568146103bd57600080fd5b806355da3dd71161010a57806355da3dd714610248578063609669a01461026f57806361a0fb34146102b057806362ca8460146102d357806373d62b46146102e6578063840a75fc1461030d57600080fd5b80630be125fe1461014757806314a66734146101a05780631d232f84146101d35780633fe3347a146101e8578063478426631461021d575b600080fd5b61018061015536600461170f565b600560209081526000928352604080842090915290825290205461ffff808216916201000090041682565b6040805161ffff9384168152929091166020830152015b60405180910390f35b6101b36101ae36600461177f565b610450565b604080519485526020850193909352918301526060820152608001610197565b6101e66101e13660046117e9565b6105f1565b005b61020f7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610197565b600154610230906001600160a01b031681565b6040516001600160a01b039091168152602001610197565b6102307f000000000000000000000000000000000000000000000000000000000000000081565b61029861027d36600461182b565b6006602052600090815260409020546001600160401b031681565b6040516001600160401b039091168152602001610197565b6102c36102be36600461170f565b6106cd565b6040519015158152602001610197565b6101e66102e136600461182b565b6106f8565b6102307f000000000000000000000000000000000000000000000000000000000000000081565b6101e661031b3660046118a8565b610776565b6101e661032e366004611967565b610b55565b600054610230906001600160a01b031681565b6102c361035436600461182b565b60036020526000908152604090205460ff1681565b61039d61037736600461182b565b6004602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b03938416815292909116602083015201610197565b6101e66103cb3660046117e9565b610e3c565b6101e66103de36600461182b565b610f78565b6101e66103f136600461170f565b610fed565b6102306104043660046119cb565b611102565b61041c61041736600461182b565b61112c565b6040516101979291906119e4565b61018061043836600461170f565b6111bc565b6101e661044b366004611add565b6111f6565b6000806000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663165cac96600660008a600001516001600160a01b03166001600160a01b0316815260200190815260200160002060010189606001516040518363ffffffff1660e01b81526004016104d6929190611b8f565b6040805180830381865afa1580156104f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105169190611be8565b9092509050801561055c5786516001600160a01b03166000908152600660205260409081902054908801516105559183906001600160401b03166113f2565b9450610593565b86516001600160a01b03166000908152600660205260409081902054908801516105909184906001600160401b03166113f2565b95505b505084516001600160a01b03908116600090815260056020818152604080842060608b0180518652908352818520549a519095168452918152818320935183529290925220549395929461ffff908116946201000090041692915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106685760405162461bcd60e51b815260206004820152601760248201527641504d3a204f4e4c595f4d41494e5f524547495354525960481b60448201526064015b60405180910390fd5b6001600160a01b038316600090815260046020526040902080548291906010906106a3908490600160801b90046001600160801b0316611c22565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555050505050565b6001600160a01b0382166000908152600460205260409020546001600160801b031615155b92915050565b6000546001600160a01b031633146107225760405162461bcd60e51b815260040161065f90611c49565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f6d9a586ef7be36e9ed3db326a9c62cce6c939c7ddae2c48f8f35562dce4fcd729060200160405180910390a150565b6000546001600160a01b031633146107a05760405162461bcd60e51b815260040161065f90611c49565b6001600160a01b03861660009081526003602052604090205460ff16156108025760405162461bcd60e51b815260206004820152601660248201527514134c8c17d0504e88185b1c9958591e48185919195960521b604482015260640161065f565b604051633f8e158b60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637f1c2b169061085290889088908b90600401611c6f565b60006040518083038186803b15801561086a57600080fd5b505afa15801561087e573d6000803e3d6000fd5b5050506001600160a01b0387166000818152600360209081526040808320805460ff1916600190811790915560028054918201815584527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b03191685179055805163313ce56760e01b8152905192945063313ce56792600480830193928290030181865afa15801561091e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109429190611cd0565b61094d90600a611dcd565b9050670de0b6b3a76400008111156109a75760405162461bcd60e51b815260206004820152601c60248201527f504d32305f41413a204d6178696d616c20313820646563696d616c7300000000604482015260640161065f565b6001600160a01b0387166000908152600660205260409020805467ffffffffffffffff19166001600160401b0383161781556109e790600101878761167b565b50610a44878585808060200260200160405190810160405280939291908181526020016000905b82821015610a3a57610a2b60808302860136819003810190611dd9565b81526020019060010190610a0e565b5050505050611410565b6001600160a01b03871660008181526004602090815260409182902080546001600160801b0319166001600160801b03871690811790915591519182527e27181bb8cc0c4150c5005856b596b2bab1577ddd41643abcc4098f505e74f4910160405180910390a26040516366a6a4bd60e01b81526001600160a01b0388811660048301527f000000000000000000000000000000000000000000000000000000000000000060248301527f000000000000000000000000000000000000000000000000000000000000000016906366a6a4bd90604401600060405180830381600087803b158015610b3457600080fd5b505af1158015610b48573d6000803e3d6000fd5b5050505050505050505050565b6000546001600160a01b03163314610b7f5760405162461bcd60e51b815260040161065f90611c49565b6001600160a01b038416600090815260066020908152604080832060010180548251818502810185019093528083529192909190830182828015610bec57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610bce575b505083519394506000925050505b81811015610ded57836001600160a01b0316838281518110610c1e57610c1e611df5565b60200260200101516001600160a01b031603610de5577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639f8a13d7848381518110610c7557610c75611df5565b60200260200101516040518263ffffffff1660e01b8152600401610ca891906001600160a01b0391909116815260200190565b602060405180830381865afa158015610cc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce99190611e0b565b15610d365760405162461bcd60e51b815260206004820152601c60248201527f504d32305f534f3a204f7261636c65207374696c6c2061637469766500000000604482015260640161065f565b604051633f8e158b60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637f1c2b1690610d8690899089908c90600401611c6f565b60006040518083038186803b158015610d9e57600080fd5b505afa158015610db2573d6000803e3d6000fd5b5050506001600160a01b0388166000908152600660205260409020610ddc9150600101878761167b565b50505050610e36565b600101610bfa565b5060405162461bcd60e51b815260206004820152601760248201527f504d32305f534f3a20556e6b6e6f776e204f7261636c65000000000000000000604482015260640161065f565b50505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610eae5760405162461bcd60e51b815260206004820152601760248201527641504d3a204f4e4c595f4d41494e5f524547495354525960481b604482015260640161065f565b6001600160a01b0383166000908152600460205260409020546001600160801b0380821691610ee6918491600160801b900416611e2d565b6001600160801b03161115610f3d5760405162461bcd60e51b815260206004820152601e60248201527f41504d5f50443a204578706f73757265206e6f7420696e206c696d6974730000604482015260640161065f565b6001600160a01b038316600090815260046020526040902080548291906010906106a3908490600160801b90046001600160801b0316611e2d565b6000546001600160a01b03163314610fa25760405162461bcd60e51b815260040161065f90611c49565b600080546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b6001546001600160a01b031633146110405760405162461bcd60e51b815260206004820152601660248201527520a8269d1027a7262cafa924a9a5afa6a0a720a3a2a960511b604482015260640161065f565b6001600160801b038111156110975760405162461bcd60e51b815260206004820152601f60248201527f41504d5f5345413a204d6178204578702e206e6f7420696e206c696d69747300604482015260640161065f565b6001600160a01b03821660008181526004602090815260409182902080546001600160801b0319166001600160801b03861690811790915591519182527e27181bb8cc0c4150c5005856b596b2bab1577ddd41643abcc4098f505e74f4910160405180910390a25050565b6002818154811061111257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b03811660009081526006602090815260408083208054600190910180548351818602810186019094528084526060946001600160401b039093169391928391908301828280156111ac57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118e575b5050505050905091509150915091565b6001600160a01b038216600090815260056020908152604080832084845290915290205461ffff80821691620100009004165b9250929050565b6001546001600160a01b031633146112495760405162461bcd60e51b815260206004820152601660248201527520a8269d1027a7262cafa924a9a5afa6a0a720a3a2a960511b604482015260640161065f565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635aea52996040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cd9190611cd0565b825190915060005b81811015610e3657828482815181106112f0576112f0611df5565b60200260200101516020015160ff161061134c5760405162461bcd60e51b815260206004820181905260248201527f41504d5f534252563a20426173654375722e206e6f7420696e206c696d697473604482015260640161065f565b6113ea84828151811061136157611361611df5565b60200260200101516000015185838151811061137f5761137f611df5565b60200260200101516020015160ff1660405180604001604052808886815181106113ab576113ab611df5565b60200260200101516040015161ffff1681526020018886815181106113d2576113d2611df5565b60200260200101516060015161ffff16815250611538565b6001016112d5565b600082600019048411830215820261140957600080fd5b5091020490565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635aea52996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611470573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114949190611cd0565b825190915060005b81811015611531578381815181106114b6576114b6611df5565b60200260200101516020015160ff1683116115135760405162461bcd60e51b815260206004820181905260248201527f41504d5f53525646413a2042617365437572206e6f7420696e206c696d697473604482015260640161065f565b6115298585838151811061137f5761137f611df5565b60010161149c565b5050505050565b8051606461ffff90911611156115905760405162461bcd60e51b815260206004820181905260248201527f41504d5f5352563a20436f6c6c2e46616374206e6f7420696e206c696d697473604482015260640161065f565b606461ffff16816020015161ffff1611156115ed5760405162461bcd60e51b815260206004820152601f60248201527f41504d5f5352563a204c69712e46616374206e6f7420696e206c696d69747300604482015260640161065f565b6001600160a01b0383166000818152600560209081526040808320868452825291829020845181548684015161ffff92831663ffffffff19909216821762010000939091169283021790925583519182529181019190915260ff851692917f39c94ba4b5b71b4770b8436f7035e62238af6282aef75ef2c6295a2541865cfd910160405180910390a3505050565b8280548282559060005260206000209081019282156116ce579160200282015b828111156116ce5781546001600160a01b0319166001600160a01b0384351617825560209092019160019091019061169b565b506116da9291506116de565b5090565b5b808211156116da57600081556001016116df565b80356001600160a01b038116811461170a57600080fd5b919050565b6000806040838503121561172257600080fd5b61172b836116f3565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561177757611777611739565b604052919050565b60006080828403121561179157600080fd5b604051608081018181106001600160401b03821117156117b3576117b3611739565b6040526117bf836116f3565b81526020830135602082015260408301356040820152606083013560608201528091505092915050565b600080600080608085870312156117ff57600080fd5b611808856116f3565b9350611816602086016116f3565b93969395505050506040820135916060013590565b60006020828403121561183d57600080fd5b611846826116f3565b9392505050565b60008083601f84011261185f57600080fd5b5081356001600160401b0381111561187657600080fd5b6020830191508360208260051b85010111156111ef57600080fd5b80356001600160801b038116811461170a57600080fd5b600080600080600080608087890312156118c157600080fd5b6118ca876116f3565b955060208701356001600160401b03808211156118e657600080fd5b6118f28a838b0161184d565b9097509550604089013591508082111561190b57600080fd5b818901915089601f83011261191f57600080fd5b81358181111561192e57600080fd5b8a60208260071b850101111561194357600080fd5b60208301955080945050505061195b60608801611891565b90509295509295509295565b6000806000806060858703121561197d57600080fd5b611986856116f3565b935060208501356001600160401b038111156119a157600080fd5b6119ad8782880161184d565b90945092506119c09050604086016116f3565b905092959194509250565b6000602082840312156119dd57600080fd5b5035919050565b6000604082016001600160401b03851683526020604081850152818551808452606086019150828701935060005b81811015611a375784516001600160a01b031683529383019391830191600101611a12565b5090979650505050505050565b803561ffff8116811461170a57600080fd5b600060808284031215611a6857600080fd5b604051608081018181106001600160401b0382111715611a8a57611a8a611739565b604052905080611a99836116f3565b8152602083013560ff81168114611aaf57600080fd5b6020820152611ac060408401611a44565b6040820152611ad160608401611a44565b60608201525092915050565b60006020808385031215611af057600080fd5b82356001600160401b0380821115611b0757600080fd5b818501915085601f830112611b1b57600080fd5b813581811115611b2d57611b2d611739565b611b3b848260051b0161174f565b818152848101925060079190911b830184019087821115611b5b57600080fd5b928401925b81841015611b8457611b728885611a56565b83528483019250608084019350611b60565b979650505050505050565b6000604082016040835280855480835260608501915086600052602092508260002060005b82811015611bd95781546001600160a01b031684529284019260019182019101611bb4565b50505092019290925292915050565b60008060408385031215611bfb57600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b6001600160801b03828116828216039080821115611c4257611c42611c0c565b5092915050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b6040808252810183905260008460608301825b86811015611cb0576001600160a01b03611c9b846116f3565b16825260209283019290910190600101611c82565b506001600160a01b03949094166020939093019290925250909392505050565b600060208284031215611ce257600080fd5b5051919050565b600181815b80851115611d24578160001904821115611d0a57611d0a611c0c565b80851615611d1757918102915b93841c9390800290611cee565b509250929050565b600082611d3b575060016106f2565b81611d48575060006106f2565b8160018114611d5e5760028114611d6857611d84565b60019150506106f2565b60ff841115611d7957611d79611c0c565b50506001821b6106f2565b5060208310610133831016604e8410600b8410161715611da7575081810a6106f2565b611db18383611ce9565b8060001904821115611dc557611dc5611c0c565b029392505050565b60006118468383611d2c565b600060808284031215611deb57600080fd5b6118468383611a56565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611e1d57600080fd5b8151801515811461184657600080fd5b6001600160801b03818116838216019080821115611c4257611c42611c0c56fea26469706673582212205e3c7c6c0b857bce98b2016f321a71419a60f339861f66f8ee453dfba7df400d64736f6c63430008110033000000000000000000000000046fc9f35eb7cb165a5e07915d37bf4022b8de33000000000000000000000000950a8833b9533a19fb4d1b2efc823ea6835f6d950000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101425760003560e01c80638ac4dbd0116100b8578063f2fde38b1161007c578063f2fde38b146103d0578063f3267a0b146103e3578063f74ed6de146103f6578063f782114414610409578063fa3a3d171461042a578063ffb29ecc1461043d57600080fd5b80638ac4dbd0146103205780638da5cb5b14610333578063b8eed0a714610346578063c4ff580314610369578063c7cc2568146103bd57600080fd5b806355da3dd71161010a57806355da3dd714610248578063609669a01461026f57806361a0fb34146102b057806362ca8460146102d357806373d62b46146102e6578063840a75fc1461030d57600080fd5b80630be125fe1461014757806314a66734146101a05780631d232f84146101d35780633fe3347a146101e8578063478426631461021d575b600080fd5b61018061015536600461170f565b600560209081526000928352604080842090915290825290205461ffff808216916201000090041682565b6040805161ffff9384168152929091166020830152015b60405180910390f35b6101b36101ae36600461177f565b610450565b604080519485526020850193909352918301526060820152608001610197565b6101e66101e13660046117e9565b6105f1565b005b61020f7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610197565b600154610230906001600160a01b031681565b6040516001600160a01b039091168152602001610197565b6102307f000000000000000000000000046fc9f35eb7cb165a5e07915d37bf4022b8de3381565b61029861027d36600461182b565b6006602052600090815260409020546001600160401b031681565b6040516001600160401b039091168152602001610197565b6102c36102be36600461170f565b6106cd565b6040519015158152602001610197565b6101e66102e136600461182b565b6106f8565b6102307f000000000000000000000000950a8833b9533a19fb4d1b2efc823ea6835f6d9581565b6101e661031b3660046118a8565b610776565b6101e661032e366004611967565b610b55565b600054610230906001600160a01b031681565b6102c361035436600461182b565b60036020526000908152604090205460ff1681565b61039d61037736600461182b565b6004602052600090815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b03938416815292909116602083015201610197565b6101e66103cb3660046117e9565b610e3c565b6101e66103de36600461182b565b610f78565b6101e66103f136600461170f565b610fed565b6102306104043660046119cb565b611102565b61041c61041736600461182b565b61112c565b6040516101979291906119e4565b61018061043836600461170f565b6111bc565b6101e661044b366004611add565b6111f6565b6000806000806000807f000000000000000000000000950a8833b9533a19fb4d1b2efc823ea6835f6d956001600160a01b031663165cac96600660008a600001516001600160a01b03166001600160a01b0316815260200190815260200160002060010189606001516040518363ffffffff1660e01b81526004016104d6929190611b8f565b6040805180830381865afa1580156104f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105169190611be8565b9092509050801561055c5786516001600160a01b03166000908152600660205260409081902054908801516105559183906001600160401b03166113f2565b9450610593565b86516001600160a01b03166000908152600660205260409081902054908801516105909184906001600160401b03166113f2565b95505b505084516001600160a01b03908116600090815260056020818152604080842060608b0180518652908352818520549a519095168452918152818320935183529290925220549395929461ffff908116946201000090041692915050565b336001600160a01b037f000000000000000000000000046fc9f35eb7cb165a5e07915d37bf4022b8de3316146106685760405162461bcd60e51b815260206004820152601760248201527641504d3a204f4e4c595f4d41494e5f524547495354525960481b60448201526064015b60405180910390fd5b6001600160a01b038316600090815260046020526040902080548291906010906106a3908490600160801b90046001600160801b0316611c22565b92506101000a8154816001600160801b0302191690836001600160801b0316021790555050505050565b6001600160a01b0382166000908152600460205260409020546001600160801b031615155b92915050565b6000546001600160a01b031633146107225760405162461bcd60e51b815260040161065f90611c49565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f6d9a586ef7be36e9ed3db326a9c62cce6c939c7ddae2c48f8f35562dce4fcd729060200160405180910390a150565b6000546001600160a01b031633146107a05760405162461bcd60e51b815260040161065f90611c49565b6001600160a01b03861660009081526003602052604090205460ff16156108025760405162461bcd60e51b815260206004820152601660248201527514134c8c17d0504e88185b1c9958591e48185919195960521b604482015260640161065f565b604051633f8e158b60e11b81526001600160a01b037f000000000000000000000000950a8833b9533a19fb4d1b2efc823ea6835f6d951690637f1c2b169061085290889088908b90600401611c6f565b60006040518083038186803b15801561086a57600080fd5b505afa15801561087e573d6000803e3d6000fd5b5050506001600160a01b0387166000818152600360209081526040808320805460ff1916600190811790915560028054918201815584527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b03191685179055805163313ce56760e01b8152905192945063313ce56792600480830193928290030181865afa15801561091e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109429190611cd0565b61094d90600a611dcd565b9050670de0b6b3a76400008111156109a75760405162461bcd60e51b815260206004820152601c60248201527f504d32305f41413a204d6178696d616c20313820646563696d616c7300000000604482015260640161065f565b6001600160a01b0387166000908152600660205260409020805467ffffffffffffffff19166001600160401b0383161781556109e790600101878761167b565b50610a44878585808060200260200160405190810160405280939291908181526020016000905b82821015610a3a57610a2b60808302860136819003810190611dd9565b81526020019060010190610a0e565b5050505050611410565b6001600160a01b03871660008181526004602090815260409182902080546001600160801b0319166001600160801b03871690811790915591519182527e27181bb8cc0c4150c5005856b596b2bab1577ddd41643abcc4098f505e74f4910160405180910390a26040516366a6a4bd60e01b81526001600160a01b0388811660048301527f000000000000000000000000000000000000000000000000000000000000000060248301527f000000000000000000000000046fc9f35eb7cb165a5e07915d37bf4022b8de3316906366a6a4bd90604401600060405180830381600087803b158015610b3457600080fd5b505af1158015610b48573d6000803e3d6000fd5b5050505050505050505050565b6000546001600160a01b03163314610b7f5760405162461bcd60e51b815260040161065f90611c49565b6001600160a01b038416600090815260066020908152604080832060010180548251818502810185019093528083529192909190830182828015610bec57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610bce575b505083519394506000925050505b81811015610ded57836001600160a01b0316838281518110610c1e57610c1e611df5565b60200260200101516001600160a01b031603610de5577f000000000000000000000000950a8833b9533a19fb4d1b2efc823ea6835f6d956001600160a01b0316639f8a13d7848381518110610c7557610c75611df5565b60200260200101516040518263ffffffff1660e01b8152600401610ca891906001600160a01b0391909116815260200190565b602060405180830381865afa158015610cc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce99190611e0b565b15610d365760405162461bcd60e51b815260206004820152601c60248201527f504d32305f534f3a204f7261636c65207374696c6c2061637469766500000000604482015260640161065f565b604051633f8e158b60e11b81526001600160a01b037f000000000000000000000000950a8833b9533a19fb4d1b2efc823ea6835f6d951690637f1c2b1690610d8690899089908c90600401611c6f565b60006040518083038186803b158015610d9e57600080fd5b505afa158015610db2573d6000803e3d6000fd5b5050506001600160a01b0388166000908152600660205260409020610ddc9150600101878761167b565b50505050610e36565b600101610bfa565b5060405162461bcd60e51b815260206004820152601760248201527f504d32305f534f3a20556e6b6e6f776e204f7261636c65000000000000000000604482015260640161065f565b50505050565b336001600160a01b037f000000000000000000000000046fc9f35eb7cb165a5e07915d37bf4022b8de331614610eae5760405162461bcd60e51b815260206004820152601760248201527641504d3a204f4e4c595f4d41494e5f524547495354525960481b604482015260640161065f565b6001600160a01b0383166000908152600460205260409020546001600160801b0380821691610ee6918491600160801b900416611e2d565b6001600160801b03161115610f3d5760405162461bcd60e51b815260206004820152601e60248201527f41504d5f50443a204578706f73757265206e6f7420696e206c696d6974730000604482015260640161065f565b6001600160a01b038316600090815260046020526040902080548291906010906106a3908490600160801b90046001600160801b0316611e2d565b6000546001600160a01b03163314610fa25760405162461bcd60e51b815260040161065f90611c49565b600080546001600160a01b0319166001600160a01b0383169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b6001546001600160a01b031633146110405760405162461bcd60e51b815260206004820152601660248201527520a8269d1027a7262cafa924a9a5afa6a0a720a3a2a960511b604482015260640161065f565b6001600160801b038111156110975760405162461bcd60e51b815260206004820152601f60248201527f41504d5f5345413a204d6178204578702e206e6f7420696e206c696d69747300604482015260640161065f565b6001600160a01b03821660008181526004602090815260409182902080546001600160801b0319166001600160801b03861690811790915591519182527e27181bb8cc0c4150c5005856b596b2bab1577ddd41643abcc4098f505e74f4910160405180910390a25050565b6002818154811061111257600080fd5b6000918252602090912001546001600160a01b0316905081565b6001600160a01b03811660009081526006602090815260408083208054600190910180548351818602810186019094528084526060946001600160401b039093169391928391908301828280156111ac57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118e575b5050505050905091509150915091565b6001600160a01b038216600090815260056020908152604080832084845290915290205461ffff80821691620100009004165b9250929050565b6001546001600160a01b031633146112495760405162461bcd60e51b815260206004820152601660248201527520a8269d1027a7262cafa924a9a5afa6a0a720a3a2a960511b604482015260640161065f565b60007f000000000000000000000000046fc9f35eb7cb165a5e07915d37bf4022b8de336001600160a01b0316635aea52996040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cd9190611cd0565b825190915060005b81811015610e3657828482815181106112f0576112f0611df5565b60200260200101516020015160ff161061134c5760405162461bcd60e51b815260206004820181905260248201527f41504d5f534252563a20426173654375722e206e6f7420696e206c696d697473604482015260640161065f565b6113ea84828151811061136157611361611df5565b60200260200101516000015185838151811061137f5761137f611df5565b60200260200101516020015160ff1660405180604001604052808886815181106113ab576113ab611df5565b60200260200101516040015161ffff1681526020018886815181106113d2576113d2611df5565b60200260200101516060015161ffff16815250611538565b6001016112d5565b600082600019048411830215820261140957600080fd5b5091020490565b60007f000000000000000000000000046fc9f35eb7cb165a5e07915d37bf4022b8de336001600160a01b0316635aea52996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611470573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114949190611cd0565b825190915060005b81811015611531578381815181106114b6576114b6611df5565b60200260200101516020015160ff1683116115135760405162461bcd60e51b815260206004820181905260248201527f41504d5f53525646413a2042617365437572206e6f7420696e206c696d697473604482015260640161065f565b6115298585838151811061137f5761137f611df5565b60010161149c565b5050505050565b8051606461ffff90911611156115905760405162461bcd60e51b815260206004820181905260248201527f41504d5f5352563a20436f6c6c2e46616374206e6f7420696e206c696d697473604482015260640161065f565b606461ffff16816020015161ffff1611156115ed5760405162461bcd60e51b815260206004820152601f60248201527f41504d5f5352563a204c69712e46616374206e6f7420696e206c696d69747300604482015260640161065f565b6001600160a01b0383166000818152600560209081526040808320868452825291829020845181548684015161ffff92831663ffffffff19909216821762010000939091169283021790925583519182529181019190915260ff851692917f39c94ba4b5b71b4770b8436f7035e62238af6282aef75ef2c6295a2541865cfd910160405180910390a3505050565b8280548282559060005260206000209081019282156116ce579160200282015b828111156116ce5781546001600160a01b0319166001600160a01b0384351617825560209092019160019091019061169b565b506116da9291506116de565b5090565b5b808211156116da57600081556001016116df565b80356001600160a01b038116811461170a57600080fd5b919050565b6000806040838503121561172257600080fd5b61172b836116f3565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561177757611777611739565b604052919050565b60006080828403121561179157600080fd5b604051608081018181106001600160401b03821117156117b3576117b3611739565b6040526117bf836116f3565b81526020830135602082015260408301356040820152606083013560608201528091505092915050565b600080600080608085870312156117ff57600080fd5b611808856116f3565b9350611816602086016116f3565b93969395505050506040820135916060013590565b60006020828403121561183d57600080fd5b611846826116f3565b9392505050565b60008083601f84011261185f57600080fd5b5081356001600160401b0381111561187657600080fd5b6020830191508360208260051b85010111156111ef57600080fd5b80356001600160801b038116811461170a57600080fd5b600080600080600080608087890312156118c157600080fd5b6118ca876116f3565b955060208701356001600160401b03808211156118e657600080fd5b6118f28a838b0161184d565b9097509550604089013591508082111561190b57600080fd5b818901915089601f83011261191f57600080fd5b81358181111561192e57600080fd5b8a60208260071b850101111561194357600080fd5b60208301955080945050505061195b60608801611891565b90509295509295509295565b6000806000806060858703121561197d57600080fd5b611986856116f3565b935060208501356001600160401b038111156119a157600080fd5b6119ad8782880161184d565b90945092506119c09050604086016116f3565b905092959194509250565b6000602082840312156119dd57600080fd5b5035919050565b6000604082016001600160401b03851683526020604081850152818551808452606086019150828701935060005b81811015611a375784516001600160a01b031683529383019391830191600101611a12565b5090979650505050505050565b803561ffff8116811461170a57600080fd5b600060808284031215611a6857600080fd5b604051608081018181106001600160401b0382111715611a8a57611a8a611739565b604052905080611a99836116f3565b8152602083013560ff81168114611aaf57600080fd5b6020820152611ac060408401611a44565b6040820152611ad160608401611a44565b60608201525092915050565b60006020808385031215611af057600080fd5b82356001600160401b0380821115611b0757600080fd5b818501915085601f830112611b1b57600080fd5b813581811115611b2d57611b2d611739565b611b3b848260051b0161174f565b818152848101925060079190911b830184019087821115611b5b57600080fd5b928401925b81841015611b8457611b728885611a56565b83528483019250608084019350611b60565b979650505050505050565b6000604082016040835280855480835260608501915086600052602092508260002060005b82811015611bd95781546001600160a01b031684529284019260019182019101611bb4565b50505092019290925292915050565b60008060408385031215611bfb57600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b6001600160801b03828116828216039080821115611c4257611c42611c0c565b5092915050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b6040808252810183905260008460608301825b86811015611cb0576001600160a01b03611c9b846116f3565b16825260209283019290910190600101611c82565b506001600160a01b03949094166020939093019290925250909392505050565b600060208284031215611ce257600080fd5b5051919050565b600181815b80851115611d24578160001904821115611d0a57611d0a611c0c565b80851615611d1757918102915b93841c9390800290611cee565b509250929050565b600082611d3b575060016106f2565b81611d48575060006106f2565b8160018114611d5e5760028114611d6857611d84565b60019150506106f2565b60ff841115611d7957611d79611c0c565b50506001821b6106f2565b5060208310610133831016604e8410600b8410161715611da7575081810a6106f2565b611db18383611ce9565b8060001904821115611dc557611dc5611c0c565b029392505050565b60006118468383611d2c565b600060808284031215611deb57600080fd5b6118468383611a56565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611e1d57600080fd5b8151801515811461184657600080fd5b6001600160801b03818116838216019080821115611c4257611c42611c0c56fea26469706673582212205e3c7c6c0b857bce98b2016f321a71419a60f339861f66f8ee453dfba7df400d64736f6c63430008110033

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

000000000000000000000000046fc9f35eb7cb165a5e07915d37bf4022b8de33000000000000000000000000950a8833b9533a19fb4d1b2efc823ea6835f6d950000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : mainRegistry_ (address): 0x046fc9f35EB7Cb165a5e07915d37bF4022b8dE33
Arg [1] : oracleHub_ (address): 0x950A8833b9533A19Fb4D1B2EFC823Ea6835f6d95
Arg [2] : assetType_ (uint256): 0

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000046fc9f35eb7cb165a5e07915d37bf4022b8de33
Arg [1] : 000000000000000000000000950a8833b9533a19fb4d1b2efc823ea6835f6d95
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

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