My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
SynthetixBridgeToBase
Compiler Version
v0.5.16+commit.9c3226ce
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Optimistic.Etherscan.io on 2022-05-10 */ /* ____ __ __ __ _ / __/__ __ ___ / /_ / / ___ / /_ (_)__ __ _\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ / /___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\ /___/ * Synthetix: SynthetixBridgeToBase.sol * * Latest source (may be newer): https://github.com/Synthetixio/synthetix/blob/master/contracts/SynthetixBridgeToBase.sol * Docs: https://docs.synthetix.io/contracts/SynthetixBridgeToBase * * Contract Dependencies: * - BaseSynthetixBridge * - IAddressResolver * - IBaseSynthetixBridge * - ISynthetixBridgeToBase * - MixinResolver * - MixinSystemSettings * - Owned * - iOVM_L2DepositedToken * Libraries: * - Math * - SafeDecimalMath * - SafeMath * - VestingEntries * * MIT License * =========== * * Copyright (c) 2022 Synthetix * * 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.synthetix.io/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.synthetix.io/contracts/source/interfaces/iaddressresolver interface IAddressResolver { function getAddress(bytes32 name) external view returns (address); function getSynth(bytes32 key) external view returns (address); function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address); } // https://docs.synthetix.io/contracts/source/interfaces/isynth interface ISynth { // Views function currencyKey() external view returns (bytes32); function transferableSynths(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 Synthetix function burn(address account, uint amount) external; function issue(address account, uint amount) external; } // https://docs.synthetix.io/contracts/source/interfaces/iissuer interface IIssuer { // Views function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid); function availableCurrencyKeys() external view returns (bytes32[] memory); function availableSynthCount() external view returns (uint); function availableSynths(uint index) external view returns (ISynth); function canBurnSynths(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 issuanceRatio() external view returns (uint); function lastIssueEvent(address account) external view returns (uint); function maxIssuableSynths(address issuer) external view returns (uint maxIssuable); function minimumStakeTime() external view returns (uint); function remainingIssuableSynths(address issuer) external view returns ( uint maxIssuable, uint alreadyIssued, uint totalSystemDebt ); function synths(bytes32 currencyKey) external view returns (ISynth); function getSynths(bytes32[] calldata currencyKeys) external view returns (ISynth[] memory); function synthsByAddress(address synthAddress) external view returns (bytes32); function totalIssuedSynths(bytes32 currencyKey, bool excludeOtherCollateral) external view returns (uint); function transferableSynthetixAndAnyRateIsInvalid(address account, uint balance) external view returns (uint transferable, bool anyRateIsInvalid); // Restricted: used internally to Synthetix function issueSynths(address from, uint amount) external; function issueSynthsOnBehalf( address issueFor, address from, uint amount ) external; function issueMaxSynths(address from) external; function issueMaxSynthsOnBehalf(address issueFor, address from) external; function burnSynths(address from, uint amount) external; function burnSynthsOnBehalf( address burnForAddress, address from, uint amount ) external; function burnSynthsToTarget(address from) external; function burnSynthsToTargetOnBehalf(address burnForAddress, address from) external; function burnForRedemption( address deprecatedSynthProxy, address account, uint balance ) external; function liquidateDelinquentAccount( address account, uint susdAmount, address liquidator ) external returns (uint totalRedeemed, uint amountToLiquidate); function setCurrentPeriodId(uint128 periodId) external; function issueSynthsWithoutDebt( bytes32 currencyKey, address to, uint amount ) external returns (bool rateInvalid); function burnSynthsWithoutDebt( bytes32 currencyKey, address to, uint amount ) external returns (bool rateInvalid); } // Inheritance // Internal references // https://docs.synthetix.io/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 getSynth(bytes32 key) external view returns (address) { IIssuer issuer = IIssuer(repository["Issuer"]); require(address(issuer) != address(0), "Cannot find Issuer address"); return address(issuer.synths(key)); } /* ========== EVENTS ========== */ event AddressImported(bytes32 name, address destination); } // Internal references // https://docs.synthetix.io/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.synthetix.io/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.synthetix.io/contracts/source/contracts/mixinsystemsettings contract MixinSystemSettings is MixinResolver { // must match the one defined SystemSettingsLib, defined in both places due to sol v0.5 limitations 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"; /* ========== Exchange Fees Related ========== */ bytes32 internal constant SETTING_EXCHANGE_FEE_RATE = "exchangeFeeRate"; bytes32 internal constant SETTING_EXCHANGE_DYNAMIC_FEE_THRESHOLD = "exchangeDynamicFeeThreshold"; bytes32 internal constant SETTING_EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY = "exchangeDynamicFeeWeightDecay"; bytes32 internal constant SETTING_EXCHANGE_DYNAMIC_FEE_ROUNDS = "exchangeDynamicFeeRounds"; bytes32 internal constant SETTING_EXCHANGE_MAX_DYNAMIC_FEE = "exchangeMaxDynamicFee"; /* ========== End Exchange Fees Related ========== */ 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_CROSS_DOMAIN_FEE_PERIOD_CLOSE_GAS_LIMIT = "crossDomainCloseGasLimit"; bytes32 internal constant SETTING_CROSS_DOMAIN_RELAY_GAS_LIMIT = "crossDomainRelayGasLimit"; bytes32 internal constant SETTING_ETHER_WRAPPER_MAX_ETH = "etherWrapperMaxETH"; bytes32 internal constant SETTING_ETHER_WRAPPER_MINT_FEE_RATE = "etherWrapperMintFeeRate"; bytes32 internal constant SETTING_ETHER_WRAPPER_BURN_FEE_RATE = "etherWrapperBurnFeeRate"; bytes32 internal constant SETTING_WRAPPER_MAX_TOKEN_AMOUNT = "wrapperMaxTokens"; bytes32 internal constant SETTING_WRAPPER_MINT_FEE_RATE = "wrapperMintFeeRate"; bytes32 internal constant SETTING_WRAPPER_BURN_FEE_RATE = "wrapperBurnFeeRate"; bytes32 internal constant SETTING_INTERACTION_DELAY = "interactionDelay"; bytes32 internal constant SETTING_COLLAPSE_FEE_RATE = "collapseFeeRate"; bytes32 internal constant SETTING_ATOMIC_MAX_VOLUME_PER_BLOCK = "atomicMaxVolumePerBlock"; bytes32 internal constant SETTING_ATOMIC_TWAP_WINDOW = "atomicTwapWindow"; bytes32 internal constant SETTING_ATOMIC_EQUIVALENT_FOR_DEX_PRICING = "atomicEquivalentForDexPricing"; bytes32 internal constant SETTING_ATOMIC_EXCHANGE_FEE_RATE = "atomicExchangeFeeRate"; bytes32 internal constant SETTING_ATOMIC_VOLATILITY_CONSIDERATION_WINDOW = "atomicVolConsiderationWindow"; bytes32 internal constant SETTING_ATOMIC_VOLATILITY_UPDATE_THRESHOLD = "atomicVolUpdateThreshold"; bytes32 internal constant SETTING_PURE_CHAINLINK_PRICE_FOR_ATOMIC_SWAPS_ENABLED = "pureChainlinkForAtomicsEnabled"; bytes32 internal constant SETTING_CROSS_SYNTH_TRANSFER_ENABLED = "crossChainSynthTransferEnabled"; bytes32 internal constant CONTRACT_FLEXIBLESTORAGE = "FlexibleStorage"; enum CrossDomainMessageGasLimits {Deposit, Escrow, Reward, Withdrawal, CloseFeePeriod, Relay} struct DynamicFeeConfig { uint threshold; uint weightDecay; uint rounds; uint maxFee; } 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 if (gasLimitType == CrossDomainMessageGasLimits.Relay) { return SETTING_CROSS_DOMAIN_RELAY_GAS_LIMIT; } else if (gasLimitType == CrossDomainMessageGasLimits.CloseFeePeriod) { return SETTING_CROSS_DOMAIN_FEE_PERIOD_CLOSE_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); } /* ========== Exchange Related Fees ========== */ function getExchangeFeeRate(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_EXCHANGE_FEE_RATE, currencyKey)) ); } /// @notice Get exchange dynamic fee related keys /// @return threshold, weight decay, rounds, and max fee function getExchangeDynamicFeeConfig() internal view returns (DynamicFeeConfig memory) { bytes32[] memory keys = new bytes32[](4); keys[0] = SETTING_EXCHANGE_DYNAMIC_FEE_THRESHOLD; keys[1] = SETTING_EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY; keys[2] = SETTING_EXCHANGE_DYNAMIC_FEE_ROUNDS; keys[3] = SETTING_EXCHANGE_MAX_DYNAMIC_FEE; uint[] memory values = flexibleStorage().getUIntValues(SETTING_CONTRACT_NAME, keys); return DynamicFeeConfig({threshold: values[0], weightDecay: values[1], rounds: values[2], maxFee: values[3]}); } /* ========== End Exchange Related Fees ========== */ 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 getEtherWrapperMaxETH() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ETHER_WRAPPER_MAX_ETH); } function getEtherWrapperMintFeeRate() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ETHER_WRAPPER_MINT_FEE_RATE); } function getEtherWrapperBurnFeeRate() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ETHER_WRAPPER_BURN_FEE_RATE); } function getWrapperMaxTokenAmount(address wrapper) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_WRAPPER_MAX_TOKEN_AMOUNT, wrapper)) ); } function getWrapperMintFeeRate(address wrapper) internal view returns (int) { return flexibleStorage().getIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_WRAPPER_MINT_FEE_RATE, wrapper)) ); } function getWrapperBurnFeeRate(address wrapper) internal view returns (int) { return flexibleStorage().getIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_WRAPPER_BURN_FEE_RATE, wrapper)) ); } function getInteractionDelay(address collateral) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_INTERACTION_DELAY, collateral)) ); } function getCollapseFeeRate(address collateral) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_COLLAPSE_FEE_RATE, collateral)) ); } function getAtomicMaxVolumePerBlock() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ATOMIC_MAX_VOLUME_PER_BLOCK); } function getAtomicTwapWindow() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ATOMIC_TWAP_WINDOW); } function getAtomicEquivalentForDexPricing(bytes32 currencyKey) internal view returns (address) { return flexibleStorage().getAddressValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_ATOMIC_EQUIVALENT_FOR_DEX_PRICING, currencyKey)) ); } function getAtomicExchangeFeeRate(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_ATOMIC_EXCHANGE_FEE_RATE, currencyKey)) ); } function getAtomicVolatilityConsiderationWindow(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_ATOMIC_VOLATILITY_CONSIDERATION_WINDOW, currencyKey)) ); } function getAtomicVolatilityUpdateThreshold(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_ATOMIC_VOLATILITY_UPDATE_THRESHOLD, currencyKey)) ); } function getPureChainlinkPriceForAtomicSwapsEnabled(bytes32 currencyKey) internal view returns (bool) { return flexibleStorage().getBoolValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_PURE_CHAINLINK_PRICE_FOR_ATOMIC_SWAPS_ENABLED, currencyKey)) ); } function getCrossChainSynthTransferEnabled(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_CROSS_SYNTH_TRANSFER_ENABLED, currencyKey)) ); } } pragma experimental ABIEncoderV2; interface IBaseSynthetixBridge { function suspendInitiation() external; function resumeInitiation() 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.synthetix.io/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; } // Computes `a - b`, setting the value to 0 if b > a. function floorsub(uint a, uint b) internal pure returns (uint) { return b >= a ? 0 : a - b; } /* ---------- Utilities ---------- */ /* * Absolute value of the input, returned as a signed number. */ function signedAbs(int x) internal pure returns (int) { return x < 0 ? -x : x; } /* * Absolute value of the input, returned as an unsigned number. */ function abs(int x) internal pure returns (uint) { return uint(signedAbs(x)); } } // Libraries // https://docs.synthetix.io/contracts/source/libraries/math library Math { using SafeMath for uint; using SafeDecimalMath for uint; /** * @dev Uses "exponentiation by squaring" algorithm where cost is 0(logN) * vs 0(N) for naive repeated multiplication. * Calculates x^n with x as fixed-point and n as regular unsigned int. * Calculates to 18 digits of precision with SafeDecimalMath.unit() */ function powDecimal(uint x, uint n) internal pure returns (uint) { // https://mpark.github.io/programming/2014/08/18/exponentiation-by-squaring/ uint result = SafeDecimalMath.unit(); while (n > 0) { if (n % 2 != 0) { result = result.multiplyDecimal(x); } x = x.multiplyDecimal(x); n /= 2; } return result; } } interface IVirtualSynth { // 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 synth() external view returns (ISynth); // Mutative functions function settle(address account) external; } // https://docs.synthetix.io/contracts/source/interfaces/isynthetix interface ISynthetix { // Views function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid); function availableCurrencyKeys() external view returns (bytes32[] memory); function availableSynthCount() external view returns (uint); function availableSynths(uint index) external view returns (ISynth); function collateral(address account) external view returns (uint); function collateralisationRatio(address issuer) external view returns (uint); function debtBalanceOf(address issuer, bytes32 currencyKey) external view returns (uint); function isWaitingPeriod(bytes32 currencyKey) external view returns (bool); function maxIssuableSynths(address issuer) external view returns (uint maxIssuable); function remainingIssuableSynths(address issuer) external view returns ( uint maxIssuable, uint alreadyIssued, uint totalSystemDebt ); function synths(bytes32 currencyKey) external view returns (ISynth); function synthsByAddress(address synthAddress) external view returns (bytes32); function totalIssuedSynths(bytes32 currencyKey) external view returns (uint); function totalIssuedSynthsExcludeOtherCollateral(bytes32 currencyKey) external view returns (uint); function transferableSynthetix(address account) external view returns (uint transferable); // Mutative Functions function burnSynths(uint amount) external; function burnSynthsOnBehalf(address burnForAddress, uint amount) external; function burnSynthsToTarget() external; function burnSynthsToTargetOnBehalf(address burnForAddress) external; function exchange( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external returns (uint amountReceived); function exchangeOnBehalf( address exchangeForAddress, bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external returns (uint amountReceived); function exchangeWithTracking( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, address rewardAddress, bytes32 trackingCode ) external returns (uint amountReceived); function exchangeWithTrackingForInitiator( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, address rewardAddress, bytes32 trackingCode ) external returns (uint amountReceived); function exchangeOnBehalfWithTracking( address exchangeForAddress, bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, address rewardAddress, bytes32 trackingCode ) external returns (uint amountReceived); function exchangeWithVirtual( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, bytes32 trackingCode ) external returns (uint amountReceived, IVirtualSynth vSynth); function exchangeAtomically( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, bytes32 trackingCode, uint minAmount ) external returns (uint amountReceived); function issueMaxSynths() external; function issueMaxSynthsOnBehalf(address issueForAddress) external; function issueSynths(uint amount) external; function issueSynthsOnBehalf(address issueForAddress, uint amount) external; function mint() external returns (bool); function settle(bytes32 currencyKey) external returns ( uint reclaimed, uint refunded, uint numEntries ); // Liquidations function liquidateDelinquentAccount(address account, uint susdAmount) external returns (bool); // Restricted Functions function mintSecondary(address account, uint amount) external; function mintSecondaryRewards(uint amount) external; function burnSecondary(address account, uint amount) external; } library VestingEntries { struct VestingEntry { uint64 endTime; uint256 escrowAmount; } struct VestingEntryWithID { uint64 endTime; uint256 escrowAmount; uint256 entryID; } } interface IRewardEscrowV2 { // Views function balanceOf(address account) external view returns (uint); function numVestingEntries(address account) external view returns (uint); function totalEscrowedAccountBalance(address account) external view returns (uint); function totalVestedAccountBalance(address account) external view returns (uint); function getVestingQuantity(address account, uint256[] calldata entryIDs) external view returns (uint); function getVestingSchedules( address account, uint256 index, uint256 pageSize ) external view returns (VestingEntries.VestingEntryWithID[] memory); function getAccountVestingEntryIDs( address account, uint256 index, uint256 pageSize ) external view returns (uint256[] memory); function getVestingEntryClaimable(address account, uint256 entryID) external view returns (uint); function getVestingEntry(address account, uint256 entryID) external view returns (uint64, uint256); // Mutative functions function vest(uint256[] calldata entryIDs) external; function createEscrowEntry( address beneficiary, uint256 deposit, uint256 duration ) external; function appendVestingEntry( address account, uint256 quantity, uint256 duration ) external; function migrateVestingSchedule(address _addressToMigrate) external; function migrateAccountEscrowBalances( address[] calldata accounts, uint256[] calldata escrowBalances, uint256[] calldata vestedBalances ) external; // Account Merging function startMergingWindow() external; function mergeAccount(address accountToMerge, uint256[] calldata entryIDs) external; function nominateAccountToMerge(address account) external; function accountMergingIsOpen() external view returns (bool); // L2 Migration function importVestingEntries( address account, uint256 escrowedAmount, VestingEntries.VestingEntry[] calldata vestingEntries ) external; // Return amount of SNX transfered to SynthetixBridgeToOptimism deposit contract function burnForMigration(address account, uint256[] calldata entryIDs) external returns (uint256 escrowedAccountBalance, VestingEntries.VestingEntry[] memory vestingEntries); } // https://docs.synthetix.io/contracts/source/interfaces/ifeepool interface IFeePool { // Views // solhint-disable-next-line func-name-mixedcase function FEE_ADDRESS() external view returns (address); function feesAvailable(address account) external view returns (uint, uint); function feePeriodDuration() external view returns (uint); function isFeesClaimable(address account) external view returns (bool); function targetThreshold() external view returns (uint); function totalFeesAvailable() external view returns (uint); function totalRewardsAvailable() external view returns (uint); // Mutative Functions function claimFees() external returns (bool); function claimOnBehalf(address claimingForAddress) external returns (bool); function closeCurrentFeePeriod() external; function closeSecondary(uint snxBackedDebt, uint debtShareSupply) external; function recordFeePaid(uint sUSDAmount) external; function setRewardsToDistribute(uint amount) external; } // https://docs.synthetix.io/contracts/source/interfaces/iexchangerates interface IExchangeRates { // Structs struct RateAndUpdatedTime { uint216 rate; uint40 time; } // 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 anyRateIsInvalidAtRound(bytes32[] calldata currencyKeys, uint[] calldata roundIds) external view returns (bool); 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 effectiveValueAndRatesAtRound( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, uint roundIdForSrc, uint roundIdForDest ) external view returns ( uint value, uint sourceRate, uint destinationRate ); function effectiveAtomicValueAndRates( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external view returns ( uint value, uint systemValue, uint systemSourceRate, uint systemDestinationRate ); function getCurrentRoundId(bytes32 currencyKey) external view returns (uint); function getLastRoundIdBeforeElapsedSecs( bytes32 currencyKey, uint startingRoundId, uint startingTimestamp, uint timediff ) external view returns (uint); function lastRateUpdateTimes(bytes32 currencyKey) external view returns (uint256); 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 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, uint roundId ) 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); function synthTooVolatileForAtomicExchange(bytes32 currencyKey) external view returns (bool); } // https://docs.synthetix.io/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 systemSuspended() external view returns (bool); function requireIssuanceActive() external view; function requireExchangeActive() external view; function requireFuturesActive() external view; function requireFuturesMarketActive(bytes32 marketKey) external view; function requireExchangeBetweenSynthsAllowed(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view; function requireSynthActive(bytes32 currencyKey) external view; function synthSuspended(bytes32 currencyKey) external view returns (bool); function requireSynthsActive(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 futuresSuspension() external view returns (bool suspended, uint248 reason); function synthExchangeSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason); function synthSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason); function futuresMarketSuspension(bytes32 marketKey) external view returns (bool suspended, uint248 reason); function getSynthExchangeSuspensions(bytes32[] calldata synths) external view returns (bool[] memory exchangeSuspensions, uint256[] memory reasons); function getSynthSuspensions(bytes32[] calldata synths) external view returns (bool[] memory suspensions, uint256[] memory reasons); function getFuturesMarketSuspensions(bytes32[] calldata marketKeys) external view returns (bool[] memory suspensions, uint256[] memory reasons); // Restricted functions function suspendIssuance(uint256 reason) external; function suspendSynth(bytes32 currencyKey, uint256 reason) external; function suspendFuturesMarket(bytes32 marketKey, uint256 reason) external; function updateAccessControl( bytes32 section, address account, bool canSuspend, bool canResume ) external; } // SPDX-License-Identifier: MIT /** * @title iAbs_BaseCrossDomainMessenger */ interface iAbs_BaseCrossDomainMessenger { /********** * Events * **********/ event SentMessage(bytes message); event RelayedMessage(bytes32 msgHash); event FailedRelayedMessage(bytes32 msgHash); /************* * Variables * *************/ function xDomainMessageSender() external view returns (address); /******************** * Public Functions * ********************/ /** * Sends a cross domain message to the target messenger. * @param _target Target contract address. * @param _message Message to send to the target. * @param _gasLimit Gas limit for the provided message. */ function sendMessage( address _target, bytes calldata _message, uint32 _gasLimit ) external; } // Inheritance // Libraries // Internal references contract BaseSynthetixBridge is Owned, MixinSystemSettings, IBaseSynthetixBridge { using SafeMath for uint; using SafeDecimalMath for uint; /* ========== ADDRESS RESOLVER CONFIGURATION ========== */ bytes32 private constant CONTRACT_EXT_MESSENGER = "ext:Messenger"; bytes32 internal constant CONTRACT_SYNTHETIX = "Synthetix"; bytes32 private constant CONTRACT_REWARDESCROW = "RewardEscrowV2"; bytes32 private constant CONTRACT_ISSUER = "Issuer"; bytes32 private constant CONTRACT_FEEPOOL = "FeePool"; bytes32 private constant CONTRACT_FLEXIBLESTORAGE = "FlexibleStorage"; bytes32 private constant CONTRACT_EXCHANGERATES = "ExchangeRates"; bytes32 private constant CONTRACT_SYSTEM_STATUS = "SystemStatus"; // have to define this function like this here because contract name is required for FlexibleStorage function CONTRACT_NAME() public pure returns (bytes32); bool public initiationActive; bytes32 private constant SYNTH_TRANSFER_NAMESPACE = "SynthTransfer"; bytes32 private constant SYNTH_TRANSFER_SENT = "Sent"; bytes32 private constant SYNTH_TRANSFER_RECV = "Recv"; // ========== CONSTRUCTOR ========== constructor(address _owner, address _resolver) public Owned(_owner) MixinSystemSettings(_resolver) { initiationActive = true; } // ========== INTERNALS ============ function messenger() internal view returns (iAbs_BaseCrossDomainMessenger) { return iAbs_BaseCrossDomainMessenger(requireAndGetAddress(CONTRACT_EXT_MESSENGER)); } function synthetix() internal view returns (ISynthetix) { return ISynthetix(requireAndGetAddress(CONTRACT_SYNTHETIX)); } function rewardEscrowV2() internal view returns (IRewardEscrowV2) { return IRewardEscrowV2(requireAndGetAddress(CONTRACT_REWARDESCROW)); } function issuer() internal view returns (IIssuer) { return IIssuer(requireAndGetAddress(CONTRACT_ISSUER)); } function feePool() internal view returns (IFeePool) { return IFeePool(requireAndGetAddress(CONTRACT_FEEPOOL)); } function flexibleStorage() internal view returns (IFlexibleStorage) { return IFlexibleStorage(requireAndGetAddress(CONTRACT_FLEXIBLESTORAGE)); } function exchangeRates() internal view returns (IExchangeRates) { return IExchangeRates(requireAndGetAddress(CONTRACT_EXCHANGERATES)); } function systemStatus() internal view returns (ISystemStatus) { return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEM_STATUS)); } function initiatingActive() internal view { require(initiationActive, "Initiation deactivated"); } function counterpart() internal view returns (address); function onlyAllowFromCounterpart() internal view { // ensure function only callable from the L2 bridge via messenger (aka relayer) iAbs_BaseCrossDomainMessenger _messenger = messenger(); require(msg.sender == address(_messenger), "Only the relayer can call this"); require(_messenger.xDomainMessageSender() == counterpart(), "Only a counterpart bridge can invoke"); } /* ========== VIEWS ========== */ function resolverAddressesRequired() public view returns (bytes32[] memory addresses) { bytes32[] memory existingAddresses = MixinSystemSettings.resolverAddressesRequired(); bytes32[] memory newAddresses = new bytes32[](8); newAddresses[0] = CONTRACT_EXT_MESSENGER; newAddresses[1] = CONTRACT_SYNTHETIX; newAddresses[2] = CONTRACT_REWARDESCROW; newAddresses[3] = CONTRACT_ISSUER; newAddresses[4] = CONTRACT_FEEPOOL; newAddresses[5] = CONTRACT_FLEXIBLESTORAGE; newAddresses[6] = CONTRACT_EXCHANGERATES; newAddresses[7] = CONTRACT_SYSTEM_STATUS; addresses = combineArrays(existingAddresses, newAddresses); } function synthTransferSent() external view returns (uint) { return _sumTransferAmounts(SYNTH_TRANSFER_SENT); } function synthTransferReceived() external view returns (uint) { return _sumTransferAmounts(SYNTH_TRANSFER_RECV); } // ========== MODIFIERS ============ modifier requireInitiationActive() { initiatingActive(); _; } modifier onlyCounterpart() { onlyAllowFromCounterpart(); _; } // ========= RESTRICTED FUNCTIONS ============== function suspendInitiation() external onlyOwner { require(initiationActive, "Initiation suspended"); initiationActive = false; emit InitiationSuspended(); } function resumeInitiation() external onlyOwner { require(!initiationActive, "Initiation not suspended"); initiationActive = true; emit InitiationResumed(); } function initiateSynthTransfer( bytes32 currencyKey, address destination, uint amount ) external requireInitiationActive { require(destination != address(0), "Cannot send to zero address"); require(getCrossChainSynthTransferEnabled(currencyKey) > 0, "Synth not enabled for cross chain transfer"); systemStatus().requireSynthActive(currencyKey); _incrementSynthsTransferCounter(SYNTH_TRANSFER_SENT, currencyKey, amount); bool rateInvalid = issuer().burnSynthsWithoutDebt(currencyKey, msg.sender, amount); require(!rateInvalid, "Cannot initiate if synth rate is invalid"); // create message payload bytes memory messageData = abi.encodeWithSelector(this.finalizeSynthTransfer.selector, currencyKey, destination, amount); // relay the message to Bridge on L1 via L2 Messenger messenger().sendMessage( counterpart(), messageData, uint32(getCrossDomainMessageGasLimit(CrossDomainMessageGasLimits.Withdrawal)) ); emit InitiateSynthTransfer(currencyKey, destination, amount); } function finalizeSynthTransfer( bytes32 currencyKey, address destination, uint amount ) external onlyCounterpart { _incrementSynthsTransferCounter(SYNTH_TRANSFER_RECV, currencyKey, amount); issuer().issueSynthsWithoutDebt(currencyKey, destination, amount); emit FinalizeSynthTransfer(currencyKey, destination, amount); } // ==== INTERNAL FUNCTIONS ==== function _incrementSynthsTransferCounter( bytes32 group, bytes32 currencyKey, uint amount ) internal { bytes32 key = keccak256(abi.encodePacked(SYNTH_TRANSFER_NAMESPACE, group, currencyKey)); uint currentSynths = flexibleStorage().getUIntValue(CONTRACT_NAME(), key); flexibleStorage().setUIntValue(CONTRACT_NAME(), key, currentSynths.add(amount)); } function _sumTransferAmounts(bytes32 group) internal view returns (uint sum) { // get list of synths from issuer bytes32[] memory currencyKeys = issuer().availableCurrencyKeys(); // get all synth rates (uint[] memory rates, bool isInvalid) = exchangeRates().ratesAndInvalidForCurrencies(currencyKeys); require(!isInvalid, "Rates are invalid"); // get all values bytes32[] memory transferAmountKeys = new bytes32[](currencyKeys.length); for (uint i = 0; i < currencyKeys.length; i++) { transferAmountKeys[i] = keccak256(abi.encodePacked(SYNTH_TRANSFER_NAMESPACE, group, currencyKeys[i])); } uint[] memory transferAmounts = flexibleStorage().getUIntValues(CONTRACT_NAME(), transferAmountKeys); for (uint i = 0; i < currencyKeys.length; i++) { sum = sum.add(transferAmounts[i].multiplyDecimalRound(rates[i])); } } // ========== EVENTS ========== event InitiationSuspended(); event InitiationResumed(); event InitiateSynthTransfer(bytes32 indexed currencyKey, address indexed destination, uint256 amount); event FinalizeSynthTransfer(bytes32 indexed currencyKey, address indexed destination, uint256 amount); } interface ISynthetixBridgeToBase { // invoked by the xDomain messenger on L2 function finalizeEscrowMigration( address account, uint256 escrowedAmount, VestingEntries.VestingEntry[] calldata vestingEntries ) external; // invoked by the xDomain messenger on L2 function finalizeRewardDeposit(address from, uint amount) external; function finalizeFeePeriodClose(uint snxBackedDebt, uint debtSharesSupply) external; } // SPDX-License-Identifier: MIT /** * @title iOVM_L2DepositedToken */ interface iOVM_L2DepositedToken { /********** * Events * **********/ event WithdrawalInitiated( address indexed _from, address _to, uint256 _amount ); event DepositFinalized( address indexed _to, uint256 _amount ); /******************** * Public Functions * ********************/ function withdraw( uint _amount ) external; function withdrawTo( address _to, uint _amount ) external; /************************* * Cross-chain Functions * *************************/ function finalizeDeposit( address _to, uint _amount ) external; } // SPDX-License-Identifier: MIT /** * @title iOVM_L1TokenGateway */ interface iOVM_L1TokenGateway { /********** * Events * **********/ event DepositInitiated( address indexed _from, address _to, uint256 _amount ); event WithdrawalFinalized( address indexed _to, uint256 _amount ); /******************** * Public Functions * ********************/ function deposit( uint _amount ) external; function depositTo( address _to, uint _amount ) external; /************************* * Cross-chain Functions * *************************/ function finalizeWithdrawal( address _to, uint _amount ) external; } // Inheritance // Internal references contract SynthetixBridgeToBase is BaseSynthetixBridge, ISynthetixBridgeToBase, iOVM_L2DepositedToken { /* ========== ADDRESS RESOLVER CONFIGURATION ========== */ bytes32 private constant CONTRACT_BASE_SYNTHETIXBRIDGETOOPTIMISM = "base:SynthetixBridgeToOptimism"; function CONTRACT_NAME() public pure returns (bytes32) { return "SynthetixBridgeToBase"; } // ========== CONSTRUCTOR ========== constructor(address _owner, address _resolver) public BaseSynthetixBridge(_owner, _resolver) {} // ========== INTERNALS ============ function synthetixBridgeToOptimism() internal view returns (address) { return requireAndGetAddress(CONTRACT_BASE_SYNTHETIXBRIDGETOOPTIMISM); } function counterpart() internal view returns (address) { return synthetixBridgeToOptimism(); } // ========== VIEWS ========== function resolverAddressesRequired() public view returns (bytes32[] memory addresses) { bytes32[] memory existingAddresses = BaseSynthetixBridge.resolverAddressesRequired(); bytes32[] memory newAddresses = new bytes32[](1); newAddresses[0] = CONTRACT_BASE_SYNTHETIXBRIDGETOOPTIMISM; addresses = combineArrays(existingAddresses, newAddresses); } // ========== PUBLIC FUNCTIONS ========= // invoked by user on L2 function withdraw(uint amount) external requireInitiationActive { _initiateWithdraw(msg.sender, amount); } function withdrawTo(address to, uint amount) external requireInitiationActive { _initiateWithdraw(to, amount); } function _initiateWithdraw(address to, uint amount) private { require(synthetix().transferableSynthetix(msg.sender) >= amount, "Not enough transferable SNX"); // instruct L2 Synthetix to burn this supply synthetix().burnSecondary(msg.sender, amount); // create message payload for L1 iOVM_L1TokenGateway bridgeToOptimism; bytes memory messageData = abi.encodeWithSelector(bridgeToOptimism.finalizeWithdrawal.selector, to, amount); // relay the message to Bridge on L1 via L2 Messenger messenger().sendMessage( synthetixBridgeToOptimism(), messageData, uint32(getCrossDomainMessageGasLimit(CrossDomainMessageGasLimits.Withdrawal)) ); emit iOVM_L2DepositedToken.WithdrawalInitiated(msg.sender, to, amount); } // ========= RESTRICTED FUNCTIONS ============== function finalizeEscrowMigration( address account, uint256 escrowedAmount, VestingEntries.VestingEntry[] calldata vestingEntries ) external onlyCounterpart { IRewardEscrowV2 rewardEscrow = rewardEscrowV2(); // First, mint the escrowed SNX that are being migrated synthetix().mintSecondary(address(rewardEscrow), escrowedAmount); rewardEscrow.importVestingEntries(account, escrowedAmount, vestingEntries); emit ImportedVestingEntries(account, escrowedAmount, vestingEntries); } // invoked by Messenger on L2 function finalizeDeposit(address to, uint256 amount) external onlyCounterpart { // now tell Synthetix to mint these tokens, deposited in L1, into the specified account for L2 synthetix().mintSecondary(to, amount); emit iOVM_L2DepositedToken.DepositFinalized(to, amount); } // invoked by Messenger on L2 function finalizeRewardDeposit(address from, uint256 amount) external onlyCounterpart { // now tell Synthetix to mint these tokens, deposited in L1, into reward escrow on L2 synthetix().mintSecondaryRewards(amount); emit RewardDepositFinalized(from, amount); } // invoked by Messenger on L2 function finalizeFeePeriodClose(uint256 snxBackedAmount, uint256 totalDebtShares) external onlyCounterpart { // now tell Synthetix to mint these tokens, deposited in L1, into reward escrow on L2 feePool().closeSecondary(snxBackedAmount, totalDebtShares); emit FeePeriodCloseFinalized(snxBackedAmount, totalDebtShares); } // ========== EVENTS ========== event ImportedVestingEntries( address indexed account, uint256 escrowedAmount, VestingEntries.VestingEntry[] vestingEntries ); event RewardDepositFinalized(address from, uint256 amount); event FeePeriodCloseFinalized(uint snxBackedAmount, uint totalDebtShares); }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"DepositFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"snxBackedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalDebtShares","type":"uint256"}],"name":"FeePeriodCloseFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FinalizeSynthTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"escrowedAmount","type":"uint256"},{"components":[{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint256","name":"escrowAmount","type":"uint256"}],"indexed":false,"internalType":"struct VestingEntries.VestingEntry[]","name":"vestingEntries","type":"tuple[]"}],"name":"ImportedVestingEntries","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"InitiateSynthTransfer","type":"event"},{"anonymous":false,"inputs":[],"name":"InitiationResumed","type":"event"},{"anonymous":false,"inputs":[],"name":"InitiationSuspended","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardDepositFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"WithdrawalInitiated","type":"event"},{"constant":true,"inputs":[],"name":"CONTRACT_NAME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"finalizeDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"escrowedAmount","type":"uint256"},{"components":[{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint256","name":"escrowAmount","type":"uint256"}],"internalType":"struct VestingEntries.VestingEntry[]","name":"vestingEntries","type":"tuple[]"}],"name":"finalizeEscrowMigration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"snxBackedAmount","type":"uint256"},{"internalType":"uint256","name":"totalDebtShares","type":"uint256"}],"name":"finalizeFeePeriodClose","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"finalizeRewardDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"finalizeSynthTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"initiateSynthTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initiationActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"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":"resumeInitiation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"suspendInitiation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"synthTransferReceived","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"synthTransferSent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162002dd138038062002dd183398101604081905262000034916200010d565b81818080836001600160a01b0381166200006b5760405162461bcd60e51b81526004016200006290620001c9565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620000b8918490620001a3565b60405180910390a150600280546001600160a01b0319166001600160a01b039290921691909117905550506004805460ff191660011790555062000224915050565b805162000107816200020a565b92915050565b600080604083850312156200012157600080fd5b60006200012f8585620000fa565b92505060206200014285828601620000fa565b9150509250929050565b6200015781620001f6565b82525050565b6200015781620001e4565b600062000177601983620001db565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b60408101620001b382856200014c565b620001c260208301846200015d565b9392505050565b60208082528101620001078162000168565b90815260200190565b60006001600160a01b03821662000107565b6000620001078260006200010782620001e4565b6200021581620001e4565b81146200022157600080fd5b50565b612b9d80620002346000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c8063614d08f8116100b85780638d6e9a5b1161007c5780638d6e9a5b1461024a5780638da5cb5b1461025d578063a616cdfb14610265578063a6492fe214610278578063bb91f6a31461028b578063f97824fe1461029357610142565b8063614d08f814610215578063698a26b21461021d578063741853601461022557806379ba50971461022d578063899ffef41461023557610142565b80632af64bd31161010a5780632af64bd3146101b55780632e1a7d4d146101bd5780633872dda3146101d05780634873966f146101d857806353a47bb7146101eb5780635aba32ae1461020057610142565b806304f3bcec14610147578063100be6d4146101655780631627540c1461017a578063205c28781461018f57806325aae563146101a2575b600080fd5b61014f6102a6565b60405161015c91906128f5565b60405180910390f35b61016d6102b5565b60405161015c919061281f565b61018d610188366004611ec2565b6102be565b005b61018d61019d366004611f06565b61031c565b61018d6101b0366004612100565b610332565b61016d6103de565b61018d6101cb3660046120c4565b6104f6565b61018d61050b565b61018d6101e6366004612077565b610573565b6101f36107fe565b60405161015c9190612747565b61020861080d565b60405161015c919061282d565b610208610824565b61018d610840565b61018d6108a3565b61018d6109f5565b61023d610a91565b60405161015c919061280e565b61018d610258366004611f06565b610b0d565b6101f3610bc1565b61018d610273366004611f06565b610bd0565b61018d610286366004612077565b610c6e565b610208610d59565b61018d6102a1366004611f40565b610d6b565b6002546001600160a01b031681565b60045460ff1681565b6102c6610e96565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610311908390612747565b60405180910390a150565b610324610ec2565b61032e8282610ee4565b5050565b61033a611105565b6103426111e1565b6001600160a01b03166373941b9683836040518363ffffffff1660e01b815260040161036f9291906128ac565b600060405180830381600087803b15801561038957600080fd5b505af115801561039d573d6000803e3d6000fd5b505050507f64691ff866d6248d6d89e8c1b6c92df685ddf8224377dc6f1e928ef732e55ace82826040516103d29291906128ac565b60405180910390a15050565b600060606103ea610a91565b905060005b81518110156104ec57600082828151811061040657fe5b602090810291909101810151600081815260039092526040918290205460025492516321f8a72160e01b81529193506001600160a01b039081169216906321f8a7219061045790859060040161282d565b60206040518083038186803b15801561046f57600080fd5b505afa158015610483573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104a79190810190611ee8565b6001600160a01b03161415806104d257506000818152600360205260409020546001600160a01b0316155b156104e357600093505050506104f3565b506001016103ef565b5060019150505b90565b6104fe610ec2565b6105083382610ee4565b50565b610513610e96565b60045460ff1661053e5760405162461bcd60e51b815260040161053590612944565b60405180910390fd5b6004805460ff191690556040517f43e00f2c8f8651a29db34d34fb689573423f8aaae8f9d32e3e871b4c35c6254690600090a1565b61057b610ec2565b6001600160a01b0382166105a15760405162461bcd60e51b815260040161053590612974565b60006105ac846111f6565b116105c95760405162461bcd60e51b8152600401610535906129a4565b6105d16112de565b6001600160a01b03166342a28e21846040518263ffffffff1660e01b81526004016105fc919061282d565b60006040518083038186803b15801561061457600080fd5b505afa158015610628573d6000803e3d6000fd5b5050505061063e6314d95b9d60e21b84836112f8565b600061064861144d565b6001600160a01b031663c81ff8fa8533856040518463ffffffff1660e01b815260040161067793929190612849565b602060405180830381600087803b15801561069157600080fd5b505af11580156106a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106c99190810190612059565b905080156106e95760405162461bcd60e51b8152600401610535906129d4565b606063a6492fe260e01b85858560405160240161070893929190612871565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050610744611461565b6001600160a01b0316633dbb202b61075a61147c565b836107656003611486565b6040518463ffffffff1660e01b815260040161078393929190612799565b600060405180830381600087803b15801561079d57600080fd5b505af11580156107b1573d6000803e3d6000fd5b50505050836001600160a01b0316857f8437572793cb04c0a02524a185d39f9b72a4284bd2e69151b0ca0cf254b2cb0b856040516107ef919061282d565b60405180910390a35050505050565b6001546001600160a01b031681565b600061081f6314d95b9d60e21b6114d6565b905090565b7453796e746865746978427269646765546f4261736560581b90565b610848610e96565b60045460ff161561086b5760405162461bcd60e51b815260040161053590612914565b6004805460ff191660011790556040517f7c88488c18e2ff121a34a4a2a44990557a5b76ab1ceb6bd95ebe7d419c7575f490600090a1565b60606108ad610a91565b905060005b815181101561032e5760008282815181106108c957fe5b602002602001015190506000600260009054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200161090b919061273c565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109379291906128d5565b60206040518083038186803b15801561094f57600080fd5b505afa158015610963573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109879190810190611ee8565b6000838152600360205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906109e3908490849061283b565b60405180910390a150506001016108b2565b6001546001600160a01b03163314610a1f5760405162461bcd60e51b815260040161053590612924565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c92610a62926001600160a01b039182169291169061277e565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b606080610a9c6117ad565b60408051600180825281830190925291925060609190602080830190803883390190505090507f626173653a53796e746865746978427269646765546f4f7074696d69736d000081600081518110610af057fe5b602002602001018181525050610b068282611916565b9250505090565b610b15611105565b610b1d6119d2565b6001600160a01b031663666ed4f183836040518363ffffffff1660e01b8152600401610b4a9291906127c8565b600060405180830381600087803b158015610b6457600080fd5b505af1158015610b78573d6000803e3d6000fd5b50505050816001600160a01b03167f162eb12ad2bd8b6ca7960f162208414ab3bc2da9f37953788ffd8cf850c3492b82604051610bb5919061282d565b60405180910390a25050565b6000546001600160a01b031681565b610bd8611105565b610be06119d2565b6001600160a01b031663d8a1f76f826040518263ffffffff1660e01b8152600401610c0b919061282d565b600060405180830381600087803b158015610c2557600080fd5b505af1158015610c39573d6000803e3d6000fd5b505050507f3b30e867826d81d6591924b1675cfdcac994f0199eed66250d8c834b3b0ed21682826040516103d29291906127c8565b610c76611105565b610c88632932b1bb60e11b84836112f8565b610c9061144d565b6001600160a01b031663890235d48484846040518463ffffffff1660e01b8152600401610cbf93929190612871565b602060405180830381600087803b158015610cd957600080fd5b505af1158015610ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d119190810190612059565b50816001600160a01b0316837f81b100a611d2b249e23d093c64f09470928821e123a7cff2a033eb24c85b797983604051610d4c919061282d565b60405180910390a3505050565b600061081f632932b1bb60e11b6114d6565b610d73611105565b6000610d7d6119e9565b9050610d876119d2565b6001600160a01b031663666ed4f182866040518363ffffffff1660e01b8152600401610db49291906127c8565b600060405180830381600087803b158015610dce57600080fd5b505af1158015610de2573d6000803e3d6000fd5b505060405163cd7b43dd60e01b81526001600160a01b038416925063cd7b43dd9150610e189088908890889088906004016127d6565b600060405180830381600087803b158015610e3257600080fd5b505af1158015610e46573d6000803e3d6000fd5b50505050846001600160a01b03167f7538b9bce825b4555048bb2f80c04ee79b5ffc422f39b959994a27c21c32c8d1858585604051610e8793929190612a04565b60405180910390a25050505050565b6000546001600160a01b03163314610ec05760405162461bcd60e51b815260040161053590612984565b565b60045460ff16610ec05760405162461bcd60e51b815260040161053590612954565b80610eed6119d2565b6001600160a01b0316636ac0bf9c336040518263ffffffff1660e01b8152600401610f189190612755565b60206040518083038186803b158015610f3057600080fd5b505afa158015610f44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f6891908101906120e2565b1015610f865760405162461bcd60e51b8152600401610535906129f4565b610f8e6119d2565b6001600160a01b031663edef719a33836040518363ffffffff1660e01b8152600401610fbb929190612763565b600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b50506040516000925060609150637a7bda0d60e11b9061100f90869086906024016127c8565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905061104b611461565b6001600160a01b0316633dbb202b611061611a05565b8361106c6003611486565b6040518463ffffffff1660e01b815260040161108a93929190612799565b600060405180830381600087803b1580156110a457600080fd5b505af11580156110b8573d6000803e3d6000fd5b50505050336001600160a01b03167fbb2689ff876f7ef453cf8865dde5ab10349d222e2e1383c5152fbdb083f02da285856040516110f79291906127c8565b60405180910390a250505050565b600061110f611461565b9050336001600160a01b038216146111395760405162461bcd60e51b8152600401610535906129b4565b61114161147c565b6001600160a01b0316816001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561118357600080fd5b505afa158015611197573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506111bb9190810190611ee8565b6001600160a01b0316146105085760405162461bcd60e51b8152600401610535906129c4565b600061081f66119959541bdbdb60ca1b611a2c565b6000611200611a89565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b7f63726f7373436861696e53796e74685472616e73666572456e61626c65640000856040516020016112539291906126bf565b604051602081830303815290604052805190602001206040518363ffffffff1660e01b81526004016112869291906128ac565b60206040518083038186803b15801561129e57600080fd5b505afa1580156112b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112d691908101906120e2565b90505b919050565b600061081f6b53797374656d53746174757360a01b611a2c565b60006c29bcb73a342a3930b739b332b960991b848460405160200161131f939291906126e5565b6040516020818303038152906040528051906020012090506000611341611a89565b6001600160a01b03166323257c2b611357610824565b846040518363ffffffff1660e01b81526004016113759291906128ac565b60206040518083038186803b15801561138d57600080fd5b505afa1580156113a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113c591908101906120e2565b90506113cf611a89565b6001600160a01b0316631d5b277f6113e5610824565b846113f6858863ffffffff611aa616565b6040518463ffffffff1660e01b8152600401611414939291906128ba565b600060405180830381600087803b15801561142e57600080fd5b505af1158015611442573d6000803e3d6000fd5b505050505050505050565b600061081f6524b9b9bab2b960d11b611a2c565b600061081f6c32bc3a1d26b2b9b9b2b733b2b960991b611a2c565b600061081f611a05565b6000611490611a89565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b6114b985611ad4565b6040518363ffffffff1660e01b81526004016112869291906128ac565b600060606114e261144d565b6001600160a01b03166372cb051f6040518163ffffffff1660e01b815260040160006040518083038186803b15801561151a57600080fd5b505afa15801561152e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115569190810190611fa8565b905060606000611564611c4f565b6001600160a01b031663c8e5bbd5846040518263ffffffff1660e01b815260040161158f919061280e565b60006040518083038186803b1580156115a757600080fd5b505afa1580156115bb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115e39190810190612012565b9150915080156116055760405162461bcd60e51b815260040161053590612964565b60608351604051908082528060200260200182016040528015611632578160200160208202803883390190505b50905060005b84518110156116ae576c29bcb73a342a3930b739b332b960991b8786838151811061165f57fe5b6020026020010151604051602001611679939291906126e5565b6040516020818303038152906040528051906020012082828151811061169b57fe5b6020908102919091010152600101611638565b5060606116b9611a89565b6001600160a01b031663b67fa7ed6116cf610824565b846040518363ffffffff1660e01b81526004016116ed92919061288c565b60006040518083038186803b15801561170557600080fd5b505afa158015611719573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117419190810190611fdd565b905060005b85518110156117a25761179861178b86838151811061176157fe5b602002602001015184848151811061177557fe5b6020026020010151611c6a90919063ffffffff16565b889063ffffffff611aa616565b9650600101611746565b505050505050919050565b6060806117b8611c7f565b60408051600880825261012082019092529192506060919060208201610100803883390190505090506c32bc3a1d26b2b9b9b2b733b2b960991b816000815181106117ff57fe5b602002602001018181525050680a6f2dce8d0cae8d2f60bb1b8160018151811061182557fe5b6020026020010181815250506d2932bbb0b93222b9b1b937bbab1960911b8160028151811061185057fe5b6020026020010181815250506524b9b9bab2b960d11b8160038151811061187357fe5b60200260200101818152505066119959541bdbdb60ca1b8160048151811061189757fe5b6020026020010181815250506e466c657869626c6553746f7261676560881b816005815181106118c357fe5b6020026020010181815250506c45786368616e6765526174657360981b816006815181106118ed57fe5b6020026020010181815250506b53797374656d53746174757360a01b81600781518110610af057fe5b60608151835101604051908082528060200260200182016040528015611946578160200160208202803883390190505b50905060005b83518110156119885783818151811061196157fe5b602002602001015182828151811061197557fe5b602090810291909101015260010161194c565b5060005b82518110156119cb578281815181106119a157fe5b60200260200101518282865101815181106119b857fe5b602090810291909101015260010161198c565b5092915050565b600061081f680a6f2dce8d0cae8d2f60bb1b611a2c565b600061081f6d2932bbb0b93222b9b1b937bbab1960911b611a2c565b600061081f7f626173653a53796e746865746978427269646765546f4f7074696d69736d00005b60008181526003602090815260408083205490516001600160a01b039091169182151591611a5c9186910161271c565b604051602081830303815290604052906119cb5760405162461bcd60e51b81526004016105359190612903565b600061081f6e466c657869626c6553746f7261676560881b611a2c565b600082820183811015611acb5760405162461bcd60e51b815260040161053590612934565b90505b92915050565b600080826005811115611ae357fe5b1415611b1057507f63726f7373446f6d61696e4465706f7369744761734c696d69740000000000006112d9565b6001826005811115611b1e57fe5b1415611b4b57507f63726f7373446f6d61696e457363726f774761734c696d6974000000000000006112d9565b6002826005811115611b5957fe5b1415611b8657507f63726f7373446f6d61696e5265776172644761734c696d6974000000000000006112d9565b6003826005811115611b9457fe5b1415611bc157507f63726f7373446f6d61696e5769746864726177616c4761734c696d69740000006112d9565b6005826005811115611bcf57fe5b1415611bfc57507f63726f7373446f6d61696e52656c61794761734c696d697400000000000000006112d9565b6004826005811115611c0a57fe5b1415611c3757507f63726f7373446f6d61696e436c6f73654761734c696d697400000000000000006112d9565b60405162461bcd60e51b8152600401610535906129e4565b600061081f6c45786368616e6765526174657360981b611a2c565b6000611acb8383670de0b6b3a7640000611cd0565b604080516001808252818301909252606091602080830190803883390190505090506e466c657869626c6553746f7261676560881b81600081518110611cc157fe5b60200260200101818152505090565b600080600a8304611ce7868663ffffffff611d0e16565b81611cee57fe5b0490506005600a820610611d0057600a015b600a900490505b9392505050565b600082611d1d57506000611ace565b82820282848281611d2a57fe5b0414611acb5760405162461bcd60e51b815260040161053590612994565b8035611ace81612b2b565b8051611ace81612b2b565b600082601f830112611d6f57600080fd5b8151611d82611d7d82612a55565b612a2e565b91508181835260208401935060208101905083856020840282011115611da757600080fd5b60005b83811015611dd35781611dbd8882611eac565b8452506020928301929190910190600101611daa565b5050505092915050565b60008083601f840112611def57600080fd5b50813567ffffffffffffffff811115611e0757600080fd5b602083019150836040820283011115611e1f57600080fd5b9250929050565b600082601f830112611e3757600080fd5b8151611e45611d7d82612a55565b91508181835260208401935060208101905083856020840282011115611e6a57600080fd5b60005b83811015611dd35781611e808882611eac565b8452506020928301929190910190600101611e6d565b8051611ace81612b3f565b8035611ace81612b48565b8051611ace81612b48565b8035611ace81612b51565b600060208284031215611ed457600080fd5b6000611ee08484611d48565b949350505050565b600060208284031215611efa57600080fd5b6000611ee08484611d53565b60008060408385031215611f1957600080fd5b6000611f258585611d48565b9250506020611f3685828601611ea1565b9150509250929050565b60008060008060608587031215611f5657600080fd5b6000611f628787611d48565b9450506020611f7387828801611ea1565b935050604085013567ffffffffffffffff811115611f9057600080fd5b611f9c87828801611ddd565b95989497509550505050565b600060208284031215611fba57600080fd5b815167ffffffffffffffff811115611fd157600080fd5b611ee084828501611d5e565b600060208284031215611fef57600080fd5b815167ffffffffffffffff81111561200657600080fd5b611ee084828501611e26565b6000806040838503121561202557600080fd5b825167ffffffffffffffff81111561203c57600080fd5b61204885828601611e26565b9250506020611f3685828601611e96565b60006020828403121561206b57600080fd5b6000611ee08484611e96565b60008060006060848603121561208c57600080fd5b60006120988686611ea1565b93505060206120a986828701611d48565b92505060406120ba86828701611ea1565b9150509250925092565b6000602082840312156120d657600080fd5b6000611ee08484611ea1565b6000602082840312156120f457600080fd5b6000611ee08484611eac565b6000806040838503121561211357600080fd5b6000611f258585611ea1565b600061212b838361220e565b505060200190565b600061213f8383612674565b505060400190565b61215081612ae3565b82525050565b61215081612ab1565b600061216a82612a7c565b6121748185612a86565b935061217f83612a76565b8060005b838110156121ad578151612197888261211f565b97506121a283612a76565b925050600101612183565b509495945050505050565b60006121c48385612a86565b93506121cf826104f3565b8060005b858110156121ad576121e58284612a8f565b6121ef8882612133565b97506121fa83612a80565b9250506001016121d3565b61215081612abc565b612150816104f3565b612150612223826104f3565b6104f3565b600061223382612a7c565b61223d8185612a86565b935061224d818560208601612af5565b61225681612b21565b9093019392505050565b61215081612aea565b6000612276601883612a86565b7f496e6974696174696f6e206e6f742073757370656e6465640000000000000000815260200192915050565b60006122af603583612a86565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527402063616e20616363657074206f776e65727368697605c1b602082015260400192915050565b6000612306601b83612a86565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061233f601483612a86565b73125b9a5d1a585d1a5bdb881cdd5cdc195b99195960621b815260200192915050565b600061236f6011836112d9565b70026b4b9b9b4b7339030b2323932b9b99d1607d1b815260110192915050565b600061239c601683612a86565b75125b9a5d1a585d1a5bdb8819195858dd1a5d985d195960521b815260200192915050565b60006123ce601183612a86565b7014985d195cc8185c99481a5b9d985b1a59607a1b815260200192915050565b60006123fb601b83612a86565b7f43616e6e6f742073656e6420746f207a65726f20616464726573730000000000815260200192915050565b6000612434602f83612a86565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681526e37b936903a3434b99030b1ba34b7b760891b602082015260400192915050565b6000612485602183612a86565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b60006124c8602a83612a86565b7f53796e7468206e6f7420656e61626c656420666f722063726f7373206368616981526937103a3930b739b332b960b11b602082015260400192915050565b6000612514601e83612a86565b7f4f6e6c79207468652072656c617965722063616e2063616c6c20746869730000815260200192915050565b600061254d6019836112d9565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000612586602483612a86565b7f4f6e6c79206120636f756e74657270617274206272696467652063616e20696e815263766f6b6560e01b602082015260400192915050565b60006125cc602883612a86565b7f43616e6e6f7420696e6974696174652069662073796e74682072617465206973815267081a5b9d985b1a5960c21b602082015260400192915050565b6000612616601683612a86565b75556e6b6e6f776e20676173206c696d6974207479706560501b815260200192915050565b6000612648601b83612a86565b7f4e6f7420656e6f756768207472616e7366657261626c6520534e580000000000815260200192915050565b604082016126828280612aa2565b61268c84826126b6565b5061269a6020830183612a93565b6126a7602085018261220e565b50505050565b61215081612acd565b61215081612ad6565b60006126cb8285612217565b6020820191506126db8284612217565b5060200192915050565b60006126f18286612217565b6020820191506127018285612217565b6020820191506127118284612217565b506020019392505050565b600061272782612362565b91506127338284612217565b50602001919050565b600061272782612540565b60208101611ace8284612156565b60208101611ace8284612147565b604081016127718285612147565b611d07602083018461220e565b6040810161278c8285612156565b611d076020830184612156565b606081016127a78286612156565b81810360208301526127b98185612228565b9050611ee060408301846126ad565b604081016127718285612156565b606081016127e48287612156565b6127f1602083018661220e565b81810360408301526128048184866121b8565b9695505050505050565b60208082528101611acb818461215f565b60208101611ace8284612205565b60208101611ace828461220e565b6040810161278c828561220e565b60608101612857828661220e565b6128646020830185612147565b611ee0604083018461220e565b6060810161287f828661220e565b6128646020830185612156565b6040810161289a828561220e565b8181036020830152611ee0818461215f565b60408101612771828561220e565b606081016128c8828661220e565b612864602083018561220e565b604081016128e3828561220e565b8181036020830152611ee08184612228565b60208101611ace8284612260565b60208082528101611acb8184612228565b602080825281016112d681612269565b602080825281016112d6816122a2565b602080825281016112d6816122f9565b602080825281016112d681612332565b602080825281016112d68161238f565b602080825281016112d6816123c1565b602080825281016112d6816123ee565b602080825281016112d681612427565b602080825281016112d681612478565b602080825281016112d6816124bb565b602080825281016112d681612507565b602080825281016112d681612579565b602080825281016112d6816125bf565b602080825281016112d681612609565b602080825281016112d68161263b565b60408101612a12828661220e565b8181036020830152612a258184866121b8565b95945050505050565b60405181810167ffffffffffffffff81118282101715612a4d57600080fd5b604052919050565b600067ffffffffffffffff821115612a6c57600080fd5b5060209081020190565b60200190565b5190565b60400190565b90815260200190565b5090565b6000611acb6020840184611ea1565b6000611acb6020840184611eb7565b60006112d682612ac1565b151590565b6001600160a01b031690565b63ffffffff1690565b67ffffffffffffffff1690565b60006112d6825b60006112d682612ab1565b60005b83811015612b10578181015183820152602001612af8565b838111156126a75750506000910152565b601f01601f191690565b612b3481612ab1565b811461050857600080fd5b612b3481612abc565b612b34816104f3565b612b3481612ad656fea365627a7a72315820f2bf16b9091e75361a5e3dadf7290baf59d8ae988954679a538c3f78e5d389126c6578706572696d656e74616cf564736f6c63430005100040000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe0000000000000000000000001cb059b7e74fd21665968c908806143e744d5f30
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101425760003560e01c8063614d08f8116100b85780638d6e9a5b1161007c5780638d6e9a5b1461024a5780638da5cb5b1461025d578063a616cdfb14610265578063a6492fe214610278578063bb91f6a31461028b578063f97824fe1461029357610142565b8063614d08f814610215578063698a26b21461021d578063741853601461022557806379ba50971461022d578063899ffef41461023557610142565b80632af64bd31161010a5780632af64bd3146101b55780632e1a7d4d146101bd5780633872dda3146101d05780634873966f146101d857806353a47bb7146101eb5780635aba32ae1461020057610142565b806304f3bcec14610147578063100be6d4146101655780631627540c1461017a578063205c28781461018f57806325aae563146101a2575b600080fd5b61014f6102a6565b60405161015c91906128f5565b60405180910390f35b61016d6102b5565b60405161015c919061281f565b61018d610188366004611ec2565b6102be565b005b61018d61019d366004611f06565b61031c565b61018d6101b0366004612100565b610332565b61016d6103de565b61018d6101cb3660046120c4565b6104f6565b61018d61050b565b61018d6101e6366004612077565b610573565b6101f36107fe565b60405161015c9190612747565b61020861080d565b60405161015c919061282d565b610208610824565b61018d610840565b61018d6108a3565b61018d6109f5565b61023d610a91565b60405161015c919061280e565b61018d610258366004611f06565b610b0d565b6101f3610bc1565b61018d610273366004611f06565b610bd0565b61018d610286366004612077565b610c6e565b610208610d59565b61018d6102a1366004611f40565b610d6b565b6002546001600160a01b031681565b60045460ff1681565b6102c6610e96565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610311908390612747565b60405180910390a150565b610324610ec2565b61032e8282610ee4565b5050565b61033a611105565b6103426111e1565b6001600160a01b03166373941b9683836040518363ffffffff1660e01b815260040161036f9291906128ac565b600060405180830381600087803b15801561038957600080fd5b505af115801561039d573d6000803e3d6000fd5b505050507f64691ff866d6248d6d89e8c1b6c92df685ddf8224377dc6f1e928ef732e55ace82826040516103d29291906128ac565b60405180910390a15050565b600060606103ea610a91565b905060005b81518110156104ec57600082828151811061040657fe5b602090810291909101810151600081815260039092526040918290205460025492516321f8a72160e01b81529193506001600160a01b039081169216906321f8a7219061045790859060040161282d565b60206040518083038186803b15801561046f57600080fd5b505afa158015610483573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104a79190810190611ee8565b6001600160a01b03161415806104d257506000818152600360205260409020546001600160a01b0316155b156104e357600093505050506104f3565b506001016103ef565b5060019150505b90565b6104fe610ec2565b6105083382610ee4565b50565b610513610e96565b60045460ff1661053e5760405162461bcd60e51b815260040161053590612944565b60405180910390fd5b6004805460ff191690556040517f43e00f2c8f8651a29db34d34fb689573423f8aaae8f9d32e3e871b4c35c6254690600090a1565b61057b610ec2565b6001600160a01b0382166105a15760405162461bcd60e51b815260040161053590612974565b60006105ac846111f6565b116105c95760405162461bcd60e51b8152600401610535906129a4565b6105d16112de565b6001600160a01b03166342a28e21846040518263ffffffff1660e01b81526004016105fc919061282d565b60006040518083038186803b15801561061457600080fd5b505afa158015610628573d6000803e3d6000fd5b5050505061063e6314d95b9d60e21b84836112f8565b600061064861144d565b6001600160a01b031663c81ff8fa8533856040518463ffffffff1660e01b815260040161067793929190612849565b602060405180830381600087803b15801561069157600080fd5b505af11580156106a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106c99190810190612059565b905080156106e95760405162461bcd60e51b8152600401610535906129d4565b606063a6492fe260e01b85858560405160240161070893929190612871565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050610744611461565b6001600160a01b0316633dbb202b61075a61147c565b836107656003611486565b6040518463ffffffff1660e01b815260040161078393929190612799565b600060405180830381600087803b15801561079d57600080fd5b505af11580156107b1573d6000803e3d6000fd5b50505050836001600160a01b0316857f8437572793cb04c0a02524a185d39f9b72a4284bd2e69151b0ca0cf254b2cb0b856040516107ef919061282d565b60405180910390a35050505050565b6001546001600160a01b031681565b600061081f6314d95b9d60e21b6114d6565b905090565b7453796e746865746978427269646765546f4261736560581b90565b610848610e96565b60045460ff161561086b5760405162461bcd60e51b815260040161053590612914565b6004805460ff191660011790556040517f7c88488c18e2ff121a34a4a2a44990557a5b76ab1ceb6bd95ebe7d419c7575f490600090a1565b60606108ad610a91565b905060005b815181101561032e5760008282815181106108c957fe5b602002602001015190506000600260009054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200161090b919061273c565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109379291906128d5565b60206040518083038186803b15801561094f57600080fd5b505afa158015610963573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109879190810190611ee8565b6000838152600360205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906109e3908490849061283b565b60405180910390a150506001016108b2565b6001546001600160a01b03163314610a1f5760405162461bcd60e51b815260040161053590612924565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c92610a62926001600160a01b039182169291169061277e565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b606080610a9c6117ad565b60408051600180825281830190925291925060609190602080830190803883390190505090507f626173653a53796e746865746978427269646765546f4f7074696d69736d000081600081518110610af057fe5b602002602001018181525050610b068282611916565b9250505090565b610b15611105565b610b1d6119d2565b6001600160a01b031663666ed4f183836040518363ffffffff1660e01b8152600401610b4a9291906127c8565b600060405180830381600087803b158015610b6457600080fd5b505af1158015610b78573d6000803e3d6000fd5b50505050816001600160a01b03167f162eb12ad2bd8b6ca7960f162208414ab3bc2da9f37953788ffd8cf850c3492b82604051610bb5919061282d565b60405180910390a25050565b6000546001600160a01b031681565b610bd8611105565b610be06119d2565b6001600160a01b031663d8a1f76f826040518263ffffffff1660e01b8152600401610c0b919061282d565b600060405180830381600087803b158015610c2557600080fd5b505af1158015610c39573d6000803e3d6000fd5b505050507f3b30e867826d81d6591924b1675cfdcac994f0199eed66250d8c834b3b0ed21682826040516103d29291906127c8565b610c76611105565b610c88632932b1bb60e11b84836112f8565b610c9061144d565b6001600160a01b031663890235d48484846040518463ffffffff1660e01b8152600401610cbf93929190612871565b602060405180830381600087803b158015610cd957600080fd5b505af1158015610ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d119190810190612059565b50816001600160a01b0316837f81b100a611d2b249e23d093c64f09470928821e123a7cff2a033eb24c85b797983604051610d4c919061282d565b60405180910390a3505050565b600061081f632932b1bb60e11b6114d6565b610d73611105565b6000610d7d6119e9565b9050610d876119d2565b6001600160a01b031663666ed4f182866040518363ffffffff1660e01b8152600401610db49291906127c8565b600060405180830381600087803b158015610dce57600080fd5b505af1158015610de2573d6000803e3d6000fd5b505060405163cd7b43dd60e01b81526001600160a01b038416925063cd7b43dd9150610e189088908890889088906004016127d6565b600060405180830381600087803b158015610e3257600080fd5b505af1158015610e46573d6000803e3d6000fd5b50505050846001600160a01b03167f7538b9bce825b4555048bb2f80c04ee79b5ffc422f39b959994a27c21c32c8d1858585604051610e8793929190612a04565b60405180910390a25050505050565b6000546001600160a01b03163314610ec05760405162461bcd60e51b815260040161053590612984565b565b60045460ff16610ec05760405162461bcd60e51b815260040161053590612954565b80610eed6119d2565b6001600160a01b0316636ac0bf9c336040518263ffffffff1660e01b8152600401610f189190612755565b60206040518083038186803b158015610f3057600080fd5b505afa158015610f44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f6891908101906120e2565b1015610f865760405162461bcd60e51b8152600401610535906129f4565b610f8e6119d2565b6001600160a01b031663edef719a33836040518363ffffffff1660e01b8152600401610fbb929190612763565b600060405180830381600087803b158015610fd557600080fd5b505af1158015610fe9573d6000803e3d6000fd5b50506040516000925060609150637a7bda0d60e11b9061100f90869086906024016127c8565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905061104b611461565b6001600160a01b0316633dbb202b611061611a05565b8361106c6003611486565b6040518463ffffffff1660e01b815260040161108a93929190612799565b600060405180830381600087803b1580156110a457600080fd5b505af11580156110b8573d6000803e3d6000fd5b50505050336001600160a01b03167fbb2689ff876f7ef453cf8865dde5ab10349d222e2e1383c5152fbdb083f02da285856040516110f79291906127c8565b60405180910390a250505050565b600061110f611461565b9050336001600160a01b038216146111395760405162461bcd60e51b8152600401610535906129b4565b61114161147c565b6001600160a01b0316816001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561118357600080fd5b505afa158015611197573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506111bb9190810190611ee8565b6001600160a01b0316146105085760405162461bcd60e51b8152600401610535906129c4565b600061081f66119959541bdbdb60ca1b611a2c565b6000611200611a89565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b7f63726f7373436861696e53796e74685472616e73666572456e61626c65640000856040516020016112539291906126bf565b604051602081830303815290604052805190602001206040518363ffffffff1660e01b81526004016112869291906128ac565b60206040518083038186803b15801561129e57600080fd5b505afa1580156112b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112d691908101906120e2565b90505b919050565b600061081f6b53797374656d53746174757360a01b611a2c565b60006c29bcb73a342a3930b739b332b960991b848460405160200161131f939291906126e5565b6040516020818303038152906040528051906020012090506000611341611a89565b6001600160a01b03166323257c2b611357610824565b846040518363ffffffff1660e01b81526004016113759291906128ac565b60206040518083038186803b15801561138d57600080fd5b505afa1580156113a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113c591908101906120e2565b90506113cf611a89565b6001600160a01b0316631d5b277f6113e5610824565b846113f6858863ffffffff611aa616565b6040518463ffffffff1660e01b8152600401611414939291906128ba565b600060405180830381600087803b15801561142e57600080fd5b505af1158015611442573d6000803e3d6000fd5b505050505050505050565b600061081f6524b9b9bab2b960d11b611a2c565b600061081f6c32bc3a1d26b2b9b9b2b733b2b960991b611a2c565b600061081f611a05565b6000611490611a89565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b6114b985611ad4565b6040518363ffffffff1660e01b81526004016112869291906128ac565b600060606114e261144d565b6001600160a01b03166372cb051f6040518163ffffffff1660e01b815260040160006040518083038186803b15801561151a57600080fd5b505afa15801561152e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115569190810190611fa8565b905060606000611564611c4f565b6001600160a01b031663c8e5bbd5846040518263ffffffff1660e01b815260040161158f919061280e565b60006040518083038186803b1580156115a757600080fd5b505afa1580156115bb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115e39190810190612012565b9150915080156116055760405162461bcd60e51b815260040161053590612964565b60608351604051908082528060200260200182016040528015611632578160200160208202803883390190505b50905060005b84518110156116ae576c29bcb73a342a3930b739b332b960991b8786838151811061165f57fe5b6020026020010151604051602001611679939291906126e5565b6040516020818303038152906040528051906020012082828151811061169b57fe5b6020908102919091010152600101611638565b5060606116b9611a89565b6001600160a01b031663b67fa7ed6116cf610824565b846040518363ffffffff1660e01b81526004016116ed92919061288c565b60006040518083038186803b15801561170557600080fd5b505afa158015611719573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117419190810190611fdd565b905060005b85518110156117a25761179861178b86838151811061176157fe5b602002602001015184848151811061177557fe5b6020026020010151611c6a90919063ffffffff16565b889063ffffffff611aa616565b9650600101611746565b505050505050919050565b6060806117b8611c7f565b60408051600880825261012082019092529192506060919060208201610100803883390190505090506c32bc3a1d26b2b9b9b2b733b2b960991b816000815181106117ff57fe5b602002602001018181525050680a6f2dce8d0cae8d2f60bb1b8160018151811061182557fe5b6020026020010181815250506d2932bbb0b93222b9b1b937bbab1960911b8160028151811061185057fe5b6020026020010181815250506524b9b9bab2b960d11b8160038151811061187357fe5b60200260200101818152505066119959541bdbdb60ca1b8160048151811061189757fe5b6020026020010181815250506e466c657869626c6553746f7261676560881b816005815181106118c357fe5b6020026020010181815250506c45786368616e6765526174657360981b816006815181106118ed57fe5b6020026020010181815250506b53797374656d53746174757360a01b81600781518110610af057fe5b60608151835101604051908082528060200260200182016040528015611946578160200160208202803883390190505b50905060005b83518110156119885783818151811061196157fe5b602002602001015182828151811061197557fe5b602090810291909101015260010161194c565b5060005b82518110156119cb578281815181106119a157fe5b60200260200101518282865101815181106119b857fe5b602090810291909101015260010161198c565b5092915050565b600061081f680a6f2dce8d0cae8d2f60bb1b611a2c565b600061081f6d2932bbb0b93222b9b1b937bbab1960911b611a2c565b600061081f7f626173653a53796e746865746978427269646765546f4f7074696d69736d00005b60008181526003602090815260408083205490516001600160a01b039091169182151591611a5c9186910161271c565b604051602081830303815290604052906119cb5760405162461bcd60e51b81526004016105359190612903565b600061081f6e466c657869626c6553746f7261676560881b611a2c565b600082820183811015611acb5760405162461bcd60e51b815260040161053590612934565b90505b92915050565b600080826005811115611ae357fe5b1415611b1057507f63726f7373446f6d61696e4465706f7369744761734c696d69740000000000006112d9565b6001826005811115611b1e57fe5b1415611b4b57507f63726f7373446f6d61696e457363726f774761734c696d6974000000000000006112d9565b6002826005811115611b5957fe5b1415611b8657507f63726f7373446f6d61696e5265776172644761734c696d6974000000000000006112d9565b6003826005811115611b9457fe5b1415611bc157507f63726f7373446f6d61696e5769746864726177616c4761734c696d69740000006112d9565b6005826005811115611bcf57fe5b1415611bfc57507f63726f7373446f6d61696e52656c61794761734c696d697400000000000000006112d9565b6004826005811115611c0a57fe5b1415611c3757507f63726f7373446f6d61696e436c6f73654761734c696d697400000000000000006112d9565b60405162461bcd60e51b8152600401610535906129e4565b600061081f6c45786368616e6765526174657360981b611a2c565b6000611acb8383670de0b6b3a7640000611cd0565b604080516001808252818301909252606091602080830190803883390190505090506e466c657869626c6553746f7261676560881b81600081518110611cc157fe5b60200260200101818152505090565b600080600a8304611ce7868663ffffffff611d0e16565b81611cee57fe5b0490506005600a820610611d0057600a015b600a900490505b9392505050565b600082611d1d57506000611ace565b82820282848281611d2a57fe5b0414611acb5760405162461bcd60e51b815260040161053590612994565b8035611ace81612b2b565b8051611ace81612b2b565b600082601f830112611d6f57600080fd5b8151611d82611d7d82612a55565b612a2e565b91508181835260208401935060208101905083856020840282011115611da757600080fd5b60005b83811015611dd35781611dbd8882611eac565b8452506020928301929190910190600101611daa565b5050505092915050565b60008083601f840112611def57600080fd5b50813567ffffffffffffffff811115611e0757600080fd5b602083019150836040820283011115611e1f57600080fd5b9250929050565b600082601f830112611e3757600080fd5b8151611e45611d7d82612a55565b91508181835260208401935060208101905083856020840282011115611e6a57600080fd5b60005b83811015611dd35781611e808882611eac565b8452506020928301929190910190600101611e6d565b8051611ace81612b3f565b8035611ace81612b48565b8051611ace81612b48565b8035611ace81612b51565b600060208284031215611ed457600080fd5b6000611ee08484611d48565b949350505050565b600060208284031215611efa57600080fd5b6000611ee08484611d53565b60008060408385031215611f1957600080fd5b6000611f258585611d48565b9250506020611f3685828601611ea1565b9150509250929050565b60008060008060608587031215611f5657600080fd5b6000611f628787611d48565b9450506020611f7387828801611ea1565b935050604085013567ffffffffffffffff811115611f9057600080fd5b611f9c87828801611ddd565b95989497509550505050565b600060208284031215611fba57600080fd5b815167ffffffffffffffff811115611fd157600080fd5b611ee084828501611d5e565b600060208284031215611fef57600080fd5b815167ffffffffffffffff81111561200657600080fd5b611ee084828501611e26565b6000806040838503121561202557600080fd5b825167ffffffffffffffff81111561203c57600080fd5b61204885828601611e26565b9250506020611f3685828601611e96565b60006020828403121561206b57600080fd5b6000611ee08484611e96565b60008060006060848603121561208c57600080fd5b60006120988686611ea1565b93505060206120a986828701611d48565b92505060406120ba86828701611ea1565b9150509250925092565b6000602082840312156120d657600080fd5b6000611ee08484611ea1565b6000602082840312156120f457600080fd5b6000611ee08484611eac565b6000806040838503121561211357600080fd5b6000611f258585611ea1565b600061212b838361220e565b505060200190565b600061213f8383612674565b505060400190565b61215081612ae3565b82525050565b61215081612ab1565b600061216a82612a7c565b6121748185612a86565b935061217f83612a76565b8060005b838110156121ad578151612197888261211f565b97506121a283612a76565b925050600101612183565b509495945050505050565b60006121c48385612a86565b93506121cf826104f3565b8060005b858110156121ad576121e58284612a8f565b6121ef8882612133565b97506121fa83612a80565b9250506001016121d3565b61215081612abc565b612150816104f3565b612150612223826104f3565b6104f3565b600061223382612a7c565b61223d8185612a86565b935061224d818560208601612af5565b61225681612b21565b9093019392505050565b61215081612aea565b6000612276601883612a86565b7f496e6974696174696f6e206e6f742073757370656e6465640000000000000000815260200192915050565b60006122af603583612a86565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527402063616e20616363657074206f776e65727368697605c1b602082015260400192915050565b6000612306601b83612a86565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061233f601483612a86565b73125b9a5d1a585d1a5bdb881cdd5cdc195b99195960621b815260200192915050565b600061236f6011836112d9565b70026b4b9b9b4b7339030b2323932b9b99d1607d1b815260110192915050565b600061239c601683612a86565b75125b9a5d1a585d1a5bdb8819195858dd1a5d985d195960521b815260200192915050565b60006123ce601183612a86565b7014985d195cc8185c99481a5b9d985b1a59607a1b815260200192915050565b60006123fb601b83612a86565b7f43616e6e6f742073656e6420746f207a65726f20616464726573730000000000815260200192915050565b6000612434602f83612a86565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681526e37b936903a3434b99030b1ba34b7b760891b602082015260400192915050565b6000612485602183612a86565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b60006124c8602a83612a86565b7f53796e7468206e6f7420656e61626c656420666f722063726f7373206368616981526937103a3930b739b332b960b11b602082015260400192915050565b6000612514601e83612a86565b7f4f6e6c79207468652072656c617965722063616e2063616c6c20746869730000815260200192915050565b600061254d6019836112d9565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000612586602483612a86565b7f4f6e6c79206120636f756e74657270617274206272696467652063616e20696e815263766f6b6560e01b602082015260400192915050565b60006125cc602883612a86565b7f43616e6e6f7420696e6974696174652069662073796e74682072617465206973815267081a5b9d985b1a5960c21b602082015260400192915050565b6000612616601683612a86565b75556e6b6e6f776e20676173206c696d6974207479706560501b815260200192915050565b6000612648601b83612a86565b7f4e6f7420656e6f756768207472616e7366657261626c6520534e580000000000815260200192915050565b604082016126828280612aa2565b61268c84826126b6565b5061269a6020830183612a93565b6126a7602085018261220e565b50505050565b61215081612acd565b61215081612ad6565b60006126cb8285612217565b6020820191506126db8284612217565b5060200192915050565b60006126f18286612217565b6020820191506127018285612217565b6020820191506127118284612217565b506020019392505050565b600061272782612362565b91506127338284612217565b50602001919050565b600061272782612540565b60208101611ace8284612156565b60208101611ace8284612147565b604081016127718285612147565b611d07602083018461220e565b6040810161278c8285612156565b611d076020830184612156565b606081016127a78286612156565b81810360208301526127b98185612228565b9050611ee060408301846126ad565b604081016127718285612156565b606081016127e48287612156565b6127f1602083018661220e565b81810360408301526128048184866121b8565b9695505050505050565b60208082528101611acb818461215f565b60208101611ace8284612205565b60208101611ace828461220e565b6040810161278c828561220e565b60608101612857828661220e565b6128646020830185612147565b611ee0604083018461220e565b6060810161287f828661220e565b6128646020830185612156565b6040810161289a828561220e565b8181036020830152611ee0818461215f565b60408101612771828561220e565b606081016128c8828661220e565b612864602083018561220e565b604081016128e3828561220e565b8181036020830152611ee08184612228565b60208101611ace8284612260565b60208082528101611acb8184612228565b602080825281016112d681612269565b602080825281016112d6816122a2565b602080825281016112d6816122f9565b602080825281016112d681612332565b602080825281016112d68161238f565b602080825281016112d6816123c1565b602080825281016112d6816123ee565b602080825281016112d681612427565b602080825281016112d681612478565b602080825281016112d6816124bb565b602080825281016112d681612507565b602080825281016112d681612579565b602080825281016112d6816125bf565b602080825281016112d681612609565b602080825281016112d68161263b565b60408101612a12828661220e565b8181036020830152612a258184866121b8565b95945050505050565b60405181810167ffffffffffffffff81118282101715612a4d57600080fd5b604052919050565b600067ffffffffffffffff821115612a6c57600080fd5b5060209081020190565b60200190565b5190565b60400190565b90815260200190565b5090565b6000611acb6020840184611ea1565b6000611acb6020840184611eb7565b60006112d682612ac1565b151590565b6001600160a01b031690565b63ffffffff1690565b67ffffffffffffffff1690565b60006112d6825b60006112d682612ab1565b60005b83811015612b10578181015183820152602001612af8565b838111156126a75750506000910152565b601f01601f191690565b612b3481612ab1565b811461050857600080fd5b612b3481612abc565b612b34816104f3565b612b3481612ad656fea365627a7a72315820f2bf16b9091e75361a5e3dadf7290baf59d8ae988954679a538c3f78e5d389126c6578706572696d656e74616cf564736f6c63430005100040
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe0000000000000000000000001cb059b7e74fd21665968c908806143e744d5f30
-----Decoded View---------------
Arg [0] : _owner (address): 0xDe910777C787903F78C89e7a0bf7F4C435cBB1Fe
Arg [1] : _resolver (address): 0x1Cb059b7e74fD21665968C908806143E744D5F30
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe
Arg [1] : 0000000000000000000000001cb059b7e74fd21665968c908806143e744d5f30
Library Used
SafeDecimalMath : 0x0142f40c25ce1f1177ed131101fa19217396cb88
SystemSettingsLib : 0xd4db55cf39c37beaa3a47f2555d57b4ea2d9ff39
SignedSafeDecimalMath : 0x253914cf059f4c3e277c28060c404acfc38fb6e2
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.