Contract
0x411a1c0130608be3aa97bc116ef183decb431fc3
1
Contract Overview
Balance:
0 DEV
My Name Tag:
Not Available
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
DebtCache
Compiler Version
v0.5.16+commit.9c3226ce
Contract Source Code (Solidity)
/** *Submitted for verification at moonbase.moonscan.io on 2022-01-11 */ /* ___ _ ___ _ | .\ ___ _ _ <_> ___ | __><_>._ _ ___ ._ _ ___ ___ | _// ._>| '_>| ||___|| _> | || ' |<_> || ' |/ | '/ ._> |_| \___.|_| |_| |_| |_||_|_|<___||_|_|\_|_.\___. * PeriFinance: DebtCache.sol * * Latest source (may be newer): https://github.com/perifinance/peri-finance/blob/master/contracts/DebtCache.sol * Docs: Will be added in the future. * https://docs.peri.finance/contracts/source/contracts/DebtCache * * Contract Dependencies: * - BaseDebtCache * - IAddressResolver * - IDebtCache * - MixinResolver * - MixinSystemSettings * - Owned * Libraries: * - SafeDecimalMath * - SafeMath * * MIT License * =========== * * Copyright (c) 2022 PeriFinance * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ pragma solidity 0.5.16; // https://docs.peri.finance/contracts/source/contracts/owned contract Owned { address public owner; address public nominatedOwner; constructor(address _owner) public { require(_owner != address(0), "Owner address cannot be 0"); owner = _owner; emit OwnerChanged(address(0), _owner); } function nominateNewOwner(address _owner) external onlyOwner { nominatedOwner = _owner; emit OwnerNominated(_owner); } function acceptOwnership() external { require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); emit OwnerChanged(owner, nominatedOwner); owner = nominatedOwner; nominatedOwner = address(0); } modifier onlyOwner { _onlyOwner(); _; } function _onlyOwner() private view { require(msg.sender == owner, "Only the contract owner may perform this action"); } event OwnerNominated(address newOwner); event OwnerChanged(address oldOwner, address newOwner); } // https://docs.peri.finance/contracts/source/interfaces/iaddressresolver interface IAddressResolver { function getAddress(bytes32 name) external view returns (address); function getPynth(bytes32 key) external view returns (address); function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address); } // https://docs.peri.finance/contracts/source/interfaces/ipynth interface IPynth { // Views function currencyKey() external view returns (bytes32); function transferablePynths(address account) external view returns (uint); // Mutative functions function transferAndSettle(address to, uint value) external returns (bool); function transferFromAndSettle( address from, address to, uint value ) external returns (bool); // Restricted: used internally to PeriFinance function burn(address account, uint amount) external; function issue(address account, uint amount) external; } // https://docs.peri.finance/contracts/source/interfaces/iissuer interface IIssuer { // Views function anyPynthOrPERIRateIsInvalid() external view returns (bool anyRateInvalid); function availableCurrencyKeys() external view returns (bytes32[] memory); function availablePynthCount() external view returns (uint); function availablePynths(uint index) external view returns (IPynth); function canBurnPynths(address account) external view returns (bool); function collateral(address account) external view returns (uint); function collateralisationRatio(address issuer) external view returns (uint); function collateralisationRatioAndAnyRatesInvalid(address _issuer) external view returns (uint cratio, bool anyRateIsInvalid); function debtBalanceOf(address issuer, bytes32 currencyKey) external view returns (uint debtBalance); function lastIssueEvent(address account) external view returns (uint); function maxIssuablePynths(address issuer) external view returns (uint maxIssuable); function externalTokenQuota( address _account, uint _addtionalpUSD, uint _addtionalExToken, bool _isIssue ) external view returns (uint); function remainingIssuablePynths(address issuer) external view returns ( uint maxIssuable, uint alreadyIssued, uint totalSystemDebt ); function pynths(bytes32 currencyKey) external view returns (IPynth); function getPynths(bytes32[] calldata currencyKeys) external view returns (IPynth[] memory); function pynthsByAddress(address pynthAddress) external view returns (bytes32); function totalIssuedPynths(bytes32 currencyKey, bool excludeEtherCollateral) external view returns (uint, bool); function transferablePeriFinanceAndAnyRateIsInvalid(address account, uint balance) external view returns (uint transferable, bool anyRateIsInvalid); function amountsToFitClaimable(address _account) external view returns (uint burnAmount, uint exTokenAmountToUnstake); // Restricted: used internally to PeriFinance function issuePynths( address _issuer, bytes32 _currencyKey, uint _issueAmount ) external; function issueMaxPynths(address _issuer) external; function issuePynthsToMaxQuota(address _issuer, bytes32 _currencyKey) external; function burnPynths( address _from, bytes32 _currencyKey, uint _burnAmount ) external; function fitToClaimable(address _from) external; function exit(address _from) external; function liquidateDelinquentAccount( address account, uint pusdAmount, address liquidator ) external returns (uint totalRedeemed, uint amountToLiquidate); } // Inheritance // Internal references // https://docs.peri.finance/contracts/source/contracts/addressresolver contract AddressResolver is Owned, IAddressResolver { mapping(bytes32 => address) public repository; constructor(address _owner) public Owned(_owner) {} /* ========== RESTRICTED FUNCTIONS ========== */ function importAddresses(bytes32[] calldata names, address[] calldata destinations) external onlyOwner { require(names.length == destinations.length, "Input lengths must match"); for (uint i = 0; i < names.length; i++) { bytes32 name = names[i]; address destination = destinations[i]; repository[name] = destination; emit AddressImported(name, destination); } } /* ========= PUBLIC FUNCTIONS ========== */ function rebuildCaches(MixinResolver[] calldata destinations) external { for (uint i = 0; i < destinations.length; i++) { destinations[i].rebuildCache(); } } /* ========== VIEWS ========== */ function areAddressesImported(bytes32[] calldata names, address[] calldata destinations) external view returns (bool) { for (uint i = 0; i < names.length; i++) { if (repository[names[i]] != destinations[i]) { return false; } } return true; } function getAddress(bytes32 name) external view returns (address) { return repository[name]; } function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address) { address _foundAddress = repository[name]; require(_foundAddress != address(0), reason); return _foundAddress; } function getPynth(bytes32 key) external view returns (address) { IIssuer issuer = IIssuer(repository["Issuer"]); require(address(issuer) != address(0), "Cannot find Issuer address"); return address(issuer.pynths(key)); } /* ========== EVENTS ========== */ event AddressImported(bytes32 name, address destination); } // solhint-disable payable-fallback // https://docs.peri.finance/contracts/source/contracts/readproxy contract ReadProxy is Owned { address public target; constructor(address _owner) public Owned(_owner) {} function setTarget(address _target) external onlyOwner { target = _target; emit TargetUpdated(target); } function() external { // The basics of a proxy read call // Note that msg.sender in the underlying will always be the address of this contract. assembly { calldatacopy(0, 0, calldatasize) // Use of staticcall - this will revert if the underlying function mutates state let result := staticcall(gas, sload(target_slot), 0, calldatasize, 0, 0) returndatacopy(0, 0, returndatasize) if iszero(result) { revert(0, returndatasize) } return(0, returndatasize) } } event TargetUpdated(address newTarget); } // Inheritance // Internal references // https://docs.peri.finance/contracts/source/contracts/mixinresolver contract MixinResolver { AddressResolver public resolver; mapping(bytes32 => address) private addressCache; constructor(address _resolver) internal { resolver = AddressResolver(_resolver); } /* ========== INTERNAL FUNCTIONS ========== */ function combineArrays(bytes32[] memory first, bytes32[] memory second) internal pure returns (bytes32[] memory combination) { combination = new bytes32[](first.length + second.length); for (uint i = 0; i < first.length; i++) { combination[i] = first[i]; } for (uint j = 0; j < second.length; j++) { combination[first.length + j] = second[j]; } } /* ========== PUBLIC FUNCTIONS ========== */ // Note: this function is public not external in order for it to be overridden and invoked via super in subclasses function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {} function rebuildCache() public { bytes32[] memory requiredAddresses = resolverAddressesRequired(); // The resolver must call this function whenver it updates its state for (uint i = 0; i < requiredAddresses.length; i++) { bytes32 name = requiredAddresses[i]; // Note: can only be invoked once the resolver has all the targets needed added address destination = resolver.requireAndGetAddress(name, string(abi.encodePacked("Resolver missing target: ", name))); addressCache[name] = destination; emit CacheUpdated(name, destination); } } /* ========== VIEWS ========== */ function isResolverCached() external view returns (bool) { bytes32[] memory requiredAddresses = resolverAddressesRequired(); for (uint i = 0; i < requiredAddresses.length; i++) { bytes32 name = requiredAddresses[i]; // false if our cache is invalid or if the resolver doesn't have the required address if (resolver.getAddress(name) != addressCache[name] || addressCache[name] == address(0)) { return false; } } return true; } /* ========== INTERNAL FUNCTIONS ========== */ function requireAndGetAddress(bytes32 name) internal view returns (address) { address _foundAddress = addressCache[name]; require(_foundAddress != address(0), string(abi.encodePacked("Missing address: ", name))); return _foundAddress; } /* ========== EVENTS ========== */ event CacheUpdated(bytes32 name, address destination); } // https://docs.peri.finance/contracts/source/interfaces/iflexiblestorage interface IFlexibleStorage { // Views function getUIntValue(bytes32 contractName, bytes32 record) external view returns (uint); function getUIntValues(bytes32 contractName, bytes32[] calldata records) external view returns (uint[] memory); function getIntValue(bytes32 contractName, bytes32 record) external view returns (int); function getIntValues(bytes32 contractName, bytes32[] calldata records) external view returns (int[] memory); function getAddressValue(bytes32 contractName, bytes32 record) external view returns (address); function getAddressValues(bytes32 contractName, bytes32[] calldata records) external view returns (address[] memory); function getBoolValue(bytes32 contractName, bytes32 record) external view returns (bool); function getBoolValues(bytes32 contractName, bytes32[] calldata records) external view returns (bool[] memory); function getBytes32Value(bytes32 contractName, bytes32 record) external view returns (bytes32); function getBytes32Values(bytes32 contractName, bytes32[] calldata records) external view returns (bytes32[] memory); // Mutative functions function deleteUIntValue(bytes32 contractName, bytes32 record) external; function deleteIntValue(bytes32 contractName, bytes32 record) external; function deleteAddressValue(bytes32 contractName, bytes32 record) external; function deleteBoolValue(bytes32 contractName, bytes32 record) external; function deleteBytes32Value(bytes32 contractName, bytes32 record) external; function setUIntValue( bytes32 contractName, bytes32 record, uint value ) external; function setUIntValues( bytes32 contractName, bytes32[] calldata records, uint[] calldata values ) external; function setIntValue( bytes32 contractName, bytes32 record, int value ) external; function setIntValues( bytes32 contractName, bytes32[] calldata records, int[] calldata values ) external; function setAddressValue( bytes32 contractName, bytes32 record, address value ) external; function setAddressValues( bytes32 contractName, bytes32[] calldata records, address[] calldata values ) external; function setBoolValue( bytes32 contractName, bytes32 record, bool value ) external; function setBoolValues( bytes32 contractName, bytes32[] calldata records, bool[] calldata values ) external; function setBytes32Value( bytes32 contractName, bytes32 record, bytes32 value ) external; function setBytes32Values( bytes32 contractName, bytes32[] calldata records, bytes32[] calldata values ) external; } // Internal references // https://docs.peri.finance/contracts/source/contracts/mixinsystemsettings contract MixinSystemSettings is MixinResolver { bytes32 internal constant SETTING_CONTRACT_NAME = "SystemSettings"; bytes32 internal constant SETTING_WAITING_PERIOD_SECS = "waitingPeriodSecs"; bytes32 internal constant SETTING_PRICE_DEVIATION_THRESHOLD_FACTOR = "priceDeviationThresholdFactor"; bytes32 internal constant SETTING_ISSUANCE_RATIO = "issuanceRatio"; bytes32 internal constant SETTING_FEE_PERIOD_DURATION = "feePeriodDuration"; bytes32 internal constant SETTING_TARGET_THRESHOLD = "targetThreshold"; bytes32 internal constant SETTING_LIQUIDATION_DELAY = "liquidationDelay"; bytes32 internal constant SETTING_LIQUIDATION_RATIO = "liquidationRatio"; bytes32 internal constant SETTING_LIQUIDATION_PENALTY = "liquidationPenalty"; bytes32 internal constant SETTING_RATE_STALE_PERIOD = "rateStalePeriod"; bytes32 internal constant SETTING_EXCHANGE_FEE_RATE = "exchangeFeeRate"; bytes32 internal constant SETTING_MINIMUM_STAKE_TIME = "minimumStakeTime"; bytes32 internal constant SETTING_AGGREGATOR_WARNING_FLAGS = "aggregatorWarningFlags"; bytes32 internal constant SETTING_TRADING_REWARDS_ENABLED = "tradingRewardsEnabled"; bytes32 internal constant SETTING_DEBT_SNAPSHOT_STALE_TIME = "debtSnapshotStaleTime"; bytes32 internal constant SETTING_CROSS_DOMAIN_DEPOSIT_GAS_LIMIT = "crossDomainDepositGasLimit"; bytes32 internal constant SETTING_CROSS_DOMAIN_ESCROW_GAS_LIMIT = "crossDomainEscrowGasLimit"; bytes32 internal constant SETTING_CROSS_DOMAIN_REWARD_GAS_LIMIT = "crossDomainRewardGasLimit"; bytes32 internal constant SETTING_CROSS_DOMAIN_WITHDRAWAL_GAS_LIMIT = "crossDomainWithdrawalGasLimit"; bytes32 internal constant SETTING_EXTERNAL_TOKEN_QUOTA = "externalTokenQuota"; bytes32 internal constant SETTING_BRIDGE_TRANSFER_GAS_COST = "bridgeTransferGasCost"; bytes32 internal constant SETTING_BRIDGE_CLAIM_GAS_COST = "bridgeClaimGasCost"; bytes32 internal constant CONTRACT_FLEXIBLESTORAGE = "FlexibleStorage"; enum CrossDomainMessageGasLimits {Deposit, Escrow, Reward, Withdrawal} constructor(address _resolver) internal MixinResolver(_resolver) {} function resolverAddressesRequired() public view returns (bytes32[] memory addresses) { addresses = new bytes32[](1); addresses[0] = CONTRACT_FLEXIBLESTORAGE; } function flexibleStorage() internal view returns (IFlexibleStorage) { return IFlexibleStorage(requireAndGetAddress(CONTRACT_FLEXIBLESTORAGE)); } function _getGasLimitSetting(CrossDomainMessageGasLimits gasLimitType) internal pure returns (bytes32) { if (gasLimitType == CrossDomainMessageGasLimits.Deposit) { return SETTING_CROSS_DOMAIN_DEPOSIT_GAS_LIMIT; } else if (gasLimitType == CrossDomainMessageGasLimits.Escrow) { return SETTING_CROSS_DOMAIN_ESCROW_GAS_LIMIT; } else if (gasLimitType == CrossDomainMessageGasLimits.Reward) { return SETTING_CROSS_DOMAIN_REWARD_GAS_LIMIT; } else if (gasLimitType == CrossDomainMessageGasLimits.Withdrawal) { return SETTING_CROSS_DOMAIN_WITHDRAWAL_GAS_LIMIT; } else { revert("Unknown gas limit type"); } } function getCrossDomainMessageGasLimit(CrossDomainMessageGasLimits gasLimitType) internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, _getGasLimitSetting(gasLimitType)); } function getTradingRewardsEnabled() internal view returns (bool) { return flexibleStorage().getBoolValue(SETTING_CONTRACT_NAME, SETTING_TRADING_REWARDS_ENABLED); } function getWaitingPeriodSecs() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_WAITING_PERIOD_SECS); } function getPriceDeviationThresholdFactor() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_PRICE_DEVIATION_THRESHOLD_FACTOR); } function getIssuanceRatio() internal view returns (uint) { // lookup on flexible storage directly for gas savings (rather than via SystemSettings) return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ISSUANCE_RATIO); } function getFeePeriodDuration() internal view returns (uint) { // lookup on flexible storage directly for gas savings (rather than via SystemSettings) return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_FEE_PERIOD_DURATION); } function getTargetThreshold() internal view returns (uint) { // lookup on flexible storage directly for gas savings (rather than via SystemSettings) return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_TARGET_THRESHOLD); } function getLiquidationDelay() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_DELAY); } function getLiquidationRatio() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_RATIO); } function getLiquidationPenalty() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_PENALTY); } function getRateStalePeriod() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_RATE_STALE_PERIOD); } function getExchangeFeeRate(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_EXCHANGE_FEE_RATE, currencyKey)) ); } function getMinimumStakeTime() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_MINIMUM_STAKE_TIME); } function getAggregatorWarningFlags() internal view returns (address) { return flexibleStorage().getAddressValue(SETTING_CONTRACT_NAME, SETTING_AGGREGATOR_WARNING_FLAGS); } function getDebtSnapshotStaleTime() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_DEBT_SNAPSHOT_STALE_TIME); } function getExternalTokenQuota() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_EXTERNAL_TOKEN_QUOTA); } function getBridgeTransferGasCost() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_BRIDGE_TRANSFER_GAS_COST); } function getBridgeClaimGasCost() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_BRIDGE_CLAIM_GAS_COST); } } interface IDebtCache { // Views function cachedDebt() external view returns (uint); function cachedPynthDebt(bytes32 currencyKey) external view returns (uint); function cacheTimestamp() external view returns (uint); function cacheInvalid() external view returns (bool); function cacheStale() external view returns (bool); function currentPynthDebts(bytes32[] calldata currencyKeys) external view returns (uint[] memory debtValues, bool anyRateIsInvalid); function cachedPynthDebts(bytes32[] calldata currencyKeys) external view returns (uint[] memory debtValues); function currentDebt() external view returns (uint debt, bool anyRateIsInvalid); function cacheInfo() external view returns ( uint debt, uint timestamp, bool isInvalid, bool isStale ); // Mutative functions function updateCachedPynthDebts(bytes32[] calldata currencyKeys) external; function updateCachedPynthDebtWithRate(bytes32 currencyKey, uint currencyRate) external; function updateCachedPynthDebtsWithRates(bytes32[] calldata currencyKeys, uint[] calldata currencyRates) external; function updateDebtCacheValidity(bool currentlyInvalid) external; function purgeCachedPynthDebt(bytes32 currencyKey) external; function takeDebtSnapshot() external; } /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); 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-solidity/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) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); 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) { require(b != 0, "SafeMath: modulo by zero"); return a % b; } } // Libraries // https://docs.peri.finance/contracts/source/libraries/safedecimalmath library SafeDecimalMath { using SafeMath for uint; /* Number of decimal places in the representations. */ uint8 public constant decimals = 18; uint8 public constant highPrecisionDecimals = 27; /* The number representing 1.0. */ uint public constant UNIT = 10**uint(decimals); /* The number representing 1.0 for higher fidelity numbers. */ uint public constant PRECISE_UNIT = 10**uint(highPrecisionDecimals); uint private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10**uint(highPrecisionDecimals - decimals); /** * @return Provides an interface to UNIT. */ function unit() external pure returns (uint) { return UNIT; } /** * @return Provides an interface to PRECISE_UNIT. */ function preciseUnit() external pure returns (uint) { return PRECISE_UNIT; } /** * @return The result of multiplying x and y, interpreting the operands as fixed-point * decimals. * * @dev A unit factor is divided out after the product of x and y is evaluated, * so that product must be less than 2**256. As this is an integer division, * the internal division always rounds down. This helps save on gas. Rounding * is more expensive on gas. */ function multiplyDecimal(uint x, uint y) internal pure returns (uint) { /* Divide by UNIT to remove the extra factor introduced by the product. */ return x.mul(y) / UNIT; } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of the specified precision unit. * * @dev The operands should be in the form of a the specified unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function _multiplyDecimalRound( uint x, uint y, uint precisionUnit ) private pure returns (uint) { /* Divide by UNIT to remove the extra factor introduced by the product. */ uint quotientTimesTen = x.mul(y) / (precisionUnit / 10); if (quotientTimesTen % 10 >= 5) { quotientTimesTen += 10; } return quotientTimesTen / 10; } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of a precise unit. * * @dev The operands should be in the precise unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function multiplyDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) { return _multiplyDecimalRound(x, y, PRECISE_UNIT); } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of a standard unit. * * @dev The operands should be in the standard unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function multiplyDecimalRound(uint x, uint y) internal pure returns (uint) { return _multiplyDecimalRound(x, y, UNIT); } /** * @return The result of safely dividing x and y. The return value is a high * precision decimal. * * @dev y is divided after the product of x and the standard precision unit * is evaluated, so the product of x and UNIT must be less than 2**256. As * this is an integer division, the result is always rounded down. * This helps save on gas. Rounding is more expensive on gas. */ function divideDecimal(uint x, uint y) internal pure returns (uint) { /* Reintroduce the UNIT factor that will be divided out by y. */ return x.mul(UNIT).div(y); } /** * @return The result of safely dividing x and y. The return value is as a rounded * decimal in the precision unit specified in the parameter. * * @dev y is divided after the product of x and the specified precision unit * is evaluated, so the product of x and the specified precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function _divideDecimalRound( uint x, uint y, uint precisionUnit ) private pure returns (uint) { uint resultTimesTen = x.mul(precisionUnit * 10).div(y); if (resultTimesTen % 10 >= 5) { resultTimesTen += 10; } return resultTimesTen / 10; } /** * @return The result of safely dividing x and y. The return value is as a rounded * standard precision decimal. * * @dev y is divided after the product of x and the standard precision unit * is evaluated, so the product of x and the standard precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function divideDecimalRound(uint x, uint y) internal pure returns (uint) { return _divideDecimalRound(x, y, UNIT); } /** * @return The result of safely dividing x and y. The return value is as a rounded * high precision decimal. * * @dev y is divided after the product of x and the high precision unit * is evaluated, so the product of x and the high precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function divideDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) { return _divideDecimalRound(x, y, PRECISE_UNIT); } /** * @dev Convert a standard decimal representation to a high precision one. */ function decimalToPreciseDecimal(uint i) internal pure returns (uint) { return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR); } /** * @dev Convert a high precision decimal to a standard decimal representation. */ function preciseDecimalToDecimal(uint i) internal pure returns (uint) { uint quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10); if (quotientTimesTen % 10 >= 5) { quotientTimesTen += 10; } return quotientTimesTen / 10; } /** * @dev Round down the value with given number */ function roundDownDecimal(uint x, uint d) internal pure returns (uint) { return x.div(10**d).mul(10**d); } /** * @dev Round up the value with given number */ function roundUpDecimal(uint x, uint d) internal pure returns (uint) { uint _decimal = 10**d; if (x % _decimal > 0) { x = x.add(10**d); } return x.div(_decimal).mul(_decimal); } } interface IVirtualPynth { // Views function balanceOfUnderlying(address account) external view returns (uint); function rate() external view returns (uint); function readyToSettle() external view returns (bool); function secsLeftInWaitingPeriod() external view returns (uint); function settled() external view returns (bool); function pynth() external view returns (IPynth); // Mutative functions function settle(address account) external; } // https://docs.peri.finance/contracts/source/interfaces/iexchanger interface IExchanger { // Views function calculateAmountAfterSettlement( address from, bytes32 currencyKey, uint amount, uint refunded ) external view returns (uint amountAfterSettlement); function isPynthRateInvalid(bytes32 currencyKey) external view returns (bool); function maxSecsLeftInWaitingPeriod(address account, bytes32 currencyKey) external view returns (uint); function settlementOwing(address account, bytes32 currencyKey) external view returns ( uint reclaimAmount, uint rebateAmount, uint numEntries ); function hasWaitingPeriodOrSettlementOwing(address account, bytes32 currencyKey) external view returns (bool); function feeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view returns (uint exchangeFeeRate); function getAmountsForExchange( uint sourceAmount, bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey ) external view returns ( uint amountReceived, uint fee, uint exchangeFeeRate ); function priceDeviationThresholdFactor() external view returns (uint); function waitingPeriodSecs() external view returns (uint); // Mutative functions function exchange( address from, bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, address destinationAddress ) external returns (uint amountReceived); function exchangeOnBehalf( address exchangeForAddress, address from, bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external returns (uint amountReceived); function exchangeWithTracking( address from, bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, address destinationAddress, address originator, bytes32 trackingCode ) external returns (uint amountReceived); function exchangeOnBehalfWithTracking( address exchangeForAddress, address from, bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, address originator, bytes32 trackingCode ) external returns (uint amountReceived); function exchangeWithVirtual( address from, bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, address destinationAddress, bytes32 trackingCode ) external returns (uint amountReceived, IVirtualPynth vPynth); function settle(address from, bytes32 currencyKey) external returns ( uint reclaimed, uint refunded, uint numEntries ); function setLastExchangeRateForPynth(bytes32 currencyKey, uint rate) external; function suspendPynthWithInvalidRate(bytes32 currencyKey) external; } // https://docs.peri.finance/contracts/source/interfaces/iexchangerates interface IExchangeRates { // Structs struct RateAndUpdatedTime { uint216 rate; uint40 time; } struct InversePricing { uint entryPoint; uint upperLimit; uint lowerLimit; bool frozenAtUpperLimit; bool frozenAtLowerLimit; } // Views function aggregators(bytes32 currencyKey) external view returns (address); function aggregatorWarningFlags() external view returns (address); function anyRateIsInvalid(bytes32[] calldata currencyKeys) external view returns (bool); function canFreezeRate(bytes32 currencyKey) external view returns (bool); function currentRoundForRate(bytes32 currencyKey) external view returns (uint); function currenciesUsingAggregator(address aggregator) external view returns (bytes32[] memory); function effectiveValue( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external view returns (uint value); function effectiveValueAndRates( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external view returns ( uint value, uint sourceRate, uint destinationRate ); function effectiveValueAtRound( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, uint roundIdForSrc, uint roundIdForDest ) external view returns (uint value); function getCurrentRoundId(bytes32 currencyKey) external view returns (uint); function getLastRoundIdBeforeElapsedSecs( bytes32 currencyKey, uint startingRoundId, uint startingTimestamp, uint timediff ) external view returns (uint); function inversePricing(bytes32 currencyKey) external view returns ( uint entryPoint, uint upperLimit, uint lowerLimit, bool frozenAtUpperLimit, bool frozenAtLowerLimit ); function lastRateUpdateTimes(bytes32 currencyKey) external view returns (uint256); function oracle() external view returns (address); function rateAndTimestampAtRound(bytes32 currencyKey, uint roundId) external view returns (uint rate, uint time); function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time); function rateAndInvalid(bytes32 currencyKey) external view returns (uint rate, bool isInvalid); function rateForCurrency(bytes32 currencyKey) external view returns (uint); function rateIsFlagged(bytes32 currencyKey) external view returns (bool); function rateIsFrozen(bytes32 currencyKey) external view returns (bool); function rateIsInvalid(bytes32 currencyKey) external view returns (bool); function rateIsStale(bytes32 currencyKey) external view returns (bool); function rateStalePeriod() external view returns (uint); function ratesAndUpdatedTimeForCurrencyLastNRounds(bytes32 currencyKey, uint numRounds) external view returns (uint[] memory rates, uint[] memory times); function ratesAndInvalidForCurrencies(bytes32[] calldata currencyKeys) external view returns (uint[] memory rates, bool anyRateInvalid); function ratesForCurrencies(bytes32[] calldata currencyKeys) external view returns (uint[] memory); // Mutative functions function freezeRate(bytes32 currencyKey) external; } // https://docs.peri.finance/contracts/source/interfaces/isystemstatus interface ISystemStatus { struct Status { bool canSuspend; bool canResume; } struct Suspension { bool suspended; // reason is an integer code, // 0 => no reason, 1 => upgrading, 2+ => defined by system usage uint248 reason; } // Views function accessControl(bytes32 section, address account) external view returns (bool canSuspend, bool canResume); function requireSystemActive() external view; function requireIssuanceActive() external view; function requireExchangeActive() external view; function requireExchangeBetweenPynthsAllowed(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view; function requirePynthActive(bytes32 currencyKey) external view; function requirePynthsActive(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view; function systemSuspension() external view returns (bool suspended, uint248 reason); function issuanceSuspension() external view returns (bool suspended, uint248 reason); function exchangeSuspension() external view returns (bool suspended, uint248 reason); function pynthExchangeSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason); function pynthSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason); function getPynthExchangeSuspensions(bytes32[] calldata pynths) external view returns (bool[] memory exchangeSuspensions, uint256[] memory reasons); function getPynthSuspensions(bytes32[] calldata pynths) external view returns (bool[] memory suspensions, uint256[] memory reasons); // Restricted functions function suspendPynth(bytes32 currencyKey, uint256 reason) external; function updateAccessControl( bytes32 section, address account, bool canSuspend, bool canResume ) external; } // https://docs.peri.finance/contracts/source/interfaces/iethercollateral interface IEtherCollateral { // Views function totalIssuedPynths() external view returns (uint256); function totalLoansCreated() external view returns (uint256); function totalOpenLoanCount() external view returns (uint256); // Mutative functions function openLoan() external payable returns (uint256 loanID); function closeLoan(uint256 loanID) external; function liquidateUnclosedLoan(address _loanCreatorsAddress, uint256 _loanID) external; } // https://docs.peri.finance/contracts/source/interfaces/iethercollateralsusd interface IEtherCollateralpUSD { // Views function totalIssuedPynths() external view returns (uint256); function totalLoansCreated() external view returns (uint256); function totalOpenLoanCount() external view returns (uint256); // Mutative functions function openLoan(uint256 _loanAmount) external payable returns (uint256 loanID); function closeLoan(uint256 loanID) external; function liquidateUnclosedLoan(address _loanCreatorsAddress, uint256 _loanID) external; function depositCollateral(address account, uint256 loanID) external payable; function withdrawCollateral(uint256 loanID, uint256 withdrawAmount) external; function repayLoan( address _loanCreatorsAddress, uint256 _loanID, uint256 _repayAmount ) external; } // https://docs.peri.finance/contracts/source/interfaces/ierc20 interface IERC20 { // ERC20 Optional Views function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); // Views function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); // Mutative functions function transfer(address to, uint value) external returns (bool); function approve(address spender, uint value) external returns (bool); function transferFrom( address from, address to, uint value ) external returns (bool); // Events event Transfer(address indexed from, address indexed to, uint value); event Approval(address indexed owner, address indexed spender, uint value); } interface ICollateralManager { // Manager information function hasCollateral(address collateral) external view returns (bool); function isPynthManaged(bytes32 currencyKey) external view returns (bool); // State information function long(bytes32 pynth) external view returns (uint amount); function short(bytes32 pynth) external view returns (uint amount); function totalLong() external view returns (uint pusdValue, bool anyRateIsInvalid); function totalShort() external view returns (uint pusdValue, bool anyRateIsInvalid); function getBorrowRate() external view returns (uint borrowRate, bool anyRateIsInvalid); function getShortRate(bytes32 pynth) external view returns (uint shortRate, bool rateIsInvalid); function getRatesAndTime(uint index) external view returns ( uint entryRate, uint lastRate, uint lastUpdated, uint newIndex ); function getShortRatesAndTime(bytes32 currency, uint index) external view returns ( uint entryRate, uint lastRate, uint lastUpdated, uint newIndex ); function exceedsDebtLimit(uint amount, bytes32 currency) external view returns (bool canIssue, bool anyRateIsInvalid); function arePynthsAndCurrenciesSet(bytes32[] calldata requiredPynthNamesInResolver, bytes32[] calldata pynthKeys) external view returns (bool); function areShortablePynthsSet(bytes32[] calldata requiredPynthNamesInResolver, bytes32[] calldata pynthKeys) external view returns (bool); // Loans function getNewLoanId() external returns (uint id); // Manager mutative function addCollaterals(address[] calldata collaterals) external; function removeCollaterals(address[] calldata collaterals) external; function addPynths(bytes32[] calldata pynthNamesInResolver, bytes32[] calldata pynthKeys) external; function removePynths(bytes32[] calldata pynths, bytes32[] calldata pynthKeys) external; function addShortablePynths(bytes32[2][] calldata requiredPynthAndInverseNamesInResolver, bytes32[] calldata pynthKeys) external; function removeShortablePynths(bytes32[] calldata pynths) external; // State mutative function updateBorrowRates(uint rate) external; function updateShortRates(bytes32 currency, uint rate) external; function incrementLongs(bytes32 pynth, uint amount) external; function decrementLongs(bytes32 pynth, uint amount) external; function incrementShorts(bytes32 pynth, uint amount) external; function decrementShorts(bytes32 pynth, uint amount) external; } // Inheritance // Libraries // Internal references // https://docs.peri.finance/contracts/source/contracts/debtcache contract BaseDebtCache is Owned, MixinSystemSettings, IDebtCache { using SafeMath for uint; using SafeDecimalMath for uint; uint internal _cachedDebt; mapping(bytes32 => uint) internal _cachedPynthDebt; uint internal _cacheTimestamp; bool internal _cacheInvalid = true; /* ========== ENCODED NAMES ========== */ bytes32 internal constant pUSD = "pUSD"; bytes32 internal constant pETH = "pETH"; /* ========== ADDRESS RESOLVER CONFIGURATION ========== */ bytes32 private constant CONTRACT_ISSUER = "Issuer"; bytes32 private constant CONTRACT_EXCHANGER = "Exchanger"; bytes32 private constant CONTRACT_EXRATES = "ExchangeRates"; bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus"; bytes32 private constant CONTRACT_ETHERCOLLATERAL = "EtherCollateral"; bytes32 private constant CONTRACT_ETHERCOLLATERAL_PUSD = "EtherCollateralpUSD"; bytes32 private constant CONTRACT_COLLATERALMANAGER = "CollateralManager"; constructor(address _owner, address _resolver) public Owned(_owner) MixinSystemSettings(_resolver) {} /* ========== VIEWS ========== */ function resolverAddressesRequired() public view returns (bytes32[] memory addresses) { bytes32[] memory existingAddresses = MixinSystemSettings.resolverAddressesRequired(); bytes32[] memory newAddresses = new bytes32[](7); newAddresses[0] = CONTRACT_ISSUER; newAddresses[1] = CONTRACT_EXCHANGER; newAddresses[2] = CONTRACT_EXRATES; newAddresses[3] = CONTRACT_SYSTEMSTATUS; newAddresses[4] = CONTRACT_ETHERCOLLATERAL; newAddresses[5] = CONTRACT_ETHERCOLLATERAL_PUSD; newAddresses[6] = CONTRACT_COLLATERALMANAGER; addresses = combineArrays(existingAddresses, newAddresses); } function issuer() internal view returns (IIssuer) { return IIssuer(requireAndGetAddress(CONTRACT_ISSUER)); } function exchanger() internal view returns (IExchanger) { return IExchanger(requireAndGetAddress(CONTRACT_EXCHANGER)); } function exchangeRates() internal view returns (IExchangeRates) { return IExchangeRates(requireAndGetAddress(CONTRACT_EXRATES)); } function systemStatus() internal view returns (ISystemStatus) { return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS)); } function etherCollateral() internal view returns (IEtherCollateral) { return IEtherCollateral(requireAndGetAddress(CONTRACT_ETHERCOLLATERAL)); } function etherCollateralpUSD() internal view returns (IEtherCollateralpUSD) { return IEtherCollateralpUSD(requireAndGetAddress(CONTRACT_ETHERCOLLATERAL_PUSD)); } function collateralManager() internal view returns (ICollateralManager) { return ICollateralManager(requireAndGetAddress(CONTRACT_COLLATERALMANAGER)); } function debtSnapshotStaleTime() external view returns (uint) { return getDebtSnapshotStaleTime(); } function cachedDebt() external view returns (uint) { return _cachedDebt; } function cachedPynthDebt(bytes32 currencyKey) external view returns (uint) { return _cachedPynthDebt[currencyKey]; } function cacheTimestamp() external view returns (uint) { return _cacheTimestamp; } function cacheInvalid() external view returns (bool) { return _cacheInvalid; } function _cacheStale(uint timestamp) internal view returns (bool) { // Note a 0 timestamp means that the cache is uninitialised. // We'll keep the check explicitly in case the stale time is // ever set to something higher than the current unix time (e.g. to turn off staleness). return getDebtSnapshotStaleTime() < block.timestamp - timestamp || timestamp == 0; } function cacheStale() external view returns (bool) { return _cacheStale(_cacheTimestamp); } function _issuedPynthValues(bytes32[] memory currencyKeys, uint[] memory rates) internal view returns (uint[] memory) { uint numValues = currencyKeys.length; uint[] memory values = new uint[](numValues); IPynth[] memory pynths = issuer().getPynths(currencyKeys); for (uint i = 0; i < numValues; i++) { bytes32 key = currencyKeys[i]; address pynthAddress = address(pynths[i]); require(pynthAddress != address(0), "Pynth does not exist"); uint supply = IERC20(pynthAddress).totalSupply(); if (collateralManager().isPynthManaged(key)) { uint collateralIssued = collateralManager().long(key); // this is an edge case -- // if a pynth other than pUSD is only issued by non PERI collateral // the long value will exceed the supply if there was a minting fee, // so we check explicitly and 0 it out to prevent // a safesub overflow. if (collateralIssued > supply) { supply = 0; } else { supply = supply.sub(collateralIssued); } } bool ispUSD = key == pUSD; if (ispUSD || key == pETH) { IEtherCollateral etherCollateralContract = ispUSD ? IEtherCollateral(address(etherCollateralpUSD())) : etherCollateral(); uint etherCollateralSupply = etherCollateralContract.totalIssuedPynths(); supply = supply.sub(etherCollateralSupply); } values[i] = supply.multiplyDecimalRound(rates[i]); } return values; } function _currentPynthDebts(bytes32[] memory currencyKeys) internal view returns (uint[] memory periIssuedDebts, bool anyRateIsInvalid) { (uint[] memory rates, bool isInvalid) = exchangeRates().ratesAndInvalidForCurrencies(currencyKeys); return (_issuedPynthValues(currencyKeys, rates), isInvalid); } function currentPynthDebts(bytes32[] calldata currencyKeys) external view returns (uint[] memory debtValues, bool anyRateIsInvalid) { return _currentPynthDebts(currencyKeys); } function _cachedPynthDebts(bytes32[] memory currencyKeys) internal view returns (uint[] memory) { uint numKeys = currencyKeys.length; uint[] memory debts = new uint[](numKeys); for (uint i = 0; i < numKeys; i++) { debts[i] = _cachedPynthDebt[currencyKeys[i]]; } return debts; } function cachedPynthDebts(bytes32[] calldata currencyKeys) external view returns (uint[] memory periIssuedDebts) { return _cachedPynthDebts(currencyKeys); } function _currentDebt() internal view returns (uint debt, bool anyRateIsInvalid) { (uint[] memory values, bool isInvalid) = _currentPynthDebts(issuer().availableCurrencyKeys()); uint numValues = values.length; uint total; for (uint i; i < numValues; i++) { total = total.add(values[i]); } // subtract the USD value of all shorts. (uint pusdValue, bool shortInvalid) = collateralManager().totalShort(); total = total.sub(pusdValue); isInvalid = isInvalid || shortInvalid; return (total, isInvalid); } function currentDebt() external view returns (uint debt, bool anyRateIsInvalid) { return _currentDebt(); } function cacheInfo() external view returns ( uint debt, uint timestamp, bool isInvalid, bool isStale ) { uint time = _cacheTimestamp; return (_cachedDebt, time, _cacheInvalid, _cacheStale(time)); } /* ========== MUTATIVE FUNCTIONS ========== */ // Stub out all mutative functions as no-ops; // since they do nothing, there are no restrictions function updateCachedPynthDebts(bytes32[] calldata currencyKeys) external {} function updateCachedPynthDebtWithRate(bytes32 currencyKey, uint currencyRate) external {} function updateCachedPynthDebtsWithRates(bytes32[] calldata currencyKeys, uint[] calldata currencyRates) external {} function updateDebtCacheValidity(bool currentlyInvalid) external {} function purgeCachedPynthDebt(bytes32 currencyKey) external {} function takeDebtSnapshot() external {} /* ========== MODIFIERS ========== */ function _requireSystemActiveIfNotOwner() internal view { if (msg.sender != owner) { systemStatus().requireSystemActive(); } } modifier requireSystemActiveIfNotOwner() { _requireSystemActiveIfNotOwner(); _; } function _onlyIssuerOrExchangerorPynthpUSD() internal view { IPynth pynthpUSD = issuer().pynths(pUSD); require( msg.sender == address(issuer()) || msg.sender == address(exchanger()) || msg.sender == address(pynthpUSD), "Sender is not Issuer or Exchanger or pynthpUSD" ); } modifier onlyIssuerOrExchangerOrPynthpUSD() { _onlyIssuerOrExchangerorPynthpUSD(); _; } } // Inheritance // https://docs.peri.finance/contracts/source/contracts/debtcache contract DebtCache is BaseDebtCache { constructor(address _owner, address _resolver) public BaseDebtCache(_owner, _resolver) {} /* ========== MUTATIVE FUNCTIONS ========== */ // This function exists in case a pynth is ever somehow removed without its snapshot being updated. function purgeCachedPynthDebt(bytes32 currencyKey) external onlyOwner { require(issuer().pynths(currencyKey) == IPynth(0), "Pynth exists"); delete _cachedPynthDebt[currencyKey]; } function takeDebtSnapshot() external requireSystemActiveIfNotOwner { bytes32[] memory currencyKeys = issuer().availableCurrencyKeys(); (uint[] memory values, bool isInvalid) = _currentPynthDebts(currencyKeys); // Subtract the USD value of all shorts. (uint shortValue, ) = collateralManager().totalShort(); uint numValues = values.length; uint periCollateralDebt; for (uint i; i < numValues; i++) { uint value = values[i]; periCollateralDebt = periCollateralDebt.add(value); _cachedPynthDebt[currencyKeys[i]] = value; } _cachedDebt = periCollateralDebt.sub(shortValue); _cacheTimestamp = block.timestamp; emit DebtCacheUpdated(periCollateralDebt); emit DebtCacheSnapshotTaken(block.timestamp); // (in)validate the cache if necessary _updateDebtCacheValidity(isInvalid); } function updateCachedPynthDebts(bytes32[] calldata currencyKeys) external requireSystemActiveIfNotOwner { (uint[] memory rates, bool anyRateInvalid) = exchangeRates().ratesAndInvalidForCurrencies(currencyKeys); _updateCachedPynthDebtsWithRates(currencyKeys, rates, anyRateInvalid); } function updateCachedPynthDebtWithRate(bytes32 currencyKey, uint currencyRate) external onlyIssuerOrExchangerOrPynthpUSD { bytes32[] memory pynthKeyArray = new bytes32[](1); pynthKeyArray[0] = currencyKey; uint[] memory pynthRateArray = new uint[](1); pynthRateArray[0] = currencyRate; _updateCachedPynthDebtsWithRates(pynthKeyArray, pynthRateArray, false); } function updateCachedPynthDebtsWithRates(bytes32[] calldata currencyKeys, uint[] calldata currencyRates) external onlyIssuerOrExchangerOrPynthpUSD { _updateCachedPynthDebtsWithRates(currencyKeys, currencyRates, false); } function updateDebtCacheValidity(bool currentlyInvalid) external onlyIssuerOrExchangerOrPynthpUSD { _updateDebtCacheValidity(currentlyInvalid); } /* ========== INTERNAL FUNCTIONS ========== */ function _updateDebtCacheValidity(bool currentlyInvalid) internal { if (_cacheInvalid != currentlyInvalid) { _cacheInvalid = currentlyInvalid; emit DebtCacheValidityChanged(currentlyInvalid); } } function _updateCachedPynthDebtsWithRates( bytes32[] memory currencyKeys, uint[] memory currentRates, bool anyRateIsInvalid ) internal { uint numKeys = currencyKeys.length; require(numKeys == currentRates.length, "Input array lengths differ"); // Update the cached values for each pynth, saving the sums as we go. uint cachedSum; uint currentSum; uint[] memory currentValues = _issuedPynthValues(currencyKeys, currentRates); for (uint i = 0; i < numKeys; i++) { bytes32 key = currencyKeys[i]; uint currentPynthDebt = currentValues[i]; cachedSum = cachedSum.add(_cachedPynthDebt[key]); currentSum = currentSum.add(currentPynthDebt); _cachedPynthDebt[key] = currentPynthDebt; } // Compute the difference and apply it to the snapshot if (cachedSum != currentSum) { uint debt = _cachedDebt; // This requirement should never fail, as the total debt snapshot is the sum of the individual pynth // debt snapshots. require(cachedSum <= debt, "Cached pynth sum exceeds total debt"); debt = debt.sub(cachedSum).add(currentSum); _cachedDebt = debt; emit DebtCacheUpdated(debt); } // A partial update can invalidate the debt cache, but a full snapshot must be performed in order // to re-validate it. if (anyRateIsInvalid) { _updateDebtCacheValidity(anyRateIsInvalid); } } /* ========== EVENTS ========== */ event DebtCacheUpdated(uint cachedDebt); event DebtCacheSnapshotTaken(uint timestamp); event DebtCacheValidityChanged(bool indexed isInvalid); }
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_resolver","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"CacheUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"DebtCacheSnapshotTaken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"cachedDebt","type":"uint256"}],"name":"DebtCacheUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isInvalid","type":"bool"}],"name":"DebtCacheValidityChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"cacheInfo","outputs":[{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bool","name":"isInvalid","type":"bool"},{"internalType":"bool","name":"isStale","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cacheInvalid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cacheStale","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cacheTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cachedDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"}],"name":"cachedPynthDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32[]","name":"currencyKeys","type":"bytes32[]"}],"name":"cachedPynthDebts","outputs":[{"internalType":"uint256[]","name":"periIssuedDebts","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentDebt","outputs":[{"internalType":"uint256","name":"debt","type":"uint256"},{"internalType":"bool","name":"anyRateIsInvalid","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32[]","name":"currencyKeys","type":"bytes32[]"}],"name":"currentPynthDebts","outputs":[{"internalType":"uint256[]","name":"debtValues","type":"uint256[]"},{"internalType":"bool","name":"anyRateIsInvalid","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"debtSnapshotStaleTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isResolverCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"}],"name":"purgeCachedPynthDebt","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"rebuildCache","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"resolver","outputs":[{"internalType":"contract AddressResolver","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32[]","name":"addresses","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"takeDebtSnapshot","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"internalType":"uint256","name":"currencyRate","type":"uint256"}],"name":"updateCachedPynthDebtWithRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32[]","name":"currencyKeys","type":"bytes32[]"}],"name":"updateCachedPynthDebts","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32[]","name":"currencyKeys","type":"bytes32[]"},{"internalType":"uint256[]","name":"currencyRates","type":"uint256[]"}],"name":"updateCachedPynthDebtsWithRates","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"currentlyInvalid","type":"bool"}],"name":"updateDebtCacheValidity","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526007805460ff1916600117905534801561001d57600080fd5b5060405161261e38038061261e8339818101604052604081101561004057600080fd5b50805160209091015181818080836001600160a01b0381166100a9576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150600280546001600160a01b039092166001600160a01b031990921691909117905550505050506124e7806101376000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c80638da5cb5b116100c3578063dae3de981161007c578063dae3de98146103dd578063e3476cd41461044b578063f7cc999f14610453578063fa9f18d314610470578063fc524773146104de578063fca28f74146104e657610158565b80638da5cb5b146102e25780639f98fb49146102ea578063a5f27edb146103a8578063af5355d8146103b0578063d0fffafd146103b8578063d6576c84146103c057610158565b806353a47bb71161011557806353a47bb71461022e5780637418536014610236578063759076e51461023e57806379ba50971461025f5780638376a78214610267578063899ffef41461028a57610158565b806304bd11e51461015d57806304f3bcec1461017e57806305393262146101a25780631627540c146101bc5780632af64bd3146101e25780633a900a2e146101fe575b600080fd5b61017c6004803603602081101561017357600080fd5b503515156105b3565b005b6101866105c7565b604080516001600160a01b039092168252519081900360200190f35b6101aa6105d6565b60408051918252519081900360200190f35b61017c600480360360208110156101d257600080fd5b50356001600160a01b03166105dd565b6101ea610639565b604080519115158252519081900360200190f35b610206610743565b6040805194855260208501939093529015158383015215156060830152519081900360800190f35b610186610774565b61017c610783565b61024661094b565b6040805192835290151560208301528051918290030190f35b61017c61095e565b61017c6004803603604081101561027d57600080fd5b5080359060200135610a1a565b610292610aad565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102ce5781810151838201526020016102b6565b505050509050019250505060405180910390f35b610186610c17565b61017c6004803603604081101561030057600080fd5b810190602081018135600160201b81111561031a57600080fd5b82018360208201111561032c57600080fd5b803590602001918460208302840111600160201b8311171561034d57600080fd5b919390929091602081019035600160201b81111561036a57600080fd5b82018360208201111561037c57600080fd5b803590602001918460208302840111600160201b8311171561039d57600080fd5b509092509050610c26565b6101ea610c9b565b6101aa610ca4565b6101aa610cb3565b61017c600480360360208110156103d657600080fd5b5035610cb9565b610292600480360360208110156103f357600080fd5b810190602081018135600160201b81111561040d57600080fd5b82018360208201111561041f57600080fd5b803590602001918460208302840111600160201b8311171561044057600080fd5b509092509050610d95565b61017c610ddc565b6101aa6004803603602081101561046957600080fd5b503561106f565b61017c6004803603602081101561048657600080fd5b810190602081018135600160201b8111156104a057600080fd5b8201836020820111156104b257600080fd5b803590602001918460208302840111600160201b831117156104d357600080fd5b509092509050611081565b6101ea611216565b610554600480360360208110156104fc57600080fd5b810190602081018135600160201b81111561051657600080fd5b82018360208201111561052857600080fd5b803590602001918460208302840111600160201b8311171561054957600080fd5b509092509050611223565b604051808060200183151515158152602001828103825284818151815260200191508051906020019060200280838360005b8381101561059e578181015183820152602001610586565b50505050905001935050505060405180910390f35b6105bb61126e565b6105c48161137d565b50565b6002546001600160a01b031681565b6004545b90565b6105e56113ca565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b60006060610645610aad565b905060005b815181101561073a57600082828151811061066157fe5b6020908102919091018101516000818152600383526040908190205460025482516321f8a72160e01b81526004810185905292519395506001600160a01b03918216949116926321f8a721926024808201939291829003018186803b1580156106c957600080fd5b505afa1580156106dd573d6000803e3d6000fd5b505050506040513d60208110156106f357600080fd5b50516001600160a01b031614158061072057506000818152600360205260409020546001600160a01b0316155b1561073157600093505050506105da565b5060010161064a565b50600191505090565b6006546004546007546000928392839283929190829060ff1661076582611415565b94509450945094505090919293565b6001546001600160a01b031681565b606061078d610aad565b905060005b81518110156109475760008282815181106107a957fe5b602090810291909101810151600254604080517f5265736f6c766572206d697373696e67207461726765743a2000000000000000818601526039808201859052825180830390910181526059820180845263dacb2d0160e01b9052605d8201858152607d83019384528151609d84015281519597506000966001600160a01b039095169563dacb2d01958995939492939260bd0191908501908083838c5b8381101561085f578181015183820152602001610847565b50505050905090810190601f16801561088c5780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b1580156108aa57600080fd5b505afa1580156108be573d6000803e3d6000fd5b505050506040513d60208110156108d457600080fd5b505160008381526003602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518681529182015281519293507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68929081900390910190a15050600101610792565b5050565b60008061095661142e565b915091509091565b6001546001600160a01b031633146109a75760405162461bcd60e51b81526004018080602001828103825260358152602001806124006035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b610a2261126e565b604080516001808252818301909252606091602080830190803883390190505090508281600081518110610a5257fe5b60209081029190910101526040805160018082528183019092526060918160200160208202803883390190505090508281600081518110610a8f57fe5b602002602001018181525050610aa78282600061162c565b50505050565b606080610ab86117e1565b6040805160078082526101008201909252919250606091906020820160e0803883390190505090506524b9b9bab2b960d11b81600081518110610af757fe5b6020026020010181815250506822bc31b430b733b2b960b91b81600181518110610b1d57fe5b6020026020010181815250506c45786368616e6765526174657360981b81600281518110610b4757fe5b6020026020010181815250506b53797374656d53746174757360a01b81600381518110610b7057fe5b6020026020010181815250506e115d1a195c90dbdb1b185d195c985b608a1b81600481518110610b9c57fe5b60200260200101818152505072115d1a195c90dbdb1b185d195c985b1c1554d1606a1b81600581518110610bcc57fe5b6020026020010181815250507021b7b63630ba32b930b626b0b730b3b2b960791b81600681518110610bfa57fe5b602002602001018181525050610c108282611832565b9250505090565b6000546001600160a01b031681565b610c2e61126e565b610aa7848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284376000920182905250925061162c915050565b60075460ff1690565b6000610cae6118ee565b905090565b60065490565b610cc16113ca565b6000610ccb61199d565b6001600160a01b03166357ad4663836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610d0e57600080fd5b505afa158015610d22573d6000803e3d6000fd5b505050506040513d6020811015610d3857600080fd5b50516001600160a01b031614610d84576040805162461bcd60e51b815260206004820152600c60248201526b50796e74682065786973747360a01b604482015290519081900360640190fd5b600090815260056020526040812055565b6060610dd38383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506119b192505050565b90505b92915050565b610de4611a41565b6060610dee61199d565b6001600160a01b03166372cb051f6040518163ffffffff1660e01b815260040160006040518083038186803b158015610e2657600080fd5b505afa158015610e3a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015610e6357600080fd5b8101908080516040519392919084600160201b821115610e8257600080fd5b908301906020820185811115610e9757600080fd5b82518660208202830111600160201b82111715610eb357600080fd5b82525081516020918201928201910280838360005b83811015610ee0578181015183820152602001610ec8565b50505050905001604052505050905060606000610efc83611aa7565b915091506000610f0a611c20565b6001600160a01b031663ad79a8586040518163ffffffff1660e01b8152600401604080518083038186803b158015610f4157600080fd5b505afa158015610f55573d6000803e3d6000fd5b505050506040513d6040811015610f6b57600080fd5b505183519091506000805b82811015610fe0576000868281518110610f8c57fe5b60200260200101519050610fa98184611c3f90919063ffffffff16565b925080600560008a8581518110610fbc57fe5b60209081029190910181015182528101919091526040016000205550600101610f76565b50610ff1818463ffffffff611c9916565b600455426006556040805182815290517f294a7c394e53042c7d754779562747d93b41db019dd4b970dd9b531db71be5999181900360200190a16040805142815290517fc481e742c89630d4b1a5ed3a0fc624c1c41ed463bd00ac26a7e93c71e932126f9181900360200190a16110678461137d565b505050505050565b60009081526005602052604090205490565b611089611a41565b60606000611095611cf6565b6001600160a01b031663c8e5bbd585856040518363ffffffff1660e01b815260040180806020018281038252848482818152602001925060200280828437600081840152601f19601f820116905080830192505050935050505060006040518083038186803b15801561110757600080fd5b505afa15801561111b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604090815281101561114457600080fd5b8101908080516040519392919084600160201b82111561116357600080fd5b90830190602082018581111561117857600080fd5b82518660208202830111600160201b8211171561119457600080fd5b82525081516020918201928201910280838360005b838110156111c15781810151838201526020016111a9565b505050509190910160408181526020938401518a850280840186019092528a8352969850959650610aa795909450899350889283925085019084908082843760009201919091525086925085915061162c9050565b6000610cae600654611415565b60606000611263848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611aa792505050565b915091509250929050565b600061127861199d565b6001600160a01b03166357ad4663631c1554d160e21b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156112c257600080fd5b505afa1580156112d6573d6000803e3d6000fd5b505050506040513d60208110156112ec57600080fd5b505190506112f861199d565b6001600160a01b0316336001600160a01b0316148061132f575061131a611d11565b6001600160a01b0316336001600160a01b0316145b806113425750336001600160a01b038216145b6105c45760405162461bcd60e51b815260040180806020018281038252602e815260200180612485602e913960400191505060405180910390fd5b60075460ff161515811515146105c4576007805460ff19168215159081179091556040517f8eebec690c34bbf0fe0d5b93e442beaf16bdaf99052569581de2dcb3e31a53a790600090a250565b6000546001600160a01b031633146114135760405162461bcd60e51b815260040180806020018281038252602f815260200180612435602f913960400191505060405180910390fd5b565b60008142036114226118ee565b1080610dd65750501590565b6000806060600061154461144061199d565b6001600160a01b03166372cb051f6040518163ffffffff1660e01b815260040160006040518083038186803b15801561147857600080fd5b505afa15801561148c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156114b557600080fd5b8101908080516040519392919084600160201b8211156114d457600080fd5b9083019060208201858111156114e957600080fd5b82518660208202830111600160201b8211171561150557600080fd5b82525081516020918201928201910280838360005b8381101561153257818101518382015260200161151a565b50505050905001604052505050611aa7565b815191935091506000805b828110156115875761157d85828151811061156657fe5b602002602001015183611c3f90919063ffffffff16565b915060010161154f565b50600080611593611c20565b6001600160a01b031663ad79a8586040518163ffffffff1660e01b8152600401604080518083038186803b1580156115ca57600080fd5b505afa1580156115de573d6000803e3d6000fd5b505050506040513d60408110156115f457600080fd5b5080516020909101519092509050611612838363ffffffff611c9916565b9250848061161d5750805b92975091955050505050509091565b825182518114611683576040805162461bcd60e51b815260206004820152601a60248201527f496e707574206172726179206c656e6774687320646966666572000000000000604482015290519081900360640190fd5b60008060606116928787611d28565b905060005b848110156117215760008882815181106116ad57fe5b6020026020010151905060008383815181106116c557fe5b602002602001015190506116f5600560008481526020019081526020016000205487611c3f90919063ffffffff16565b9550611707858263ffffffff611c3f16565b600092835260056020526040909220559250600101611697565b508183146117c9576004548084111561176b5760405162461bcd60e51b81526004018080602001828103825260238152602001806123dd6023913960400191505060405180910390fd5b61178b8361177f838763ffffffff611c9916565b9063ffffffff611c3f16565b60048190556040805182815290519192507f294a7c394e53042c7d754779562747d93b41db019dd4b970dd9b531db71be599919081900360200190a1505b84156117d8576117d88561137d565b50505050505050565b604080516001808252818301909252606091602080830190803883390190505090506e466c657869626c6553746f7261676560881b8160008151811061182357fe5b60200260200101818152505090565b60608151835101604051908082528060200260200182016040528015611862578160200160208202803883390190505b50905060005b83518110156118a45783818151811061187d57fe5b602002602001015182828151811061189157fe5b6020908102919091010152600101611868565b5060005b82518110156118e7578281815181106118bd57fe5b60200260200101518282865101815181106118d457fe5b60209081029190910101526001016118a8565b5092915050565b60006118f86121eb565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b7464656274536e617073686f745374616c6554696d6560581b6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561196c57600080fd5b505afa158015611980573d6000803e3d6000fd5b505050506040513d602081101561199657600080fd5b5051905090565b6000610cae6524b9b9bab2b960d11b612204565b60606000825190506060816040519080825280602002602001820160405280156119e5578160200160208202803883390190505b50905060005b82811015611a395760056000868381518110611a0357fe5b6020026020010151815260200190815260200160002054828281518110611a2657fe5b60209081029190910101526001016119eb565b509392505050565b6000546001600160a01b0316331461141357611a5b6122e1565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015611a9357600080fd5b505afa158015610aa7573d6000803e3d6000fd5b6060600060606000611ab7611cf6565b6001600160a01b031663c8e5bbd5866040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b83811015611b15578181015183820152602001611afd565b505050509050019250505060006040518083038186803b158015611b3857600080fd5b505afa158015611b4c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015611b7557600080fd5b8101908080516040519392919084600160201b821115611b9457600080fd5b908301906020820185811115611ba957600080fd5b82518660208202830111600160201b82111715611bc557600080fd5b82525081516020918201928201910280838360005b83811015611bf2578181015183820152602001611bda565b50505050919091016040525060200151929450919250611c16915086905083611d28565b9350915050915091565b6000610cae7021b7b63630ba32b930b626b0b730b3b2b960791b612204565b600082820183811015610dd3576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082821115611cf0576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000610cae6c45786368616e6765526174657360981b612204565b6000610cae6822bc31b430b733b2b960b91b612204565b6060600083519050606081604051908082528060200260200182016040528015611d5c578160200160208202803883390190505b5090506060611d6961199d565b6001600160a01b0316631db63a33876040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b83811015611dc7578181015183820152602001611daf565b505050509050019250505060006040518083038186803b158015611dea57600080fd5b505afa158015611dfe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015611e2757600080fd5b8101908080516040519392919084600160201b821115611e4657600080fd5b908301906020820185811115611e5b57600080fd5b82518660208202830111600160201b82111715611e7757600080fd5b82525081516020918201928201910280838360005b83811015611ea4578181015183820152602001611e8c565b50505050905001604052505050905060008090505b838110156121e0576000878281518110611ecf57fe5b602002602001015190506000838381518110611ee757fe5b6020026020010151905060006001600160a01b0316816001600160a01b03161415611f50576040805162461bcd60e51b8152602060048201526014602482015273141e5b9d1a08191bd95cc81b9bdd08195e1a5cdd60621b604482015290519081900360640190fd5b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f8b57600080fd5b505afa158015611f9f573d6000803e3d6000fd5b505050506040513d6020811015611fb557600080fd5b50519050611fc1611c20565b6001600160a01b03166342e32f13846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561200457600080fd5b505afa158015612018573d6000803e3d6000fd5b505050506040513d602081101561202e57600080fd5b5051156120d657600061203f611c20565b6001600160a01b031663d2f00475856040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561208257600080fd5b505afa158015612096573d6000803e3d6000fd5b505050506040513d60208110156120ac57600080fd5b50519050818111156120c157600091506120d4565b6120d1828263ffffffff611c9916565b91505b505b631c1554d160e21b831480806120f25750630e08aa8960e31b84145b156121935760008161210b576121066122fb565b612113565b612113612318565b90506000816001600160a01b03166357b219206040518163ffffffff1660e01b815260040160206040518083038186803b15801561215057600080fd5b505afa158015612164573d6000803e3d6000fd5b505050506040513d602081101561217a57600080fd5b5051905061218e848263ffffffff611c9916565b935050505b6121b98a86815181106121a257fe5b60200260200101518361233990919063ffffffff16565b8786815181106121c557fe5b6020908102919091010152505060019092019150611eb99050565b509095945050505050565b6000610cae6e466c657869626c6553746f7261676560881b5b600081815260036020908152604080832054815170026b4b9b9b4b7339030b2323932b9b99d1607d1b9381019390935260318084018690528251808503909101815260519093019091526001600160a01b031690816118e75760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156122a657818101518382015260200161228e565b50505050905090810190601f1680156122d35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6000610cae6b53797374656d53746174757360a01b612204565b6000610cae6e115d1a195c90dbdb1b185d195c985b608a1b612204565b6000610cae72115d1a195c90dbdb1b185d195c985b1c1554d1606a1b612204565b6000610dd38383670de0b6b3a7640000848067016345785d8a000061235e8686612383565b8161236557fe5b0490506005600a82061061237757600a015b600a9004949350505050565b60008261239257506000610dd6565b8282028284828161239f57fe5b0414610dd35760405162461bcd60e51b81526004018080602001828103825260218152602001806124646021913960400191505060405180910390fdfe4361636865642070796e74682073756d206578636565647320746f74616c2064656274596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e6572736869704f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753656e646572206973206e6f7420497373756572206f722045786368616e676572206f722070796e746870555344a265627a7a723158201255a1e8b8b81586db1e0d227fdf2a31ece8463f93252df7378453a2857bf43264736f6c63430005100032000000000000000000000000166220468aff631290b7e1ddff7f45b052de832400000000000000000000000022f5d16097cf2396d6c893a77ea3b97234c0c114
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000166220468aff631290b7e1ddff7f45b052de832400000000000000000000000022f5d16097cf2396d6c893a77ea3b97234c0c114
-----Decoded View---------------
Arg [0] : _owner (address): 0x166220468aff631290b7e1ddff7f45b052de8324
Arg [1] : _resolver (address): 0x22f5d16097cf2396d6c893a77ea3b97234c0c114
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000166220468aff631290b7e1ddff7f45b052de8324
Arg [1] : 00000000000000000000000022f5d16097cf2396d6c893a77ea3b97234c0c114
Deployed ByteCode Sourcemap
60426:4772:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60426:4772:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62913:159;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62913:159:0;;;;:::i;:::-;;10269:31;;;:::i;:::-;;;;-1:-1:-1;;;;;10269:31:0;;;;;;;;;;;;;;53973:88;;;:::i;:::-;;;;;;;;;;;;;;;;2211:141;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2211:141:0;-1:-1:-1;;;;;2211:141:0;;:::i;11964:537::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;58572:313;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1980:29;;;:::i;11258:657::-;;;:::i;58444:120::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;2360:271;;;:::i;62208:432::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62208:432:0;;;;;;;:::i;52073:669::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;52073:669:0;;;;;;;;;;;;;;;;;1953:20;;;:::i;62648:257::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;62648:257:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;62648:257:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;62648:257:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;62648:257:0;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;62648:257:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;62648:257:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;62648:257:0;;-1:-1:-1;62648:257:0;-1:-1:-1;62648:257:0;:::i;54311:92::-;;;:::i;53851:114::-;;;:::i;54207:96::-;;;:::i;60725:202::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60725:202:0;;:::i;57643:170::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;57643:170:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;57643:170:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;57643:170:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;57643:170:0;;-1:-1:-1;57643:170:0;-1:-1:-1;57643:170:0;:::i;60935:951::-;;;:::i;54069:130::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54069:130:0;;:::i;61894:306::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;61894:306:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;61894:306:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;61894:306:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;61894:306:0;;-1:-1:-1;61894:306:0;-1:-1:-1;61894:306:0;:::i;54823:105::-;;;:::i;57065:222::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;57065:222:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;57065:222:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;57065:222:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;57065:222:0;;-1:-1:-1;57065:222:0;-1:-1:-1;57065:222:0;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;57065:222:0;;;;;;;;;;;;;;;;;;62913:159;60275:35;:33;:35::i;:::-;63022:42;63047:16;63022:24;:42::i;:::-;62913:159;:::o;10269:31::-;;;-1:-1:-1;;;;;10269:31:0;;:::o;53973:88::-;54042:11;;53973:88;;:::o;2211:141::-;2669:12;:10;:12::i;:::-;2283:14;:23;;-1:-1:-1;;;;;2283:23:0;;-1:-1:-1;;;;;;2283:23:0;;;;;;;;2322:22;;;;;;;;;;;;;;;;2211:141;:::o;11964:537::-;12015:4;12032:34;12069:27;:25;:27::i;:::-;12032:64;-1:-1:-1;12112:6:0;12107:363;12128:17;:24;12124:1;:28;12107:363;;;12174:12;12189:17;12207:1;12189:20;;;;;;;;;;;;;;;;;;;12356:18;;;;:12;:18;;;;;;;;12327:8;;:25;;-1:-1:-1;;;12327:25:0;;;;;;;;;;12189:20;;-1:-1:-1;;;;;;12356:18:0;;;;12327:8;;;:19;;:25;;;;;12189:20;12327:25;;;;;;:8;:25;;;5:2:-1;;;;30:1;27;20:12;5:2;12327:25:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;12327:25:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;12327:25:0;-1:-1:-1;;;;;12327:47:0;;;;:83;;-1:-1:-1;12408:1:0;12378:18;;;:12;:18;;;;;;-1:-1:-1;;;;;12378:18:0;:32;12327:83;12323:136;;;12438:5;12431:12;;;;;;;12323:136;-1:-1:-1;12154:3:0;;12107:363;;;;12489:4;12482:11;;;11964:537;:::o;58572:313::-;58791:15;;58825:11;;58844:13;;58657:9;;;;;;;;58791:15;58825:11;58791:15;;58844:13;;58859:17;58791:15;58859:11;:17::i;:::-;58817:60;;;;;;;;;58572:313;;;;:::o;1980:29::-;;;-1:-1:-1;;;;;1980:29:0;;:::o;11258:657::-;11300:34;11337:27;:25;:27::i;:::-;11300:64;-1:-1:-1;11458:6:0;11453:455;11474:17;:24;11470:1;:28;11453:455;;;11520:12;11535:17;11553:1;11535:20;;;;;;;;;;;;;;;;;;;11702:8;;11745:51;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;11745:51:0;;;;;;-1:-1:-1;;;11702:96:0;;;;;;;;;;;;;;;;;;;;;;11535:20;;-1:-1:-1;11663:19:0;;-1:-1:-1;;;;;11702:8:0;;;;:29;;11535:20;;11745:51;;11702:96;;;;;;;;;;;;;11663:19;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;11702:96:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11702:96:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;11702:96:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11702:96:0;11813:18;;;;:12;11702:96;11813:18;;;;;;;;:32;;-1:-1:-1;;;;;;11813:32:0;-1:-1:-1;;;;;11813:32:0;;;;;;;;11865:31;;;;;;;;;;;11702:96;;-1:-1:-1;11865:31:0;;;;;;;;;;;-1:-1:-1;;11500:3:0;;11453:455;;;;11258:657;:::o;58444:120::-;58490:9;58501:21;58542:14;:12;:14::i;:::-;58535:21;;;;58444:120;;:::o;2360:271::-;2429:14;;-1:-1:-1;;;;;2429:14:0;2415:10;:28;2407:94;;;;-1:-1:-1;;;2407:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2530:5;;;2537:14;2517:35;;;-1:-1:-1;;;;;2530:5:0;;;2517:35;;2537:14;;;;2517:35;;;;;;;;;;;;;;;;2571:14;;;;2563:22;;-1:-1:-1;;;;;;2563:22:0;;;-1:-1:-1;;;;;2571:14:0;;2563:22;;;;2596:27;;;2360:271::o;62208:432::-;60275:35;:33;:35::i;:::-;62396:16;;;62410:1;62396:16;;;;;;;;;62363:30;;62396:16;;;;;;105:10:-1;62396:16:0;88:34:-1;136:17;;-1:-1;62396:16:0;62363:49;;62442:11;62423:13;62437:1;62423:16;;;;;;;;;;;;;;;;;:30;62495:13;;;62506:1;62495:13;;;;;;;;;62464:28;;62495:13;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;62495:13:0;62464:44;;62539:12;62519:14;62534:1;62519:17;;;;;;;;;;;;;:32;;;;;62562:70;62595:13;62610:14;62626:5;62562:32;:70::i;:::-;60321:1;;62208:432;;:::o;52073:669::-;52131:26;52170:34;52207:47;:45;:47::i;:::-;52297:16;;;52311:1;52297:16;;;;;;;;;52170:84;;-1:-1:-1;52265:29:0;;52297:16;;;;17:15:-1;;105:10;52297:16:0;88:34:-1;136:17;;-1:-1;52297:16:0;52265:48;;-1:-1:-1;;;52324:12:0;52337:1;52324:15;;;;;;;;;;;;;:33;;;;;-1:-1:-1;;;52368:12:0;52381:1;52368:15;;;;;;;;;;;;;:36;;;;;-1:-1:-1;;;52415:12:0;52428:1;52415:15;;;;;;;;;;;;;:34;;;;;-1:-1:-1;;;52460:12:0;52473:1;52460:15;;;;;;;;;;;;;:39;;;;;-1:-1:-1;;;52510:12:0;52523:1;52510:15;;;;;;;;;;;;;:42;;;;;-1:-1:-1;;;52563:12:0;52576:1;52563:15;;;;;;;;;;;;;:47;;;;;-1:-1:-1;;;52621:12:0;52634:1;52621:15;;;;;;;;;;;;;:44;;;;;52688:46;52702:17;52721:12;52688:13;:46::i;:::-;52676:58;;52073:669;;;:::o;1953:20::-;;;-1:-1:-1;;;;;1953:20:0;;:::o;62648:257::-;60275:35;:33;:35::i;:::-;62829:68;62862:12;;62829:68;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;62829:68:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62876:13:0;;-1:-1:-1;62876:13:0;;;;62829:68;;;62876:13;;62829:68;62876:13;62829:68;1:33:-1;99:1;81:16;;74:27;;;-1:-1;99:1;-1:-1;62829:32:0;;-1:-1:-1;;62829:68:0:i;54311:92::-;54382:13;;;;54311:92;:::o;53851:114::-;53907:4;53931:26;:24;:26::i;:::-;53924:33;;53851:114;:::o;54207:96::-;54280:15;;54207:96;:::o;60725:202::-;2669:12;:10;:12::i;:::-;60853:1;60814:8;:6;:8::i;:::-;-1:-1:-1;;;;;60814:15:0;;60830:11;60814:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60814:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60814:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60814:28:0;-1:-1:-1;;;;;60814:41:0;;60806:66;;;;;-1:-1:-1;;;60806:66:0;;;;;;;;;;;;-1:-1:-1;;;60806:66:0;;;;;;;;;;;;;;;60890:29;;;;:16;:29;;;;;60883:36;60725:202::o;57643:170::-;57725:29;57774:31;57792:12;;57774:31;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;57774:17:0;;-1:-1:-1;;;57774:31:0:i;:::-;57767:38;;57643:170;;;;;:::o;60935:951::-;59822:32;:30;:32::i;:::-;61013:29;61045:8;:6;:8::i;:::-;-1:-1:-1;;;;;61045:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;61045:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;61045:32:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;61045:32:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;61045:32:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;61045:32:0;;421:4:-1;412:14;;;;61045:32:0;;;;;412:14:-1;61045:32:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;61045:32:0;;;;;;;;;;;61013:64;;61089:20;61111:14;61129:32;61148:12;61129:18;:32::i;:::-;61088:73;;;;61225:15;61246:19;:17;:19::i;:::-;-1:-1:-1;;;;;61246:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;61246:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;61246:32:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;61246:32:0;61308:13;;61246:32;;-1:-1:-1;61291:14:0;;61366:205;61383:9;61379:1;:13;61366:205;;;61414:10;61427:6;61434:1;61427:9;;;;;;;;;;;;;;61414:22;;61474:29;61497:5;61474:18;:22;;:29;;;;:::i;:::-;61453:50;;61554:5;61518:16;:33;61535:12;61548:1;61535:15;;;;;;;;;;;;;;;;;;;61518:33;;;;;;;;;;-1:-1:-1;61518:33:0;:41;-1:-1:-1;61394:3:0;;61366:205;;;-1:-1:-1;61597:34:0;:18;61620:10;61597:34;:22;:34;:::i;:::-;61583:11;:48;61660:15;61642;:33;61691:36;;;;;;;;;;;;;;;;;61743:39;;;61766:15;61743:39;;;;;;;;;;;;;61843:35;61868:9;61843:24;:35::i;:::-;59865:1;;;;;;60935:951::o;54069:130::-;54138:4;54162:29;;;:16;:29;;;;;;;54069:130::o;61894:306::-;59822:32;:30;:32::i;:::-;62010:19;62031;62054:15;:13;:15::i;:::-;-1:-1:-1;;;;;62054:44:0;;62099:12;;62054:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;62054:58:0;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;62054:58:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62054:58:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;62054:58:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;;;5:11;;2:2;;;29:1;26;19:12;2:2;62054:58:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;62054:58:0;;421:4:-1;412:14;;;;62054:58:0;;;;;412:14:-1;62054:58:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;-1:-1;;;;62054:58:0;;;;;;;;;;;;;62123:69;;;;;;;;;;;;;;62009:103;;-1:-1:-1;62054:58:0;;-1:-1:-1;62123:69:0;;62054:58;;-1:-1:-1;62156:12:0;;-1:-1:-1;62156:12:0;;;;-1:-1:-1;62123:69:0;;;62156:12;;62123:69;62156:12;62123:69;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;62170:5:0;;-1:-1:-1;62177:14:0;;-1:-1:-1;62123:32:0;;-1:-1:-1;62123:69:0:i;54823:105::-;54868:4;54892:28;54904:15;;54892:11;:28::i;57065:222::-;57175:24;57201:21;57247:32;57266:12;;57247:32;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;57247:18:0;;-1:-1:-1;;;57247:32:0:i;:::-;57240:39;;;;57065:222;;;;;:::o;59882:330::-;59952:16;59971:8;:6;:8::i;:::-;-1:-1:-1;;;;;59971:15:0;;-1:-1:-1;;;59971:21:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59971:21:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;59971:21:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;59971:21:0;;-1:-1:-1;60047:8:0;:6;:8::i;:::-;-1:-1:-1;;;;;60025:31:0;:10;-1:-1:-1;;;;;60025:31:0;;:69;;;;60082:11;:9;:11::i;:::-;-1:-1:-1;;;;;60060:34:0;:10;-1:-1:-1;;;;;60060:34:0;;60025:69;:105;;;-1:-1:-1;60098:10:0;-1:-1:-1;;;;;60098:32:0;;;60025:105;60003:201;;;;-1:-1:-1;;;60003:201:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63134:244;63215:13;;;;:33;;;;;;63211:160;;63265:13;:32;;-1:-1:-1;;63265:32:0;;;;;;;;;;63317:42;;;;-1:-1:-1;;63317:42:0;63134:244;:::o;2709:133::-;2777:5;;-1:-1:-1;;;;;2777:5:0;2763:10;:19;2755:79;;;;-1:-1:-1;;;2755:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2709:133::o;54411:404::-;54471:4;54780:9;54762:15;:27;54733:26;:24;:26::i;:::-;:56;:74;;;-1:-1:-1;;54793:14:0;;54411:404::o;57821:615::-;57868:9;57879:21;57914:20;57936:14;57954:52;57973:8;:6;:8::i;:::-;-1:-1:-1;;;;;57973:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57973:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;57973:32:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;57973:32:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;57973:32:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;57973:32:0;;421:4:-1;412:14;;;;57973:32:0;;;;;412:14:-1;57973:32:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;57973:32:0;;;;;;;;;;;57954:18;:52::i;:::-;58034:13;;57913:93;;-1:-1:-1;57913:93:0;-1:-1:-1;58017:14:0;;58079:88;58096:9;58092:1;:13;58079:88;;;58135:20;58145:6;58152:1;58145:9;;;;;;;;;;;;;;58135:5;:9;;:20;;;;:::i;:::-;58127:28;-1:-1:-1;58107:3:0;;58079:88;;;;58230:14;58246:17;58267:19;:17;:19::i;:::-;-1:-1:-1;;;;;58267:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;58267:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;58267:32:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58267:32:0;;;;;;;;;-1:-1:-1;58267:32:0;-1:-1:-1;58320:20:0;:5;58267:32;58320:20;:9;:20;:::i;:::-;58312:28;;58365:9;:25;;;;58378:12;58365:25;58411:5;;-1:-1:-1;58353:37:0;;-1:-1:-1;;;;;;57821:615:0;;:::o;63386:1607::-;63579:19;;63628;;63617:30;;63609:69;;;;;-1:-1:-1;;;63609:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;63770:14;63795:15;63821:27;63851:46;63870:12;63884;63851:18;:46::i;:::-;63821:76;-1:-1:-1;63913:6:0;63908:324;63929:7;63925:1;:11;63908:324;;;63958:11;63972:12;63985:1;63972:15;;;;;;;;;;;;;;63958:29;;64002:21;64026:13;64040:1;64026:16;;;;;;;;;;;;;;64002:40;;64069:36;64083:16;:21;64100:3;64083:21;;;;;;;;;;;;64069:9;:13;;:36;;;;:::i;:::-;64057:48;-1:-1:-1;64133:32:0;:10;64148:16;64133:32;:14;:32;:::i;:::-;64180:21;;;;:16;:21;;;;;;:40;64120:45;-1:-1:-1;63938:3:0;;63908:324;;;;64325:10;64312:9;:23;64308:437;;64364:11;;64544:17;;;;64536:65;;;;-1:-1:-1;;;64536:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64623:35;64647:10;64623:19;:4;64632:9;64623:19;:8;:19;:::i;:::-;:23;:35;:23;:35;:::i;:::-;64673:11;:18;;;64711:22;;;;;;;;64616:42;;-1:-1:-1;64711:22:0;;;;;;;;;;64308:437;;64899:16;64895:91;;;64932:42;64957:16;64932:24;:42::i;:::-;63386:1607;;;;;;;:::o;18283:183::-;18392:16;;;18406:1;18392:16;;;;;;;;;18341:26;;18392:16;;;;;;105:10:-1;18392:16:0;88:34:-1;136:17;;-1:-1;18392:16:0;18380:28;;-1:-1:-1;;;18419:9:0;18429:1;18419:12;;;;;;;;;;;;;:39;;;;;18283:183;:::o;10524:458::-;10646:28;10735:6;:13;10720:5;:12;:28;10706:43;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;10706:43:0;-1:-1:-1;10692:57:0;-1:-1:-1;10767:6:0;10762:92;10783:5;:12;10779:1;:16;10762:92;;;10834:5;10840:1;10834:8;;;;;;;;;;;;;;10817:11;10829:1;10817:14;;;;;;;;;;;;;;;;;:25;10797:3;;10762:92;;;-1:-1:-1;10871:6:0;10866:109;10887:6;:13;10883:1;:17;10866:109;;;10954:6;10961:1;10954:9;;;;;;;;;;;;;;10922:11;10949:1;10934:5;:12;:16;10922:29;;;;;;;;;;;;;;;;;:41;10902:3;;10866:109;;;;10524:458;;;;:::o;22337:178::-;22396:4;22420:17;:15;:17::i;:::-;-1:-1:-1;;;;;22420:30:0;;-1:-1:-1;;;;;;22420:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;22420:87:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;22420:87:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;22420:87:0;;-1:-1:-1;22337:178:0;:::o;52750:122::-;52791:7;52826:37;-1:-1:-1;;;52826:20:0;:37::i;57295:340::-;57376:13;57402:12;57417;:19;57402:34;;57447:19;57480:7;57469:19;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;57469:19:0;-1:-1:-1;57447:41:0;-1:-1:-1;57504:6:0;57499:106;57520:7;57516:1;:11;57499:106;;;57560:16;:33;57577:12;57590:1;57577:15;;;;;;;;;;;;;;57560:33;;;;;;;;;;;;57549:5;57555:1;57549:8;;;;;;;;;;;;;;;;;:44;57529:3;;57499:106;;;-1:-1:-1;57622:5:0;57295:340;-1:-1:-1;;;57295:340:0:o;59600:162::-;59685:5;;-1:-1:-1;;;;;59685:5:0;59671:10;:19;59667:88;;59707:14;:12;:14::i;:::-;-1:-1:-1;;;;;59707:34:0;;:36;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59707:36:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;56702:355:0;56811:29;56842:21;56882:19;56903:14;56921:15;:13;:15::i;:::-;-1:-1:-1;;;;;56921:44:0;;56966:12;56921:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;56921:58:0;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56921:58:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56921:58:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;56921:58:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;;;5:11;;2:2;;;29:1;26;19:12;2:2;56921:58:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;56921:58:0;;421:4:-1;412:14;;;;56921:58:0;;;;;412:14:-1;56921:58:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;-1:-1;;;;56921:58:0;;;;;;-1:-1:-1;56921:58:0;;;56881:98;;-1:-1:-1;56921:58:0;;-1:-1:-1;56998:39:0;;-1:-1:-1;57017:12:0;;-1:-1:-1;56881:98:0;56998:18;:39::i;:::-;56990:59;-1:-1:-1;57039:9:0;-1:-1:-1;;56702:355:0;;;:::o;53677:166::-;53729:18;53786:48;-1:-1:-1;;;53786:20:0;:48::i;25356:181::-;25414:7;25446:5;;;25470:6;;;;25462:46;;;;;-1:-1:-1;;;25462:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;25812:184;25870:7;25903:1;25898;:6;;25890:49;;;;;-1:-1:-1;;;25890:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;25962:5:0;;;25812:184::o;53022:144::-;53070:14;53119:38;-1:-1:-1;;;53119:20:0;:38::i;52880:134::-;52924:10;52965:40;-1:-1:-1;;;52965:20:0;:40::i;54936:1758::-;55039:13;55065:14;55082:12;:19;55065:36;;55112:20;55146:9;55135:21;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;55135:21:0;;55112:44;;55167:22;55192:8;:6;:8::i;:::-;-1:-1:-1;;;;;55192:18:0;;55211:12;55192:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;55192:32:0;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;55192:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;55192:32:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;55192:32:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;55192:32:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;55192:32:0;;421:4:-1;412:14;;;;55192:32:0;;;;;412:14:-1;55192:32:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;55192:32:0;;;;;;;;;;;55167:57;;55242:6;55251:1;55242:10;;55237:1426;55258:9;55254:1;:13;55237:1426;;;55289:11;55303:12;55316:1;55303:15;;;;;;;;;;;;;;55289:29;;55333:20;55364:6;55371:1;55364:9;;;;;;;;;;;;;;55333:41;;55421:1;-1:-1:-1;;;;;55397:26:0;:12;-1:-1:-1;;;;;55397:26:0;;;55389:59;;;;;-1:-1:-1;;;55389:59:0;;;;;;;;;;;;-1:-1:-1;;;55389:59:0;;;;;;;;;;;;;;;55463:11;55484:12;-1:-1:-1;;;;;55477:32:0;;:34;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;55477:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;55477:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;55477:34:0;;-1:-1:-1;55532:19:0;:17;:19::i;:::-;-1:-1:-1;;;;;55532:34:0;;55567:3;55532:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;55532:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;55532:39:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;55532:39:0;55528:647;;;55592:21;55616:19;:17;:19::i;:::-;-1:-1:-1;;;;;55616:24:0;;55641:3;55616:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;55616:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;55616:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;55616:29:0;;-1:-1:-1;55994:25:0;;;55990:170;;;56053:1;56044:10;;55990:170;;;56112:28;:6;56123:16;56112:28;:10;:28;:::i;:::-;56103:37;;55990:170;55528:647;;-1:-1:-1;;;56205:11:0;;;;56235:21;;;-1:-1:-1;;;56245:3:0;:11;56235:21;56231:355;;;56277:40;56341:6;:77;;56401:17;:15;:17::i;:::-;56341:77;;;56375:21;:19;:21::i;:::-;56277:141;;56437:26;56466:23;-1:-1:-1;;;;;56466:41:0;;:43;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56466:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56466:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56466:43:0;;-1:-1:-1;56537:33:0;:6;56466:43;56537:33;:10;:33;:::i;:::-;56528:42;;56231:355;;;56614:37;56642:5;56648:1;56642:8;;;;;;;;;;;;;;56614:6;:27;;:37;;;;:::i;:::-;56602:6;56609:1;56602:9;;;;;;;;;;;;;;;;;:49;-1:-1:-1;;55269:3:0;;;;;-1:-1:-1;55237:1426:0;;-1:-1:-1;55237:1426:0;;-1:-1:-1;56680:6:0;;54936:1758;-1:-1:-1;;;;;54936:1758:0:o;18474:158::-;18524:16;18577:46;-1:-1:-1;;;12563:268:0;12630:7;12674:18;;;:12;:18;;;;;;;;;12747:43;;-1:-1:-1;;;12747:43:0;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;12747:43:0;;;;;;;-1:-1:-1;;;;;12674:18:0;;12711:27;12703:89;;;;-1:-1:-1;;;12703:89:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;12703:89:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53174:146;53221:13;53268:43;-1:-1:-1;;;53268:20:0;:43::i;53328:158::-;53378:16;53431:46;-1:-1:-1;;;53431:20:0;:46::i;53494:175::-;53548:20;53609:51;-1:-1:-1;;;53609:20:0;:51::i;32105:134::-;32174:4;32198:33;32220:1;32223;28517:18;32174:4;;30615:18;30603:8;32220:1;32223;30603:5;:8::i;:::-;:31;;;;;;;-1:-1:-1;30676:1:0;30670:2;30603:31;30651:21;:26;30647:81;;30714:2;30694:22;30647:81;30766:2;30747:21;;;;-1:-1:-1;;;;30355:421:0:o;26247:470::-;26305:7;26549:6;26545:47;;-1:-1:-1;26579:1:0;26572:8;;26545:47;26616:5;;;26620:1;26616;:5;:1;26640:5;;;;;:10;26632:56;;;;-1:-1:-1;;;26632:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Swarm Source
bzzr://1255a1e8b8b81586db1e0d227fdf2a31ece8463f93252df7378453a2857bf432
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|