diff --git a/.circleci/config.yml b/.circleci/config.yml index 3c56272501..eaba017f3f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,6 +42,31 @@ jobs: - attach_workspace: at: . - run: npx hardhat compile --optimizer --fail-oversize + job-fork-tests-ovm: + working_directory: ~/repo + docker: + - image: synthetixio/docker-node:16.13-ubuntu + auth: + username: $DOCKERHUB_USERNAME + password: $DOCKERHUB_TOKEN + steps: + - checkout + - attach_workspace: + at: . + - run: + command: npm run fork:ovm + background: true + - cmd-wait-for-port: + port: 8545 + - run: + name: Run integration tests on l2 + command: | + NEW_CONTRACTS=$(node bin.js sips --layer=base --unreleased --with-sources) + if [ -z "$NEW_CONTRACTS" ]; then + npx hardhat test:integration:l2 --use-fork + else + npx hardhat test:integration:l2 --compile --deploy --use-sips --use-fork + fi; job-fork-tests: working_directory: ~/repo docker: @@ -57,15 +82,15 @@ jobs: command: npm run fork:mainnet background: true - cmd-wait-for-port: - port: 8545 + port: 9545 - run: name: Run integration tests on l1 command: | NEW_CONTRACTS=$(node bin.js sips --layer=base --unreleased --with-sources) if [ -z "$NEW_CONTRACTS" ]; then - npx hardhat test:integration:l1 --use-fork + npx hardhat test:integration:l1 --use-fork --provider-port 9545 else - npx hardhat test:integration:l1 --compile --deploy --use-sips --use-fork + npx hardhat test:integration:l1 --compile --deploy --use-sips --use-fork --provider-port 9545 fi; job-integration-tests: working_directory: ~/repo @@ -406,6 +431,9 @@ workflows: - job-fork-tests: requires: - job-prepare + - job-fork-tests-ovm: + requires: + - job-prepare - job-simulate-release: requires: - job-prepare diff --git a/.circleci/src/jobs/job-fork-tests-ovm.yml b/.circleci/src/jobs/job-fork-tests-ovm.yml new file mode 100644 index 0000000000..7382d89aea --- /dev/null +++ b/.circleci/src/jobs/job-fork-tests-ovm.yml @@ -0,0 +1,21 @@ +# Starts a fork of OVM, deploys the latest release, and runs L2 integration tests +{{> job-header-node.yml}} +steps: + - checkout + - attach_workspace: + at: . + - run: + command: npm run fork:ovm + background: true + - cmd-wait-for-port: + port: 8545 + - run: + name: Run integration tests on l2 + command: | + # Only compile and deploy when there are new contracts + NEW_CONTRACTS=$(node bin.js sips --layer=base --unreleased --with-sources) + if [ -z "$NEW_CONTRACTS" ]; then + npx hardhat test:integration:l2 --use-fork + else + npx hardhat test:integration:l2 --compile --deploy --use-sips --use-fork + fi; diff --git a/.circleci/src/jobs/job-fork-tests.yml b/.circleci/src/jobs/job-fork-tests.yml index 518edec476..858019e9ee 100644 --- a/.circleci/src/jobs/job-fork-tests.yml +++ b/.circleci/src/jobs/job-fork-tests.yml @@ -8,14 +8,14 @@ steps: command: npm run fork:mainnet background: true - cmd-wait-for-port: - port: 8545 + port: 9545 - run: name: Run integration tests on l1 command: | # Only compile and deploy when there are new contracts NEW_CONTRACTS=$(node bin.js sips --layer=base --unreleased --with-sources) if [ -z "$NEW_CONTRACTS" ]; then - npx hardhat test:integration:l1 --use-fork + npx hardhat test:integration:l1 --use-fork --provider-port 9545 else - npx hardhat test:integration:l1 --compile --deploy --use-sips --use-fork + npx hardhat test:integration:l1 --compile --deploy --use-sips --use-fork --provider-port 9545 fi; diff --git a/.circleci/src/workflows/workflow-all.yml b/.circleci/src/workflows/workflow-all.yml index 952ea16c09..d86e73abf2 100644 --- a/.circleci/src/workflows/workflow-all.yml +++ b/.circleci/src/workflows/workflow-all.yml @@ -31,6 +31,8 @@ jobs: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - job-fork-tests: {{> require-prepare.yml}} + - job-fork-tests-ovm: + {{> require-prepare.yml}} # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Simulate release on fork & test diff --git a/contracts/ExchangeCircuitBreaker.sol b/contracts/ExchangeCircuitBreaker.sol index bd93078431..33b47d7832 100644 --- a/contracts/ExchangeCircuitBreaker.sol +++ b/contracts/ExchangeCircuitBreaker.sol @@ -188,7 +188,7 @@ contract ExchangeCircuitBreaker is Owned, MixinSystemSettings, IExchangeCircuitB } // if no last exchange for this synth, then we need to look up last 3 rates (+1 for current rate) - (uint[] memory rates, ) = _exchangeRates().ratesAndUpdatedTimeForCurrencyLastNRounds(currencyKey, 4); + (uint[] memory rates, ) = _exchangeRates().ratesAndUpdatedTimeForCurrencyLastNRounds(currencyKey, 4, 0); // start at index 1 to ignore current rate for (uint i = 1; i < rates.length; i++) { diff --git a/contracts/ExchangeRates.sol b/contracts/ExchangeRates.sol index 2ab1303ccf..04ef3d5372 100644 --- a/contracts/ExchangeRates.sol +++ b/contracts/ExchangeRates.sol @@ -117,25 +117,34 @@ contract ExchangeRates is Owned, MixinSystemSettings, IExchangeRates { return _getCurrentRoundId(currencyKey); } - function effectiveValueAtRound( + function effectiveValueAndRatesAtRound( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, uint roundIdForSrc, uint roundIdForDest - ) external view returns (uint value) { + ) + external + view + returns ( + uint value, + uint sourceRate, + uint destinationRate + ) + { + (sourceRate, ) = _getRateAndTimestampAtRound(sourceCurrencyKey, roundIdForSrc); // If there's no change in the currency, then just return the amount they gave us - if (sourceCurrencyKey == destinationCurrencyKey) return sourceAmount; - - (uint srcRate, ) = _getRateAndTimestampAtRound(sourceCurrencyKey, roundIdForSrc); - (uint destRate, ) = _getRateAndTimestampAtRound(destinationCurrencyKey, roundIdForDest); - if (destRate == 0) { - // prevent divide-by 0 error (this can happen when roundIDs jump epochs due - // to aggregator upgrades) - return 0; + if (sourceCurrencyKey == destinationCurrencyKey) { + destinationRate = sourceRate; + value = sourceAmount; + } else { + (destinationRate, ) = _getRateAndTimestampAtRound(destinationCurrencyKey, roundIdForDest); + // prevent divide-by 0 error (this happens if the dest is not a valid rate) + if (destinationRate > 0) { + // Calculate the effective value by going from source -> USD -> destination + value = sourceAmount.multiplyDecimalRound(sourceRate).divideDecimalRound(destinationRate); + } } - // Calculate the effective value by going from source -> USD -> destination - value = sourceAmount.multiplyDecimalRound(srcRate).divideDecimalRound(destRate); } function rateAndTimestampAtRound(bytes32 currencyKey, uint roundId) external view returns (uint rate, uint time) { @@ -202,15 +211,20 @@ contract ExchangeRates is Owned, MixinSystemSettings, IExchangeRates { return _getRateAndUpdatedTime(currencyKey).rate; } - function ratesAndUpdatedTimeForCurrencyLastNRounds(bytes32 currencyKey, uint numRounds) - external - view - returns (uint[] memory rates, uint[] memory times) - { + /// @notice getting N rounds of rates for a currency at a specific round + /// @param currencyKey the currency key + /// @param numRounds the number of rounds to get + /// @param roundId the round id + /// @return a list of rates and a list of times + function ratesAndUpdatedTimeForCurrencyLastNRounds( + bytes32 currencyKey, + uint numRounds, + uint roundId + ) external view returns (uint[] memory rates, uint[] memory times) { rates = new uint[](numRounds); times = new uint[](numRounds); - uint roundId = _getCurrentRoundId(currencyKey); + roundId = roundId > 0 ? roundId : _getCurrentRoundId(currencyKey); for (uint i = 0; i < numRounds; i++) { // fetch the rate and treat is as current, so inverse limits if frozen will always be applied // regardless of current rate @@ -299,6 +313,30 @@ contract ExchangeRates is Owned, MixinSystemSettings, IExchangeRates { return false; } + /// this method checks whether any rate is: + /// 1. flagged + /// 2. stale with respect to current time (now) + function anyRateIsInvalidAtRound(bytes32[] calldata currencyKeys, uint[] calldata roundIds) + external + view + returns (bool) + { + // Loop through each key and check whether the data point is stale. + + require(roundIds.length == currencyKeys.length, "roundIds must be the same length as currencyKeys"); + + uint256 _rateStalePeriod = getRateStalePeriod(); + bool[] memory flagList = getFlagsForRates(currencyKeys); + + for (uint i = 0; i < currencyKeys.length; i++) { + if (flagList[i] || _rateIsStaleAtRound(currencyKeys[i], roundIds[i], _rateStalePeriod)) { + return true; + } + } + + return false; + } + function synthTooVolatileForAtomicExchange(bytes32) external view returns (bool) { _notImplemented(); } @@ -379,7 +417,7 @@ contract ExchangeRates is Owned, MixinSystemSettings, IExchangeRates { function _getCurrentRoundId(bytes32 currencyKey) internal view returns (uint) { if (currencyKey == sUSD) { - return 0; // no roundIds for sUSD + return 0; } AggregatorV2V3Interface aggregator = aggregators[currencyKey]; if (aggregator != AggregatorV2V3Interface(0)) { @@ -395,7 +433,6 @@ contract ExchangeRates is Owned, MixinSystemSettings, IExchangeRates { return (SafeDecimalMath.unit(), 0); } else { AggregatorV2V3Interface aggregator = aggregators[currencyKey]; - if (aggregator != AggregatorV2V3Interface(0)) { // this view from the aggregator is the most gas efficient but it can throw when there's no data, // so let's call it low-level to suppress any reverts @@ -450,18 +487,34 @@ contract ExchangeRates is Owned, MixinSystemSettings, IExchangeRates { function _rateIsStale(bytes32 currencyKey, uint _rateStalePeriod) internal view returns (bool) { // sUSD is a special case and is never stale (check before an SLOAD of getRateAndUpdatedTime) - if (currencyKey == sUSD) return false; - + if (currencyKey == sUSD) { + return false; + } return _rateIsStaleWithTime(_rateStalePeriod, _getUpdatedTime(currencyKey)); } + function _rateIsStaleAtRound( + bytes32 currencyKey, + uint roundId, + uint _rateStalePeriod + ) internal view returns (bool) { + // sUSD is a special case and is never stale (check before an SLOAD of getRateAndUpdatedTime) + if (currencyKey == sUSD) { + return false; + } + (, uint time) = _getRateAndTimestampAtRound(currencyKey, roundId); + return _rateIsStaleWithTime(_rateStalePeriod, time); + } + function _rateIsStaleWithTime(uint _rateStalePeriod, uint _time) internal view returns (bool) { return _time.add(_rateStalePeriod) < now; } function _rateIsFlagged(bytes32 currencyKey, FlagsInterface flags) internal view returns (bool) { // sUSD is a special case and is never invalid - if (currencyKey == sUSD) return false; + if (currencyKey == sUSD) { + return false; + } address aggregator = address(aggregators[currencyKey]); // when no aggregator or when the flags haven't been setup if (aggregator == address(0) || flags == FlagsInterface(0)) { diff --git a/contracts/Exchanger.sol b/contracts/Exchanger.sol index 8120375f8a..67aa41e90f 100644 --- a/contracts/Exchanger.sol +++ b/contracts/Exchanger.sol @@ -74,17 +74,6 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { using SafeMath for uint; using SafeDecimalMath for uint; - struct ExchangeEntrySettlement { - bytes32 src; - uint amount; - bytes32 dest; - uint reclaim; - uint rebate; - uint srcRoundIdAtPeriodEnd; - uint destRoundIdAtPeriodEnd; - uint timestamp; - } - bytes32 public constant CONTRACT_NAME = "Exchanger"; bytes32 internal constant sUSD = "sUSD"; @@ -202,14 +191,14 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { uint reclaimAmount, uint rebateAmount, uint numEntries, - ExchangeEntrySettlement[] memory + IExchanger.ExchangeEntrySettlement[] memory ) { // Need to sum up all reclaim and rebate amounts for the user and the currency key numEntries = exchangeState().getLengthOfEntries(account, currencyKey); // For each unsettled exchange - ExchangeEntrySettlement[] memory settlements = new ExchangeEntrySettlement[](numEntries); + IExchanger.ExchangeEntrySettlement[] memory settlements = new IExchanger.ExchangeEntrySettlement[](numEntries); for (uint i = 0; i < numEntries; i++) { uint reclaim; uint rebate; @@ -220,8 +209,8 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { (uint srcRoundIdAtPeriodEnd, uint destRoundIdAtPeriodEnd) = getRoundIdsAtPeriodEnd(exchangeEntry); // given these round ids, determine what effective value they should have received - uint destinationAmount = - exchangeRates().effectiveValueAtRound( + (uint destinationAmount, , ) = + exchangeRates().effectiveValueAndRatesAtRound( exchangeEntry.src, exchangeEntry.amount, exchangeEntry.dest, @@ -248,7 +237,7 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { } } - settlements[i] = ExchangeEntrySettlement({ + settlements[i] = IExchanger.ExchangeEntrySettlement({ src: exchangeEntry.src, amount: exchangeEntry.amount, dest: exchangeEntry.dest, @@ -443,7 +432,33 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { IVirtualSynth vSynth ) { - _ensureCanExchange(sourceCurrencyKey, sourceAmount, destinationCurrencyKey); + // Using struct to resolve stack too deep error + IExchanger.ExchangeEntry memory entry; + + entry.roundIdForSrc = exchangeRates().getCurrentRoundId(sourceCurrencyKey); + entry.roundIdForDest = exchangeRates().getCurrentRoundId(destinationCurrencyKey); + + (entry.destinationAmount, entry.sourceRate, entry.destinationRate) = exchangeRates().effectiveValueAndRatesAtRound( + sourceCurrencyKey, + sourceAmount, + destinationCurrencyKey, + entry.roundIdForSrc, + entry.roundIdForDest + ); + + _ensureCanExchangeAtRound( + sourceCurrencyKey, + sourceAmount, + destinationCurrencyKey, + entry.roundIdForSrc, + entry.roundIdForDest + ); + + // SIP-65: Decentralized Circuit Breaker + // mutative call to suspend system if the rate is invalid + if (_exchangeRatesCircuitBroken(sourceCurrencyKey, destinationCurrencyKey)) { + return (0, 0, IVirtualSynth(0)); + } uint sourceAmountAfterSettlement = _settleAndCalcSourceAmountRemaining(sourceAmount, from, sourceCurrencyKey); @@ -453,25 +468,26 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { return (0, 0, IVirtualSynth(0)); } - // SIP-65: Decentralized Circuit Breaker - if (_exchangeRatesCircuitBroken(sourceCurrencyKey, destinationCurrencyKey)) { + bool tooVolatile; + (entry.exchangeFeeRate, tooVolatile) = _feeRateForExchangeAtRounds( + sourceCurrencyKey, + destinationCurrencyKey, + entry.roundIdForSrc, + entry.roundIdForDest + ); + + if (tooVolatile) { + // do not exchange if rates are too volatile, this to prevent charging + // dynamic fees that are over the max value return (0, 0, IVirtualSynth(0)); } - uint exchangeFeeRate; - uint sourceRate; - uint destinationRate; - + amountReceived = _deductFeesFromAmount(entry.destinationAmount, entry.exchangeFeeRate); // Note: `fee` is denominated in the destinationCurrencyKey. - (amountReceived, fee, exchangeFeeRate, sourceRate, destinationRate) = _getAmountsForExchangeMinusFees( - sourceAmountAfterSettlement, - sourceCurrencyKey, - destinationCurrencyKey - ); + fee = entry.destinationAmount.sub(amountReceived); - // Note: We don't need to check their balance as the burn() below will do a safe subtraction which requires + // Note: We don't need to check their balance as the _convert() below will do a safe subtraction which requires // the subtraction to not overflow, which would happen if their balance is not sufficient. - vSynth = _convert( sourceCurrencyKey, from, @@ -505,7 +521,10 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { // Nothing changes as far as issuance data goes because the total value in the system hasn't changed. // But we will update the debt snapshot in case exchange rates have fluctuated since the last exchange // in these currencies - _updateSNXIssuedDebtOnExchange([sourceCurrencyKey, destinationCurrencyKey], [sourceRate, destinationRate]); + _updateSNXIssuedDebtOnExchange( + [sourceCurrencyKey, destinationCurrencyKey], + [entry.sourceRate, entry.destinationRate] + ); // Let the DApps know there was a Synth exchange ISynthetixInternal(address(synthetix())).emitSynthExchange( @@ -526,7 +545,7 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { sourceAmountAfterSettlement, destinationCurrencyKey, amountReceived, - exchangeFeeRate + entry.exchangeFeeRate ); } } @@ -617,7 +636,27 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { bytes32[] memory synthKeys = new bytes32[](2); synthKeys[0] = sourceCurrencyKey; synthKeys[1] = destinationCurrencyKey; - require(!exchangeRates().anyRateIsInvalid(synthKeys), "Src/dest rate invalid or not found"); + require(!exchangeRates().anyRateIsInvalid(synthKeys), "src/dest rate stale or flagged"); + } + + function _ensureCanExchangeAtRound( + bytes32 sourceCurrencyKey, + uint sourceAmount, + bytes32 destinationCurrencyKey, + uint roundIdForSrc, + uint roundIdForDest + ) internal view { + require(sourceCurrencyKey != destinationCurrencyKey, "Can't be same synth"); + require(sourceAmount > 0, "Zero amount"); + + bytes32[] memory synthKeys = new bytes32[](2); + synthKeys[0] = sourceCurrencyKey; + synthKeys[1] = destinationCurrencyKey; + + uint[] memory roundIds = new uint[](2); + roundIds[0] = roundIdForSrc; + roundIds[1] = roundIdForDest; + require(!exchangeRates().anyRateIsInvalidAtRound(synthKeys, roundIds), "src/dest rate stale or flagged"); } function _internalSettle( @@ -634,7 +673,7 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { { require(maxSecsLeftInWaitingPeriod(from, currencyKey) == 0, "Cannot settle during waiting period"); - (uint reclaimAmount, uint rebateAmount, uint entries, ExchangeEntrySettlement[] memory settlements) = + (uint reclaimAmount, uint rebateAmount, uint entries, IExchanger.ExchangeEntrySettlement[] memory settlements) = _settlementOwing(from, currencyKey); if (reclaimAmount > rebateAmount) { @@ -703,39 +742,190 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { return timestamp.add(_waitingPeriodSecs).sub(now); } + /* ========== Exchange Related Fees ========== */ + /// @notice public function to get the total fee rate for a given exchange + /// @param sourceCurrencyKey The source currency key + /// @param destinationCurrencyKey The destination currency key + /// @return The exchange fee rate, and whether the rates are too volatile function feeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view - returns (uint exchangeFeeRate) + returns (uint feeRate, bool tooVolatile) + { + return _feeRateForExchange(sourceCurrencyKey, destinationCurrencyKey); + } + + /// @notice public function to get the dynamic fee rate for a given exchange + /// @param sourceCurrencyKey The source currency key + /// @param destinationCurrencyKey The destination currency key + /// @return The exchange dynamic fee rate and if rates are too volatile + function dynamicFeeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) + external + view + returns (uint feeRate, bool tooVolatile) { - exchangeFeeRate = _feeRateForExchange(sourceCurrencyKey, destinationCurrencyKey); + return _dynamicFeeRateForExchange(sourceCurrencyKey, destinationCurrencyKey); } - function _feeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) internal view returns (uint) { + /// @notice Calculate the exchange fee for a given source and destination currency key + /// @param sourceCurrencyKey The source currency key + /// @param destinationCurrencyKey The destination currency key + /// @return The exchange fee rate + /// @return The exchange dynamic fee rate and if rates are too volatile + function _feeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) + internal + view + returns (uint feeRate, bool tooVolatile) + { // Get the exchange fee rate as per destination currencyKey uint baseRate = getExchangeFeeRate(destinationCurrencyKey); - return _calculateFeeRateFromExchangeSynths(baseRate, sourceCurrencyKey, destinationCurrencyKey); + uint dynamicFee; + (dynamicFee, tooVolatile) = _dynamicFeeRateForExchange(sourceCurrencyKey, destinationCurrencyKey); + return (baseRate.add(dynamicFee), tooVolatile); } - function _calculateFeeRateFromExchangeSynths( - uint exchangeFeeRate, + /// @notice Calculate the exchange fee for a given source and destination currency key + /// @param sourceCurrencyKey The source currency key + /// @param destinationCurrencyKey The destination currency key + /// @param roundIdForSrc The round id of the source currency. + /// @param roundIdForDest The round id of the target currency. + /// @return The exchange fee rate + /// @return The exchange dynamic fee rate + function _feeRateForExchangeAtRounds( bytes32 sourceCurrencyKey, - bytes32 destinationCurrencyKey + bytes32 destinationCurrencyKey, + uint roundIdForSrc, + uint roundIdForDest + ) internal view returns (uint feeRate, bool tooVolatile) { + // Get the exchange fee rate as per destination currencyKey + uint baseRate = getExchangeFeeRate(destinationCurrencyKey); + uint dynamicFee; + (dynamicFee, tooVolatile) = _dynamicFeeRateForExchangeAtRounds( + sourceCurrencyKey, + destinationCurrencyKey, + roundIdForSrc, + roundIdForDest + ); + return (baseRate.add(dynamicFee), tooVolatile); + } + + function _dynamicFeeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) + internal + view + returns (uint dynamicFee, bool tooVolatile) + { + DynamicFeeConfig memory config = getExchangeDynamicFeeConfig(); + (uint dynamicFeeDst, bool dstVolatile) = _dynamicFeeRateForCurrency(destinationCurrencyKey, config); + (uint dynamicFeeSrc, bool srcVolatile) = _dynamicFeeRateForCurrency(sourceCurrencyKey, config); + dynamicFee = dynamicFeeDst.add(dynamicFeeSrc); + // cap to maxFee + bool overMax = dynamicFee > config.maxFee; + dynamicFee = overMax ? config.maxFee : dynamicFee; + return (dynamicFee, overMax || dstVolatile || srcVolatile); + } + + function _dynamicFeeRateForExchangeAtRounds( + bytes32 sourceCurrencyKey, + bytes32 destinationCurrencyKey, + uint roundIdForSrc, + uint roundIdForDest + ) internal view returns (uint dynamicFee, bool tooVolatile) { + DynamicFeeConfig memory config = getExchangeDynamicFeeConfig(); + (uint dynamicFeeDst, bool dstVolatile) = + _dynamicFeeRateForCurrencyRound(destinationCurrencyKey, roundIdForDest, config); + (uint dynamicFeeSrc, bool srcVolatile) = _dynamicFeeRateForCurrencyRound(sourceCurrencyKey, roundIdForSrc, config); + dynamicFee = dynamicFeeDst.add(dynamicFeeSrc); + // cap to maxFee + bool overMax = dynamicFee > config.maxFee; + dynamicFee = overMax ? config.maxFee : dynamicFee; + return (dynamicFee, overMax || dstVolatile || srcVolatile); + } + + /// @notice Get dynamic dynamicFee for a given currency key (SIP-184) + /// @param currencyKey The given currency key + /// @param config dynamic fee calculation configuration params + /// @return The dynamic fee and if it exceeds max dynamic fee set in config + function _dynamicFeeRateForCurrency(bytes32 currencyKey, DynamicFeeConfig memory config) + internal + view + returns (uint dynamicFee, bool tooVolatile) + { + // no dynamic dynamicFee for sUSD or too few rounds + if (currencyKey == sUSD || config.rounds <= 1) { + return (0, false); + } + uint roundId = exchangeRates().getCurrentRoundId(currencyKey); + return _dynamicFeeRateForCurrencyRound(currencyKey, roundId, config); + } + + /// @notice Get dynamicFee for a given currency key (SIP-184) + /// @param currencyKey The given currency key + /// @param roundId The round id + /// @param config dynamic fee calculation configuration params + /// @return The dynamic fee and if it exceeds max dynamic fee set in config + function _dynamicFeeRateForCurrencyRound( + bytes32 currencyKey, + uint roundId, + DynamicFeeConfig memory config + ) internal view returns (uint dynamicFee, bool tooVolatile) { + // no dynamic dynamicFee for sUSD or too few rounds + if (currencyKey == sUSD || config.rounds <= 1) { + return (0, false); + } + uint[] memory prices; + (prices, ) = exchangeRates().ratesAndUpdatedTimeForCurrencyLastNRounds(currencyKey, config.rounds, roundId); + dynamicFee = _dynamicFeeCalculation(prices, config.threshold, config.weightDecay); + // cap to maxFee + bool overMax = dynamicFee > config.maxFee; + dynamicFee = overMax ? config.maxFee : dynamicFee; + return (dynamicFee, overMax); + } + + /// @notice Calculate dynamic fee according to SIP-184 + /// @param prices A list of prices from the current round to the previous rounds + /// @param threshold A threshold to clip the price deviation ratop + /// @param weightDecay A weight decay constant + /// @return uint dynamic fee rate as decimal + function _dynamicFeeCalculation( + uint[] memory prices, + uint threshold, + uint weightDecay ) internal pure returns (uint) { - if (sourceCurrencyKey == sUSD || destinationCurrencyKey == sUSD) { - return exchangeFeeRate; + // don't underflow + if (prices.length == 0) { + return 0; } - // Is this a swing trade? long to short or short to long skipping sUSD. - if ( - (sourceCurrencyKey[0] == 0x73 && destinationCurrencyKey[0] == 0x69) || - (sourceCurrencyKey[0] == 0x69 && destinationCurrencyKey[0] == 0x73) - ) { - // Double the exchange fee - return exchangeFeeRate.mul(2); + uint dynamicFee = 0; // start with 0 + // go backwards in price array + for (uint i = prices.length - 1; i > 0; i--) { + // apply decay from previous round (will be 0 for first round) + dynamicFee = dynamicFee.multiplyDecimal(weightDecay); + // calculate price deviation + uint deviation = _thresholdedAbsDeviationRatio(prices[i - 1], prices[i], threshold); + // add to total fee + dynamicFee = dynamicFee.add(deviation); } + return dynamicFee; + } - return exchangeFeeRate; + /// absolute price deviation ratio used by dynamic fee calculation + /// deviationRatio = (abs(current - previous) / previous) - threshold + /// if negative, zero is returned + function _thresholdedAbsDeviationRatio( + uint price, + uint previousPrice, + uint threshold + ) internal pure returns (uint) { + if (previousPrice == 0) { + return 0; // don't divide by zero + } + // abs difference between prices + uint absDelta = price > previousPrice ? price - previousPrice : previousPrice - price; + // relative to previous price + uint deviationRatio = absDelta.divideDecimal(previousPrice); + // only the positive difference from threshold + return deviationRatio > threshold ? deviationRatio - threshold : 0; } function getAmountsForExchange( @@ -751,35 +941,32 @@ contract Exchanger is Owned, MixinSystemSettings, IExchanger { uint exchangeFeeRate ) { - (amountReceived, fee, exchangeFeeRate, , ) = _getAmountsForExchangeMinusFees( - sourceAmount, - sourceCurrencyKey, - destinationCurrencyKey - ); - } + // The checks are added for consistency with the checks performed in _exchange() + // The reverts (instead of no-op returns) are used order to prevent incorrect usage in calling contracts + // (The no-op in _exchange() is in order to trigger system suspension if needed) + + // check synths active + systemStatus().requireSynthActive(sourceCurrencyKey); + systemStatus().requireSynthActive(destinationCurrencyKey); + + // check rates don't deviate above ciruit breaker allowed deviation + (, bool srcInvalid) = exchangeCircuitBreaker().rateWithInvalid(sourceCurrencyKey); + (, bool dstInvalid) = exchangeCircuitBreaker().rateWithInvalid(destinationCurrencyKey); + require(!srcInvalid, "source synth rate invalid"); + require(!dstInvalid, "destinatino synth rate invalid"); + + // check rates not stale or flagged + _ensureCanExchange(sourceCurrencyKey, sourceAmount, destinationCurrencyKey); + + bool tooVolatile; + (exchangeFeeRate, tooVolatile) = _feeRateForExchange(sourceCurrencyKey, destinationCurrencyKey); + + // check rates volatility result + require(!tooVolatile, "exchange rates too volatile"); + + (uint destinationAmount, , ) = + exchangeRates().effectiveValueAndRates(sourceCurrencyKey, sourceAmount, destinationCurrencyKey); - function _getAmountsForExchangeMinusFees( - uint sourceAmount, - bytes32 sourceCurrencyKey, - bytes32 destinationCurrencyKey - ) - internal - view - returns ( - uint amountReceived, - uint fee, - uint exchangeFeeRate, - uint sourceRate, - uint destinationRate - ) - { - uint destinationAmount; - (destinationAmount, sourceRate, destinationRate) = exchangeRates().effectiveValueAndRates( - sourceCurrencyKey, - sourceAmount, - destinationCurrencyKey - ); - exchangeFeeRate = _feeRateForExchange(sourceCurrencyKey, destinationCurrencyKey); amountReceived = _deductFeesFromAmount(destinationAmount, exchangeFeeRate); fee = destinationAmount.sub(amountReceived); } diff --git a/contracts/ExchangerWithFeeRecAlternatives.sol b/contracts/ExchangerWithFeeRecAlternatives.sol index f7d77b2c6f..9ede257f88 100644 --- a/contracts/ExchangerWithFeeRecAlternatives.sol +++ b/contracts/ExchangerWithFeeRecAlternatives.sol @@ -269,6 +269,9 @@ contract ExchangerWithFeeRecAlternatives is MinimalProxyFactory, Exchanger { view returns (uint) { + // unused + sourceCurrencyKey; + // Get the exchange fee rate as per destination currencyKey uint baseRate = getAtomicExchangeFeeRate(destinationCurrencyKey); if (baseRate == 0) { @@ -276,7 +279,7 @@ contract ExchangerWithFeeRecAlternatives is MinimalProxyFactory, Exchanger { baseRate = getExchangeFeeRate(destinationCurrencyKey); } - return _calculateFeeRateFromExchangeSynths(baseRate, sourceCurrencyKey, destinationCurrencyKey); + return baseRate; } function _getAmountsForAtomicExchangeMinusFees( diff --git a/contracts/FuturesMarket.sol b/contracts/FuturesMarket.sol index b215e46c37..443bad8354 100644 --- a/contracts/FuturesMarket.sol +++ b/contracts/FuturesMarket.sol @@ -6,12 +6,6 @@ import "./MixinFuturesNextPriceOrders.sol"; import "./MixinFuturesViews.sol"; import "./interfaces/IFuturesMarket.sol"; -// Internal references -import "./interfaces/IExchangeCircuitBreaker.sol"; -import "./interfaces/IExchangeRates.sol"; -import "./interfaces/ISystemStatus.sol"; -import "./interfaces/IERC20.sol"; - /* * Synthetic Futures * ================= diff --git a/contracts/MixinSystemSettings.sol b/contracts/MixinSystemSettings.sol index 7e59eec559..0facfd1794 100644 --- a/contracts/MixinSystemSettings.sol +++ b/contracts/MixinSystemSettings.sol @@ -19,7 +19,13 @@ contract MixinSystemSettings is MixinResolver { 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"; @@ -49,6 +55,13 @@ contract MixinSystemSettings is MixinResolver { enum CrossDomainMessageGasLimits {Deposit, Escrow, Reward, Withdrawal, 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) { @@ -123,6 +136,7 @@ contract MixinSystemSettings is MixinResolver { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_RATE_STALE_PERIOD); } + /* ========== Exchange Related Fees ========== */ function getExchangeFeeRate(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( @@ -131,6 +145,20 @@ contract MixinSystemSettings is MixinResolver { ); } + /// @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); } diff --git a/contracts/SystemSettings.sol b/contracts/SystemSettings.sol index ac754726a4..cb7a5dc048 100644 --- a/contracts/SystemSettings.sol +++ b/contracts/SystemSettings.sol @@ -2,7 +2,6 @@ pragma solidity ^0.5.16; // Inheritance import "./Owned.sol"; -import "./MixinResolver.sol"; import "./MixinSystemSettings.sol"; import "./interfaces/ISystemSettings.sol"; import "./SystemSettingsLib.sol"; @@ -84,10 +83,38 @@ contract SystemSettings is Owned, MixinSystemSettings, ISystemSettings { return getRateStalePeriod(); } + /* ========== Exchange Related Fees ========== */ function exchangeFeeRate(bytes32 currencyKey) external view returns (uint) { return getExchangeFeeRate(currencyKey); } + // SIP-184 Dynamic Fee + /// @notice Get the dynamic fee threshold + /// @return The dynamic fee threshold + function exchangeDynamicFeeThreshold() external view returns (uint) { + return getExchangeDynamicFeeConfig().threshold; + } + + /// @notice Get the dynamic fee weight decay per round + /// @return The dynamic fee weight decay per round + function exchangeDynamicFeeWeightDecay() external view returns (uint) { + return getExchangeDynamicFeeConfig().weightDecay; + } + + /// @notice Get the dynamic fee total rounds for calculation + /// @return The dynamic fee total rounds for calculation + function exchangeDynamicFeeRounds() external view returns (uint) { + return getExchangeDynamicFeeConfig().rounds; + } + + /// @notice Get the max dynamic fee + /// @return The max dynamic fee + function exchangeMaxDynamicFee() external view returns (uint) { + return getExchangeDynamicFeeConfig().maxFee; + } + + /* ========== End Exchange Related Fees ========== */ + function minimumStakeTime() external view returns (uint) { return getMinimumStakeTime(); } @@ -206,9 +233,9 @@ contract SystemSettings is Owned, MixinSystemSettings, ISystemSettings { emit CrossDomainMessageGasLimitChanged(_gasLimitType, _crossDomainMessageGasLimit); } - function setIssuanceRatio(uint issuanceRatio) external onlyOwner { - flexibleStorage().setIssuanceRatio(SETTING_ISSUANCE_RATIO, issuanceRatio); - emit IssuanceRatioUpdated(issuanceRatio); + function setIssuanceRatio(uint ratio) external onlyOwner { + flexibleStorage().setIssuanceRatio(SETTING_ISSUANCE_RATIO, ratio); + emit IssuanceRatioUpdated(ratio); } function setTradingRewardsEnabled(bool _tradingRewardsEnabled) external onlyOwner { @@ -235,8 +262,8 @@ contract SystemSettings is Owned, MixinSystemSettings, ISystemSettings { } function setTargetThreshold(uint percent) external onlyOwner { - uint targetThreshold = flexibleStorage().setTargetThreshold(SETTING_TARGET_THRESHOLD, percent); - emit TargetThresholdUpdated(targetThreshold); + uint threshold = flexibleStorage().setTargetThreshold(SETTING_TARGET_THRESHOLD, percent); + emit TargetThresholdUpdated(threshold); } function setLiquidationDelay(uint time) external onlyOwner { @@ -266,6 +293,7 @@ contract SystemSettings is Owned, MixinSystemSettings, ISystemSettings { emit RateStalePeriodUpdated(period); } + /* ========== Exchange Fees Related ========== */ function setExchangeFeeRateForSynths(bytes32[] calldata synthKeys, uint256[] calldata exchangeFeeRates) external onlyOwner @@ -276,6 +304,45 @@ contract SystemSettings is Owned, MixinSystemSettings, ISystemSettings { } } + /// @notice Set exchange dynamic fee threshold constant in decimal ratio + /// @param threshold The exchange dynamic fee threshold + /// @return uint threshold constant + function setExchangeDynamicFeeThreshold(uint threshold) external onlyOwner { + require(threshold != 0, "Threshold cannot be 0"); + + flexibleStorage().setUIntValue(SETTING_CONTRACT_NAME, SETTING_EXCHANGE_DYNAMIC_FEE_THRESHOLD, threshold); + + emit ExchangeDynamicFeeThresholdUpdated(threshold); + } + + /// @notice Set exchange dynamic fee weight decay constant + /// @param weightDecay The exchange dynamic fee weight decay + /// @return uint weight decay constant + function setExchangeDynamicFeeWeightDecay(uint weightDecay) external onlyOwner { + require(weightDecay != 0, "Weight decay cannot be 0"); + + flexibleStorage().setUIntValue(SETTING_CONTRACT_NAME, SETTING_EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY, weightDecay); + + emit ExchangeDynamicFeeWeightDecayUpdated(weightDecay); + } + + /// @notice Set exchange dynamic fee last N rounds with minimum 2 rounds + /// @param rounds The exchange dynamic fee last N rounds + /// @return uint dynamic fee last N rounds + function setExchangeDynamicFeeRounds(uint rounds) external onlyOwner { + flexibleStorage().setUIntValue(SETTING_CONTRACT_NAME, SETTING_EXCHANGE_DYNAMIC_FEE_ROUNDS, rounds); + + emit ExchangeDynamicFeeRoundsUpdated(rounds); + } + + /// @notice Set max exchange dynamic fee + /// @param maxFee The max exchange dynamic fee + /// @return uint dynamic fee last N rounds + function setExchangeMaxDynamicFee(uint maxFee) external onlyOwner { + flexibleStorage().setExchangeMaxDynamicFee(SETTING_EXCHANGE_MAX_DYNAMIC_FEE, maxFee); + emit ExchangeMaxDynamicFeeUpdated(maxFee); + } + function setMinimumStakeTime(uint _seconds) external onlyOwner { flexibleStorage().setMinimumStakeTime(SETTING_MINIMUM_STAKE_TIME, _seconds); emit MinimumStakeTimeUpdated(_seconds); @@ -400,7 +467,13 @@ contract SystemSettings is Owned, MixinSystemSettings, ISystemSettings { event LiquidationRatioUpdated(uint newRatio); event LiquidationPenaltyUpdated(uint newPenalty); event RateStalePeriodUpdated(uint rateStalePeriod); + /* ========== Exchange Fees Related ========== */ event ExchangeFeeUpdated(bytes32 synthKey, uint newExchangeFeeRate); + event ExchangeDynamicFeeThresholdUpdated(uint dynamicFeeThreshold); + event ExchangeDynamicFeeWeightDecayUpdated(uint dynamicFeeWeightDecay); + event ExchangeDynamicFeeRoundsUpdated(uint dynamicFeeRounds); + event ExchangeMaxDynamicFeeUpdated(uint maxDynamicFee); + /* ========== End Exchange Fees Related ========== */ event MinimumStakeTimeUpdated(uint minimumStakeTime); event DebtSnapshotStaleTimeUpdated(uint debtSnapshotStaleTime); event AggregatorWarningFlagsUpdated(address flags); diff --git a/contracts/SystemSettingsLib.sol b/contracts/SystemSettingsLib.sol index 1a137ea43d..7dfa271812 100644 --- a/contracts/SystemSettingsLib.sol +++ b/contracts/SystemSettingsLib.sol @@ -8,6 +8,8 @@ import "./SafeDecimalMath.sol"; /// This library is to reduce SystemSettings contract size only and is not really /// a proper library - so it shares knowledge of implementation details +/// Some of the setters were refactored into this library, and some setters remain in the +/// contract itself (SystemSettings) library SystemSettingsLib { using SafeMath for uint; using SafeDecimalMath for uint; @@ -76,10 +78,10 @@ library SystemSettingsLib { function setIssuanceRatio( IFlexibleStorage flexibleStorage, bytes32 settingName, - uint issuanceRatio + uint ratio ) external { - require(issuanceRatio <= MAX_ISSUANCE_RATIO, "New issuance ratio cannot exceed MAX_ISSUANCE_RATIO"); - flexibleStorage.setUIntValue(SETTINGS_CONTRACT_NAME, settingName, issuanceRatio); + require(ratio <= MAX_ISSUANCE_RATIO, "New issuance ratio cannot exceed MAX_ISSUANCE_RATIO"); + flexibleStorage.setUIntValue(SETTINGS_CONTRACT_NAME, settingName, ratio); } function setTradingRewardsEnabled( @@ -120,12 +122,12 @@ library SystemSettingsLib { function setTargetThreshold( IFlexibleStorage flexibleStorage, bytes32 settingName, - uint _percent - ) external returns (uint targetThreshold) { - require(_percent <= MAX_TARGET_THRESHOLD, "Threshold too high"); - targetThreshold = _percent.mul(SafeDecimalMath.unit()).div(100); + uint percent + ) external returns (uint threshold) { + require(percent <= MAX_TARGET_THRESHOLD, "Threshold too high"); + threshold = percent.mul(SafeDecimalMath.unit()).div(100); - flexibleStorage.setUIntValue(SETTINGS_CONTRACT_NAME, settingName, targetThreshold); + flexibleStorage.setUIntValue(SETTINGS_CONTRACT_NAME, settingName, threshold); } function setLiquidationDelay( @@ -419,4 +421,15 @@ library SystemSettingsLib { _threshold ); } + + function setExchangeMaxDynamicFee( + IFlexibleStorage flexibleStorage, + bytes32 settingName, + uint maxFee + ) external { + require(maxFee != 0, "Max dynamic fee cannot be 0"); + require(maxFee <= MAX_EXCHANGE_FEE_RATE, "MAX_EXCHANGE_FEE_RATE exceeded"); + + flexibleStorage.setUIntValue(SETTINGS_CONTRACT_NAME, settingName, maxFee); + } } diff --git a/contracts/interfaces/IExchangeRates.sol b/contracts/interfaces/IExchangeRates.sol index e55b1e87f0..43e4f7fbfa 100644 --- a/contracts/interfaces/IExchangeRates.sol +++ b/contracts/interfaces/IExchangeRates.sol @@ -15,6 +15,8 @@ interface IExchangeRates { 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( @@ -36,6 +38,21 @@ interface IExchangeRates { 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, @@ -50,14 +67,6 @@ interface IExchangeRates { uint systemDestinationRate ); - function effectiveValueAtRound( - bytes32 sourceCurrencyKey, - uint sourceAmount, - bytes32 destinationCurrencyKey, - uint roundIdForSrc, - uint roundIdForDest - ) external view returns (uint value); - function getCurrentRoundId(bytes32 currencyKey) external view returns (uint); function getLastRoundIdBeforeElapsedSecs( @@ -85,10 +94,11 @@ interface IExchangeRates { function rateStalePeriod() external view returns (uint); - function ratesAndUpdatedTimeForCurrencyLastNRounds(bytes32 currencyKey, uint numRounds) - external - view - returns (uint[] memory rates, uint[] memory times); + function ratesAndUpdatedTimeForCurrencyLastNRounds( + bytes32 currencyKey, + uint numRounds, + uint roundId + ) external view returns (uint[] memory rates, uint[] memory times); function ratesAndInvalidForCurrencies(bytes32[] calldata currencyKeys) external diff --git a/contracts/interfaces/IExchanger.sol b/contracts/interfaces/IExchanger.sol index eb27fb097e..6660e1b2d9 100644 --- a/contracts/interfaces/IExchanger.sol +++ b/contracts/interfaces/IExchanger.sol @@ -4,6 +4,27 @@ import "./IVirtualSynth.sol"; // https://docs.synthetix.io/contracts/source/interfaces/iexchanger interface IExchanger { + struct ExchangeEntrySettlement { + bytes32 src; + uint amount; + bytes32 dest; + uint reclaim; + uint rebate; + uint srcRoundIdAtPeriodEnd; + uint destRoundIdAtPeriodEnd; + uint timestamp; + } + + struct ExchangeEntry { + uint sourceRate; + uint destinationRate; + uint destinationAmount; + uint exchangeFeeRate; + uint exchangeDynamicFeeRate; + uint roundIdForSrc; + uint roundIdForDest; + } + // Views function calculateAmountAfterSettlement( address from, @@ -30,7 +51,12 @@ interface IExchanger { function feeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view - returns (uint exchangeFeeRate); + returns (uint exchangeFeeRate, bool tooVolatile); + + function dynamicFeeRateForExchange(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) + external + view + returns (uint feeRate, bool tooVolatile); function getAmountsForExchange( uint sourceAmount, diff --git a/contracts/migrations/Migration_Peacock.sol b/contracts/migrations/Migration_Peacock.sol new file mode 100644 index 0000000000..e5ca2643f6 --- /dev/null +++ b/contracts/migrations/Migration_Peacock.sol @@ -0,0 +1,203 @@ +pragma solidity ^0.5.16; + +import "../BaseMigration.sol"; +import "../AddressResolver.sol"; +import "../Proxy.sol"; +import "../FeePoolEternalStorage.sol"; +import "../FeePoolState.sol"; +import "../RewardEscrow.sol"; +import "../FeePool.sol"; + +interface ISynthetixNamedContract { + // solhint-disable func-name-mixedcase + function CONTRACT_NAME() external view returns (bytes32); +} + +// solhint-disable contract-name-camelcase +contract Migration_Peacock is BaseMigration { + // https://etherscan.io/address/0xEb3107117FEAd7de89Cd14D463D340A2E6917769; + address public constant OWNER = 0xEb3107117FEAd7de89Cd14D463D340A2E6917769; + + // ---------------------------- + // EXISTING SYNTHETIX CONTRACTS + // ---------------------------- + + // https://etherscan.io/address/0x823bE81bbF96BEc0e25CA13170F5AaCb5B79ba83 + AddressResolver public constant addressresolver_i = AddressResolver(0x823bE81bbF96BEc0e25CA13170F5AaCb5B79ba83); + // https://etherscan.io/address/0xb440DD674e1243644791a4AdfE3A2AbB0A92d309 + Proxy public constant proxyfeepool_i = Proxy(0xb440DD674e1243644791a4AdfE3A2AbB0A92d309); + // https://etherscan.io/address/0xC9DFff5fA5605fd94F8B7927b892F2B57391e8bB + FeePoolEternalStorage public constant feepooleternalstorage_i = + FeePoolEternalStorage(0xC9DFff5fA5605fd94F8B7927b892F2B57391e8bB); + // https://etherscan.io/address/0x11164F6a47C3f8472D19b9aDd516Fc780cb7Ee02 + FeePoolState public constant feepoolstate_i = FeePoolState(0x11164F6a47C3f8472D19b9aDd516Fc780cb7Ee02); + // https://etherscan.io/address/0xb671F2210B1F6621A2607EA63E6B2DC3e2464d1F + RewardEscrow public constant rewardescrow_i = RewardEscrow(0xb671F2210B1F6621A2607EA63E6B2DC3e2464d1F); + // https://etherscan.io/address/0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd + FeePool public constant feepool_i = FeePool(0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd); + + // ---------------------------------- + // NEW CONTRACTS DEPLOYED TO BE ADDED + // ---------------------------------- + + // https://etherscan.io/address/0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd + address public constant new_FeePool_contract = 0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd; + + constructor() public BaseMigration(OWNER) {} + + function contractsRequiringOwnership() public pure returns (address[] memory contracts) { + contracts = new address[](6); + contracts[0] = address(addressresolver_i); + contracts[1] = address(proxyfeepool_i); + contracts[2] = address(feepooleternalstorage_i); + contracts[3] = address(feepoolstate_i); + contracts[4] = address(rewardescrow_i); + contracts[5] = address(feepool_i); + } + + function migrate(address currentOwner) external onlyDeployer { + require(owner == currentOwner, "Only the assigned owner can be re-assigned when complete"); + + require( + ISynthetixNamedContract(new_FeePool_contract).CONTRACT_NAME() == "FeePool", + "Invalid contract supplied for FeePool" + ); + + // ACCEPT OWNERSHIP for all contracts that require ownership to make changes + acceptAll(); + + // MIGRATION + // Import all new contracts into the address resolver; + addressresolver_importAddresses_0(); + // Rebuild the resolver caches in all MixinResolver contracts - batch 1; + addressresolver_rebuildCaches_1(); + // Rebuild the resolver caches in all MixinResolver contracts - batch 2; + addressresolver_rebuildCaches_2(); + // Ensure the ProxyFeePool contract has the correct FeePool target set; + proxyfeepool_i.setTarget(Proxyable(new_FeePool_contract)); + // Ensure the FeePool contract can write to its EternalStorage; + feepooleternalstorage_i.setAssociatedContract(new_FeePool_contract); + // Ensure the FeePool contract can write to its State; + feepoolstate_i.setFeePool(IFeePool(new_FeePool_contract)); + // Ensure the legacy RewardEscrow contract is connected to the FeePool contract; + rewardescrow_i.setFeePool(IFeePool(new_FeePool_contract)); + // Import fee period from existing fee pool at index 0; + importFeePeriod_0(); + // Import fee period from existing fee pool at index 1; + importFeePeriod_1(); + + // NOMINATE OWNERSHIP back to owner for aforementioned contracts + nominateAll(); + } + + function acceptAll() internal { + address[] memory contracts = contractsRequiringOwnership(); + for (uint i = 0; i < contracts.length; i++) { + Owned(contracts[i]).acceptOwnership(); + } + } + + function nominateAll() internal { + address[] memory contracts = contractsRequiringOwnership(); + for (uint i = 0; i < contracts.length; i++) { + returnOwnership(contracts[i]); + } + } + + function addressresolver_importAddresses_0() internal { + bytes32[] memory addressresolver_importAddresses_names_0_0 = new bytes32[](1); + addressresolver_importAddresses_names_0_0[0] = bytes32("FeePool"); + address[] memory addressresolver_importAddresses_destinations_0_1 = new address[](1); + addressresolver_importAddresses_destinations_0_1[0] = address(new_FeePool_contract); + addressresolver_i.importAddresses( + addressresolver_importAddresses_names_0_0, + addressresolver_importAddresses_destinations_0_1 + ); + } + + function addressresolver_rebuildCaches_1() internal { + MixinResolver[] memory addressresolver_rebuildCaches_destinations_1_0 = new MixinResolver[](20); + addressresolver_rebuildCaches_destinations_1_0[0] = MixinResolver(0xDA4eF8520b1A57D7d63f1E249606D1A459698876); + addressresolver_rebuildCaches_destinations_1_0[1] = MixinResolver(0x2A417C61B8062363e4ff50900779463b45d235f6); + addressresolver_rebuildCaches_destinations_1_0[2] = MixinResolver(0xC2F1F551bfAd1E9A3b4816513bFd41d77f40F915); + addressresolver_rebuildCaches_destinations_1_0[3] = MixinResolver(0x02f9bC46beD33acdB9cb002fe346734CeF8a9480); + addressresolver_rebuildCaches_destinations_1_0[4] = MixinResolver(0xAFDd6B5A8aB32156dBFb4060ff87F6d9E31191bA); + addressresolver_rebuildCaches_destinations_1_0[5] = MixinResolver(0xe301da3d2D3e96e57D05b8E557656629cDdbe7A0); + addressresolver_rebuildCaches_destinations_1_0[6] = MixinResolver(0x4ed5c5D5793f86c8a85E1a96E37b6d374DE0E85A); + addressresolver_rebuildCaches_destinations_1_0[7] = MixinResolver(0x005d19CA7ff9D79a5Bdf0805Fc01D9D7c53B6827); + addressresolver_rebuildCaches_destinations_1_0[8] = MixinResolver(0xde3892383965FBa6eC434bE6350F85f140098708); + addressresolver_rebuildCaches_destinations_1_0[9] = MixinResolver(0x39DDbbb113AF3434048b9d8018a3e99d67C6eE0D); + addressresolver_rebuildCaches_destinations_1_0[10] = MixinResolver(0xe2f532c389deb5E42DCe53e78A9762949A885455); + addressresolver_rebuildCaches_destinations_1_0[11] = MixinResolver(0x2B3eb5eF0EF06f2E02ef60B3F36Be4793d321353); + addressresolver_rebuildCaches_destinations_1_0[12] = MixinResolver(0xc70B42930BD8D30A79B55415deC3be60827559f7); + addressresolver_rebuildCaches_destinations_1_0[13] = MixinResolver(0x3FFE35c3d412150C3B91d3E22eBA60E16030C608); + addressresolver_rebuildCaches_destinations_1_0[14] = MixinResolver(0x8f9fa817200F5B95f9572c8Acf2b31410C00335a); + addressresolver_rebuildCaches_destinations_1_0[15] = MixinResolver(0x0705F0716b12a703d4F8832Ec7b97C61771f0361); + addressresolver_rebuildCaches_destinations_1_0[16] = MixinResolver(0xfA60918C4417b64E722ca15d79C751c1f24Ab995); + addressresolver_rebuildCaches_destinations_1_0[17] = MixinResolver(0xcc3aab773e2171b2E257Ee17001400eE378aa52B); + addressresolver_rebuildCaches_destinations_1_0[18] = MixinResolver(0xe59dFC746D566EB40F92ed0B162004e24E3AC932); + addressresolver_rebuildCaches_destinations_1_0[19] = MixinResolver(0xC1AAE9d18bBe386B102435a8632C8063d31e747C); + addressresolver_i.rebuildCaches(addressresolver_rebuildCaches_destinations_1_0); + } + + function addressresolver_rebuildCaches_2() internal { + MixinResolver[] memory addressresolver_rebuildCaches_destinations_2_0 = new MixinResolver[](4); + addressresolver_rebuildCaches_destinations_2_0[0] = MixinResolver(0x5c8344bcdC38F1aB5EB5C1d4a35DdEeA522B5DfA); + addressresolver_rebuildCaches_destinations_2_0[1] = MixinResolver(0xaa03aB31b55DceEeF845C8d17890CC61cD98eD04); + addressresolver_rebuildCaches_destinations_2_0[2] = MixinResolver(0x1F2c3a1046c32729862fcB038369696e3273a516); + addressresolver_rebuildCaches_destinations_2_0[3] = MixinResolver(new_FeePool_contract); + addressresolver_i.rebuildCaches(addressresolver_rebuildCaches_destinations_2_0); + } + + function importFeePeriod_0() internal { + // https://etherscan.io/address/0xc398406FFfBEd5B0680e706634490062CB1DB579; + FeePool existingFeePool = FeePool(0xc398406FFfBEd5B0680e706634490062CB1DB579); + // https://etherscan.io/address/0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd; + FeePool newFeePool = FeePool(0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd); + ( + uint64 feePeriodId_0, + uint64 startingDebtIndex_0, + uint64 startTime_0, + uint feesToDistribute_0, + uint feesClaimed_0, + uint rewardsToDistribute_0, + uint rewardsClaimed_0 + ) = existingFeePool.recentFeePeriods(0); + newFeePool.importFeePeriod( + 0, + feePeriodId_0, + startingDebtIndex_0, + startTime_0, + feesToDistribute_0, + feesClaimed_0, + rewardsToDistribute_0, + rewardsClaimed_0 + ); + } + + function importFeePeriod_1() internal { + // https://etherscan.io/address/0xc398406FFfBEd5B0680e706634490062CB1DB579; + FeePool existingFeePool = FeePool(0xc398406FFfBEd5B0680e706634490062CB1DB579); + // https://etherscan.io/address/0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd; + FeePool newFeePool = FeePool(0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd); + ( + uint64 feePeriodId_1, + uint64 startingDebtIndex_1, + uint64 startTime_1, + uint feesToDistribute_1, + uint feesClaimed_1, + uint rewardsToDistribute_1, + uint rewardsClaimed_1 + ) = existingFeePool.recentFeePeriods(1); + newFeePool.importFeePeriod( + 1, + feePeriodId_1, + startingDebtIndex_1, + startTime_1, + feesToDistribute_1, + feesClaimed_1, + rewardsToDistribute_1, + rewardsClaimed_1 + ); + } +} diff --git a/contracts/migrations/Migration_PeacockOptimism.sol b/contracts/migrations/Migration_PeacockOptimism.sol new file mode 100644 index 0000000000..b621894c10 --- /dev/null +++ b/contracts/migrations/Migration_PeacockOptimism.sol @@ -0,0 +1,177 @@ +pragma solidity ^0.5.16; + +import "../BaseMigration.sol"; +import "../AddressResolver.sol"; +import "../Proxy.sol"; +import "../FeePoolEternalStorage.sol"; +import "../FeePoolState.sol"; +import "../FeePool.sol"; + +interface ISynthetixNamedContract { + // solhint-disable func-name-mixedcase + function CONTRACT_NAME() external view returns (bytes32); +} + +// solhint-disable contract-name-camelcase +contract Migration_PeacockOptimism is BaseMigration { + // https://explorer.optimism.io/address/0x6d4a64C57612841c2C6745dB2a4E4db34F002D20; + address public constant OWNER = 0x6d4a64C57612841c2C6745dB2a4E4db34F002D20; + + // ---------------------------- + // EXISTING SYNTHETIX CONTRACTS + // ---------------------------- + + // https://explorer.optimism.io/address/0x95A6a3f44a70172E7d50a9e28c85Dfd712756B8C + AddressResolver public constant addressresolver_i = AddressResolver(0x95A6a3f44a70172E7d50a9e28c85Dfd712756B8C); + // https://explorer.optimism.io/address/0x4a16A42407AA491564643E1dfc1fd50af29794eF + Proxy public constant proxyfeepool_i = Proxy(0x4a16A42407AA491564643E1dfc1fd50af29794eF); + // https://explorer.optimism.io/address/0x41140Bf6498a36f2E44eFd49f21dAe3bbb7367c8 + FeePoolEternalStorage public constant feepooleternalstorage_i = + FeePoolEternalStorage(0x41140Bf6498a36f2E44eFd49f21dAe3bbb7367c8); + // https://explorer.optimism.io/address/0x6e0d26cffc3a63d763F1546f749bf62ebC7d72D8 + FeePoolState public constant feepoolstate_i = FeePoolState(0x6e0d26cffc3a63d763F1546f749bf62ebC7d72D8); + // https://explorer.optimism.io/address/0xFDf3Be612c65464AEB4859047350a6220F304F52 + FeePool public constant feepool_i = FeePool(0xFDf3Be612c65464AEB4859047350a6220F304F52); + + // ---------------------------------- + // NEW CONTRACTS DEPLOYED TO BE ADDED + // ---------------------------------- + + // https://explorer.optimism.io/address/0xFDf3Be612c65464AEB4859047350a6220F304F52 + address public constant new_FeePool_contract = 0xFDf3Be612c65464AEB4859047350a6220F304F52; + + constructor() public BaseMigration(OWNER) {} + + function contractsRequiringOwnership() public pure returns (address[] memory contracts) { + contracts = new address[](5); + contracts[0] = address(addressresolver_i); + contracts[1] = address(proxyfeepool_i); + contracts[2] = address(feepooleternalstorage_i); + contracts[3] = address(feepoolstate_i); + contracts[4] = address(feepool_i); + } + + function migrate(address currentOwner) external onlyDeployer { + require(owner == currentOwner, "Only the assigned owner can be re-assigned when complete"); + + require( + ISynthetixNamedContract(new_FeePool_contract).CONTRACT_NAME() == "FeePool", + "Invalid contract supplied for FeePool" + ); + + // ACCEPT OWNERSHIP for all contracts that require ownership to make changes + acceptAll(); + + // MIGRATION + // Import all new contracts into the address resolver; + addressresolver_importAddresses_0(); + // Rebuild the resolver caches in all MixinResolver contracts - batch 1; + addressresolver_rebuildCaches_1(); + // Ensure the ProxyFeePool contract has the correct FeePool target set; + proxyfeepool_i.setTarget(Proxyable(new_FeePool_contract)); + // Ensure the FeePool contract can write to its EternalStorage; + feepooleternalstorage_i.setAssociatedContract(new_FeePool_contract); + // Ensure the FeePool contract can write to its State; + feepoolstate_i.setFeePool(IFeePool(new_FeePool_contract)); + // Import fee period from existing fee pool at index 0; + importFeePeriod_0(); + // Import fee period from existing fee pool at index 1; + importFeePeriod_1(); + + // NOMINATE OWNERSHIP back to owner for aforementioned contracts + nominateAll(); + } + + function acceptAll() internal { + address[] memory contracts = contractsRequiringOwnership(); + for (uint i = 0; i < contracts.length; i++) { + Owned(contracts[i]).acceptOwnership(); + } + } + + function nominateAll() internal { + address[] memory contracts = contractsRequiringOwnership(); + for (uint i = 0; i < contracts.length; i++) { + returnOwnership(contracts[i]); + } + } + + function addressresolver_importAddresses_0() internal { + bytes32[] memory addressresolver_importAddresses_names_0_0 = new bytes32[](1); + addressresolver_importAddresses_names_0_0[0] = bytes32("FeePool"); + address[] memory addressresolver_importAddresses_destinations_0_1 = new address[](1); + addressresolver_importAddresses_destinations_0_1[0] = address(new_FeePool_contract); + addressresolver_i.importAddresses( + addressresolver_importAddresses_names_0_0, + addressresolver_importAddresses_destinations_0_1 + ); + } + + function addressresolver_rebuildCaches_1() internal { + MixinResolver[] memory addressresolver_rebuildCaches_destinations_1_0 = new MixinResolver[](11); + addressresolver_rebuildCaches_destinations_1_0[0] = MixinResolver(0x47eE58801C1AC44e54FF2651aE50525c5cfc66d0); + addressresolver_rebuildCaches_destinations_1_0[1] = MixinResolver(0xFe06fbe87E9f705B5D337D82dF8Fd812774974F9); + addressresolver_rebuildCaches_destinations_1_0[2] = MixinResolver(0xA2412e0654CdD40F5677Aaad1a0c572e75dF246C); + addressresolver_rebuildCaches_destinations_1_0[3] = MixinResolver(0x27be2EFAd45DeBd732C1EBf5C9F7b49D498D4a93); + addressresolver_rebuildCaches_destinations_1_0[4] = MixinResolver(0x78aAA3fb165deCAA729DFE3cf0E97Ab6FCF484da); + addressresolver_rebuildCaches_destinations_1_0[5] = MixinResolver(0xBD2657CF89F930F27eE1854EF4B389773DF43b29); + addressresolver_rebuildCaches_destinations_1_0[6] = MixinResolver(0x8Ce809a955DB85b41e7A378D7659e348e0C6AdD2); + addressresolver_rebuildCaches_destinations_1_0[7] = MixinResolver(0xF33e7B48538C9D0480a48f3b5eEf79026e2a28f6); + addressresolver_rebuildCaches_destinations_1_0[8] = MixinResolver(0x308AD16ef90fe7caCb85B784A603CB6E71b1A41a); + addressresolver_rebuildCaches_destinations_1_0[9] = MixinResolver(0xEbCe9728E2fDdC26C9f4B00df5180BdC5e184953); + addressresolver_rebuildCaches_destinations_1_0[10] = MixinResolver(new_FeePool_contract); + addressresolver_i.rebuildCaches(addressresolver_rebuildCaches_destinations_1_0); + } + + function importFeePeriod_0() internal { + // https://explorer.optimism.io/address/0xbc12131c93Da011B2844FA76c373A8cf5b0db4B5; + FeePool existingFeePool = FeePool(0xbc12131c93Da011B2844FA76c373A8cf5b0db4B5); + // https://explorer.optimism.io/address/0xFDf3Be612c65464AEB4859047350a6220F304F52; + FeePool newFeePool = FeePool(0xFDf3Be612c65464AEB4859047350a6220F304F52); + ( + uint64 feePeriodId_0, + uint64 startingDebtIndex_0, + uint64 startTime_0, + uint feesToDistribute_0, + uint feesClaimed_0, + uint rewardsToDistribute_0, + uint rewardsClaimed_0 + ) = existingFeePool.recentFeePeriods(0); + newFeePool.importFeePeriod( + 0, + feePeriodId_0, + startingDebtIndex_0, + startTime_0, + feesToDistribute_0, + feesClaimed_0, + rewardsToDistribute_0, + rewardsClaimed_0 + ); + } + + function importFeePeriod_1() internal { + // https://explorer.optimism.io/address/0xbc12131c93Da011B2844FA76c373A8cf5b0db4B5; + FeePool existingFeePool = FeePool(0xbc12131c93Da011B2844FA76c373A8cf5b0db4B5); + // https://explorer.optimism.io/address/0xFDf3Be612c65464AEB4859047350a6220F304F52; + FeePool newFeePool = FeePool(0xFDf3Be612c65464AEB4859047350a6220F304F52); + ( + uint64 feePeriodId_1, + uint64 startingDebtIndex_1, + uint64 startTime_1, + uint feesToDistribute_1, + uint feesClaimed_1, + uint rewardsToDistribute_1, + uint rewardsClaimed_1 + ) = existingFeePool.recentFeePeriods(1); + newFeePool.importFeePeriod( + 1, + feePeriodId_1, + startingDebtIndex_1, + startTime_1, + feesToDistribute_1, + feesClaimed_1, + rewardsToDistribute_1, + rewardsClaimed_1 + ); + } +} diff --git a/contracts/test-helpers/TestableDynamicFee.sol b/contracts/test-helpers/TestableDynamicFee.sol new file mode 100644 index 0000000000..121a10e323 --- /dev/null +++ b/contracts/test-helpers/TestableDynamicFee.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.5.16; + +// Libraries +import "../Exchanger.sol"; + +contract TestableDynamicFee is Exchanger { + constructor(address _owner, address _resolver) public Exchanger(_owner, _resolver) {} + + function thresholdedAbsDeviationRatio( + uint price, + uint previousPrice, + uint threshold + ) external view returns (uint) { + return _thresholdedAbsDeviationRatio(price, previousPrice, threshold); + } + + function dynamicFeeCalculation( + uint[] calldata prices, + uint threshold, + uint weightDecay + ) external view returns (uint) { + return _dynamicFeeCalculation(prices, threshold, weightDecay); + } +} diff --git a/hardhat.config.js b/hardhat.config.js index da0b4644e0..d8115cd303 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -75,6 +75,12 @@ module.exports = { url: process.env.OVM_PROVIDER_URL || 'https://kovan.optimism.io/', chainId: 69, }, + local: { + url: process.env.PROVIDER_URL || 'http://localhost:8545/', + }, + 'local-ovm': { + url: process.env.OVM_PROVIDER_URL || 'http://localhost:9545/', + }, }, gasReporter: { enabled: false, diff --git a/hardhat/tasks/task-node.js b/hardhat/tasks/task-node.js index 42dc834ca1..1dbec4a4cc 100644 --- a/hardhat/tasks/task-node.js +++ b/hardhat/tasks/task-node.js @@ -7,6 +7,7 @@ const { TASK_NODE_SERVER_READY } = require('hardhat/builtin-tasks/task-names'); task('node', 'Run a node') .addOptionalParam('targetNetwork', 'Target network to simulate, i.e. mainnet or local', 'local') + .addFlag('useOvm', 'Use OVM', false) .setAction(async (taskArguments, hre, runSuper) => { // Enable forking if necessary if (taskArguments.fork) { @@ -17,12 +18,18 @@ task('node', 'Run a node') ); } const network = taskArguments.targetNetwork; + const useOvm = taskArguments.useOvm; if (network !== 'local') { + const networkHostReplace = (taskArguments.useOvm ? 'optimism-' : '') + network; + if (network === 'mainnet') { - taskArguments.fork = process.env.PROVIDER_URL_MAINNET; + taskArguments.fork = process.env.PROVIDER_URL_MAINNET.replace( + 'network', + networkHostReplace + ); } taskArguments.fork = - taskArguments.fork || process.env.PROVIDER_URL.replace('network', network); + taskArguments.fork || process.env.PROVIDER_URL.replace('network', networkHostReplace); console.log(yellow(`Forking ${network}...`)); } @@ -37,13 +44,20 @@ task('node', 'Run a node') // Unlock any specified accounts, plus those // known as protocol users of the target network. const { getUsers } = wrap({ network, fs, path }); - const accounts = getUsers({ network }) + const accounts = getUsers({ network, useOvm }) .filter(account => account.name !== 'fee') .filter(account => account.name !== 'zero') .concat(knownAccounts[network] || []); await Promise.all( - accounts.map(account => { - console.log(gray(` > Unlocking ${account.name}: ${account.address}`)); + accounts.map(async account => { + console.log(gray(` > Unlocking & Funding ${account.name}: ${account.address}`)); + + // owner might not have eth when we impersonate them + + await provider.request({ + method: 'hardhat_setBalance', + params: [account.address, '0x10000000000000000000000'], + }); return provider.request({ method: 'hardhat_impersonateAccount', diff --git a/hardhat/tasks/task-test-integration.js b/hardhat/tasks/task-test-integration.js index 13ce60807f..90e1dfb0ca 100644 --- a/hardhat/tasks/task-test-integration.js +++ b/hardhat/tasks/task-test-integration.js @@ -81,6 +81,13 @@ task('test:integration:l2', 'run isolated layer 2 production tests') .addFlag('debugOptimism', 'Debug Optimism activity') .addFlag('compile', 'Compile an l2 instance before running the tests') .addFlag('deploy', 'Deploy an l2 instance before running the tests') + .addFlag('useSips', 'Use sources from SIPs directly, instead of releases') + .addFlag('useFork', 'Run the tests against a fork of mainnet') + .addOptionalParam( + 'providerPort', + 'The target port for the running local chain to test on', + '8545' + ) .setAction(async (taskArguments, hre) => { hre.config.paths.tests = './test/integration/l2/'; hre.config.debugOptimism = taskArguments.debugOptimism; @@ -89,25 +96,47 @@ task('test:integration:l2', 'run isolated layer 2 production tests') const providerUrl = (hre.config.providerUrl = 'http://localhost'); hre.config.providerPortL1 = '9545'; - const providerPortL2 = (hre.config.providerPortL2 = '8545'); + const providerPortL2 = (hre.config.providerPortL2 = taskArguments.providerPort); const useOvm = true; - const buildPath = path.join(__dirname, '..', '..', `${BUILD_FOLDER}-ovm`); + const buildPath = path.join(__dirname, '..', '..', BUILD_FOLDER); if (taskArguments.compile) { await compileInstance({ useOvm, buildPath }); } + if (taskArguments.useFork) { + hre.config.fork = true; + } if (taskArguments.deploy) { - const network = 'local'; - await prepareDeploy({ network, synthsToAdd, useOvm }); - await deployInstance({ - addNewSynths: true, - buildPath, - network, - providerPort: providerPortL2, - providerUrl, - useOvm, - }); + if (taskArguments.useFork) { + await prepareDeploy({ + network: 'mainnet', + synthsToAdd, + useOvm, + useSips: taskArguments.useSips, + }); + await deployInstance({ + addNewSynths: true, + buildPath, + freshDeploy: false, + network: 'mainnet', + providerPort: providerPortL2, + providerUrl, + useFork: true, + useOvm, + }); + } else { + const network = 'local'; + await prepareDeploy({ network, synthsToAdd, useOvm, useReleases: false, useSips: false }); + await deployInstance({ + addNewSynths: true, + buildPath, + network, + providerPort: providerPortL2, + providerUrl, + useOvm, + }); + } hre.config.addedSynths = synthsToAdd; } @@ -127,12 +156,10 @@ task('test:integration:dual', 'run integrated layer 1 and layer 2 production tes const providerUrl = (hre.config.providerUrl = 'http://localhost'); const providerPortL1 = (hre.config.providerPortL1 = '9545'); const providerPortL2 = (hre.config.providerPortL2 = '8545'); - const buildPathEvm = path.join(__dirname, '..', '..', BUILD_FOLDER); - const buildPathOvm = path.join(__dirname, '..', '..', `${BUILD_FOLDER}-ovm`); + const buildPath = path.join(__dirname, '..', '..', BUILD_FOLDER); if (taskArguments.compile) { - await compileInstance({ useOvm: false, buildPath: buildPathEvm }); - await compileInstance({ useOvm: true, buildPath: buildPathOvm }); + await compileInstance({ useOvm: false, buildPath: buildPath }); } if (taskArguments.deploy) { @@ -140,14 +167,14 @@ task('test:integration:dual', 'run integrated layer 1 and layer 2 production tes useOvm: false, providerUrl, providerPort: providerPortL1, - buildPath: buildPathEvm, + buildPath: buildPath, }); await deployInstance({ useOvm: true, providerUrl, providerPort: providerPortL2, - buildPath: buildPathOvm, + buildPath: buildPath, }); } diff --git a/index.js b/index.js index f2d94e14ab..ac5d9b7d38 100644 --- a/index.js +++ b/index.js @@ -137,6 +137,10 @@ const defaults = { crypto: w3utils.toWei('0.01'), index: w3utils.toWei('0.01'), }, + EXCHANGE_DYNAMIC_FEE_THRESHOLD: w3utils.toWei('0.004'), // 40 bps + EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY: w3utils.toWei('0.9'), // dynamic fee weight decay for each round + EXCHANGE_DYNAMIC_FEE_ROUNDS: '10', // dynamic fee rounds + EXCHANGE_MAX_DYNAMIC_FEE: w3utils.toWei('0.05'), // cap max dynamic fee to 5% MINIMUM_STAKE_TIME: (3600 * 24).toString(), // 1 days DEBT_SNAPSHOT_STALE_TIME: (43800).toString(), // 12 hour heartbeat + 10 minutes mining time AGGREGATOR_WARNING_FLAGS: { @@ -523,9 +527,12 @@ const getUsers = ({ network = 'mainnet', user, useOvm = false } = {}) => { oracle: '0xaC1ED4Fabbd5204E02950D68b6FC8c446AC95362', }), kovan: Object.assign({}, base), - 'kovan-ovm': Object.assign({}, base), + 'kovan-ovm': Object.assign({}, base, { + owner: '0x7509FeAEE952F7dA93f746CF7134CFDE8f249C94', + }), 'mainnet-ovm': Object.assign({}, base, { owner: '0x6d4a64C57612841c2C6745dB2a4E4db34F002D20', + deployer: '0xDe910777C787903F78C89e7a0bf7F4C435cBB1Fe', }), rinkeby: Object.assign({}, base), ropsten: Object.assign({}, base), diff --git a/package-lock.json b/package-lock.json index 889883594d..4f3b52fdde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "synthetix", - "version": "2.56.1", + "version": "2.57.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "synthetix", - "version": "2.56.1", + "version": "2.57.1", "license": "MIT", "dependencies": { "abi-decoder": "2.3.0", @@ -54,7 +54,7 @@ "ethers": "5.4.6", "execa": "^4.1.0", "fs-extra": "9.0.1", - "hardhat": "2.6.4", + "hardhat": "2.8.2", "hardhat-gas-reporter": "~1.0.4", "hardhat-interact": "^0.2.0", "husky": "^4.3.0", @@ -2576,10 +2576,13 @@ } }, "node_modules/@solidity-parser/parser": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.11.1.tgz", - "integrity": "sha512-H8BSBoKE8EubJa0ONqecA2TviT3TnHeC4NpgnAHSUiuhZoQBfPB4L2P9bs8R6AoTW10Endvh3vc+fomVMIDIYQ==", - "dev": true + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.0.tgz", + "integrity": "sha512-cX0JJRcmPtNUJpzD2K7FdA7qQsTOk1UZnFx2k7qAg9ZRvuaH5NBe5IEdBMXGlmf2+FmjhqbygJ26H8l2SV7aKQ==", + "dev": true, + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } }, "node_modules/@synthetixio/wei": { "version": "2.56.3", @@ -8527,15 +8530,6 @@ } } }, - "node_modules/eth-gas-reporter/node_modules/@solidity-parser/parser": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.0.tgz", - "integrity": "sha512-cX0JJRcmPtNUJpzD2K7FdA7qQsTOk1UZnFx2k7qAg9ZRvuaH5NBe5IEdBMXGlmf2+FmjhqbygJ26H8l2SV7aKQ==", - "dev": true, - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, "node_modules/eth-gas-reporter/node_modules/@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", @@ -13121,19 +13115,19 @@ } }, "node_modules/hardhat": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.6.4.tgz", - "integrity": "sha512-6QNfu1FptjtyGJ+jBR7LMX7AMY9gWWw9kAUD7v0YZNZH1ZBgsZdMHqXKiSzO5pLQXo+fy9zZovKAUNYbjQ/1fw==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.8.2.tgz", + "integrity": "sha512-cBUqzZGOi+lwKHArWl5Be7zeFIwlu1IUXOna6k5XhORZ8hAWDVbAJBVfxgmjkcX5GffIf0C5g841zRxo36sQ5g==", "dev": true, "dependencies": { - "@ethereumjs/block": "^3.4.0", - "@ethereumjs/blockchain": "^5.4.0", - "@ethereumjs/common": "^2.4.0", - "@ethereumjs/tx": "^3.3.0", - "@ethereumjs/vm": "^5.5.2", + "@ethereumjs/block": "^3.6.0", + "@ethereumjs/blockchain": "^5.5.0", + "@ethereumjs/common": "^2.6.0", + "@ethereumjs/tx": "^3.4.0", + "@ethereumjs/vm": "^5.6.0", "@ethersproject/abi": "^5.1.2", "@sentry/node": "^5.18.1", - "@solidity-parser/parser": "^0.11.0", + "@solidity-parser/parser": "^0.14.0", "@types/bn.js": "^5.1.0", "@types/lru-cache": "^5.1.0", "abort-controller": "^3.0.0", @@ -13148,7 +13142,7 @@ "eth-sig-util": "^2.5.2", "ethereum-cryptography": "^0.1.2", "ethereumjs-abi": "^0.6.8", - "ethereumjs-util": "^7.1.0", + "ethereumjs-util": "^7.1.3", "find-up": "^2.1.0", "fp-ts": "1.19.3", "fs-extra": "^7.0.1", @@ -13157,9 +13151,9 @@ "immutable": "^4.0.0-rc.12", "io-ts": "1.10.4", "lodash": "^4.17.11", - "merkle-patricia-tree": "^4.2.0", + "merkle-patricia-tree": "^4.2.2", "mnemonist": "^0.38.0", - "mocha": "^7.1.2", + "mocha": "^7.2.0", "node-fetch": "^2.6.0", "qs": "^6.7.0", "raw-body": "^2.4.1", @@ -13171,7 +13165,7 @@ "stacktrace-parser": "^0.1.10", "true-case-path": "^2.2.1", "tsort": "0.0.1", - "uuid": "^3.3.2", + "uuid": "^8.3.2", "ws": "^7.4.6" }, "bin": { @@ -14175,6 +14169,15 @@ "node": ">= 4.0.0" } }, + "node_modules/hardhat/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/hardhat/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -31074,10 +31077,13 @@ "dev": true }, "@solidity-parser/parser": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.11.1.tgz", - "integrity": "sha512-H8BSBoKE8EubJa0ONqecA2TviT3TnHeC4NpgnAHSUiuhZoQBfPB4L2P9bs8R6AoTW10Endvh3vc+fomVMIDIYQ==", - "dev": true + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.0.tgz", + "integrity": "sha512-cX0JJRcmPtNUJpzD2K7FdA7qQsTOk1UZnFx2k7qAg9ZRvuaH5NBe5IEdBMXGlmf2+FmjhqbygJ26H8l2SV7aKQ==", + "dev": true, + "requires": { + "antlr4ts": "^0.5.0-alpha.4" + } }, "@synthetixio/wei": { "version": "2.56.3", @@ -36143,15 +36149,6 @@ "sync-request": "^6.0.0" }, "dependencies": { - "@solidity-parser/parser": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.0.tgz", - "integrity": "sha512-cX0JJRcmPtNUJpzD2K7FdA7qQsTOk1UZnFx2k7qAg9ZRvuaH5NBe5IEdBMXGlmf2+FmjhqbygJ26H8l2SV7aKQ==", - "dev": true, - "requires": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, "@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", @@ -39828,19 +39825,19 @@ } }, "hardhat": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.6.4.tgz", - "integrity": "sha512-6QNfu1FptjtyGJ+jBR7LMX7AMY9gWWw9kAUD7v0YZNZH1ZBgsZdMHqXKiSzO5pLQXo+fy9zZovKAUNYbjQ/1fw==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.8.2.tgz", + "integrity": "sha512-cBUqzZGOi+lwKHArWl5Be7zeFIwlu1IUXOna6k5XhORZ8hAWDVbAJBVfxgmjkcX5GffIf0C5g841zRxo36sQ5g==", "dev": true, "requires": { - "@ethereumjs/block": "^3.4.0", - "@ethereumjs/blockchain": "^5.4.0", - "@ethereumjs/common": "^2.4.0", - "@ethereumjs/tx": "^3.3.0", - "@ethereumjs/vm": "^5.5.2", + "@ethereumjs/block": "^3.6.0", + "@ethereumjs/blockchain": "^5.5.0", + "@ethereumjs/common": "^2.6.0", + "@ethereumjs/tx": "^3.4.0", + "@ethereumjs/vm": "^5.6.0", "@ethersproject/abi": "^5.1.2", "@sentry/node": "^5.18.1", - "@solidity-parser/parser": "^0.11.0", + "@solidity-parser/parser": "^0.14.0", "@types/bn.js": "^5.1.0", "@types/lru-cache": "^5.1.0", "abort-controller": "^3.0.0", @@ -39855,7 +39852,7 @@ "eth-sig-util": "^2.5.2", "ethereum-cryptography": "^0.1.2", "ethereumjs-abi": "^0.6.8", - "ethereumjs-util": "^7.1.0", + "ethereumjs-util": "^7.1.3", "find-up": "^2.1.0", "fp-ts": "1.19.3", "fs-extra": "^7.0.1", @@ -39864,9 +39861,9 @@ "immutable": "^4.0.0-rc.12", "io-ts": "1.10.4", "lodash": "^4.17.11", - "merkle-patricia-tree": "^4.2.0", + "merkle-patricia-tree": "^4.2.2", "mnemonist": "^0.38.0", - "mocha": "^7.1.2", + "mocha": "^7.2.0", "node-fetch": "^2.6.0", "qs": "^6.7.0", "raw-body": "^2.4.1", @@ -39878,7 +39875,7 @@ "stacktrace-parser": "^0.1.10", "true-case-path": "^2.2.1", "tsort": "0.0.1", - "uuid": "^3.3.2", + "uuid": "^8.3.2", "ws": "^7.4.6" }, "dependencies": { @@ -40321,6 +40318,12 @@ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index 33bb4085a2..59e02668ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "synthetix", - "version": "2.56.1", + "version": "2.57.1", "license": "MIT", "author": "Synthetix", "description": "The smart contracts which make up the Synthetix system. (synthetix.io)", @@ -15,10 +15,10 @@ "build:ci": "node .circleci/pack.js", "slither": "python3 -m venv .venv && .venv/bin/python -m pip install slither-analyzer && .venv/bin/python -m slither .", "pack": "webpack --mode production", - "prepublishOnly": "npm run describe && npm run pack", "fork": "node --max-old-space-size=4096 ./node_modules/.bin/hardhat node", - "fork:mainnet": "node --max-old-space-size=4096 ./node_modules/.bin/hardhat node --target-network mainnet", - "test": "hardhat test", + "fork:mainnet": "node --max-old-space-size=4096 ./node_modules/.bin/hardhat node --target-network mainnet --port 9545", + "fork:ovm": "node --max-old-space-size=4096 ./node_modules/.bin/hardhat node --target-network mainnet --use-ovm", + "test": "node --max-old-space-size=4096 ./node_modules/.bin/hardhat test", "describe": "hardhat describe", "test:deployments": "mocha test/deployments -- --timeout 60000", "test:etherscan": "node test/etherscan", @@ -106,7 +106,7 @@ "ethers": "5.4.6", "execa": "^4.1.0", "fs-extra": "9.0.1", - "hardhat": "2.6.4", + "hardhat": "2.8.2", "hardhat-gas-reporter": "~1.0.4", "hardhat-interact": "^0.2.0", "husky": "^4.3.0", diff --git a/publish/deployed/kovan-ovm/deployment.json b/publish/deployed/kovan-ovm/deployment.json index bf603e0ecf..7bab2aaae2 100644 --- a/publish/deployed/kovan-ovm/deployment.json +++ b/publish/deployed/kovan-ovm/deployment.json @@ -72,15 +72,6 @@ "txn": "", "network": "kovan" }, - "RewardEscrow": { - "name": "RewardEscrow", - "address": "0x9952e42fF92149f48b3b7dee3f921A6DD106F79F", - "source": "RewardEscrow", - "link": "https://kovan-explorer.optimism.io/address/0x9952e42fF92149f48b3b7dee3f921A6DD106F79F", - "timestamp": "2021-01-14T17:20:33.145Z", - "txn": "", - "network": "kovan" - }, "RewardEscrowV2": { "name": "RewardEscrowV2", "address": "0xB613d148E47525478bD8A91eF7Cf2F7F63d81858", @@ -164,11 +155,11 @@ }, "FeePool": { "name": "FeePool", - "address": "0x2F737bf6a32bf3AcBef4d5148DA507569204Fb61", + "address": "0x129fd2f3a799bD156e8c00599760AfC2f0f953dA", "source": "FeePool", - "link": "https://kovan-explorer.optimism.io/address/0x2F737bf6a32bf3AcBef4d5148DA507569204Fb61", - "timestamp": "2021-10-27T22:52:55.212Z", - "txn": "", + "link": "https://kovan-explorer.optimism.io/address/0x129fd2f3a799bD156e8c00599760AfC2f0f953dA", + "timestamp": "2022-01-14T22:42:00.000Z", + "txn": "https://kovan-explorer.optimism.io/tx/0x55afbfcde0349a562421f00fc4a583508b063931289e3f1e968ad0e1965a3701", "network": "kovan" }, "FeePoolState": { @@ -12355,7 +12346,7 @@ } }, "FeePool": { - "bytecode": "6080604052631cd554d160e21b6007553480156200001c57600080fd5b506040516200472c3803806200472c8339810160408190526200003f9162000221565b8080621baf8085856001600160a01b038116620000795760405162461bcd60e51b8152600401620000709062000343565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620000c69184906200030b565b60405180910390a1506000546001600160a01b0316620000fa5760405162461bcd60e51b8152600401620000709062000331565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9062000147908390620002fb565b60405180910390a1504201600455600580546001600160a01b0319166001600160a01b0392909216919091179055506001620001846000620001e2565b80546001600160401b0319166001600160401b039290921691909117905542620001af6000620001e2565b80546001600160401b0392909216600160801b02600160801b600160c01b0319909216919091179055506200039e915050565b60006008600260ff16836012540181620001f857fe5b06600281106200020457fe5b6005020192915050565b80516200021b8162000384565b92915050565b6000806000606084860312156200023757600080fd5b60006200024586866200020e565b935050602062000258868287016200020e565b92505060406200026b868287016200020e565b9150509250925092565b620002808162000370565b82525050565b62000280816200035e565b6000620002a060118362000355565b7013dddb995c881b5d5cdd081899481cd95d607a1b815260200192915050565b6000620002cf60198362000355565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b602081016200021b828462000275565b604081016200031b828562000275565b6200032a602083018462000286565b9392505050565b602080825281016200021b8162000291565b602080825281016200021b81620002c0565b90815260200190565b60006001600160a01b0382166200021b565b60006200021b8260006200021b826200035e565b6200038f816200035e565b81146200039b57600080fd5b50565b61437e80620003ae6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80636de813f111610145578063b410a034116100bd578063d67bdd251161008c578063eb1edd6111610071578063eb1edd611461045c578063ec55688914610464578063fd1f498d1461046c57610241565b8063d67bdd251461044c578063e0e6393d1461045457610241565b8063b410a03414610414578063bc67f8321461041c578063cff2ddad1461042f578063d294f0931461044457610241565b8063899ffef41161011457806397107d6d116100f957806397107d6d146103e6578063ac834193146103f9578063b10090b81461040157610241565b8063899ffef4146103c95780638da5cb5b146103de57610241565b80636de813f11461039e57806374185360146103a657806379ba5097146103ae57806386645274146103b657610241565b806333140016116101d857806353a47bb7116101a757806359a2f19f1161018c57806359a2f19f14610370578063614d08f8146103835780636466f45e1461038b57610241565b806353a47bb714610353578063569249d01461036857610241565b806333140016146102fd5780633ebc457a1461031d5780633fcd22401461032557806346ba2d901461034b57610241565b80631627540c116102145780631627540c146102b857806322425fa4146102cd57806322bf55ef146102d55780632af64bd3146102e857610241565b806304f3bcec1461024657806307ea50cd146102645780630813071c146102845780630de5861514610297575b600080fd5b61024e61047f565b60405161025b9190614023565b60405180910390f35b610277610272366004613262565b61048e565b60405161025b9190613f40565b6102776102923660046132a6565b610563565b6102aa6102a5366004613262565b6106af565b60405161025b929190613f5c565b6102cb6102c6366004613262565b610731565b005b61027761078f565b6102cb6102e3366004613387565b61079f565b6102f0610978565b60405161025b9190613f32565b61031061030b366004613262565b610aa8565b60405161025b9190613f13565b6102cb610d0c565b610338610333366004613387565b611112565b60405161025b97969594939291906141c0565b6102776111bb565b61035b6111c1565b60405161025b9190613e40565b6102776111d0565b6102f061037e366004613262565b61122b565b61027761123d565b6102f0610399366004613262565b611261565b61027761138d565b6102cb6113e2565b6102cb611534565b6102cb6103c43660046132e0565b6115d0565b6103d1611710565b60405161025b9190613f21565b61035b611a30565b6102cb6103f4366004613262565b611a3f565b610277611a92565b6102cb61040f366004613405565b611b32565b610277611d2c565b6102cb61042a366004613262565b611d36565b610437611d60565b60405161025b9190614228565b6102f0611d65565b61035b611ddc565b610277611deb565b61035b611df5565b61024e611e0d565b6102cb61047a366004613387565b611e1c565b6005546001600160a01b031681565b6000610498611e99565b6001600160a01b031663bdc963d87f6c6173745f6665655f7769746864726177616c00000000000000000000000000846040516020016104d9929190613dce565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161050b9190613f40565b60206040518083038186803b15801561052357600080fd5b505afa158015610537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061055b919081019061334b565b90505b919050565b60008161058b5760405162461bcd60e51b815260040161058290614192565b60405180910390fd5b600282106105ab5760405162461bcd60e51b815260040161058290614142565b6105b760018303611ec4565b5468010000000000000000900467ffffffffffffffff166105da575060006106a9565b600061060a60016105ed60018603611ec4565b5468010000000000000000900467ffffffffffffffff1690611eee565b9050600080610617611f16565b6001600160a01b031663d29c000a87856040518363ffffffff1660e01b8152600401610644929190613e92565b604080518083038186803b15801561065b57600080fd5b505afa15801561066f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061069391908101906133d5565b90925090506106a3838383611f41565b93505050505b92915050565b6000806106ba61317a565b6106c384610aa8565b905060008060015b6002811015610724576106f08482600281106106e357fe5b602002015151849061208c565b925061071a84826002811061070157fe5b602002015160016020020151839063ffffffff61208c16565b91506001016106cb565b509093509150505b915091565b6107396120b1565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610784908390613e40565b60405180910390a150565b60006107996120dd565b90505b90565b60006107a96121a4565b6001600160a01b0316331490506000806107c16121cf565b6001600160a01b03166316b2213f336040518263ffffffff1660e01b81526004016107ec9190613e4e565b60206040518083038186803b15801561080457600080fd5b505afa158015610818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061083c919081019061334b565b14159050600061084a6121e3565b6001600160a01b031663b38988f7336040518263ffffffff1660e01b81526004016108759190613e4e565b60206040518083038186803b15801561088d57600080fd5b505afa1580156108a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108c5919081019061332d565b905060006108d161220e565b6001600160a01b0316336001600160a01b031614905060006108f1612239565b6001600160a01b0316336001600160a01b031614905084806109105750835b806109185750825b806109205750815b806109285750805b6109445760405162461bcd60e51b815260040161058290614042565b610962866109526000611ec4565b600101549063ffffffff61208c16565b61096c6000611ec4565b60010155505050505050565b60006060610984611710565b905060005b8151811015610a9f5760008282815181106109a057fe5b602090810291909101810151600081815260069092526040918290205460055492517f21f8a7210000000000000000000000000000000000000000000000000000000081529193506001600160a01b039081169216906321f8a72190610a0a908590600401613f40565b60206040518083038186803b158015610a2257600080fd5b505afa158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a5a9190810190613288565b6001600160a01b0316141580610a8557506000818152600660205260409020546001600160a01b0316155b15610a96576000935050505061079c565b50600101610989565b50600191505090565b610ab061317a565b6000806000610abd611f16565b6040517fb326f84e0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0382169063b326f84e90610b08908890600090600401613e77565b604080518083038186803b158015610b1f57600080fd5b505afa158015610b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b5791908101906133d5565b909350915081158015610b68575082155b15610b8057610b7561317a565b935061055e92505050565b600080610b8f60008686612264565b8751829052875160200181905290925090506000610bac8861048e565b905060015b8015610d005760001981016000610bc782611ec4565b5468010000000000000000900467ffffffffffffffff1690508015801590610c015750610bf383611ec4565b5467ffffffffffffffff1684105b15610cf5576000610c1982600163ffffffff611eee16565b6040517fd29c000a0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0389169063d29c000a90610c63908f908590600401613e92565b604080518083038186803b158015610c7a57600080fd5b505afa158015610c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610cb291908101906133d5565b909a509850610cc2848b8b612264565b9097509550868b8560028110610cd457fe5b602002015152858b8560028110610ce757fe5b602002015160016020020152505b505060001901610bb1565b50505050505050919050565b610d14612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015610d4c57600080fd5b505afa158015610d60573d6000803e3d6000fd5b505050506000610d6e6120dd565b11610d8b5760405162461bcd60e51b8152600401610582906141a2565b610d936120dd565b4203610d9f6000611ec4565b54600160801b900467ffffffffffffffff161115610dcf5760405162461bcd60e51b815260040161058290614062565b610dd761220e565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e1157600080fd5b505af1158015610e25573d6000803e3d6000fd5b50505050610e31612239565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e6b57600080fd5b505af1158015610e7f573d6000803e3d6000fd5b5060009250610e919150829050611ec4565b90506000610e9f6001611ec4565b9050610ed08260010154610ec483600201548460010154611eee90919063ffffffff16565b9063ffffffff61208c16565b610eda6000611ec4565b60010155600380830154600483015491830154610f0192610ec4919063ffffffff611eee16565b610f0b6000611ec4565b60030155601254610f4890600290610f3c90600190610f30908463ffffffff61208c16565b9063ffffffff611eee16565b9063ffffffff61233116565b601281905560089060028110610f5a57fe5b6005020180547fffffffffffffffff000000000000000000000000000000000000000000000000168155600060018083018290556002830182905560038301829055600490920155610fc690610faf81611ec4565b5467ffffffffffffffff169063ffffffff61208c16565b610fd06000611ec4565b805467ffffffffffffffff191667ffffffffffffffff92909216919091179055610ff8612361565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561103057600080fd5b505afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611068919081019061334b565b6110726000611ec4565b805467ffffffffffffffff9290921668010000000000000000026fffffffffffffffff000000000000000019909216919091179055426110b26000611ec4565b805467ffffffffffffffff92909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905561110e6110fe6001611ec4565b5467ffffffffffffffff1661238c565b5050565b60008060008060008060006111256131a7565b61112e89611ec4565b6040805160e081018252825467ffffffffffffffff808216808452680100000000000000008304821660208501819052600160801b909304909116938301849052600185015460608401819052600286015460808501819052600387015460a0860181905260049097015460c0909501859052919f929e50939c50929a5091985091965090945092505050565b60045481565b6001546001600160a01b031681565b60008060015b6002811015611225576111fc6111eb82611ec4565b60010154839063ffffffff61208c16565b915061121b61120a82611ec4565b60020154839063ffffffff611eee16565b91506001016111d6565b50905090565b600061123682612444565b5092915050565b7f466565506f6f6c0000000000000000000000000000000000000000000000000081565b600061126b612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156112a357600080fd5b505afa1580156112b7573d6000803e3d6000fd5b505050506112c3612538565b6112cb612577565b6003546040517f21f4ae570000000000000000000000000000000000000000000000000000000081526001600160a01b03928316926321f4ae579261131892879290911690600401613e5c565b60206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611368919081019061332d565b6113845760405162461bcd60e51b8152600401610582906140e2565b61055b826125a2565b60008060015b6002811015611225576113b96113a882611ec4565b60030154839063ffffffff61208c16565b91506113d86113c782611ec4565b60040154839063ffffffff611eee16565b9150600101611393565b60606113ec611710565b905060005b815181101561110e57600082828151811061140857fe5b602002602001015190506000600560009054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200161144a9190613e2a565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611476929190613f6a565b60206040518083038186803b15801561148e57600080fd5b505afa1580156114a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114c69190810190613288565b6000838152600660205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906115229084908490613f4e565b60405180910390a150506001016113f1565b6001546001600160a01b0316331461155e5760405162461bcd60e51b815260040161058290614052565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c926115a1926001600160a01b0391821692911690613e5c565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006115da6121cf565b6001600160a01b0316336001600160a01b031614905060006115fa612361565b6001600160a01b0316336001600160a01b031614905081806116195750805b6116355760405162461bcd60e51b815260040161058290614182565b61163d611f16565b6001600160a01b03166394e1a4488686866116586000611ec4565b5460405160e086901b7fffffffff000000000000000000000000000000000000000000000000000000001681526116ab9493929168010000000000000000900467ffffffffffffffff1690600401613ed5565b600060405180830381600087803b1580156116c557600080fd5b505af11580156116d9573d6000803e3d6000fd5b505050506117098585856116ed6000611ec4565b5468010000000000000000900467ffffffffffffffff16612697565b5050505050565b60608061171b612766565b60408051600d8082526101c0820190925291925060609190602082016101a0803883390190505090507f53797374656d53746174757300000000000000000000000000000000000000008160008151811061177257fe5b6020026020010181815250507f53796e7468657469780000000000000000000000000000000000000000000000816001815181106117ac57fe5b6020026020010181815250507f466565506f6f6c53746174650000000000000000000000000000000000000000816002815181106117e657fe5b6020026020010181815250507f466565506f6f6c457465726e616c53746f7261676500000000000000000000008160038151811061182057fe5b6020026020010181815250507f45786368616e67657200000000000000000000000000000000000000000000008160048151811061185a57fe5b6020026020010181815250506524b9b9bab2b960d11b8160058151811061187d57fe5b6020026020010181815250507f53796e7468657469785374617465000000000000000000000000000000000000816006815181106118b757fe5b6020026020010181815250507f526577617264457363726f775632000000000000000000000000000000000000816007815181106118f157fe5b6020026020010181815250507f44656c6567617465417070726f76616c730000000000000000000000000000008160088151811061192b57fe5b6020026020010181815250507f52657761726473446973747269627574696f6e000000000000000000000000008160098151811061196557fe5b6020026020010181815250507f436f6c6c61746572616c4d616e6167657200000000000000000000000000000081600a8151811061199f57fe5b6020026020010181815250507f57726170706572466163746f727900000000000000000000000000000000000081600b815181106119d957fe5b6020026020010181815250507f457468657257726170706572000000000000000000000000000000000000000081600c81518110611a1357fe5b602002602001018181525050611a2982826127c5565b9250505090565b6000546001600160a01b031681565b611a476120b1565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e90610784908390613e4e565b6000610799611b1e611aa261287a565b7387a479d8433121e4583d45d37b4a349b4350b79f63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611ae657600080fd5b505af4158015611afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ec4919081019061334b565b611b266128f1565b9063ffffffff61296816565b611b3a612992565b6004544210611b5b5760405162461bcd60e51b815260040161058290614152565b611b63612361565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b9b57600080fd5b505afa158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611bd3919081019061334b565b861115611bf25760405162461bcd60e51b815260040161058290614132565b6040518060e001604052808867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018667ffffffffffffffff168152602001858152602001848152602001838152602001828152506008611c62600260ff16610f3c8c60125461208c90919063ffffffff16565b60028110611c6c57fe5b82516005919091029190910180546020840151604085015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff000000000000000019166801000000000000000091851691909102177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b9390911692909202919091178155606082015160018201556080820151600282015560a0820151600382015560c0909101516004909101555050505050505050565b60006107996128f1565b611d3e612a00565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600281565b6000611d6f612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611da757600080fd5b505afa158015611dbb573d6000803e3d6000fd5b50505050611dc7612538565b600354610799906001600160a01b03166125a2565b6003546001600160a01b031681565b600061079961287a565b73feefeefeefeefeefeefeefeefeefeefeefeefeef81565b6002546001600160a01b031681565b6000611e26612a2a565b6003549091506001600160a01b0380831691161480611e4d5750336001600160a01b038216145b611e695760405162461bcd60e51b8152600401610582906140f2565b611e8782611e776000611ec4565b600301549063ffffffff61208c16565b611e916000611ec4565b600301555050565b60006107997f466565506f6f6c457465726e616c53746f726167650000000000000000000000612a51565b60006008600260ff16836012540181611ed957fe5b0660028110611ee457fe5b6005020192915050565b600082821115611f105760405162461bcd60e51b815260040161058290614092565b50900390565b60006107997f466565506f6f6c53746174650000000000000000000000000000000000000000612a51565b600080611f4c612361565b9050600061208085612074846001600160a01b03166308d95cd5886040518263ffffffff1660e01b8152600401611f839190613f40565b60206040518083038186803b158015611f9b57600080fd5b505afa158015611faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611fd3919081019061334b565b6040517f08d95cd50000000000000000000000000000000000000000000000000000000081526001600160a01b038716906308d95cd590612018908d90600401613f40565b60206040518083038186803b15801561203057600080fd5b505afa158015612044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612068919081019061334b565b9063ffffffff612aae16565b9063ffffffff612ac716565b925050505b9392505050565b6000828201838110156120855760405162461bcd60e51b815260040161058290614082565b6000546001600160a01b031633146120db5760405162461bcd60e51b815260040161058290614102565b565b60006120e7612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f666565506572696f644475726174696f6e0000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b60206040518083038186803b15801561216c57600080fd5b505afa158015612180573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610799919081019061334b565b60006107997f45786368616e6765720000000000000000000000000000000000000000000000612a51565b60006107996524b9b9bab2b960d11b612a51565b60006107997f436f6c6c61746572616c4d616e61676572000000000000000000000000000000612a51565b60006107997f4574686572577261707065720000000000000000000000000000000000000000612a51565b60006107997f57726170706572466163746f7279000000000000000000000000000000000000612a51565b60008083612277575060009050806122fe565b8385156122a257600061229160016105ed60018a03611ec4565b905061229e818787611f41565b9150505b60006122c1826122b189611ec4565b600101549063ffffffff61296816565b905060006122e2836122d28a611ec4565b600301549063ffffffff61296816565b90506122ed82612b0b565b6122f682612b0b565b945094505050505b935093915050565b60006107997f53797374656d5374617475730000000000000000000000000000000000000000612a51565b6000816123505760405162461bcd60e51b8152600401610582906140d2565b81838161235957fe5b069392505050565b60006107997f53796e7468657469785374617465000000000000000000000000000000000000612a51565b6002546040516001600160a01b039091169063907dff97906123b2908490602001613f40565b60405160208183030381529060405260016040516123cf90613e35565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261241693929160009081908190600401613f8a565b600060405180830381600087803b15801561243057600080fd5b505af1158015611709573d6000803e3d6000fd5b6000806000806124526121cf565b6001600160a01b031663ae3bbbbb866040518263ffffffff1660e01b815260040161247d9190613e40565b604080518083038186803b15801561249457600080fd5b505afa1580156124a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124cc91908101906133a5565b9150915060006124da6128f1565b9050808310156124f2575060019350915061072c9050565b600061250f612502611aa261287a565b839063ffffffff61296816565b90508084111561252957600083955095505050505061072c565b50600194509092505050915091565b6002546001600160a01b0316331480159061255e57506003546001600160a01b03163314155b156120db57600380546001600160a01b03191633179055565b60006107997f44656c6567617465417070726f76616c73000000000000000000000000000000612a51565b60008080808080806125b388612444565b91509150816125d45760405162461bcd60e51b815260040161058290614112565b80156125f25760405162461bcd60e51b8152600401610582906140c2565b6125fb886106af565b90945092508315158061260e5750600083115b61262a5760405162461bcd60e51b8152600401610582906140b2565b612648886126386001611ec4565b5467ffffffffffffffff16612b2d565b83156126635761265784612be0565b94506126638886612cbc565b821561267e5761267283612e58565b955061267e8887612f32565b612689888688612fac565b506001979650505050505050565b6002546040516001600160a01b039091169063907dff97906126c1908690869086906020016141b2565b60405160208183030381529060405260026040516126de90613dff565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261272e9392916001600160a01b038b16906000908190600401613fe9565b600060405180830381600087803b15801561274857600080fd5b505af115801561275c573d6000803e3d6000fd5b5050505050505050565b604080516001808252818301909252606091602080830190803883390190505090507f466c657869626c6553746f726167650000000000000000000000000000000000816000815181106127b657fe5b60200260200101818152505090565b606081518351016040519080825280602002602001820160405280156127f5578160200160208202803883390190505b50905060005b83518110156128375783818151811061281057fe5b602002602001015182828151811061282457fe5b60209081029190910101526001016127fb565b5060005b82518110156112365782818151811061285057fe5b602002602001015182828651018151811061286757fe5b602090810291909101015260010161283b565b6000612884612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f7461726765745468726573686f6c6400000000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b60006128fb612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f69737375616e6365526174696f000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b6000670de0b6b3a7640000612983848463ffffffff61307116565b8161298a57fe5b049392505050565b6002546001600160a01b031633148015906129b857506003546001600160a01b03163314155b156129d057600380546001600160a01b031916331790555b6000546003546001600160a01b039081169116146120db5760405162461bcd60e51b815260040161058290614072565b6002546001600160a01b031633146120db5760405162461bcd60e51b815260040161058290614172565b60006107997f52657761726473446973747269627574696f6e000000000000000000000000005b60008181526006602090815260408083205490516001600160a01b039091169182151591612a8191869101613e0a565b604051602081830303815290604052906112365760405162461bcd60e51b81526004016105829190614031565b600061208583836b033b2e3c9fd0803ce80000006130ab565b600061208583836b033b2e3c9fd0803ce80000006130ef565b60006107997f466c657869626c6553746f726167650000000000000000000000000000000000612a51565b60006305f5e10082046005600a820610612b2357600a015b600a900492915050565b612b35611e99565b6001600160a01b0316633562fd207f6c6173745f6665655f7769746864726177616c0000000000000000000000000084604051602001612b76929190613dce565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b8152600401612baa929190613f5c565b600060405180830381600087803b158015612bc457600080fd5b505af1158015612bd8573d6000803e3d6000fd5b505050505050565b6000818160015b6002811015612cb4576000612bfb82611ec4565b6002015490506000612c2082612c1085611ec4565b600101549063ffffffff611eee16565b90508015612ca9576000858210612c375785612c39565b815b9050612c4b838263ffffffff61208c16565b612c5485611ec4565b60020155612c68868263ffffffff611eee16565b9550612c7a858263ffffffff61208c16565b945085612c8f5784965050505050505061055e565b83158015612c9d5750600086115b15612ca757600095505b505b505060001901612be7565b509392505050565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612cfa5760405162461bcd60e51b815260040161058290614162565b6000612d046121cf565b6001600160a01b031663326080396007546040518263ffffffff1660e01b8152600401612d319190613f40565b60206040518083038186803b158015612d4957600080fd5b505afa158015612d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d819190810190613369565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081529091506001600160a01b03821690639dc29fac90612ddf9073feefeefeefeefeefeefeefeefeefeefeefeefeef908790600401613e92565b600060405180830381600087803b158015612df957600080fd5b505af1158015612e0d573d6000803e3d6000fd5b50506040517f867904b40000000000000000000000000000000000000000000000000000000081526001600160a01b038416925063867904b4915061272e9087908790600401613e92565b6000818160015b6002811015612cb4576000612e93612e7683611ec4565b60040154612e8384611ec4565b600301549063ffffffff611eee16565b90508015612f28576000848210612eaa5784612eac565b815b9050612ecb81612ebb85611ec4565b600401549063ffffffff61208c16565b612ed484611ec4565b60040155612ee8858263ffffffff611eee16565b9450612efa848263ffffffff61208c16565b935084612f0e57839550505050505061055e565b82158015612f1c5750600085115b15612f2657600094505b505b5060001901612e5f565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612f705760405162461bcd60e51b815260040161058290614162565b6301dfe200612f7d61311a565b6001600160a01b0316631bb47b448585846040518463ffffffff1660e01b815260040161272e93929190613ead565b6002546040516001600160a01b039091169063907dff9790612fd690869086908690602001613ead565b6040516020818303038152906040526001604051612ff390613df4565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261303a93929160009081908190600401613f8a565b600060405180830381600087803b15801561305457600080fd5b505af1158015613068573d6000803e3d6000fd5b50505050505050565b600082613080575060006106a9565b8282028284828161308d57fe5b04146120855760405162461bcd60e51b815260040161058290614122565b6000806130d1846130c587600a870263ffffffff61307116565b9063ffffffff61314516565b90506005600a825b06106130e357600a015b600a9004949350505050565b600080600a8304613106868663ffffffff61307116565b8161310d57fe5b0490506005600a826130d9565b60006107997f526577617264457363726f775632000000000000000000000000000000000000612a51565b60008082116131665760405162461bcd60e51b8152600401610582906140a2565b600082848161317157fe5b04949350505050565b60405180604001604052806002905b613191613202565b8152602001906001900390816131895790505090565b6040518060e00160405280600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b80356106a981614309565b80516106a981614309565b80516106a981614320565b80516106a981614329565b80516106a981614332565b80356106a981614329565b60006020828403121561327457600080fd5b60006132808484613220565b949350505050565b60006020828403121561329a57600080fd5b6000613280848461322b565b600080604083850312156132b957600080fd5b60006132c58585613220565b92505060206132d685828601613257565b9150509250929050565b6000806000606084860312156132f557600080fd5b60006133018686613220565b935050602061331286828701613257565b925050604061332386828701613257565b9150509250925092565b60006020828403121561333f57600080fd5b60006132808484613236565b60006020828403121561335d57600080fd5b60006132808484613241565b60006020828403121561337b57600080fd5b6000613280848461324c565b60006020828403121561339957600080fd5b60006132808484613257565b600080604083850312156133b857600080fd5b60006133c48585613241565b92505060206132d685828601613236565b600080604083850312156133e857600080fd5b60006133f48585613241565b92505060206132d685828601613241565b600080600080600080600080610100898b03121561342257600080fd5b600061342e8b8b613257565b985050602061343f8b828c01613257565b97505060406134508b828c01613257565b96505060606134618b828c01613257565b95505060806134728b828c01613257565b94505060a06134838b828c01613257565b93505060c06134948b828c01613257565b92505060e06134a58b828c01613257565b9150509295985092959890939650565b60006134c183836135ab565b505060400190565b60006134d58383613600565b505060200190565b6134e681614289565b82525050565b6134e68161424f565b6134e66135018261424f565b6142e8565b61350f8161423c565b613519818461055e565b92506135248261079c565b8060005b83811015612bd857815161353c87826134b5565b965061354783614236565b925050600101613528565b600061355d82614242565b6135678185614246565b935061357283614236565b8060005b838110156135a057815161358a88826134c9565b975061359583614236565b925050600101613576565b509495945050505050565b6135b48161423c565b6135be818461055e565b92506135c98261079c565b8060005b83811015612bd85781516135e187826134c9565b96506135ec83614236565b9250506001016135cd565b6134e68161425a565b6134e68161079c565b6134e66136158261079c565b61079c565b600061362582614242565b61362f8185614246565b935061363f8185602086016142b8565b613648816142f9565b9093019392505050565b6134e68161425f565b6134e681614294565b6134e6816142a2565b600061367a601783614246565b7f4f6e6c7920496e7465726e616c20436f6e747261637473000000000000000000815260200192915050565b60006136b3603583614246565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015260400192915050565b6000613712601d83614246565b7f546f6f206561726c7920746f20636c6f73652066656520706572696f64000000815260200192915050565b600061374b601383614246565b7f4f776e6572206f6e6c792066756e6374696f6e00000000000000000000000000815260200192915050565b600061378460248361055e565b7f46656573436c61696d656428616464726573732c75696e743235362c75696e7481527f3235362900000000000000000000000000000000000000000000000000000000602082015260240192915050565b60006137e360378361055e565b7f49737375616e636544656274526174696f456e74727928616464726573732c7581527f696e743235362c75696e743235362c75696e7432353629000000000000000000602082015260370192915050565b6000613842601b83614246565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061387b601e83614246565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b60006138b4601a83614246565b7f536166654d6174683a206469766973696f6e206279207a65726f000000000000815260200192915050565b60006138ed604083614246565b7f4e6f2066656573206f72207265776172647320617661696c61626c6520666f7281527f20706572696f642c206f72206665657320616c726561647920636c61696d6564602082015260400192915050565b600061394c60118361055e565b7f4d697373696e6720616464726573733a20000000000000000000000000000000815260110192915050565b6000613985601e83614246565b7f412073796e7468206f7220534e58207261746520697320696e76616c69640000815260200192915050565b60006139be601883614246565b7f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815260200192915050565b60006139f7601f83614246565b7f4e6f7420617070726f76656420746f20636c61696d206f6e20626568616c6600815260200192915050565b6000613a30601e83614246565b7f43616c6c6572206973206e6f742072657761726473417574686f726974790000815260200192915050565b6000613a69602f83614246565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015260400192915050565b6000613ac8601f83614246565b7f432d526174696f2062656c6f772070656e616c7479207468726573686f6c6400815260200192915050565b6000613b01602183614246565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613b60601683614246565b7f43616e6e6f7420696d706f727420626164206461746100000000000000000000815260200192915050565b6000613b99601d83614246565b7f4578636565647320746865204645455f504552494f445f4c454e475448000000815260200192915050565b6000613bd2602983614246565b7f43616e206f6e6c7920706572666f726d207468697320616374696f6e2064757281527f696e672073657475700000000000000000000000000000000000000000000000602082015260400192915050565b6000613c3160198361055e565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000613c6a601783614246565b7f4665652061646472657373206e6f7420616c6c6f776564000000000000000000815260200192915050565b6000613ca360188361055e565b7f466565506572696f64436c6f7365642875696e74323536290000000000000000815260180192915050565b6000613cdc601783614246565b7f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000815260200192915050565b6000613d15601e83614246565b7f49737375657220616e642053796e7468657469785374617465206f6e6c790000815260200192915050565b6000613d4e602083614246565b7f43757272656e7420706572696f64206973206e6f7420636c6f73656420796574815260200192915050565b6000613d87601b83614246565b7f46656520506572696f64204475726174696f6e206e6f74207365740000000000815260200192915050565b6134e6816142ad565b6134e681614276565b6134e681614283565b6000613dda8285613609565b602082019150613dea82846134f5565b5060140192915050565b60006106a982613777565b60006106a9826137d6565b6000613e158261393f565b9150613e218284613609565b50602001919050565b6000613e1582613c24565b60006106a982613c96565b602081016106a982846134ec565b602081016106a982846134dd565b60408101613e6a82856134ec565b61208560208301846134ec565b60408101613e8582856134ec565b6120856020830184613664565b60408101613ea082856134ec565b6120856020830184613600565b60608101613ebb82866134ec565b613ec86020830185613600565b6132806040830184613600565b60808101613ee382876134ec565b613ef06020830186613600565b613efd6040830185613600565b613f0a6060830184613db3565b95945050505050565b608081016106a98284613506565b602080825281016120858184613552565b602081016106a982846135f7565b602081016106a98284613600565b60408101613e6a8285613600565b60408101613ea08285613600565b60408101613f788285613600565b8181036020830152613280818461361a565b60c08082528101613f9b818961361a565b9050613faa6020830188613664565b613fb76040830187613600565b613fc4606083018661365b565b613fd1608083018561365b565b613fde60a083018461365b565b979650505050505050565b60c08082528101613ffa818961361a565b90506140096020830188613664565b6140166040830187613600565b613fc46060830186613600565b602081016106a98284613652565b60208082528101612085818461361a565b6020808252810161055b8161366d565b6020808252810161055b816136a6565b6020808252810161055b81613705565b6020808252810161055b8161373e565b6020808252810161055b81613835565b6020808252810161055b8161386e565b6020808252810161055b816138a7565b6020808252810161055b816138e0565b6020808252810161055b81613978565b6020808252810161055b816139b1565b6020808252810161055b816139ea565b6020808252810161055b81613a23565b6020808252810161055b81613a5c565b6020808252810161055b81613abb565b6020808252810161055b81613af4565b6020808252810161055b81613b53565b6020808252810161055b81613b8c565b6020808252810161055b81613bc5565b6020808252810161055b81613c5d565b6020808252810161055b81613ccf565b6020808252810161055b81613d08565b6020808252810161055b81613d41565b6020808252810161055b81613d7a565b60608101613ebb8286613600565b60e081016141ce828a613dbc565b6141db6020830189613dbc565b6141e86040830188613dbc565b6141f56060830187613600565b6142026080830186613600565b61420f60a0830185613600565b61421c60c0830184613600565b98975050505050505050565b602081016106a98284613dc5565b60200190565b50600290565b5190565b90815260200190565b600061055b8261426a565b151590565b600061055b8261424f565b6001600160a01b031690565b67ffffffffffffffff1690565b60ff1690565b600061055b8261425f565b600061055b6136158361079c565b600061055b8261079c565b600061055b82614276565b60005b838110156142d35781810151838201526020016142bb565b838111156142e2576000848401525b50505050565b600061055b82600061055b82614303565b601f01601f191690565b60601b90565b6143128161424f565b811461431d57600080fd5b50565b6143128161425a565b6143128161079c565b6143128161425f56fea365627a7a7231582027c6d550873108a7d60713319b7fa5e4bbba69ffb8ed82ee57ccd2f3d0e2330a6c6578706572696d656e74616cf564736f6c63430005100040", + "bytecode": "6080604052631cd554d160e21b6007553480156200001c57600080fd5b506040516200471b3803806200471b8339810160408190526200003f9162000221565b8080621baf8085856001600160a01b038116620000795760405162461bcd60e51b8152600401620000709062000343565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620000c69184906200030b565b60405180910390a1506000546001600160a01b0316620000fa5760405162461bcd60e51b8152600401620000709062000331565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9062000147908390620002fb565b60405180910390a1504201600455600580546001600160a01b0319166001600160a01b0392909216919091179055506001620001846000620001e2565b80546001600160401b0319166001600160401b039290921691909117905542620001af6000620001e2565b80546001600160401b0392909216600160801b02600160801b600160c01b0319909216919091179055506200039e915050565b60006008600260ff16836012540181620001f857fe5b06600281106200020457fe5b6005020192915050565b80516200021b8162000384565b92915050565b6000806000606084860312156200023757600080fd5b60006200024586866200020e565b935050602062000258868287016200020e565b92505060406200026b868287016200020e565b9150509250925092565b620002808162000370565b82525050565b62000280816200035e565b6000620002a060118362000355565b7013dddb995c881b5d5cdd081899481cd95d607a1b815260200192915050565b6000620002cf60198362000355565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b602081016200021b828462000275565b604081016200031b828562000275565b6200032a602083018462000286565b9392505050565b602080825281016200021b8162000291565b602080825281016200021b81620002c0565b90815260200190565b60006001600160a01b0382166200021b565b60006200021b8260006200021b826200035e565b6200038f816200035e565b81146200039b57600080fd5b50565b61436d80620003ae6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80636de813f111610145578063b410a034116100bd578063d67bdd251161008c578063eb1edd6111610071578063eb1edd611461045c578063ec55688914610464578063fd1f498d1461046c57610241565b8063d67bdd251461044c578063e0e6393d1461045457610241565b8063b410a03414610414578063bc67f8321461041c578063cff2ddad1461042f578063d294f0931461044457610241565b8063899ffef41161011457806397107d6d116100f957806397107d6d146103e6578063ac834193146103f9578063b10090b81461040157610241565b8063899ffef4146103c95780638da5cb5b146103de57610241565b80636de813f11461039e57806374185360146103a657806379ba5097146103ae57806386645274146103b657610241565b806333140016116101d857806353a47bb7116101a757806359a2f19f1161018c57806359a2f19f14610370578063614d08f8146103835780636466f45e1461038b57610241565b806353a47bb714610353578063569249d01461036857610241565b806333140016146102fd5780633ebc457a1461031d5780633fcd22401461032557806346ba2d901461034b57610241565b80631627540c116102145780631627540c146102b857806322425fa4146102cd57806322bf55ef146102d55780632af64bd3146102e857610241565b806304f3bcec1461024657806307ea50cd146102645780630813071c146102845780630de5861514610297575b600080fd5b61024e61047f565b60405161025b9190614012565b60405180910390f35b610277610272366004613251565b61048e565b60405161025b9190613f2f565b610277610292366004613295565b610563565b6102aa6102a5366004613251565b6106af565b60405161025b929190613f4b565b6102cb6102c6366004613251565b610731565b005b61027761078f565b6102cb6102e3366004613376565b61079f565b6102f0610978565b60405161025b9190613f21565b61031061030b366004613251565b610aa8565b60405161025b9190613f02565b6102cb610d0c565b610338610333366004613376565b611112565b60405161025b97969594939291906141af565b6102776111bb565b61035b6111c1565b60405161025b9190613e2f565b6102776111d0565b6102f061037e366004613251565b61122b565b61027761123d565b6102f0610399366004613251565b611261565b61027761138d565b6102cb6113e2565b6102cb611534565b6102cb6103c43660046132cf565b6115d0565b6103d1611710565b60405161025b9190613f10565b61035b611a30565b6102cb6103f4366004613251565b611a3f565b610277611a92565b6102cb61040f3660046133f4565b611b32565b610277611d2c565b6102cb61042a366004613251565b611d36565b610437611d60565b60405161025b9190614217565b6102f0611d65565b61035b611ddc565b610277611deb565b61035b611df5565b61024e611e0d565b6102cb61047a366004613376565b611e1c565b6005546001600160a01b031681565b6000610498611e88565b6001600160a01b031663bdc963d87f6c6173745f6665655f7769746864726177616c00000000000000000000000000846040516020016104d9929190613dbd565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161050b9190613f2f565b60206040518083038186803b15801561052357600080fd5b505afa158015610537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061055b919081019061333a565b90505b919050565b60008161058b5760405162461bcd60e51b815260040161058290614181565b60405180910390fd5b600282106105ab5760405162461bcd60e51b815260040161058290614131565b6105b760018303611eb3565b5468010000000000000000900467ffffffffffffffff166105da575060006106a9565b600061060a60016105ed60018603611eb3565b5468010000000000000000900467ffffffffffffffff1690611edd565b9050600080610617611f05565b6001600160a01b031663d29c000a87856040518363ffffffff1660e01b8152600401610644929190613e81565b604080518083038186803b15801561065b57600080fd5b505afa15801561066f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061069391908101906133c4565b90925090506106a3838383611f30565b93505050505b92915050565b6000806106ba613169565b6106c384610aa8565b905060008060015b6002811015610724576106f08482600281106106e357fe5b602002015151849061207b565b925061071a84826002811061070157fe5b602002015160016020020151839063ffffffff61207b16565b91506001016106cb565b509093509150505b915091565b6107396120a0565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610784908390613e2f565b60405180910390a150565b60006107996120cc565b90505b90565b60006107a9612193565b6001600160a01b0316331490506000806107c16121be565b6001600160a01b03166316b2213f336040518263ffffffff1660e01b81526004016107ec9190613e3d565b60206040518083038186803b15801561080457600080fd5b505afa158015610818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061083c919081019061333a565b14159050600061084a6121d2565b6001600160a01b031663b38988f7336040518263ffffffff1660e01b81526004016108759190613e3d565b60206040518083038186803b15801561088d57600080fd5b505afa1580156108a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108c5919081019061331c565b905060006108d16121fd565b6001600160a01b0316336001600160a01b031614905060006108f1612228565b6001600160a01b0316336001600160a01b031614905084806109105750835b806109185750825b806109205750815b806109285750805b6109445760405162461bcd60e51b815260040161058290614031565b610962866109526000611eb3565b600101549063ffffffff61207b16565b61096c6000611eb3565b60010155505050505050565b60006060610984611710565b905060005b8151811015610a9f5760008282815181106109a057fe5b602090810291909101810151600081815260069092526040918290205460055492517f21f8a7210000000000000000000000000000000000000000000000000000000081529193506001600160a01b039081169216906321f8a72190610a0a908590600401613f2f565b60206040518083038186803b158015610a2257600080fd5b505afa158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a5a9190810190613277565b6001600160a01b0316141580610a8557506000818152600660205260409020546001600160a01b0316155b15610a96576000935050505061079c565b50600101610989565b50600191505090565b610ab0613169565b6000806000610abd611f05565b6040517fb326f84e0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0382169063b326f84e90610b08908890600090600401613e66565b604080518083038186803b158015610b1f57600080fd5b505afa158015610b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b5791908101906133c4565b909350915081158015610b68575082155b15610b8057610b75613169565b935061055e92505050565b600080610b8f60008686612253565b8751829052875160200181905290925090506000610bac8861048e565b905060015b8015610d005760001981016000610bc782611eb3565b5468010000000000000000900467ffffffffffffffff1690508015801590610c015750610bf383611eb3565b5467ffffffffffffffff1684105b15610cf5576000610c1982600163ffffffff611edd16565b6040517fd29c000a0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0389169063d29c000a90610c63908f908590600401613e81565b604080518083038186803b158015610c7a57600080fd5b505afa158015610c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610cb291908101906133c4565b909a509850610cc2848b8b612253565b9097509550868b8560028110610cd457fe5b602002015152858b8560028110610ce757fe5b602002015160016020020152505b505060001901610bb1565b50505050505050919050565b610d146122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015610d4c57600080fd5b505afa158015610d60573d6000803e3d6000fd5b505050506000610d6e6120cc565b11610d8b5760405162461bcd60e51b815260040161058290614191565b610d936120cc565b4203610d9f6000611eb3565b54600160801b900467ffffffffffffffff161115610dcf5760405162461bcd60e51b815260040161058290614051565b610dd76121fd565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e1157600080fd5b505af1158015610e25573d6000803e3d6000fd5b50505050610e31612228565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e6b57600080fd5b505af1158015610e7f573d6000803e3d6000fd5b5060009250610e919150829050611eb3565b90506000610e9f6001611eb3565b9050610ed08260010154610ec483600201548460010154611edd90919063ffffffff16565b9063ffffffff61207b16565b610eda6000611eb3565b60010155600380830154600483015491830154610f0192610ec4919063ffffffff611edd16565b610f0b6000611eb3565b60030155601254610f4890600290610f3c90600190610f30908463ffffffff61207b16565b9063ffffffff611edd16565b9063ffffffff61232016565b601281905560089060028110610f5a57fe5b6005020180547fffffffffffffffff000000000000000000000000000000000000000000000000168155600060018083018290556002830182905560038301829055600490920155610fc690610faf81611eb3565b5467ffffffffffffffff169063ffffffff61207b16565b610fd06000611eb3565b805467ffffffffffffffff191667ffffffffffffffff92909216919091179055610ff8612350565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561103057600080fd5b505afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611068919081019061333a565b6110726000611eb3565b805467ffffffffffffffff9290921668010000000000000000026fffffffffffffffff000000000000000019909216919091179055426110b26000611eb3565b805467ffffffffffffffff92909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905561110e6110fe6001611eb3565b5467ffffffffffffffff1661237b565b5050565b6000806000806000806000611125613196565b61112e89611eb3565b6040805160e081018252825467ffffffffffffffff808216808452680100000000000000008304821660208501819052600160801b909304909116938301849052600185015460608401819052600286015460808501819052600387015460a0860181905260049097015460c0909501859052919f929e50939c50929a5091985091965090945092505050565b60045481565b6001546001600160a01b031681565b60008060015b6002811015611225576111fc6111eb82611eb3565b60010154839063ffffffff61207b16565b915061121b61120a82611eb3565b60020154839063ffffffff611edd16565b91506001016111d6565b50905090565b600061123682612433565b5092915050565b7f466565506f6f6c0000000000000000000000000000000000000000000000000081565b600061126b6122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156112a357600080fd5b505afa1580156112b7573d6000803e3d6000fd5b505050506112c3612527565b6112cb612566565b6003546040517f21f4ae570000000000000000000000000000000000000000000000000000000081526001600160a01b03928316926321f4ae579261131892879290911690600401613e4b565b60206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611368919081019061331c565b6113845760405162461bcd60e51b8152600401610582906140e1565b61055b82612591565b60008060015b6002811015611225576113b96113a882611eb3565b60030154839063ffffffff61207b16565b91506113d86113c782611eb3565b60040154839063ffffffff611edd16565b9150600101611393565b60606113ec611710565b905060005b815181101561110e57600082828151811061140857fe5b602002602001015190506000600560009054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200161144a9190613e19565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611476929190613f59565b60206040518083038186803b15801561148e57600080fd5b505afa1580156114a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114c69190810190613277565b6000838152600660205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906115229084908490613f3d565b60405180910390a150506001016113f1565b6001546001600160a01b0316331461155e5760405162461bcd60e51b815260040161058290614041565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c926115a1926001600160a01b0391821692911690613e4b565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006115da6121be565b6001600160a01b0316336001600160a01b031614905060006115fa612350565b6001600160a01b0316336001600160a01b031614905081806116195750805b6116355760405162461bcd60e51b815260040161058290614171565b61163d611f05565b6001600160a01b03166394e1a4488686866116586000611eb3565b5460405160e086901b7fffffffff000000000000000000000000000000000000000000000000000000001681526116ab9493929168010000000000000000900467ffffffffffffffff1690600401613ec4565b600060405180830381600087803b1580156116c557600080fd5b505af11580156116d9573d6000803e3d6000fd5b505050506117098585856116ed6000611eb3565b5468010000000000000000900467ffffffffffffffff16612686565b5050505050565b60608061171b612755565b60408051600d8082526101c0820190925291925060609190602082016101a0803883390190505090507f53797374656d53746174757300000000000000000000000000000000000000008160008151811061177257fe5b6020026020010181815250507f53796e7468657469780000000000000000000000000000000000000000000000816001815181106117ac57fe5b6020026020010181815250507f466565506f6f6c53746174650000000000000000000000000000000000000000816002815181106117e657fe5b6020026020010181815250507f466565506f6f6c457465726e616c53746f7261676500000000000000000000008160038151811061182057fe5b6020026020010181815250507f45786368616e67657200000000000000000000000000000000000000000000008160048151811061185a57fe5b6020026020010181815250506524b9b9bab2b960d11b8160058151811061187d57fe5b6020026020010181815250507f53796e7468657469785374617465000000000000000000000000000000000000816006815181106118b757fe5b6020026020010181815250507f526577617264457363726f775632000000000000000000000000000000000000816007815181106118f157fe5b6020026020010181815250507f44656c6567617465417070726f76616c730000000000000000000000000000008160088151811061192b57fe5b6020026020010181815250507f52657761726473446973747269627574696f6e000000000000000000000000008160098151811061196557fe5b6020026020010181815250507f436f6c6c61746572616c4d616e6167657200000000000000000000000000000081600a8151811061199f57fe5b6020026020010181815250507f57726170706572466163746f727900000000000000000000000000000000000081600b815181106119d957fe5b6020026020010181815250507f457468657257726170706572000000000000000000000000000000000000000081600c81518110611a1357fe5b602002602001018181525050611a2982826127b4565b9250505090565b6000546001600160a01b031681565b611a476120a0565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e90610784908390613e3d565b6000610799611b1e611aa2612869565b73__$f9217daff40bcb29719cec84f7ab900933$__63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611ae657600080fd5b505af4158015611afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ec4919081019061333a565b611b266128e0565b9063ffffffff61295716565b611b3a612981565b6004544210611b5b5760405162461bcd60e51b815260040161058290614141565b611b63612350565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b9b57600080fd5b505afa158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611bd3919081019061333a565b861115611bf25760405162461bcd60e51b815260040161058290614121565b6040518060e001604052808867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018667ffffffffffffffff168152602001858152602001848152602001838152602001828152506008611c62600260ff16610f3c8c60125461207b90919063ffffffff16565b60028110611c6c57fe5b82516005919091029190910180546020840151604085015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff000000000000000019166801000000000000000091851691909102177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b9390911692909202919091178155606082015160018201556080820151600282015560a0820151600382015560c0909101516004909101555050505050505050565b60006107996128e0565b611d3e6129ef565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600281565b6000611d6f6122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611da757600080fd5b505afa158015611dbb573d6000803e3d6000fd5b50505050611dc7612527565b600354610799906001600160a01b0316612591565b6003546001600160a01b031681565b6000610799612869565b73feefeefeefeefeefeefeefeefeefeefeefeefeef81565b6002546001600160a01b031681565b611e24612527565b611e2c612a19565b6003546001600160a01b03908116911614611e595760405162461bcd60e51b8152600401610582906140b1565b611e7781611e676000611eb3565b600301549063ffffffff61207b16565b611e816000611eb3565b6003015550565b60006107997f466565506f6f6c457465726e616c53746f726167650000000000000000000000612a40565b60006008600260ff16836012540181611ec857fe5b0660028110611ed357fe5b6005020192915050565b600082821115611eff5760405162461bcd60e51b815260040161058290614081565b50900390565b60006107997f466565506f6f6c53746174650000000000000000000000000000000000000000612a40565b600080611f3b612350565b9050600061206f85612063846001600160a01b03166308d95cd5886040518263ffffffff1660e01b8152600401611f729190613f2f565b60206040518083038186803b158015611f8a57600080fd5b505afa158015611f9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611fc2919081019061333a565b6040517f08d95cd50000000000000000000000000000000000000000000000000000000081526001600160a01b038716906308d95cd590612007908d90600401613f2f565b60206040518083038186803b15801561201f57600080fd5b505afa158015612033573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612057919081019061333a565b9063ffffffff612a9d16565b9063ffffffff612ab616565b925050505b9392505050565b6000828201838110156120745760405162461bcd60e51b815260040161058290614071565b6000546001600160a01b031633146120ca5760405162461bcd60e51b8152600401610582906140f1565b565b60006120d6612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f666565506572696f644475726174696f6e0000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b60206040518083038186803b15801561215b57600080fd5b505afa15801561216f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610799919081019061333a565b60006107997f45786368616e6765720000000000000000000000000000000000000000000000612a40565b60006107996524b9b9bab2b960d11b612a40565b60006107997f436f6c6c61746572616c4d616e61676572000000000000000000000000000000612a40565b60006107997f4574686572577261707065720000000000000000000000000000000000000000612a40565b60006107997f57726170706572466163746f7279000000000000000000000000000000000000612a40565b60008083612266575060009050806122ed565b83851561229157600061228060016105ed60018a03611eb3565b905061228d818787611f30565b9150505b60006122b0826122a089611eb3565b600101549063ffffffff61295716565b905060006122d1836122c18a611eb3565b600301549063ffffffff61295716565b90506122dc82612afa565b6122e582612afa565b945094505050505b935093915050565b60006107997f53797374656d5374617475730000000000000000000000000000000000000000612a40565b60008161233f5760405162461bcd60e51b8152600401610582906140d1565b81838161234857fe5b069392505050565b60006107997f53796e7468657469785374617465000000000000000000000000000000000000612a40565b6002546040516001600160a01b039091169063907dff97906123a1908490602001613f2f565b60405160208183030381529060405260016040516123be90613e24565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261240593929160009081908190600401613f79565b600060405180830381600087803b15801561241f57600080fd5b505af1158015611709573d6000803e3d6000fd5b6000806000806124416121be565b6001600160a01b031663ae3bbbbb866040518263ffffffff1660e01b815260040161246c9190613e2f565b604080518083038186803b15801561248357600080fd5b505afa158015612497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124bb9190810190613394565b9150915060006124c96128e0565b9050808310156124e1575060019350915061072c9050565b60006124fe6124f1611aa2612869565b839063ffffffff61295716565b90508084111561251857600083955095505050505061072c565b50600194509092505050915091565b6002546001600160a01b0316331480159061254d57506003546001600160a01b03163314155b156120ca57600380546001600160a01b03191633179055565b60006107997f44656c6567617465417070726f76616c73000000000000000000000000000000612a40565b60008080808080806125a288612433565b91509150816125c35760405162461bcd60e51b815260040161058290614101565b80156125e15760405162461bcd60e51b8152600401610582906140c1565b6125ea886106af565b9094509250831515806125fd5750600083115b6126195760405162461bcd60e51b8152600401610582906140a1565b612637886126276001611eb3565b5467ffffffffffffffff16612b1c565b83156126525761264684612bcf565b94506126528886612cab565b821561266d5761266183612e47565b955061266d8887612f21565b612678888688612f9b565b506001979650505050505050565b6002546040516001600160a01b039091169063907dff97906126b0908690869086906020016141a1565b60405160208183030381529060405260026040516126cd90613dee565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261271d9392916001600160a01b038b16906000908190600401613fd8565b600060405180830381600087803b15801561273757600080fd5b505af115801561274b573d6000803e3d6000fd5b5050505050505050565b604080516001808252818301909252606091602080830190803883390190505090507f466c657869626c6553746f726167650000000000000000000000000000000000816000815181106127a557fe5b60200260200101818152505090565b606081518351016040519080825280602002602001820160405280156127e4578160200160208202803883390190505b50905060005b8351811015612826578381815181106127ff57fe5b602002602001015182828151811061281357fe5b60209081029190910101526001016127ea565b5060005b82518110156112365782818151811061283f57fe5b602002602001015182828651018151811061285657fe5b602090810291909101015260010161282a565b6000612873612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f7461726765745468726573686f6c6400000000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b60006128ea612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f69737375616e6365526174696f000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b6000670de0b6b3a7640000612972848463ffffffff61306016565b8161297957fe5b049392505050565b6002546001600160a01b031633148015906129a757506003546001600160a01b03163314155b156129bf57600380546001600160a01b031916331790555b6000546003546001600160a01b039081169116146120ca5760405162461bcd60e51b815260040161058290614061565b6002546001600160a01b031633146120ca5760405162461bcd60e51b815260040161058290614161565b60006107997f52657761726473446973747269627574696f6e000000000000000000000000005b60008181526006602090815260408083205490516001600160a01b039091169182151591612a7091869101613df9565b604051602081830303815290604052906112365760405162461bcd60e51b81526004016105829190614020565b600061207483836b033b2e3c9fd0803ce800000061309a565b600061207483836b033b2e3c9fd0803ce80000006130de565b60006107997f466c657869626c6553746f726167650000000000000000000000000000000000612a40565b60006305f5e10082046005600a820610612b1257600a015b600a900492915050565b612b24611e88565b6001600160a01b0316633562fd207f6c6173745f6665655f7769746864726177616c0000000000000000000000000084604051602001612b65929190613dbd565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b8152600401612b99929190613f4b565b600060405180830381600087803b158015612bb357600080fd5b505af1158015612bc7573d6000803e3d6000fd5b505050505050565b6000818160015b6002811015612ca3576000612bea82611eb3565b6002015490506000612c0f82612bff85611eb3565b600101549063ffffffff611edd16565b90508015612c98576000858210612c265785612c28565b815b9050612c3a838263ffffffff61207b16565b612c4385611eb3565b60020155612c57868263ffffffff611edd16565b9550612c69858263ffffffff61207b16565b945085612c7e5784965050505050505061055e565b83158015612c8c5750600086115b15612c9657600095505b505b505060001901612bd6565b509392505050565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612ce95760405162461bcd60e51b815260040161058290614151565b6000612cf36121be565b6001600160a01b031663326080396007546040518263ffffffff1660e01b8152600401612d209190613f2f565b60206040518083038186803b158015612d3857600080fd5b505afa158015612d4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d709190810190613358565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081529091506001600160a01b03821690639dc29fac90612dce9073feefeefeefeefeefeefeefeefeefeefeefeefeef908790600401613e81565b600060405180830381600087803b158015612de857600080fd5b505af1158015612dfc573d6000803e3d6000fd5b50506040517f867904b40000000000000000000000000000000000000000000000000000000081526001600160a01b038416925063867904b4915061271d9087908790600401613e81565b6000818160015b6002811015612ca3576000612e82612e6583611eb3565b60040154612e7284611eb3565b600301549063ffffffff611edd16565b90508015612f17576000848210612e995784612e9b565b815b9050612eba81612eaa85611eb3565b600401549063ffffffff61207b16565b612ec384611eb3565b60040155612ed7858263ffffffff611edd16565b9450612ee9848263ffffffff61207b16565b935084612efd57839550505050505061055e565b82158015612f0b5750600085115b15612f1557600094505b505b5060001901612e4e565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612f5f5760405162461bcd60e51b815260040161058290614151565b6301dfe200612f6c613109565b6001600160a01b0316631bb47b448585846040518463ffffffff1660e01b815260040161271d93929190613e9c565b6002546040516001600160a01b039091169063907dff9790612fc590869086908690602001613e9c565b6040516020818303038152906040526001604051612fe290613de3565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261302993929160009081908190600401613f79565b600060405180830381600087803b15801561304357600080fd5b505af1158015613057573d6000803e3d6000fd5b50505050505050565b60008261306f575060006106a9565b8282028284828161307c57fe5b04146120745760405162461bcd60e51b815260040161058290614111565b6000806130c0846130b487600a870263ffffffff61306016565b9063ffffffff61313416565b90506005600a825b06106130d257600a015b600a9004949350505050565b600080600a83046130f5868663ffffffff61306016565b816130fc57fe5b0490506005600a826130c8565b60006107997f526577617264457363726f775632000000000000000000000000000000000000612a40565b60008082116131555760405162461bcd60e51b815260040161058290614091565b600082848161316057fe5b04949350505050565b60405180604001604052806002905b6131806131f1565b8152602001906001900390816131785790505090565b6040518060e00160405280600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b80356106a9816142f8565b80516106a9816142f8565b80516106a98161430f565b80516106a981614318565b80516106a981614321565b80356106a981614318565b60006020828403121561326357600080fd5b600061326f848461320f565b949350505050565b60006020828403121561328957600080fd5b600061326f848461321a565b600080604083850312156132a857600080fd5b60006132b4858561320f565b92505060206132c585828601613246565b9150509250929050565b6000806000606084860312156132e457600080fd5b60006132f0868661320f565b935050602061330186828701613246565b925050604061331286828701613246565b9150509250925092565b60006020828403121561332e57600080fd5b600061326f8484613225565b60006020828403121561334c57600080fd5b600061326f8484613230565b60006020828403121561336a57600080fd5b600061326f848461323b565b60006020828403121561338857600080fd5b600061326f8484613246565b600080604083850312156133a757600080fd5b60006133b38585613230565b92505060206132c585828601613225565b600080604083850312156133d757600080fd5b60006133e38585613230565b92505060206132c585828601613230565b600080600080600080600080610100898b03121561341157600080fd5b600061341d8b8b613246565b985050602061342e8b828c01613246565b975050604061343f8b828c01613246565b96505060606134508b828c01613246565b95505060806134618b828c01613246565b94505060a06134728b828c01613246565b93505060c06134838b828c01613246565b92505060e06134948b828c01613246565b9150509295985092959890939650565b60006134b0838361359a565b505060400190565b60006134c483836135ef565b505060200190565b6134d581614278565b82525050565b6134d58161423e565b6134d56134f08261423e565b6142d7565b6134fe8161422b565b613508818461055e565b92506135138261079c565b8060005b83811015612bc757815161352b87826134a4565b965061353683614225565b925050600101613517565b600061354c82614231565b6135568185614235565b935061356183614225565b8060005b8381101561358f57815161357988826134b8565b975061358483614225565b925050600101613565565b509495945050505050565b6135a38161422b565b6135ad818461055e565b92506135b88261079c565b8060005b83811015612bc75781516135d087826134b8565b96506135db83614225565b9250506001016135bc565b6134d581614249565b6134d58161079c565b6134d56136048261079c565b61079c565b600061361482614231565b61361e8185614235565b935061362e8185602086016142a7565b613637816142e8565b9093019392505050565b6134d58161424e565b6134d581614283565b6134d581614291565b6000613669601783614235565b7f4f6e6c7920496e7465726e616c20436f6e747261637473000000000000000000815260200192915050565b60006136a2603583614235565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015260400192915050565b6000613701601d83614235565b7f546f6f206561726c7920746f20636c6f73652066656520706572696f64000000815260200192915050565b600061373a601383614235565b7f4f776e6572206f6e6c792066756e6374696f6e00000000000000000000000000815260200192915050565b600061377360248361055e565b7f46656573436c61696d656428616464726573732c75696e743235362c75696e7481527f3235362900000000000000000000000000000000000000000000000000000000602082015260240192915050565b60006137d260378361055e565b7f49737375616e636544656274526174696f456e74727928616464726573732c7581527f696e743235362c75696e743235362c75696e7432353629000000000000000000602082015260370192915050565b6000613831601b83614235565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061386a601e83614235565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b60006138a3601a83614235565b7f536166654d6174683a206469766973696f6e206279207a65726f000000000000815260200192915050565b60006138dc604083614235565b7f4e6f2066656573206f72207265776172647320617661696c61626c6520666f7281527f20706572696f642c206f72206665657320616c726561647920636c61696d6564602082015260400192915050565b600061393b60118361055e565b7f4d697373696e6720616464726573733a20000000000000000000000000000000815260110192915050565b6000613974601883614235565b7f52657761726473446973747269627574696f6e206f6e6c790000000000000000815260200192915050565b60006139ad601e83614235565b7f412073796e7468206f7220534e58207261746520697320696e76616c69640000815260200192915050565b60006139e6601883614235565b7f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815260200192915050565b6000613a1f601f83614235565b7f4e6f7420617070726f76656420746f20636c61696d206f6e20626568616c6600815260200192915050565b6000613a58602f83614235565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015260400192915050565b6000613ab7601f83614235565b7f432d526174696f2062656c6f772070656e616c7479207468726573686f6c6400815260200192915050565b6000613af0602183614235565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613b4f601683614235565b7f43616e6e6f7420696d706f727420626164206461746100000000000000000000815260200192915050565b6000613b88601d83614235565b7f4578636565647320746865204645455f504552494f445f4c454e475448000000815260200192915050565b6000613bc1602983614235565b7f43616e206f6e6c7920706572666f726d207468697320616374696f6e2064757281527f696e672073657475700000000000000000000000000000000000000000000000602082015260400192915050565b6000613c2060198361055e565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000613c59601783614235565b7f4665652061646472657373206e6f7420616c6c6f776564000000000000000000815260200192915050565b6000613c9260188361055e565b7f466565506572696f64436c6f7365642875696e74323536290000000000000000815260180192915050565b6000613ccb601783614235565b7f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000815260200192915050565b6000613d04601e83614235565b7f49737375657220616e642053796e7468657469785374617465206f6e6c790000815260200192915050565b6000613d3d602083614235565b7f43757272656e7420706572696f64206973206e6f7420636c6f73656420796574815260200192915050565b6000613d76601b83614235565b7f46656520506572696f64204475726174696f6e206e6f74207365740000000000815260200192915050565b6134d58161429c565b6134d581614265565b6134d581614272565b6000613dc982856135f8565b602082019150613dd982846134e4565b5060140192915050565b60006106a982613766565b60006106a9826137c5565b6000613e048261392e565b9150613e1082846135f8565b50602001919050565b6000613e0482613c13565b60006106a982613c85565b602081016106a982846134db565b602081016106a982846134cc565b60408101613e5982856134db565b61207460208301846134db565b60408101613e7482856134db565b6120746020830184613653565b60408101613e8f82856134db565b61207460208301846135ef565b60608101613eaa82866134db565b613eb760208301856135ef565b61326f60408301846135ef565b60808101613ed282876134db565b613edf60208301866135ef565b613eec60408301856135ef565b613ef96060830184613da2565b95945050505050565b608081016106a982846134f5565b602080825281016120748184613541565b602081016106a982846135e6565b602081016106a982846135ef565b60408101613e5982856135ef565b60408101613e8f82856135ef565b60408101613f6782856135ef565b818103602083015261326f8184613609565b60c08082528101613f8a8189613609565b9050613f996020830188613653565b613fa660408301876135ef565b613fb3606083018661364a565b613fc0608083018561364a565b613fcd60a083018461364a565b979650505050505050565b60c08082528101613fe98189613609565b9050613ff86020830188613653565b61400560408301876135ef565b613fb360608301866135ef565b602081016106a98284613641565b602080825281016120748184613609565b6020808252810161055b8161365c565b6020808252810161055b81613695565b6020808252810161055b816136f4565b6020808252810161055b8161372d565b6020808252810161055b81613824565b6020808252810161055b8161385d565b6020808252810161055b81613896565b6020808252810161055b816138cf565b6020808252810161055b81613967565b6020808252810161055b816139a0565b6020808252810161055b816139d9565b6020808252810161055b81613a12565b6020808252810161055b81613a4b565b6020808252810161055b81613aaa565b6020808252810161055b81613ae3565b6020808252810161055b81613b42565b6020808252810161055b81613b7b565b6020808252810161055b81613bb4565b6020808252810161055b81613c4c565b6020808252810161055b81613cbe565b6020808252810161055b81613cf7565b6020808252810161055b81613d30565b6020808252810161055b81613d69565b60608101613eaa82866135ef565b60e081016141bd828a613dab565b6141ca6020830189613dab565b6141d76040830188613dab565b6141e460608301876135ef565b6141f160808301866135ef565b6141fe60a08301856135ef565b61420b60c08301846135ef565b98975050505050505050565b602081016106a98284613db4565b60200190565b50600290565b5190565b90815260200190565b600061055b82614259565b151590565b600061055b8261423e565b6001600160a01b031690565b67ffffffffffffffff1690565b60ff1690565b600061055b8261424e565b600061055b6136048361079c565b600061055b8261079c565b600061055b82614265565b60005b838110156142c25781810151838201526020016142aa565b838111156142d1576000848401525b50505050565b600061055b82600061055b826142f2565b601f01601f191690565b60601b90565b6143018161423e565b811461430c57600080fd5b50565b61430181614249565b6143018161079c565b6143018161424e56fea365627a7a72315820311ca67b066d8aa30c5fc3e5d4e569051e36efc62ebf3c8ccc4f5172288bdb2b6c6578706572696d656e74616cf564736f6c63430005100040", "abi": [ { "inputs": [ @@ -13148,10 +13139,10 @@ } ], "source": { - "keccak256": "0x8a65c401cfedc5e54b3544097f5873fff54bed8a0facdd2db530c816e53a93e0", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914", "urls": [ - "bzz-raw://b6de3d5f4f3f6e81c55d6d688ee1160c9c6a8377d554cf9498d439e6251bef07", - "dweb:/ipfs/QmPKF1vLdUUkLm49hUdULnrdBHMX6oqfpgHzGSSKAH7fab" + "bzz-raw://d45068f4b97b8568117b6c095694b7270cad2b0337ea0c2b8b24550dfa93fdbc", + "dweb:/ipfs/QmWYtWcqTszbsZ6tJTg6GcDWdWdGcnNkALBgzRpYPL3EH7" ] }, "metadata": { @@ -13173,10 +13164,10 @@ }, "sources": { "FeePool.sol": { - "keccak256": "0x8a65c401cfedc5e54b3544097f5873fff54bed8a0facdd2db530c816e53a93e0", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914", "urls": [ - "bzz-raw://b6de3d5f4f3f6e81c55d6d688ee1160c9c6a8377d554cf9498d439e6251bef07", - "dweb:/ipfs/QmPKF1vLdUUkLm49hUdULnrdBHMX6oqfpgHzGSSKAH7fab" + "bzz-raw://d45068f4b97b8568117b6c095694b7270cad2b0337ea0c2b8b24550dfa93fdbc", + "dweb:/ipfs/QmWYtWcqTszbsZ6tJTg6GcDWdWdGcnNkALBgzRpYPL3EH7" ] } }, diff --git a/publish/deployed/kovan-ovm/feeds.json b/publish/deployed/kovan-ovm/feeds.json index 59fca0151e..5637fba30f 100644 --- a/publish/deployed/kovan-ovm/feeds.json +++ b/publish/deployed/kovan-ovm/feeds.json @@ -1,19 +1,19 @@ { "SNX": { "asset": "SNX", - "feed": "0xd9E9047ED2d6e2130395a2Fe08033e756CC7e288" + "feed": "0x38D2f492B4Ef886E71D111c592c9338374e1bd8d" }, "ETH": { "asset": "ETH", - "feed": "0xCb7895bDC70A1a1Dce69b689FD7e43A627475A06" + "feed": "0x7f8847242a530E809E17bF2DA5D2f9d2c4A43261" }, "BTC": { "asset": "BTC", - "feed": "0x81AE7F8fF54070C52f0eB4EB5b8890e1506AA4f4" + "feed": "0xd9BdB42229F1aefe47Cdf028408272686445D3ff" }, "LINK": { "asset": "LINK", - "feed": "0xb37aA79EBc31B93864Bff2d5390b385bE482897b" + "feed": "0x4e5A8fe9d533dec45C7CB57D548B049785BA9861" }, "UNI": { "asset": "UNI", diff --git a/publish/deployed/kovan-ovm/versions.json b/publish/deployed/kovan-ovm/versions.json index 32a1899fae..568d011c80 100644 --- a/publish/deployed/kovan-ovm/versions.json +++ b/publish/deployed/kovan-ovm/versions.json @@ -887,8 +887,9 @@ }, "FeePool": { "address": "0x2F737bf6a32bf3AcBef4d5148DA507569204Fb61", - "status": "current", - "keccak256": "0x8a65c401cfedc5e54b3544097f5873fff54bed8a0facdd2db530c816e53a93e0" + "status": "replaced", + "keccak256": "0x8a65c401cfedc5e54b3544097f5873fff54bed8a0facdd2db530c816e53a93e0", + "replaced_in": "v2.57.0-alpha" }, "DebtCache": { "address": "0xFC6D35EB364951953FD86bb8A1a5b0ba8Cbb6Eb2", @@ -1004,5 +1005,20 @@ "keccak256": "0xd83c3667bcacd4d33cf0fc649cee03d85e7d3914abb7ce6c9898e6ee1d66da81" } } + }, + "v2.57.0-alpha": { + "tag": "v2.57.0-alpha", + "fulltag": "v2.57.0-alpha", + "release": "Peacock", + "network": "kovan", + "date": "2022-01-14T20:06:28-05:00", + "commit": "9d1655f6992b32e16a3a8c898a82a9552de886e5", + "contracts": { + "FeePool": { + "address": "0x129fd2f3a799bD156e8c00599760AfC2f0f953dA", + "status": "current", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914" + } + } } } diff --git a/publish/deployed/kovan/deployment.json b/publish/deployed/kovan/deployment.json index 418c14ca41..6d76708700 100644 --- a/publish/deployed/kovan/deployment.json +++ b/publish/deployed/kovan/deployment.json @@ -29,11 +29,11 @@ }, "FeePool": { "name": "FeePool", - "address": "0xE532C9336934DA37aacc0143D07314d7F9D2a8c0", + "address": "0x288cA161F9382d54dD27803AbF45C78Da95D19b0", "source": "FeePool", - "link": "https://kovan.etherscan.io/address/0xE532C9336934DA37aacc0143D07314d7F9D2a8c0", - "timestamp": "2021-11-16T16:15:24.000Z", - "txn": "https://kovan.etherscan.io/tx/0xdd26aec35a24cac358d35b7b3ffdb5b05ed9b497468063585740b14440f09037", + "link": "https://kovan.etherscan.io/address/0x288cA161F9382d54dD27803AbF45C78Da95D19b0", + "timestamp": "2022-01-14T21:51:36.000Z", + "txn": "https://kovan.etherscan.io/tx/0x67b804188bf9a74bb12abe605b8efab8b11c5c298d67118aa8cb38728f312790", "network": "kovan" }, "ProxyFeePool": { @@ -2488,7 +2488,7 @@ ] }, "FeePool": { - "bytecode": "6080604052631cd554d160e21b6007553480156200001c57600080fd5b506040516200472c3803806200472c8339810160408190526200003f9162000221565b8080621baf8085856001600160a01b038116620000795760405162461bcd60e51b8152600401620000709062000343565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620000c69184906200030b565b60405180910390a1506000546001600160a01b0316620000fa5760405162461bcd60e51b8152600401620000709062000331565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9062000147908390620002fb565b60405180910390a1504201600455600580546001600160a01b0319166001600160a01b0392909216919091179055506001620001846000620001e2565b80546001600160401b0319166001600160401b039290921691909117905542620001af6000620001e2565b80546001600160401b0392909216600160801b02600160801b600160c01b0319909216919091179055506200039e915050565b60006008600260ff16836012540181620001f857fe5b06600281106200020457fe5b6005020192915050565b80516200021b8162000384565b92915050565b6000806000606084860312156200023757600080fd5b60006200024586866200020e565b935050602062000258868287016200020e565b92505060406200026b868287016200020e565b9150509250925092565b620002808162000370565b82525050565b62000280816200035e565b6000620002a060118362000355565b7013dddb995c881b5d5cdd081899481cd95d607a1b815260200192915050565b6000620002cf60198362000355565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b602081016200021b828462000275565b604081016200031b828562000275565b6200032a602083018462000286565b9392505050565b602080825281016200021b8162000291565b602080825281016200021b81620002c0565b90815260200190565b60006001600160a01b0382166200021b565b60006200021b8260006200021b826200035e565b6200038f816200035e565b81146200039b57600080fd5b50565b61437e80620003ae6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80636de813f111610145578063b410a034116100bd578063d67bdd251161008c578063eb1edd6111610071578063eb1edd611461045c578063ec55688914610464578063fd1f498d1461046c57610241565b8063d67bdd251461044c578063e0e6393d1461045457610241565b8063b410a03414610414578063bc67f8321461041c578063cff2ddad1461042f578063d294f0931461044457610241565b8063899ffef41161011457806397107d6d116100f957806397107d6d146103e6578063ac834193146103f9578063b10090b81461040157610241565b8063899ffef4146103c95780638da5cb5b146103de57610241565b80636de813f11461039e57806374185360146103a657806379ba5097146103ae57806386645274146103b657610241565b806333140016116101d857806353a47bb7116101a757806359a2f19f1161018c57806359a2f19f14610370578063614d08f8146103835780636466f45e1461038b57610241565b806353a47bb714610353578063569249d01461036857610241565b806333140016146102fd5780633ebc457a1461031d5780633fcd22401461032557806346ba2d901461034b57610241565b80631627540c116102145780631627540c146102b857806322425fa4146102cd57806322bf55ef146102d55780632af64bd3146102e857610241565b806304f3bcec1461024657806307ea50cd146102645780630813071c146102845780630de5861514610297575b600080fd5b61024e61047f565b60405161025b9190614023565b60405180910390f35b610277610272366004613262565b61048e565b60405161025b9190613f40565b6102776102923660046132a6565b610563565b6102aa6102a5366004613262565b6106af565b60405161025b929190613f5c565b6102cb6102c6366004613262565b610731565b005b61027761078f565b6102cb6102e3366004613387565b61079f565b6102f0610978565b60405161025b9190613f32565b61031061030b366004613262565b610aa8565b60405161025b9190613f13565b6102cb610d0c565b610338610333366004613387565b611112565b60405161025b97969594939291906141c0565b6102776111bb565b61035b6111c1565b60405161025b9190613e40565b6102776111d0565b6102f061037e366004613262565b61122b565b61027761123d565b6102f0610399366004613262565b611261565b61027761138d565b6102cb6113e2565b6102cb611534565b6102cb6103c43660046132e0565b6115d0565b6103d1611710565b60405161025b9190613f21565b61035b611a30565b6102cb6103f4366004613262565b611a3f565b610277611a92565b6102cb61040f366004613405565b611b32565b610277611d2c565b6102cb61042a366004613262565b611d36565b610437611d60565b60405161025b9190614228565b6102f0611d65565b61035b611ddc565b610277611deb565b61035b611df5565b61024e611e0d565b6102cb61047a366004613387565b611e1c565b6005546001600160a01b031681565b6000610498611e99565b6001600160a01b031663bdc963d87f6c6173745f6665655f7769746864726177616c00000000000000000000000000846040516020016104d9929190613dce565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161050b9190613f40565b60206040518083038186803b15801561052357600080fd5b505afa158015610537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061055b919081019061334b565b90505b919050565b60008161058b5760405162461bcd60e51b815260040161058290614192565b60405180910390fd5b600282106105ab5760405162461bcd60e51b815260040161058290614142565b6105b760018303611ec4565b5468010000000000000000900467ffffffffffffffff166105da575060006106a9565b600061060a60016105ed60018603611ec4565b5468010000000000000000900467ffffffffffffffff1690611eee565b9050600080610617611f16565b6001600160a01b031663d29c000a87856040518363ffffffff1660e01b8152600401610644929190613e92565b604080518083038186803b15801561065b57600080fd5b505afa15801561066f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061069391908101906133d5565b90925090506106a3838383611f41565b93505050505b92915050565b6000806106ba61317a565b6106c384610aa8565b905060008060015b6002811015610724576106f08482600281106106e357fe5b602002015151849061208c565b925061071a84826002811061070157fe5b602002015160016020020151839063ffffffff61208c16565b91506001016106cb565b509093509150505b915091565b6107396120b1565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610784908390613e40565b60405180910390a150565b60006107996120dd565b90505b90565b60006107a96121a4565b6001600160a01b0316331490506000806107c16121cf565b6001600160a01b03166316b2213f336040518263ffffffff1660e01b81526004016107ec9190613e4e565b60206040518083038186803b15801561080457600080fd5b505afa158015610818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061083c919081019061334b565b14159050600061084a6121e3565b6001600160a01b031663b38988f7336040518263ffffffff1660e01b81526004016108759190613e4e565b60206040518083038186803b15801561088d57600080fd5b505afa1580156108a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108c5919081019061332d565b905060006108d161220e565b6001600160a01b0316336001600160a01b031614905060006108f1612239565b6001600160a01b0316336001600160a01b031614905084806109105750835b806109185750825b806109205750815b806109285750805b6109445760405162461bcd60e51b815260040161058290614042565b610962866109526000611ec4565b600101549063ffffffff61208c16565b61096c6000611ec4565b60010155505050505050565b60006060610984611710565b905060005b8151811015610a9f5760008282815181106109a057fe5b602090810291909101810151600081815260069092526040918290205460055492517f21f8a7210000000000000000000000000000000000000000000000000000000081529193506001600160a01b039081169216906321f8a72190610a0a908590600401613f40565b60206040518083038186803b158015610a2257600080fd5b505afa158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a5a9190810190613288565b6001600160a01b0316141580610a8557506000818152600660205260409020546001600160a01b0316155b15610a96576000935050505061079c565b50600101610989565b50600191505090565b610ab061317a565b6000806000610abd611f16565b6040517fb326f84e0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0382169063b326f84e90610b08908890600090600401613e77565b604080518083038186803b158015610b1f57600080fd5b505afa158015610b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b5791908101906133d5565b909350915081158015610b68575082155b15610b8057610b7561317a565b935061055e92505050565b600080610b8f60008686612264565b8751829052875160200181905290925090506000610bac8861048e565b905060015b8015610d005760001981016000610bc782611ec4565b5468010000000000000000900467ffffffffffffffff1690508015801590610c015750610bf383611ec4565b5467ffffffffffffffff1684105b15610cf5576000610c1982600163ffffffff611eee16565b6040517fd29c000a0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0389169063d29c000a90610c63908f908590600401613e92565b604080518083038186803b158015610c7a57600080fd5b505afa158015610c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610cb291908101906133d5565b909a509850610cc2848b8b612264565b9097509550868b8560028110610cd457fe5b602002015152858b8560028110610ce757fe5b602002015160016020020152505b505060001901610bb1565b50505050505050919050565b610d14612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015610d4c57600080fd5b505afa158015610d60573d6000803e3d6000fd5b505050506000610d6e6120dd565b11610d8b5760405162461bcd60e51b8152600401610582906141a2565b610d936120dd565b4203610d9f6000611ec4565b54600160801b900467ffffffffffffffff161115610dcf5760405162461bcd60e51b815260040161058290614062565b610dd761220e565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e1157600080fd5b505af1158015610e25573d6000803e3d6000fd5b50505050610e31612239565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e6b57600080fd5b505af1158015610e7f573d6000803e3d6000fd5b5060009250610e919150829050611ec4565b90506000610e9f6001611ec4565b9050610ed08260010154610ec483600201548460010154611eee90919063ffffffff16565b9063ffffffff61208c16565b610eda6000611ec4565b60010155600380830154600483015491830154610f0192610ec4919063ffffffff611eee16565b610f0b6000611ec4565b60030155601254610f4890600290610f3c90600190610f30908463ffffffff61208c16565b9063ffffffff611eee16565b9063ffffffff61233116565b601281905560089060028110610f5a57fe5b6005020180547fffffffffffffffff000000000000000000000000000000000000000000000000168155600060018083018290556002830182905560038301829055600490920155610fc690610faf81611ec4565b5467ffffffffffffffff169063ffffffff61208c16565b610fd06000611ec4565b805467ffffffffffffffff191667ffffffffffffffff92909216919091179055610ff8612361565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561103057600080fd5b505afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611068919081019061334b565b6110726000611ec4565b805467ffffffffffffffff9290921668010000000000000000026fffffffffffffffff000000000000000019909216919091179055426110b26000611ec4565b805467ffffffffffffffff92909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905561110e6110fe6001611ec4565b5467ffffffffffffffff1661238c565b5050565b60008060008060008060006111256131a7565b61112e89611ec4565b6040805160e081018252825467ffffffffffffffff808216808452680100000000000000008304821660208501819052600160801b909304909116938301849052600185015460608401819052600286015460808501819052600387015460a0860181905260049097015460c0909501859052919f929e50939c50929a5091985091965090945092505050565b60045481565b6001546001600160a01b031681565b60008060015b6002811015611225576111fc6111eb82611ec4565b60010154839063ffffffff61208c16565b915061121b61120a82611ec4565b60020154839063ffffffff611eee16565b91506001016111d6565b50905090565b600061123682612444565b5092915050565b7f466565506f6f6c0000000000000000000000000000000000000000000000000081565b600061126b612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156112a357600080fd5b505afa1580156112b7573d6000803e3d6000fd5b505050506112c3612538565b6112cb612577565b6003546040517f21f4ae570000000000000000000000000000000000000000000000000000000081526001600160a01b03928316926321f4ae579261131892879290911690600401613e5c565b60206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611368919081019061332d565b6113845760405162461bcd60e51b8152600401610582906140e2565b61055b826125a2565b60008060015b6002811015611225576113b96113a882611ec4565b60030154839063ffffffff61208c16565b91506113d86113c782611ec4565b60040154839063ffffffff611eee16565b9150600101611393565b60606113ec611710565b905060005b815181101561110e57600082828151811061140857fe5b602002602001015190506000600560009054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200161144a9190613e2a565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611476929190613f6a565b60206040518083038186803b15801561148e57600080fd5b505afa1580156114a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114c69190810190613288565b6000838152600660205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906115229084908490613f4e565b60405180910390a150506001016113f1565b6001546001600160a01b0316331461155e5760405162461bcd60e51b815260040161058290614052565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c926115a1926001600160a01b0391821692911690613e5c565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006115da6121cf565b6001600160a01b0316336001600160a01b031614905060006115fa612361565b6001600160a01b0316336001600160a01b031614905081806116195750805b6116355760405162461bcd60e51b815260040161058290614182565b61163d611f16565b6001600160a01b03166394e1a4488686866116586000611ec4565b5460405160e086901b7fffffffff000000000000000000000000000000000000000000000000000000001681526116ab9493929168010000000000000000900467ffffffffffffffff1690600401613ed5565b600060405180830381600087803b1580156116c557600080fd5b505af11580156116d9573d6000803e3d6000fd5b505050506117098585856116ed6000611ec4565b5468010000000000000000900467ffffffffffffffff16612697565b5050505050565b60608061171b612766565b60408051600d8082526101c0820190925291925060609190602082016101a0803883390190505090507f53797374656d53746174757300000000000000000000000000000000000000008160008151811061177257fe5b6020026020010181815250507f53796e7468657469780000000000000000000000000000000000000000000000816001815181106117ac57fe5b6020026020010181815250507f466565506f6f6c53746174650000000000000000000000000000000000000000816002815181106117e657fe5b6020026020010181815250507f466565506f6f6c457465726e616c53746f7261676500000000000000000000008160038151811061182057fe5b6020026020010181815250507f45786368616e67657200000000000000000000000000000000000000000000008160048151811061185a57fe5b6020026020010181815250506524b9b9bab2b960d11b8160058151811061187d57fe5b6020026020010181815250507f53796e7468657469785374617465000000000000000000000000000000000000816006815181106118b757fe5b6020026020010181815250507f526577617264457363726f775632000000000000000000000000000000000000816007815181106118f157fe5b6020026020010181815250507f44656c6567617465417070726f76616c730000000000000000000000000000008160088151811061192b57fe5b6020026020010181815250507f52657761726473446973747269627574696f6e000000000000000000000000008160098151811061196557fe5b6020026020010181815250507f436f6c6c61746572616c4d616e6167657200000000000000000000000000000081600a8151811061199f57fe5b6020026020010181815250507f57726170706572466163746f727900000000000000000000000000000000000081600b815181106119d957fe5b6020026020010181815250507f457468657257726170706572000000000000000000000000000000000000000081600c81518110611a1357fe5b602002602001018181525050611a2982826127c5565b9250505090565b6000546001600160a01b031681565b611a476120b1565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e90610784908390613e4e565b6000610799611b1e611aa261287a565b73__$f9217daff40bcb29719cec84f7ab900933$__63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611ae657600080fd5b505af4158015611afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ec4919081019061334b565b611b266128f1565b9063ffffffff61296816565b611b3a612992565b6004544210611b5b5760405162461bcd60e51b815260040161058290614152565b611b63612361565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b9b57600080fd5b505afa158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611bd3919081019061334b565b861115611bf25760405162461bcd60e51b815260040161058290614132565b6040518060e001604052808867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018667ffffffffffffffff168152602001858152602001848152602001838152602001828152506008611c62600260ff16610f3c8c60125461208c90919063ffffffff16565b60028110611c6c57fe5b82516005919091029190910180546020840151604085015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff000000000000000019166801000000000000000091851691909102177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b9390911692909202919091178155606082015160018201556080820151600282015560a0820151600382015560c0909101516004909101555050505050505050565b60006107996128f1565b611d3e612a00565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600281565b6000611d6f612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611da757600080fd5b505afa158015611dbb573d6000803e3d6000fd5b50505050611dc7612538565b600354610799906001600160a01b03166125a2565b6003546001600160a01b031681565b600061079961287a565b73feefeefeefeefeefeefeefeefeefeefeefeefeef81565b6002546001600160a01b031681565b6000611e26612a2a565b6003549091506001600160a01b0380831691161480611e4d5750336001600160a01b038216145b611e695760405162461bcd60e51b8152600401610582906140f2565b611e8782611e776000611ec4565b600301549063ffffffff61208c16565b611e916000611ec4565b600301555050565b60006107997f466565506f6f6c457465726e616c53746f726167650000000000000000000000612a51565b60006008600260ff16836012540181611ed957fe5b0660028110611ee457fe5b6005020192915050565b600082821115611f105760405162461bcd60e51b815260040161058290614092565b50900390565b60006107997f466565506f6f6c53746174650000000000000000000000000000000000000000612a51565b600080611f4c612361565b9050600061208085612074846001600160a01b03166308d95cd5886040518263ffffffff1660e01b8152600401611f839190613f40565b60206040518083038186803b158015611f9b57600080fd5b505afa158015611faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611fd3919081019061334b565b6040517f08d95cd50000000000000000000000000000000000000000000000000000000081526001600160a01b038716906308d95cd590612018908d90600401613f40565b60206040518083038186803b15801561203057600080fd5b505afa158015612044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612068919081019061334b565b9063ffffffff612aae16565b9063ffffffff612ac716565b925050505b9392505050565b6000828201838110156120855760405162461bcd60e51b815260040161058290614082565b6000546001600160a01b031633146120db5760405162461bcd60e51b815260040161058290614102565b565b60006120e7612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f666565506572696f644475726174696f6e0000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b60206040518083038186803b15801561216c57600080fd5b505afa158015612180573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610799919081019061334b565b60006107997f45786368616e6765720000000000000000000000000000000000000000000000612a51565b60006107996524b9b9bab2b960d11b612a51565b60006107997f436f6c6c61746572616c4d616e61676572000000000000000000000000000000612a51565b60006107997f4574686572577261707065720000000000000000000000000000000000000000612a51565b60006107997f57726170706572466163746f7279000000000000000000000000000000000000612a51565b60008083612277575060009050806122fe565b8385156122a257600061229160016105ed60018a03611ec4565b905061229e818787611f41565b9150505b60006122c1826122b189611ec4565b600101549063ffffffff61296816565b905060006122e2836122d28a611ec4565b600301549063ffffffff61296816565b90506122ed82612b0b565b6122f682612b0b565b945094505050505b935093915050565b60006107997f53797374656d5374617475730000000000000000000000000000000000000000612a51565b6000816123505760405162461bcd60e51b8152600401610582906140d2565b81838161235957fe5b069392505050565b60006107997f53796e7468657469785374617465000000000000000000000000000000000000612a51565b6002546040516001600160a01b039091169063907dff97906123b2908490602001613f40565b60405160208183030381529060405260016040516123cf90613e35565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261241693929160009081908190600401613f8a565b600060405180830381600087803b15801561243057600080fd5b505af1158015611709573d6000803e3d6000fd5b6000806000806124526121cf565b6001600160a01b031663ae3bbbbb866040518263ffffffff1660e01b815260040161247d9190613e40565b604080518083038186803b15801561249457600080fd5b505afa1580156124a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124cc91908101906133a5565b9150915060006124da6128f1565b9050808310156124f2575060019350915061072c9050565b600061250f612502611aa261287a565b839063ffffffff61296816565b90508084111561252957600083955095505050505061072c565b50600194509092505050915091565b6002546001600160a01b0316331480159061255e57506003546001600160a01b03163314155b156120db57600380546001600160a01b03191633179055565b60006107997f44656c6567617465417070726f76616c73000000000000000000000000000000612a51565b60008080808080806125b388612444565b91509150816125d45760405162461bcd60e51b815260040161058290614112565b80156125f25760405162461bcd60e51b8152600401610582906140c2565b6125fb886106af565b90945092508315158061260e5750600083115b61262a5760405162461bcd60e51b8152600401610582906140b2565b612648886126386001611ec4565b5467ffffffffffffffff16612b2d565b83156126635761265784612be0565b94506126638886612cbc565b821561267e5761267283612e58565b955061267e8887612f32565b612689888688612fac565b506001979650505050505050565b6002546040516001600160a01b039091169063907dff97906126c1908690869086906020016141b2565b60405160208183030381529060405260026040516126de90613dff565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261272e9392916001600160a01b038b16906000908190600401613fe9565b600060405180830381600087803b15801561274857600080fd5b505af115801561275c573d6000803e3d6000fd5b5050505050505050565b604080516001808252818301909252606091602080830190803883390190505090507f466c657869626c6553746f726167650000000000000000000000000000000000816000815181106127b657fe5b60200260200101818152505090565b606081518351016040519080825280602002602001820160405280156127f5578160200160208202803883390190505b50905060005b83518110156128375783818151811061281057fe5b602002602001015182828151811061282457fe5b60209081029190910101526001016127fb565b5060005b82518110156112365782818151811061285057fe5b602002602001015182828651018151811061286757fe5b602090810291909101015260010161283b565b6000612884612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f7461726765745468726573686f6c6400000000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b60006128fb612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f69737375616e6365526174696f000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b6000670de0b6b3a7640000612983848463ffffffff61307116565b8161298a57fe5b049392505050565b6002546001600160a01b031633148015906129b857506003546001600160a01b03163314155b156129d057600380546001600160a01b031916331790555b6000546003546001600160a01b039081169116146120db5760405162461bcd60e51b815260040161058290614072565b6002546001600160a01b031633146120db5760405162461bcd60e51b815260040161058290614172565b60006107997f52657761726473446973747269627574696f6e000000000000000000000000005b60008181526006602090815260408083205490516001600160a01b039091169182151591612a8191869101613e0a565b604051602081830303815290604052906112365760405162461bcd60e51b81526004016105829190614031565b600061208583836b033b2e3c9fd0803ce80000006130ab565b600061208583836b033b2e3c9fd0803ce80000006130ef565b60006107997f466c657869626c6553746f726167650000000000000000000000000000000000612a51565b60006305f5e10082046005600a820610612b2357600a015b600a900492915050565b612b35611e99565b6001600160a01b0316633562fd207f6c6173745f6665655f7769746864726177616c0000000000000000000000000084604051602001612b76929190613dce565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b8152600401612baa929190613f5c565b600060405180830381600087803b158015612bc457600080fd5b505af1158015612bd8573d6000803e3d6000fd5b505050505050565b6000818160015b6002811015612cb4576000612bfb82611ec4565b6002015490506000612c2082612c1085611ec4565b600101549063ffffffff611eee16565b90508015612ca9576000858210612c375785612c39565b815b9050612c4b838263ffffffff61208c16565b612c5485611ec4565b60020155612c68868263ffffffff611eee16565b9550612c7a858263ffffffff61208c16565b945085612c8f5784965050505050505061055e565b83158015612c9d5750600086115b15612ca757600095505b505b505060001901612be7565b509392505050565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612cfa5760405162461bcd60e51b815260040161058290614162565b6000612d046121cf565b6001600160a01b031663326080396007546040518263ffffffff1660e01b8152600401612d319190613f40565b60206040518083038186803b158015612d4957600080fd5b505afa158015612d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d819190810190613369565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081529091506001600160a01b03821690639dc29fac90612ddf9073feefeefeefeefeefeefeefeefeefeefeefeefeef908790600401613e92565b600060405180830381600087803b158015612df957600080fd5b505af1158015612e0d573d6000803e3d6000fd5b50506040517f867904b40000000000000000000000000000000000000000000000000000000081526001600160a01b038416925063867904b4915061272e9087908790600401613e92565b6000818160015b6002811015612cb4576000612e93612e7683611ec4565b60040154612e8384611ec4565b600301549063ffffffff611eee16565b90508015612f28576000848210612eaa5784612eac565b815b9050612ecb81612ebb85611ec4565b600401549063ffffffff61208c16565b612ed484611ec4565b60040155612ee8858263ffffffff611eee16565b9450612efa848263ffffffff61208c16565b935084612f0e57839550505050505061055e565b82158015612f1c5750600085115b15612f2657600094505b505b5060001901612e5f565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612f705760405162461bcd60e51b815260040161058290614162565b6301dfe200612f7d61311a565b6001600160a01b0316631bb47b448585846040518463ffffffff1660e01b815260040161272e93929190613ead565b6002546040516001600160a01b039091169063907dff9790612fd690869086908690602001613ead565b6040516020818303038152906040526001604051612ff390613df4565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261303a93929160009081908190600401613f8a565b600060405180830381600087803b15801561305457600080fd5b505af1158015613068573d6000803e3d6000fd5b50505050505050565b600082613080575060006106a9565b8282028284828161308d57fe5b04146120855760405162461bcd60e51b815260040161058290614122565b6000806130d1846130c587600a870263ffffffff61307116565b9063ffffffff61314516565b90506005600a825b06106130e357600a015b600a9004949350505050565b600080600a8304613106868663ffffffff61307116565b8161310d57fe5b0490506005600a826130d9565b60006107997f526577617264457363726f775632000000000000000000000000000000000000612a51565b60008082116131665760405162461bcd60e51b8152600401610582906140a2565b600082848161317157fe5b04949350505050565b60405180604001604052806002905b613191613202565b8152602001906001900390816131895790505090565b6040518060e00160405280600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b80356106a981614309565b80516106a981614309565b80516106a981614320565b80516106a981614329565b80516106a981614332565b80356106a981614329565b60006020828403121561327457600080fd5b60006132808484613220565b949350505050565b60006020828403121561329a57600080fd5b6000613280848461322b565b600080604083850312156132b957600080fd5b60006132c58585613220565b92505060206132d685828601613257565b9150509250929050565b6000806000606084860312156132f557600080fd5b60006133018686613220565b935050602061331286828701613257565b925050604061332386828701613257565b9150509250925092565b60006020828403121561333f57600080fd5b60006132808484613236565b60006020828403121561335d57600080fd5b60006132808484613241565b60006020828403121561337b57600080fd5b6000613280848461324c565b60006020828403121561339957600080fd5b60006132808484613257565b600080604083850312156133b857600080fd5b60006133c48585613241565b92505060206132d685828601613236565b600080604083850312156133e857600080fd5b60006133f48585613241565b92505060206132d685828601613241565b600080600080600080600080610100898b03121561342257600080fd5b600061342e8b8b613257565b985050602061343f8b828c01613257565b97505060406134508b828c01613257565b96505060606134618b828c01613257565b95505060806134728b828c01613257565b94505060a06134838b828c01613257565b93505060c06134948b828c01613257565b92505060e06134a58b828c01613257565b9150509295985092959890939650565b60006134c183836135ab565b505060400190565b60006134d58383613600565b505060200190565b6134e681614289565b82525050565b6134e68161424f565b6134e66135018261424f565b6142e8565b61350f8161423c565b613519818461055e565b92506135248261079c565b8060005b83811015612bd857815161353c87826134b5565b965061354783614236565b925050600101613528565b600061355d82614242565b6135678185614246565b935061357283614236565b8060005b838110156135a057815161358a88826134c9565b975061359583614236565b925050600101613576565b509495945050505050565b6135b48161423c565b6135be818461055e565b92506135c98261079c565b8060005b83811015612bd85781516135e187826134c9565b96506135ec83614236565b9250506001016135cd565b6134e68161425a565b6134e68161079c565b6134e66136158261079c565b61079c565b600061362582614242565b61362f8185614246565b935061363f8185602086016142b8565b613648816142f9565b9093019392505050565b6134e68161425f565b6134e681614294565b6134e6816142a2565b600061367a601783614246565b7f4f6e6c7920496e7465726e616c20436f6e747261637473000000000000000000815260200192915050565b60006136b3603583614246565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015260400192915050565b6000613712601d83614246565b7f546f6f206561726c7920746f20636c6f73652066656520706572696f64000000815260200192915050565b600061374b601383614246565b7f4f776e6572206f6e6c792066756e6374696f6e00000000000000000000000000815260200192915050565b600061378460248361055e565b7f46656573436c61696d656428616464726573732c75696e743235362c75696e7481527f3235362900000000000000000000000000000000000000000000000000000000602082015260240192915050565b60006137e360378361055e565b7f49737375616e636544656274526174696f456e74727928616464726573732c7581527f696e743235362c75696e743235362c75696e7432353629000000000000000000602082015260370192915050565b6000613842601b83614246565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061387b601e83614246565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b60006138b4601a83614246565b7f536166654d6174683a206469766973696f6e206279207a65726f000000000000815260200192915050565b60006138ed604083614246565b7f4e6f2066656573206f72207265776172647320617661696c61626c6520666f7281527f20706572696f642c206f72206665657320616c726561647920636c61696d6564602082015260400192915050565b600061394c60118361055e565b7f4d697373696e6720616464726573733a20000000000000000000000000000000815260110192915050565b6000613985601e83614246565b7f412073796e7468206f7220534e58207261746520697320696e76616c69640000815260200192915050565b60006139be601883614246565b7f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815260200192915050565b60006139f7601f83614246565b7f4e6f7420617070726f76656420746f20636c61696d206f6e20626568616c6600815260200192915050565b6000613a30601e83614246565b7f43616c6c6572206973206e6f742072657761726473417574686f726974790000815260200192915050565b6000613a69602f83614246565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015260400192915050565b6000613ac8601f83614246565b7f432d526174696f2062656c6f772070656e616c7479207468726573686f6c6400815260200192915050565b6000613b01602183614246565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613b60601683614246565b7f43616e6e6f7420696d706f727420626164206461746100000000000000000000815260200192915050565b6000613b99601d83614246565b7f4578636565647320746865204645455f504552494f445f4c454e475448000000815260200192915050565b6000613bd2602983614246565b7f43616e206f6e6c7920706572666f726d207468697320616374696f6e2064757281527f696e672073657475700000000000000000000000000000000000000000000000602082015260400192915050565b6000613c3160198361055e565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000613c6a601783614246565b7f4665652061646472657373206e6f7420616c6c6f776564000000000000000000815260200192915050565b6000613ca360188361055e565b7f466565506572696f64436c6f7365642875696e74323536290000000000000000815260180192915050565b6000613cdc601783614246565b7f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000815260200192915050565b6000613d15601e83614246565b7f49737375657220616e642053796e7468657469785374617465206f6e6c790000815260200192915050565b6000613d4e602083614246565b7f43757272656e7420706572696f64206973206e6f7420636c6f73656420796574815260200192915050565b6000613d87601b83614246565b7f46656520506572696f64204475726174696f6e206e6f74207365740000000000815260200192915050565b6134e6816142ad565b6134e681614276565b6134e681614283565b6000613dda8285613609565b602082019150613dea82846134f5565b5060140192915050565b60006106a982613777565b60006106a9826137d6565b6000613e158261393f565b9150613e218284613609565b50602001919050565b6000613e1582613c24565b60006106a982613c96565b602081016106a982846134ec565b602081016106a982846134dd565b60408101613e6a82856134ec565b61208560208301846134ec565b60408101613e8582856134ec565b6120856020830184613664565b60408101613ea082856134ec565b6120856020830184613600565b60608101613ebb82866134ec565b613ec86020830185613600565b6132806040830184613600565b60808101613ee382876134ec565b613ef06020830186613600565b613efd6040830185613600565b613f0a6060830184613db3565b95945050505050565b608081016106a98284613506565b602080825281016120858184613552565b602081016106a982846135f7565b602081016106a98284613600565b60408101613e6a8285613600565b60408101613ea08285613600565b60408101613f788285613600565b8181036020830152613280818461361a565b60c08082528101613f9b818961361a565b9050613faa6020830188613664565b613fb76040830187613600565b613fc4606083018661365b565b613fd1608083018561365b565b613fde60a083018461365b565b979650505050505050565b60c08082528101613ffa818961361a565b90506140096020830188613664565b6140166040830187613600565b613fc46060830186613600565b602081016106a98284613652565b60208082528101612085818461361a565b6020808252810161055b8161366d565b6020808252810161055b816136a6565b6020808252810161055b81613705565b6020808252810161055b8161373e565b6020808252810161055b81613835565b6020808252810161055b8161386e565b6020808252810161055b816138a7565b6020808252810161055b816138e0565b6020808252810161055b81613978565b6020808252810161055b816139b1565b6020808252810161055b816139ea565b6020808252810161055b81613a23565b6020808252810161055b81613a5c565b6020808252810161055b81613abb565b6020808252810161055b81613af4565b6020808252810161055b81613b53565b6020808252810161055b81613b8c565b6020808252810161055b81613bc5565b6020808252810161055b81613c5d565b6020808252810161055b81613ccf565b6020808252810161055b81613d08565b6020808252810161055b81613d41565b6020808252810161055b81613d7a565b60608101613ebb8286613600565b60e081016141ce828a613dbc565b6141db6020830189613dbc565b6141e86040830188613dbc565b6141f56060830187613600565b6142026080830186613600565b61420f60a0830185613600565b61421c60c0830184613600565b98975050505050505050565b602081016106a98284613dc5565b60200190565b50600290565b5190565b90815260200190565b600061055b8261426a565b151590565b600061055b8261424f565b6001600160a01b031690565b67ffffffffffffffff1690565b60ff1690565b600061055b8261425f565b600061055b6136158361079c565b600061055b8261079c565b600061055b82614276565b60005b838110156142d35781810151838201526020016142bb565b838111156142e2576000848401525b50505050565b600061055b82600061055b82614303565b601f01601f191690565b60601b90565b6143128161424f565b811461431d57600080fd5b50565b6143128161425a565b6143128161079c565b6143128161425f56fea365627a7a7231582023fb25e610f0e82a8e13a44599008ec503839a1c5669bf3ffe153f41941fe4c36c6578706572696d656e74616cf564736f6c63430005100040", + "bytecode": "6080604052631cd554d160e21b6007553480156200001c57600080fd5b506040516200471b3803806200471b8339810160408190526200003f9162000221565b8080621baf8085856001600160a01b038116620000795760405162461bcd60e51b8152600401620000709062000343565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620000c69184906200030b565b60405180910390a1506000546001600160a01b0316620000fa5760405162461bcd60e51b8152600401620000709062000331565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9062000147908390620002fb565b60405180910390a1504201600455600580546001600160a01b0319166001600160a01b0392909216919091179055506001620001846000620001e2565b80546001600160401b0319166001600160401b039290921691909117905542620001af6000620001e2565b80546001600160401b0392909216600160801b02600160801b600160c01b0319909216919091179055506200039e915050565b60006008600260ff16836012540181620001f857fe5b06600281106200020457fe5b6005020192915050565b80516200021b8162000384565b92915050565b6000806000606084860312156200023757600080fd5b60006200024586866200020e565b935050602062000258868287016200020e565b92505060406200026b868287016200020e565b9150509250925092565b620002808162000370565b82525050565b62000280816200035e565b6000620002a060118362000355565b7013dddb995c881b5d5cdd081899481cd95d607a1b815260200192915050565b6000620002cf60198362000355565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b602081016200021b828462000275565b604081016200031b828562000275565b6200032a602083018462000286565b9392505050565b602080825281016200021b8162000291565b602080825281016200021b81620002c0565b90815260200190565b60006001600160a01b0382166200021b565b60006200021b8260006200021b826200035e565b6200038f816200035e565b81146200039b57600080fd5b50565b61436d80620003ae6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80636de813f111610145578063b410a034116100bd578063d67bdd251161008c578063eb1edd6111610071578063eb1edd611461045c578063ec55688914610464578063fd1f498d1461046c57610241565b8063d67bdd251461044c578063e0e6393d1461045457610241565b8063b410a03414610414578063bc67f8321461041c578063cff2ddad1461042f578063d294f0931461044457610241565b8063899ffef41161011457806397107d6d116100f957806397107d6d146103e6578063ac834193146103f9578063b10090b81461040157610241565b8063899ffef4146103c95780638da5cb5b146103de57610241565b80636de813f11461039e57806374185360146103a657806379ba5097146103ae57806386645274146103b657610241565b806333140016116101d857806353a47bb7116101a757806359a2f19f1161018c57806359a2f19f14610370578063614d08f8146103835780636466f45e1461038b57610241565b806353a47bb714610353578063569249d01461036857610241565b806333140016146102fd5780633ebc457a1461031d5780633fcd22401461032557806346ba2d901461034b57610241565b80631627540c116102145780631627540c146102b857806322425fa4146102cd57806322bf55ef146102d55780632af64bd3146102e857610241565b806304f3bcec1461024657806307ea50cd146102645780630813071c146102845780630de5861514610297575b600080fd5b61024e61047f565b60405161025b9190614012565b60405180910390f35b610277610272366004613251565b61048e565b60405161025b9190613f2f565b610277610292366004613295565b610563565b6102aa6102a5366004613251565b6106af565b60405161025b929190613f4b565b6102cb6102c6366004613251565b610731565b005b61027761078f565b6102cb6102e3366004613376565b61079f565b6102f0610978565b60405161025b9190613f21565b61031061030b366004613251565b610aa8565b60405161025b9190613f02565b6102cb610d0c565b610338610333366004613376565b611112565b60405161025b97969594939291906141af565b6102776111bb565b61035b6111c1565b60405161025b9190613e2f565b6102776111d0565b6102f061037e366004613251565b61122b565b61027761123d565b6102f0610399366004613251565b611261565b61027761138d565b6102cb6113e2565b6102cb611534565b6102cb6103c43660046132cf565b6115d0565b6103d1611710565b60405161025b9190613f10565b61035b611a30565b6102cb6103f4366004613251565b611a3f565b610277611a92565b6102cb61040f3660046133f4565b611b32565b610277611d2c565b6102cb61042a366004613251565b611d36565b610437611d60565b60405161025b9190614217565b6102f0611d65565b61035b611ddc565b610277611deb565b61035b611df5565b61024e611e0d565b6102cb61047a366004613376565b611e1c565b6005546001600160a01b031681565b6000610498611e88565b6001600160a01b031663bdc963d87f6c6173745f6665655f7769746864726177616c00000000000000000000000000846040516020016104d9929190613dbd565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161050b9190613f2f565b60206040518083038186803b15801561052357600080fd5b505afa158015610537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061055b919081019061333a565b90505b919050565b60008161058b5760405162461bcd60e51b815260040161058290614181565b60405180910390fd5b600282106105ab5760405162461bcd60e51b815260040161058290614131565b6105b760018303611eb3565b5468010000000000000000900467ffffffffffffffff166105da575060006106a9565b600061060a60016105ed60018603611eb3565b5468010000000000000000900467ffffffffffffffff1690611edd565b9050600080610617611f05565b6001600160a01b031663d29c000a87856040518363ffffffff1660e01b8152600401610644929190613e81565b604080518083038186803b15801561065b57600080fd5b505afa15801561066f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061069391908101906133c4565b90925090506106a3838383611f30565b93505050505b92915050565b6000806106ba613169565b6106c384610aa8565b905060008060015b6002811015610724576106f08482600281106106e357fe5b602002015151849061207b565b925061071a84826002811061070157fe5b602002015160016020020151839063ffffffff61207b16565b91506001016106cb565b509093509150505b915091565b6107396120a0565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610784908390613e2f565b60405180910390a150565b60006107996120cc565b90505b90565b60006107a9612193565b6001600160a01b0316331490506000806107c16121be565b6001600160a01b03166316b2213f336040518263ffffffff1660e01b81526004016107ec9190613e3d565b60206040518083038186803b15801561080457600080fd5b505afa158015610818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061083c919081019061333a565b14159050600061084a6121d2565b6001600160a01b031663b38988f7336040518263ffffffff1660e01b81526004016108759190613e3d565b60206040518083038186803b15801561088d57600080fd5b505afa1580156108a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108c5919081019061331c565b905060006108d16121fd565b6001600160a01b0316336001600160a01b031614905060006108f1612228565b6001600160a01b0316336001600160a01b031614905084806109105750835b806109185750825b806109205750815b806109285750805b6109445760405162461bcd60e51b815260040161058290614031565b610962866109526000611eb3565b600101549063ffffffff61207b16565b61096c6000611eb3565b60010155505050505050565b60006060610984611710565b905060005b8151811015610a9f5760008282815181106109a057fe5b602090810291909101810151600081815260069092526040918290205460055492517f21f8a7210000000000000000000000000000000000000000000000000000000081529193506001600160a01b039081169216906321f8a72190610a0a908590600401613f2f565b60206040518083038186803b158015610a2257600080fd5b505afa158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a5a9190810190613277565b6001600160a01b0316141580610a8557506000818152600660205260409020546001600160a01b0316155b15610a96576000935050505061079c565b50600101610989565b50600191505090565b610ab0613169565b6000806000610abd611f05565b6040517fb326f84e0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0382169063b326f84e90610b08908890600090600401613e66565b604080518083038186803b158015610b1f57600080fd5b505afa158015610b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b5791908101906133c4565b909350915081158015610b68575082155b15610b8057610b75613169565b935061055e92505050565b600080610b8f60008686612253565b8751829052875160200181905290925090506000610bac8861048e565b905060015b8015610d005760001981016000610bc782611eb3565b5468010000000000000000900467ffffffffffffffff1690508015801590610c015750610bf383611eb3565b5467ffffffffffffffff1684105b15610cf5576000610c1982600163ffffffff611edd16565b6040517fd29c000a0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0389169063d29c000a90610c63908f908590600401613e81565b604080518083038186803b158015610c7a57600080fd5b505afa158015610c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610cb291908101906133c4565b909a509850610cc2848b8b612253565b9097509550868b8560028110610cd457fe5b602002015152858b8560028110610ce757fe5b602002015160016020020152505b505060001901610bb1565b50505050505050919050565b610d146122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015610d4c57600080fd5b505afa158015610d60573d6000803e3d6000fd5b505050506000610d6e6120cc565b11610d8b5760405162461bcd60e51b815260040161058290614191565b610d936120cc565b4203610d9f6000611eb3565b54600160801b900467ffffffffffffffff161115610dcf5760405162461bcd60e51b815260040161058290614051565b610dd76121fd565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e1157600080fd5b505af1158015610e25573d6000803e3d6000fd5b50505050610e31612228565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e6b57600080fd5b505af1158015610e7f573d6000803e3d6000fd5b5060009250610e919150829050611eb3565b90506000610e9f6001611eb3565b9050610ed08260010154610ec483600201548460010154611edd90919063ffffffff16565b9063ffffffff61207b16565b610eda6000611eb3565b60010155600380830154600483015491830154610f0192610ec4919063ffffffff611edd16565b610f0b6000611eb3565b60030155601254610f4890600290610f3c90600190610f30908463ffffffff61207b16565b9063ffffffff611edd16565b9063ffffffff61232016565b601281905560089060028110610f5a57fe5b6005020180547fffffffffffffffff000000000000000000000000000000000000000000000000168155600060018083018290556002830182905560038301829055600490920155610fc690610faf81611eb3565b5467ffffffffffffffff169063ffffffff61207b16565b610fd06000611eb3565b805467ffffffffffffffff191667ffffffffffffffff92909216919091179055610ff8612350565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561103057600080fd5b505afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611068919081019061333a565b6110726000611eb3565b805467ffffffffffffffff9290921668010000000000000000026fffffffffffffffff000000000000000019909216919091179055426110b26000611eb3565b805467ffffffffffffffff92909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905561110e6110fe6001611eb3565b5467ffffffffffffffff1661237b565b5050565b6000806000806000806000611125613196565b61112e89611eb3565b6040805160e081018252825467ffffffffffffffff808216808452680100000000000000008304821660208501819052600160801b909304909116938301849052600185015460608401819052600286015460808501819052600387015460a0860181905260049097015460c0909501859052919f929e50939c50929a5091985091965090945092505050565b60045481565b6001546001600160a01b031681565b60008060015b6002811015611225576111fc6111eb82611eb3565b60010154839063ffffffff61207b16565b915061121b61120a82611eb3565b60020154839063ffffffff611edd16565b91506001016111d6565b50905090565b600061123682612433565b5092915050565b7f466565506f6f6c0000000000000000000000000000000000000000000000000081565b600061126b6122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156112a357600080fd5b505afa1580156112b7573d6000803e3d6000fd5b505050506112c3612527565b6112cb612566565b6003546040517f21f4ae570000000000000000000000000000000000000000000000000000000081526001600160a01b03928316926321f4ae579261131892879290911690600401613e4b565b60206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611368919081019061331c565b6113845760405162461bcd60e51b8152600401610582906140e1565b61055b82612591565b60008060015b6002811015611225576113b96113a882611eb3565b60030154839063ffffffff61207b16565b91506113d86113c782611eb3565b60040154839063ffffffff611edd16565b9150600101611393565b60606113ec611710565b905060005b815181101561110e57600082828151811061140857fe5b602002602001015190506000600560009054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200161144a9190613e19565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611476929190613f59565b60206040518083038186803b15801561148e57600080fd5b505afa1580156114a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114c69190810190613277565b6000838152600660205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906115229084908490613f3d565b60405180910390a150506001016113f1565b6001546001600160a01b0316331461155e5760405162461bcd60e51b815260040161058290614041565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c926115a1926001600160a01b0391821692911690613e4b565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006115da6121be565b6001600160a01b0316336001600160a01b031614905060006115fa612350565b6001600160a01b0316336001600160a01b031614905081806116195750805b6116355760405162461bcd60e51b815260040161058290614171565b61163d611f05565b6001600160a01b03166394e1a4488686866116586000611eb3565b5460405160e086901b7fffffffff000000000000000000000000000000000000000000000000000000001681526116ab9493929168010000000000000000900467ffffffffffffffff1690600401613ec4565b600060405180830381600087803b1580156116c557600080fd5b505af11580156116d9573d6000803e3d6000fd5b505050506117098585856116ed6000611eb3565b5468010000000000000000900467ffffffffffffffff16612686565b5050505050565b60608061171b612755565b60408051600d8082526101c0820190925291925060609190602082016101a0803883390190505090507f53797374656d53746174757300000000000000000000000000000000000000008160008151811061177257fe5b6020026020010181815250507f53796e7468657469780000000000000000000000000000000000000000000000816001815181106117ac57fe5b6020026020010181815250507f466565506f6f6c53746174650000000000000000000000000000000000000000816002815181106117e657fe5b6020026020010181815250507f466565506f6f6c457465726e616c53746f7261676500000000000000000000008160038151811061182057fe5b6020026020010181815250507f45786368616e67657200000000000000000000000000000000000000000000008160048151811061185a57fe5b6020026020010181815250506524b9b9bab2b960d11b8160058151811061187d57fe5b6020026020010181815250507f53796e7468657469785374617465000000000000000000000000000000000000816006815181106118b757fe5b6020026020010181815250507f526577617264457363726f775632000000000000000000000000000000000000816007815181106118f157fe5b6020026020010181815250507f44656c6567617465417070726f76616c730000000000000000000000000000008160088151811061192b57fe5b6020026020010181815250507f52657761726473446973747269627574696f6e000000000000000000000000008160098151811061196557fe5b6020026020010181815250507f436f6c6c61746572616c4d616e6167657200000000000000000000000000000081600a8151811061199f57fe5b6020026020010181815250507f57726170706572466163746f727900000000000000000000000000000000000081600b815181106119d957fe5b6020026020010181815250507f457468657257726170706572000000000000000000000000000000000000000081600c81518110611a1357fe5b602002602001018181525050611a2982826127b4565b9250505090565b6000546001600160a01b031681565b611a476120a0565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e90610784908390613e3d565b6000610799611b1e611aa2612869565b73__$f9217daff40bcb29719cec84f7ab900933$__63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611ae657600080fd5b505af4158015611afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ec4919081019061333a565b611b266128e0565b9063ffffffff61295716565b611b3a612981565b6004544210611b5b5760405162461bcd60e51b815260040161058290614141565b611b63612350565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b9b57600080fd5b505afa158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611bd3919081019061333a565b861115611bf25760405162461bcd60e51b815260040161058290614121565b6040518060e001604052808867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018667ffffffffffffffff168152602001858152602001848152602001838152602001828152506008611c62600260ff16610f3c8c60125461207b90919063ffffffff16565b60028110611c6c57fe5b82516005919091029190910180546020840151604085015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff000000000000000019166801000000000000000091851691909102177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b9390911692909202919091178155606082015160018201556080820151600282015560a0820151600382015560c0909101516004909101555050505050505050565b60006107996128e0565b611d3e6129ef565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600281565b6000611d6f6122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611da757600080fd5b505afa158015611dbb573d6000803e3d6000fd5b50505050611dc7612527565b600354610799906001600160a01b0316612591565b6003546001600160a01b031681565b6000610799612869565b73feefeefeefeefeefeefeefeefeefeefeefeefeef81565b6002546001600160a01b031681565b611e24612527565b611e2c612a19565b6003546001600160a01b03908116911614611e595760405162461bcd60e51b8152600401610582906140b1565b611e7781611e676000611eb3565b600301549063ffffffff61207b16565b611e816000611eb3565b6003015550565b60006107997f466565506f6f6c457465726e616c53746f726167650000000000000000000000612a40565b60006008600260ff16836012540181611ec857fe5b0660028110611ed357fe5b6005020192915050565b600082821115611eff5760405162461bcd60e51b815260040161058290614081565b50900390565b60006107997f466565506f6f6c53746174650000000000000000000000000000000000000000612a40565b600080611f3b612350565b9050600061206f85612063846001600160a01b03166308d95cd5886040518263ffffffff1660e01b8152600401611f729190613f2f565b60206040518083038186803b158015611f8a57600080fd5b505afa158015611f9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611fc2919081019061333a565b6040517f08d95cd50000000000000000000000000000000000000000000000000000000081526001600160a01b038716906308d95cd590612007908d90600401613f2f565b60206040518083038186803b15801561201f57600080fd5b505afa158015612033573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612057919081019061333a565b9063ffffffff612a9d16565b9063ffffffff612ab616565b925050505b9392505050565b6000828201838110156120745760405162461bcd60e51b815260040161058290614071565b6000546001600160a01b031633146120ca5760405162461bcd60e51b8152600401610582906140f1565b565b60006120d6612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f666565506572696f644475726174696f6e0000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b60206040518083038186803b15801561215b57600080fd5b505afa15801561216f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610799919081019061333a565b60006107997f45786368616e6765720000000000000000000000000000000000000000000000612a40565b60006107996524b9b9bab2b960d11b612a40565b60006107997f436f6c6c61746572616c4d616e61676572000000000000000000000000000000612a40565b60006107997f4574686572577261707065720000000000000000000000000000000000000000612a40565b60006107997f57726170706572466163746f7279000000000000000000000000000000000000612a40565b60008083612266575060009050806122ed565b83851561229157600061228060016105ed60018a03611eb3565b905061228d818787611f30565b9150505b60006122b0826122a089611eb3565b600101549063ffffffff61295716565b905060006122d1836122c18a611eb3565b600301549063ffffffff61295716565b90506122dc82612afa565b6122e582612afa565b945094505050505b935093915050565b60006107997f53797374656d5374617475730000000000000000000000000000000000000000612a40565b60008161233f5760405162461bcd60e51b8152600401610582906140d1565b81838161234857fe5b069392505050565b60006107997f53796e7468657469785374617465000000000000000000000000000000000000612a40565b6002546040516001600160a01b039091169063907dff97906123a1908490602001613f2f565b60405160208183030381529060405260016040516123be90613e24565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261240593929160009081908190600401613f79565b600060405180830381600087803b15801561241f57600080fd5b505af1158015611709573d6000803e3d6000fd5b6000806000806124416121be565b6001600160a01b031663ae3bbbbb866040518263ffffffff1660e01b815260040161246c9190613e2f565b604080518083038186803b15801561248357600080fd5b505afa158015612497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124bb9190810190613394565b9150915060006124c96128e0565b9050808310156124e1575060019350915061072c9050565b60006124fe6124f1611aa2612869565b839063ffffffff61295716565b90508084111561251857600083955095505050505061072c565b50600194509092505050915091565b6002546001600160a01b0316331480159061254d57506003546001600160a01b03163314155b156120ca57600380546001600160a01b03191633179055565b60006107997f44656c6567617465417070726f76616c73000000000000000000000000000000612a40565b60008080808080806125a288612433565b91509150816125c35760405162461bcd60e51b815260040161058290614101565b80156125e15760405162461bcd60e51b8152600401610582906140c1565b6125ea886106af565b9094509250831515806125fd5750600083115b6126195760405162461bcd60e51b8152600401610582906140a1565b612637886126276001611eb3565b5467ffffffffffffffff16612b1c565b83156126525761264684612bcf565b94506126528886612cab565b821561266d5761266183612e47565b955061266d8887612f21565b612678888688612f9b565b506001979650505050505050565b6002546040516001600160a01b039091169063907dff97906126b0908690869086906020016141a1565b60405160208183030381529060405260026040516126cd90613dee565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261271d9392916001600160a01b038b16906000908190600401613fd8565b600060405180830381600087803b15801561273757600080fd5b505af115801561274b573d6000803e3d6000fd5b5050505050505050565b604080516001808252818301909252606091602080830190803883390190505090507f466c657869626c6553746f726167650000000000000000000000000000000000816000815181106127a557fe5b60200260200101818152505090565b606081518351016040519080825280602002602001820160405280156127e4578160200160208202803883390190505b50905060005b8351811015612826578381815181106127ff57fe5b602002602001015182828151811061281357fe5b60209081029190910101526001016127ea565b5060005b82518110156112365782818151811061283f57fe5b602002602001015182828651018151811061285657fe5b602090810291909101015260010161282a565b6000612873612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f7461726765745468726573686f6c6400000000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b60006128ea612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f69737375616e6365526174696f000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b6000670de0b6b3a7640000612972848463ffffffff61306016565b8161297957fe5b049392505050565b6002546001600160a01b031633148015906129a757506003546001600160a01b03163314155b156129bf57600380546001600160a01b031916331790555b6000546003546001600160a01b039081169116146120ca5760405162461bcd60e51b815260040161058290614061565b6002546001600160a01b031633146120ca5760405162461bcd60e51b815260040161058290614161565b60006107997f52657761726473446973747269627574696f6e000000000000000000000000005b60008181526006602090815260408083205490516001600160a01b039091169182151591612a7091869101613df9565b604051602081830303815290604052906112365760405162461bcd60e51b81526004016105829190614020565b600061207483836b033b2e3c9fd0803ce800000061309a565b600061207483836b033b2e3c9fd0803ce80000006130de565b60006107997f466c657869626c6553746f726167650000000000000000000000000000000000612a40565b60006305f5e10082046005600a820610612b1257600a015b600a900492915050565b612b24611e88565b6001600160a01b0316633562fd207f6c6173745f6665655f7769746864726177616c0000000000000000000000000084604051602001612b65929190613dbd565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b8152600401612b99929190613f4b565b600060405180830381600087803b158015612bb357600080fd5b505af1158015612bc7573d6000803e3d6000fd5b505050505050565b6000818160015b6002811015612ca3576000612bea82611eb3565b6002015490506000612c0f82612bff85611eb3565b600101549063ffffffff611edd16565b90508015612c98576000858210612c265785612c28565b815b9050612c3a838263ffffffff61207b16565b612c4385611eb3565b60020155612c57868263ffffffff611edd16565b9550612c69858263ffffffff61207b16565b945085612c7e5784965050505050505061055e565b83158015612c8c5750600086115b15612c9657600095505b505b505060001901612bd6565b509392505050565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612ce95760405162461bcd60e51b815260040161058290614151565b6000612cf36121be565b6001600160a01b031663326080396007546040518263ffffffff1660e01b8152600401612d209190613f2f565b60206040518083038186803b158015612d3857600080fd5b505afa158015612d4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d709190810190613358565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081529091506001600160a01b03821690639dc29fac90612dce9073feefeefeefeefeefeefeefeefeefeefeefeefeef908790600401613e81565b600060405180830381600087803b158015612de857600080fd5b505af1158015612dfc573d6000803e3d6000fd5b50506040517f867904b40000000000000000000000000000000000000000000000000000000081526001600160a01b038416925063867904b4915061271d9087908790600401613e81565b6000818160015b6002811015612ca3576000612e82612e6583611eb3565b60040154612e7284611eb3565b600301549063ffffffff611edd16565b90508015612f17576000848210612e995784612e9b565b815b9050612eba81612eaa85611eb3565b600401549063ffffffff61207b16565b612ec384611eb3565b60040155612ed7858263ffffffff611edd16565b9450612ee9848263ffffffff61207b16565b935084612efd57839550505050505061055e565b82158015612f0b5750600085115b15612f1557600094505b505b5060001901612e4e565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612f5f5760405162461bcd60e51b815260040161058290614151565b6301dfe200612f6c613109565b6001600160a01b0316631bb47b448585846040518463ffffffff1660e01b815260040161271d93929190613e9c565b6002546040516001600160a01b039091169063907dff9790612fc590869086908690602001613e9c565b6040516020818303038152906040526001604051612fe290613de3565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261302993929160009081908190600401613f79565b600060405180830381600087803b15801561304357600080fd5b505af1158015613057573d6000803e3d6000fd5b50505050505050565b60008261306f575060006106a9565b8282028284828161307c57fe5b04146120745760405162461bcd60e51b815260040161058290614111565b6000806130c0846130b487600a870263ffffffff61306016565b9063ffffffff61313416565b90506005600a825b06106130d257600a015b600a9004949350505050565b600080600a83046130f5868663ffffffff61306016565b816130fc57fe5b0490506005600a826130c8565b60006107997f526577617264457363726f775632000000000000000000000000000000000000612a40565b60008082116131555760405162461bcd60e51b815260040161058290614091565b600082848161316057fe5b04949350505050565b60405180604001604052806002905b6131806131f1565b8152602001906001900390816131785790505090565b6040518060e00160405280600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b80356106a9816142f8565b80516106a9816142f8565b80516106a98161430f565b80516106a981614318565b80516106a981614321565b80356106a981614318565b60006020828403121561326357600080fd5b600061326f848461320f565b949350505050565b60006020828403121561328957600080fd5b600061326f848461321a565b600080604083850312156132a857600080fd5b60006132b4858561320f565b92505060206132c585828601613246565b9150509250929050565b6000806000606084860312156132e457600080fd5b60006132f0868661320f565b935050602061330186828701613246565b925050604061331286828701613246565b9150509250925092565b60006020828403121561332e57600080fd5b600061326f8484613225565b60006020828403121561334c57600080fd5b600061326f8484613230565b60006020828403121561336a57600080fd5b600061326f848461323b565b60006020828403121561338857600080fd5b600061326f8484613246565b600080604083850312156133a757600080fd5b60006133b38585613230565b92505060206132c585828601613225565b600080604083850312156133d757600080fd5b60006133e38585613230565b92505060206132c585828601613230565b600080600080600080600080610100898b03121561341157600080fd5b600061341d8b8b613246565b985050602061342e8b828c01613246565b975050604061343f8b828c01613246565b96505060606134508b828c01613246565b95505060806134618b828c01613246565b94505060a06134728b828c01613246565b93505060c06134838b828c01613246565b92505060e06134948b828c01613246565b9150509295985092959890939650565b60006134b0838361359a565b505060400190565b60006134c483836135ef565b505060200190565b6134d581614278565b82525050565b6134d58161423e565b6134d56134f08261423e565b6142d7565b6134fe8161422b565b613508818461055e565b92506135138261079c565b8060005b83811015612bc757815161352b87826134a4565b965061353683614225565b925050600101613517565b600061354c82614231565b6135568185614235565b935061356183614225565b8060005b8381101561358f57815161357988826134b8565b975061358483614225565b925050600101613565565b509495945050505050565b6135a38161422b565b6135ad818461055e565b92506135b88261079c565b8060005b83811015612bc75781516135d087826134b8565b96506135db83614225565b9250506001016135bc565b6134d581614249565b6134d58161079c565b6134d56136048261079c565b61079c565b600061361482614231565b61361e8185614235565b935061362e8185602086016142a7565b613637816142e8565b9093019392505050565b6134d58161424e565b6134d581614283565b6134d581614291565b6000613669601783614235565b7f4f6e6c7920496e7465726e616c20436f6e747261637473000000000000000000815260200192915050565b60006136a2603583614235565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015260400192915050565b6000613701601d83614235565b7f546f6f206561726c7920746f20636c6f73652066656520706572696f64000000815260200192915050565b600061373a601383614235565b7f4f776e6572206f6e6c792066756e6374696f6e00000000000000000000000000815260200192915050565b600061377360248361055e565b7f46656573436c61696d656428616464726573732c75696e743235362c75696e7481527f3235362900000000000000000000000000000000000000000000000000000000602082015260240192915050565b60006137d260378361055e565b7f49737375616e636544656274526174696f456e74727928616464726573732c7581527f696e743235362c75696e743235362c75696e7432353629000000000000000000602082015260370192915050565b6000613831601b83614235565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061386a601e83614235565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b60006138a3601a83614235565b7f536166654d6174683a206469766973696f6e206279207a65726f000000000000815260200192915050565b60006138dc604083614235565b7f4e6f2066656573206f72207265776172647320617661696c61626c6520666f7281527f20706572696f642c206f72206665657320616c726561647920636c61696d6564602082015260400192915050565b600061393b60118361055e565b7f4d697373696e6720616464726573733a20000000000000000000000000000000815260110192915050565b6000613974601883614235565b7f52657761726473446973747269627574696f6e206f6e6c790000000000000000815260200192915050565b60006139ad601e83614235565b7f412073796e7468206f7220534e58207261746520697320696e76616c69640000815260200192915050565b60006139e6601883614235565b7f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815260200192915050565b6000613a1f601f83614235565b7f4e6f7420617070726f76656420746f20636c61696d206f6e20626568616c6600815260200192915050565b6000613a58602f83614235565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015260400192915050565b6000613ab7601f83614235565b7f432d526174696f2062656c6f772070656e616c7479207468726573686f6c6400815260200192915050565b6000613af0602183614235565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613b4f601683614235565b7f43616e6e6f7420696d706f727420626164206461746100000000000000000000815260200192915050565b6000613b88601d83614235565b7f4578636565647320746865204645455f504552494f445f4c454e475448000000815260200192915050565b6000613bc1602983614235565b7f43616e206f6e6c7920706572666f726d207468697320616374696f6e2064757281527f696e672073657475700000000000000000000000000000000000000000000000602082015260400192915050565b6000613c2060198361055e565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000613c59601783614235565b7f4665652061646472657373206e6f7420616c6c6f776564000000000000000000815260200192915050565b6000613c9260188361055e565b7f466565506572696f64436c6f7365642875696e74323536290000000000000000815260180192915050565b6000613ccb601783614235565b7f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000815260200192915050565b6000613d04601e83614235565b7f49737375657220616e642053796e7468657469785374617465206f6e6c790000815260200192915050565b6000613d3d602083614235565b7f43757272656e7420706572696f64206973206e6f7420636c6f73656420796574815260200192915050565b6000613d76601b83614235565b7f46656520506572696f64204475726174696f6e206e6f74207365740000000000815260200192915050565b6134d58161429c565b6134d581614265565b6134d581614272565b6000613dc982856135f8565b602082019150613dd982846134e4565b5060140192915050565b60006106a982613766565b60006106a9826137c5565b6000613e048261392e565b9150613e1082846135f8565b50602001919050565b6000613e0482613c13565b60006106a982613c85565b602081016106a982846134db565b602081016106a982846134cc565b60408101613e5982856134db565b61207460208301846134db565b60408101613e7482856134db565b6120746020830184613653565b60408101613e8f82856134db565b61207460208301846135ef565b60608101613eaa82866134db565b613eb760208301856135ef565b61326f60408301846135ef565b60808101613ed282876134db565b613edf60208301866135ef565b613eec60408301856135ef565b613ef96060830184613da2565b95945050505050565b608081016106a982846134f5565b602080825281016120748184613541565b602081016106a982846135e6565b602081016106a982846135ef565b60408101613e5982856135ef565b60408101613e8f82856135ef565b60408101613f6782856135ef565b818103602083015261326f8184613609565b60c08082528101613f8a8189613609565b9050613f996020830188613653565b613fa660408301876135ef565b613fb3606083018661364a565b613fc0608083018561364a565b613fcd60a083018461364a565b979650505050505050565b60c08082528101613fe98189613609565b9050613ff86020830188613653565b61400560408301876135ef565b613fb360608301866135ef565b602081016106a98284613641565b602080825281016120748184613609565b6020808252810161055b8161365c565b6020808252810161055b81613695565b6020808252810161055b816136f4565b6020808252810161055b8161372d565b6020808252810161055b81613824565b6020808252810161055b8161385d565b6020808252810161055b81613896565b6020808252810161055b816138cf565b6020808252810161055b81613967565b6020808252810161055b816139a0565b6020808252810161055b816139d9565b6020808252810161055b81613a12565b6020808252810161055b81613a4b565b6020808252810161055b81613aaa565b6020808252810161055b81613ae3565b6020808252810161055b81613b42565b6020808252810161055b81613b7b565b6020808252810161055b81613bb4565b6020808252810161055b81613c4c565b6020808252810161055b81613cbe565b6020808252810161055b81613cf7565b6020808252810161055b81613d30565b6020808252810161055b81613d69565b60608101613eaa82866135ef565b60e081016141bd828a613dab565b6141ca6020830189613dab565b6141d76040830188613dab565b6141e460608301876135ef565b6141f160808301866135ef565b6141fe60a08301856135ef565b61420b60c08301846135ef565b98975050505050505050565b602081016106a98284613db4565b60200190565b50600290565b5190565b90815260200190565b600061055b82614259565b151590565b600061055b8261423e565b6001600160a01b031690565b67ffffffffffffffff1690565b60ff1690565b600061055b8261424e565b600061055b6136048361079c565b600061055b8261079c565b600061055b82614265565b60005b838110156142c25781810151838201526020016142aa565b838111156142d1576000848401525b50505050565b600061055b82600061055b826142f2565b601f01601f191690565b60601b90565b6143018161423e565b811461430c57600080fd5b50565b61430181614249565b6143018161079c565b6143018161424e56fea365627a7a72315820311ca67b066d8aa30c5fc3e5d4e569051e36efc62ebf3c8ccc4f5172288bdb2b6c6578706572696d656e74616cf564736f6c63430005100040", "abi": [ { "inputs": [ @@ -3281,10 +3281,10 @@ } ], "source": { - "keccak256": "0x9e381069cb34a10eb54ca9fb651d514a2cbcdcb328adfe943956b9d759c5ebac", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914", "urls": [ - "bzz-raw://c8d6ae1feaa83b97ed46b18a34b336e2014ebbe064b07276bd35c33f8000aa71", - "dweb:/ipfs/QmUECjHzMVyjue53V4xAvbmXThvvxChgJg5FkVSZfs8Zam" + "bzz-raw://d45068f4b97b8568117b6c095694b7270cad2b0337ea0c2b8b24550dfa93fdbc", + "dweb:/ipfs/QmWYtWcqTszbsZ6tJTg6GcDWdWdGcnNkALBgzRpYPL3EH7" ] }, "metadata": { @@ -3306,10 +3306,10 @@ }, "sources": { "FeePool.sol": { - "keccak256": "0x9e381069cb34a10eb54ca9fb651d514a2cbcdcb328adfe943956b9d759c5ebac", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914", "urls": [ - "bzz-raw://c8d6ae1feaa83b97ed46b18a34b336e2014ebbe064b07276bd35c33f8000aa71", - "dweb:/ipfs/QmUECjHzMVyjue53V4xAvbmXThvvxChgJg5FkVSZfs8Zam" + "bzz-raw://d45068f4b97b8568117b6c095694b7270cad2b0337ea0c2b8b24550dfa93fdbc", + "dweb:/ipfs/QmWYtWcqTszbsZ6tJTg6GcDWdWdGcnNkALBgzRpYPL3EH7" ] } }, diff --git a/publish/deployed/kovan/versions.json b/publish/deployed/kovan/versions.json index 397289fcd5..593da42dd5 100644 --- a/publish/deployed/kovan/versions.json +++ b/publish/deployed/kovan/versions.json @@ -6728,8 +6728,9 @@ }, "FeePool": { "address": "0xE532C9336934DA37aacc0143D07314d7F9D2a8c0", - "status": "current", - "keccak256": "0x9e381069cb34a10eb54ca9fb651d514a2cbcdcb328adfe943956b9d759c5ebac" + "status": "replaced", + "keccak256": "0x9e381069cb34a10eb54ca9fb651d514a2cbcdcb328adfe943956b9d759c5ebac", + "replaced_in": "v2.57.0-alpha" }, "Synthetix": { "address": "0x2346860A4B189161187303B24442389C4363b4D1", @@ -6854,5 +6855,20 @@ "keccak256": "0x582cac91f50cfefc154d67097081d0dd0d4877333df51c3cfe19485f80ef7e74" } } + }, + "v2.57.0-alpha": { + "tag": "v2.57.0-alpha", + "fulltag": "v2.57.0-alpha", + "release": "Peacock", + "network": "kovan", + "date": "2022-01-14T20:06:28-05:00", + "commit": "9d1655f6992b32e16a3a8c898a82a9552de886e5", + "contracts": { + "FeePool": { + "address": "0x288cA161F9382d54dD27803AbF45C78Da95D19b0", + "status": "current", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914" + } + } } } diff --git a/publish/deployed/mainnet-ovm/config.json b/publish/deployed/mainnet-ovm/config.json index 913ffbe2d9..c6e32d05fa 100644 --- a/publish/deployed/mainnet-ovm/config.json +++ b/publish/deployed/mainnet-ovm/config.json @@ -163,5 +163,11 @@ }, "CollateralEth": { "deploy": false + }, + "StakingRewardssUSDDAIUniswapV3": { + "deploy": true + }, + "StakingRewardsSNXWETHUniswapV3": { + "deploy": true } } diff --git a/publish/deployed/mainnet-ovm/deployment.json b/publish/deployed/mainnet-ovm/deployment.json index 38be0e7262..8c7bd29399 100644 --- a/publish/deployed/mainnet-ovm/deployment.json +++ b/publish/deployed/mainnet-ovm/deployment.json @@ -72,15 +72,6 @@ "txn": "", "network": "mainnet" }, - "RewardEscrow": { - "name": "RewardEscrow", - "address": "0xd32138018210edA0028240638f35b70ECC0D8C22", - "source": "RewardEscrow", - "link": "https://etherscan.io/address/0xd32138018210edA0028240638f35b70ECC0D8C22", - "timestamp": "2021-01-15T05:40:59.117Z", - "txn": "", - "network": "mainnet" - }, "RewardEscrowV2": { "name": "RewardEscrowV2", "address": "0x47eE58801C1AC44e54FF2651aE50525c5cfc66d0", @@ -164,11 +155,11 @@ }, "FeePool": { "name": "FeePool", - "address": "0xbc12131c93Da011B2844FA76c373A8cf5b0db4B5", + "address": "0xFDf3Be612c65464AEB4859047350a6220F304F52", "source": "FeePool", - "link": "https://explorer.optimism.io/address/0xbc12131c93Da011B2844FA76c373A8cf5b0db4B5", - "timestamp": "2021-12-03T04:42:18.000Z", - "txn": "https://explorer.optimism.io/tx/0xaa715a8c484dd3257e5d310e61c7334e7517b45bab79867f52a497cb03d3496f", + "link": "https://explorer.optimism.io/address/0xFDf3Be612c65464AEB4859047350a6220F304F52", + "timestamp": "2022-01-18T21:45:29.000Z", + "txn": "https://explorer.optimism.io/tx/0x831793bbc57f77306c250bc67f4f7aa931cf372e6fcda530d08a457f8d287e84", "network": "mainnet" }, "FeePoolState": { @@ -521,6 +512,24 @@ "timestamp": "2021-12-15T21:06:22.000Z", "txn": "https://explorer.optimism.io/tx/0x7849ba45a602863e4d20a0abd2d0e7d7d9ca6b5b369da56356b91f382a7e034a", "network": "mainnet" + }, + "StakingRewardssUSDDAIUniswapV3": { + "name": "StakingRewardssUSDDAIUniswapV3", + "address": "0x7E11c004d20b502729918687E6E6777b28499085", + "source": "StakingRewards", + "link": "https://explorer.optimism.io/address/0x7E11c004d20b502729918687E6E6777b28499085", + "timestamp": "2022-01-15T21:10:49.985Z", + "txn": "", + "network": "mainnet" + }, + "StakingRewardsSNXWETHUniswapV3": { + "name": "StakingRewardsSNXWETHUniswapV3", + "address": "0xfD49C7EE330fE060ca66feE33d49206eB96F146D", + "source": "StakingRewards", + "link": "https://explorer.optimism.io/address/0xfD49C7EE330fE060ca66feE33d49206eB96F146D", + "timestamp": "2022-01-15T21:11:04.782Z", + "txn": "", + "network": "mainnet" } }, "sources": { @@ -11897,7 +11906,7 @@ } }, "FeePool": { - "bytecode": "6080604052631cd554d160e21b6007553480156200001c57600080fd5b506040516200472c3803806200472c8339810160408190526200003f9162000221565b8080621baf8085856001600160a01b038116620000795760405162461bcd60e51b8152600401620000709062000343565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620000c69184906200030b565b60405180910390a1506000546001600160a01b0316620000fa5760405162461bcd60e51b8152600401620000709062000331565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9062000147908390620002fb565b60405180910390a1504201600455600580546001600160a01b0319166001600160a01b0392909216919091179055506001620001846000620001e2565b80546001600160401b0319166001600160401b039290921691909117905542620001af6000620001e2565b80546001600160401b0392909216600160801b02600160801b600160c01b0319909216919091179055506200039e915050565b60006008600260ff16836012540181620001f857fe5b06600281106200020457fe5b6005020192915050565b80516200021b8162000384565b92915050565b6000806000606084860312156200023757600080fd5b60006200024586866200020e565b935050602062000258868287016200020e565b92505060406200026b868287016200020e565b9150509250925092565b620002808162000370565b82525050565b62000280816200035e565b6000620002a060118362000355565b7013dddb995c881b5d5cdd081899481cd95d607a1b815260200192915050565b6000620002cf60198362000355565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b602081016200021b828462000275565b604081016200031b828562000275565b6200032a602083018462000286565b9392505050565b602080825281016200021b8162000291565b602080825281016200021b81620002c0565b90815260200190565b60006001600160a01b0382166200021b565b60006200021b8260006200021b826200035e565b6200038f816200035e565b81146200039b57600080fd5b50565b61437e80620003ae6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80636de813f111610145578063b410a034116100bd578063d67bdd251161008c578063eb1edd6111610071578063eb1edd611461045c578063ec55688914610464578063fd1f498d1461046c57610241565b8063d67bdd251461044c578063e0e6393d1461045457610241565b8063b410a03414610414578063bc67f8321461041c578063cff2ddad1461042f578063d294f0931461044457610241565b8063899ffef41161011457806397107d6d116100f957806397107d6d146103e6578063ac834193146103f9578063b10090b81461040157610241565b8063899ffef4146103c95780638da5cb5b146103de57610241565b80636de813f11461039e57806374185360146103a657806379ba5097146103ae57806386645274146103b657610241565b806333140016116101d857806353a47bb7116101a757806359a2f19f1161018c57806359a2f19f14610370578063614d08f8146103835780636466f45e1461038b57610241565b806353a47bb714610353578063569249d01461036857610241565b806333140016146102fd5780633ebc457a1461031d5780633fcd22401461032557806346ba2d901461034b57610241565b80631627540c116102145780631627540c146102b857806322425fa4146102cd57806322bf55ef146102d55780632af64bd3146102e857610241565b806304f3bcec1461024657806307ea50cd146102645780630813071c146102845780630de5861514610297575b600080fd5b61024e61047f565b60405161025b9190614023565b60405180910390f35b610277610272366004613262565b61048e565b60405161025b9190613f40565b6102776102923660046132a6565b610563565b6102aa6102a5366004613262565b6106af565b60405161025b929190613f5c565b6102cb6102c6366004613262565b610731565b005b61027761078f565b6102cb6102e3366004613387565b61079f565b6102f0610978565b60405161025b9190613f32565b61031061030b366004613262565b610aa8565b60405161025b9190613f13565b6102cb610d0c565b610338610333366004613387565b611112565b60405161025b97969594939291906141c0565b6102776111bb565b61035b6111c1565b60405161025b9190613e40565b6102776111d0565b6102f061037e366004613262565b61122b565b61027761123d565b6102f0610399366004613262565b611261565b61027761138d565b6102cb6113e2565b6102cb611534565b6102cb6103c43660046132e0565b6115d0565b6103d1611710565b60405161025b9190613f21565b61035b611a30565b6102cb6103f4366004613262565b611a3f565b610277611a92565b6102cb61040f366004613405565b611b32565b610277611d2c565b6102cb61042a366004613262565b611d36565b610437611d60565b60405161025b9190614228565b6102f0611d65565b61035b611ddc565b610277611deb565b61035b611df5565b61024e611e0d565b6102cb61047a366004613387565b611e1c565b6005546001600160a01b031681565b6000610498611e99565b6001600160a01b031663bdc963d87f6c6173745f6665655f7769746864726177616c00000000000000000000000000846040516020016104d9929190613dce565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161050b9190613f40565b60206040518083038186803b15801561052357600080fd5b505afa158015610537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061055b919081019061334b565b90505b919050565b60008161058b5760405162461bcd60e51b815260040161058290614192565b60405180910390fd5b600282106105ab5760405162461bcd60e51b815260040161058290614142565b6105b760018303611ec4565b5468010000000000000000900467ffffffffffffffff166105da575060006106a9565b600061060a60016105ed60018603611ec4565b5468010000000000000000900467ffffffffffffffff1690611eee565b9050600080610617611f16565b6001600160a01b031663d29c000a87856040518363ffffffff1660e01b8152600401610644929190613e92565b604080518083038186803b15801561065b57600080fd5b505afa15801561066f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061069391908101906133d5565b90925090506106a3838383611f41565b93505050505b92915050565b6000806106ba61317a565b6106c384610aa8565b905060008060015b6002811015610724576106f08482600281106106e357fe5b602002015151849061208c565b925061071a84826002811061070157fe5b602002015160016020020151839063ffffffff61208c16565b91506001016106cb565b509093509150505b915091565b6107396120b1565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610784908390613e40565b60405180910390a150565b60006107996120dd565b90505b90565b60006107a96121a4565b6001600160a01b0316331490506000806107c16121cf565b6001600160a01b03166316b2213f336040518263ffffffff1660e01b81526004016107ec9190613e4e565b60206040518083038186803b15801561080457600080fd5b505afa158015610818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061083c919081019061334b565b14159050600061084a6121e3565b6001600160a01b031663b38988f7336040518263ffffffff1660e01b81526004016108759190613e4e565b60206040518083038186803b15801561088d57600080fd5b505afa1580156108a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108c5919081019061332d565b905060006108d161220e565b6001600160a01b0316336001600160a01b031614905060006108f1612239565b6001600160a01b0316336001600160a01b031614905084806109105750835b806109185750825b806109205750815b806109285750805b6109445760405162461bcd60e51b815260040161058290614042565b610962866109526000611ec4565b600101549063ffffffff61208c16565b61096c6000611ec4565b60010155505050505050565b60006060610984611710565b905060005b8151811015610a9f5760008282815181106109a057fe5b602090810291909101810151600081815260069092526040918290205460055492517f21f8a7210000000000000000000000000000000000000000000000000000000081529193506001600160a01b039081169216906321f8a72190610a0a908590600401613f40565b60206040518083038186803b158015610a2257600080fd5b505afa158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a5a9190810190613288565b6001600160a01b0316141580610a8557506000818152600660205260409020546001600160a01b0316155b15610a96576000935050505061079c565b50600101610989565b50600191505090565b610ab061317a565b6000806000610abd611f16565b6040517fb326f84e0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0382169063b326f84e90610b08908890600090600401613e77565b604080518083038186803b158015610b1f57600080fd5b505afa158015610b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b5791908101906133d5565b909350915081158015610b68575082155b15610b8057610b7561317a565b935061055e92505050565b600080610b8f60008686612264565b8751829052875160200181905290925090506000610bac8861048e565b905060015b8015610d005760001981016000610bc782611ec4565b5468010000000000000000900467ffffffffffffffff1690508015801590610c015750610bf383611ec4565b5467ffffffffffffffff1684105b15610cf5576000610c1982600163ffffffff611eee16565b6040517fd29c000a0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0389169063d29c000a90610c63908f908590600401613e92565b604080518083038186803b158015610c7a57600080fd5b505afa158015610c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610cb291908101906133d5565b909a509850610cc2848b8b612264565b9097509550868b8560028110610cd457fe5b602002015152858b8560028110610ce757fe5b602002015160016020020152505b505060001901610bb1565b50505050505050919050565b610d14612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015610d4c57600080fd5b505afa158015610d60573d6000803e3d6000fd5b505050506000610d6e6120dd565b11610d8b5760405162461bcd60e51b8152600401610582906141a2565b610d936120dd565b4203610d9f6000611ec4565b54600160801b900467ffffffffffffffff161115610dcf5760405162461bcd60e51b815260040161058290614062565b610dd761220e565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e1157600080fd5b505af1158015610e25573d6000803e3d6000fd5b50505050610e31612239565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e6b57600080fd5b505af1158015610e7f573d6000803e3d6000fd5b5060009250610e919150829050611ec4565b90506000610e9f6001611ec4565b9050610ed08260010154610ec483600201548460010154611eee90919063ffffffff16565b9063ffffffff61208c16565b610eda6000611ec4565b60010155600380830154600483015491830154610f0192610ec4919063ffffffff611eee16565b610f0b6000611ec4565b60030155601254610f4890600290610f3c90600190610f30908463ffffffff61208c16565b9063ffffffff611eee16565b9063ffffffff61233116565b601281905560089060028110610f5a57fe5b6005020180547fffffffffffffffff000000000000000000000000000000000000000000000000168155600060018083018290556002830182905560038301829055600490920155610fc690610faf81611ec4565b5467ffffffffffffffff169063ffffffff61208c16565b610fd06000611ec4565b805467ffffffffffffffff191667ffffffffffffffff92909216919091179055610ff8612361565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561103057600080fd5b505afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611068919081019061334b565b6110726000611ec4565b805467ffffffffffffffff9290921668010000000000000000026fffffffffffffffff000000000000000019909216919091179055426110b26000611ec4565b805467ffffffffffffffff92909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905561110e6110fe6001611ec4565b5467ffffffffffffffff1661238c565b5050565b60008060008060008060006111256131a7565b61112e89611ec4565b6040805160e081018252825467ffffffffffffffff808216808452680100000000000000008304821660208501819052600160801b909304909116938301849052600185015460608401819052600286015460808501819052600387015460a0860181905260049097015460c0909501859052919f929e50939c50929a5091985091965090945092505050565b60045481565b6001546001600160a01b031681565b60008060015b6002811015611225576111fc6111eb82611ec4565b60010154839063ffffffff61208c16565b915061121b61120a82611ec4565b60020154839063ffffffff611eee16565b91506001016111d6565b50905090565b600061123682612444565b5092915050565b7f466565506f6f6c0000000000000000000000000000000000000000000000000081565b600061126b612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156112a357600080fd5b505afa1580156112b7573d6000803e3d6000fd5b505050506112c3612538565b6112cb612577565b6003546040517f21f4ae570000000000000000000000000000000000000000000000000000000081526001600160a01b03928316926321f4ae579261131892879290911690600401613e5c565b60206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611368919081019061332d565b6113845760405162461bcd60e51b8152600401610582906140e2565b61055b826125a2565b60008060015b6002811015611225576113b96113a882611ec4565b60030154839063ffffffff61208c16565b91506113d86113c782611ec4565b60040154839063ffffffff611eee16565b9150600101611393565b60606113ec611710565b905060005b815181101561110e57600082828151811061140857fe5b602002602001015190506000600560009054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200161144a9190613e2a565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611476929190613f6a565b60206040518083038186803b15801561148e57600080fd5b505afa1580156114a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114c69190810190613288565b6000838152600660205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906115229084908490613f4e565b60405180910390a150506001016113f1565b6001546001600160a01b0316331461155e5760405162461bcd60e51b815260040161058290614052565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c926115a1926001600160a01b0391821692911690613e5c565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006115da6121cf565b6001600160a01b0316336001600160a01b031614905060006115fa612361565b6001600160a01b0316336001600160a01b031614905081806116195750805b6116355760405162461bcd60e51b815260040161058290614182565b61163d611f16565b6001600160a01b03166394e1a4488686866116586000611ec4565b5460405160e086901b7fffffffff000000000000000000000000000000000000000000000000000000001681526116ab9493929168010000000000000000900467ffffffffffffffff1690600401613ed5565b600060405180830381600087803b1580156116c557600080fd5b505af11580156116d9573d6000803e3d6000fd5b505050506117098585856116ed6000611ec4565b5468010000000000000000900467ffffffffffffffff16612697565b5050505050565b60608061171b612766565b60408051600d8082526101c0820190925291925060609190602082016101a0803883390190505090507f53797374656d53746174757300000000000000000000000000000000000000008160008151811061177257fe5b6020026020010181815250507f53796e7468657469780000000000000000000000000000000000000000000000816001815181106117ac57fe5b6020026020010181815250507f466565506f6f6c53746174650000000000000000000000000000000000000000816002815181106117e657fe5b6020026020010181815250507f466565506f6f6c457465726e616c53746f7261676500000000000000000000008160038151811061182057fe5b6020026020010181815250507f45786368616e67657200000000000000000000000000000000000000000000008160048151811061185a57fe5b6020026020010181815250506524b9b9bab2b960d11b8160058151811061187d57fe5b6020026020010181815250507f53796e7468657469785374617465000000000000000000000000000000000000816006815181106118b757fe5b6020026020010181815250507f526577617264457363726f775632000000000000000000000000000000000000816007815181106118f157fe5b6020026020010181815250507f44656c6567617465417070726f76616c730000000000000000000000000000008160088151811061192b57fe5b6020026020010181815250507f52657761726473446973747269627574696f6e000000000000000000000000008160098151811061196557fe5b6020026020010181815250507f436f6c6c61746572616c4d616e6167657200000000000000000000000000000081600a8151811061199f57fe5b6020026020010181815250507f57726170706572466163746f727900000000000000000000000000000000000081600b815181106119d957fe5b6020026020010181815250507f457468657257726170706572000000000000000000000000000000000000000081600c81518110611a1357fe5b602002602001018181525050611a2982826127c5565b9250505090565b6000546001600160a01b031681565b611a476120b1565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e90610784908390613e4e565b6000610799611b1e611aa261287a565b73__$f9217daff40bcb29719cec84f7ab900933$__63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611ae657600080fd5b505af4158015611afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ec4919081019061334b565b611b266128f1565b9063ffffffff61296816565b611b3a612992565b6004544210611b5b5760405162461bcd60e51b815260040161058290614152565b611b63612361565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b9b57600080fd5b505afa158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611bd3919081019061334b565b861115611bf25760405162461bcd60e51b815260040161058290614132565b6040518060e001604052808867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018667ffffffffffffffff168152602001858152602001848152602001838152602001828152506008611c62600260ff16610f3c8c60125461208c90919063ffffffff16565b60028110611c6c57fe5b82516005919091029190910180546020840151604085015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff000000000000000019166801000000000000000091851691909102177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b9390911692909202919091178155606082015160018201556080820151600282015560a0820151600382015560c0909101516004909101555050505050505050565b60006107996128f1565b611d3e612a00565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600281565b6000611d6f612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611da757600080fd5b505afa158015611dbb573d6000803e3d6000fd5b50505050611dc7612538565b600354610799906001600160a01b03166125a2565b6003546001600160a01b031681565b600061079961287a565b73feefeefeefeefeefeefeefeefeefeefeefeefeef81565b6002546001600160a01b031681565b6000611e26612a2a565b6003549091506001600160a01b0380831691161480611e4d5750336001600160a01b038216145b611e695760405162461bcd60e51b8152600401610582906140f2565b611e8782611e776000611ec4565b600301549063ffffffff61208c16565b611e916000611ec4565b600301555050565b60006107997f466565506f6f6c457465726e616c53746f726167650000000000000000000000612a51565b60006008600260ff16836012540181611ed957fe5b0660028110611ee457fe5b6005020192915050565b600082821115611f105760405162461bcd60e51b815260040161058290614092565b50900390565b60006107997f466565506f6f6c53746174650000000000000000000000000000000000000000612a51565b600080611f4c612361565b9050600061208085612074846001600160a01b03166308d95cd5886040518263ffffffff1660e01b8152600401611f839190613f40565b60206040518083038186803b158015611f9b57600080fd5b505afa158015611faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611fd3919081019061334b565b6040517f08d95cd50000000000000000000000000000000000000000000000000000000081526001600160a01b038716906308d95cd590612018908d90600401613f40565b60206040518083038186803b15801561203057600080fd5b505afa158015612044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612068919081019061334b565b9063ffffffff612aae16565b9063ffffffff612ac716565b925050505b9392505050565b6000828201838110156120855760405162461bcd60e51b815260040161058290614082565b6000546001600160a01b031633146120db5760405162461bcd60e51b815260040161058290614102565b565b60006120e7612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f666565506572696f644475726174696f6e0000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b60206040518083038186803b15801561216c57600080fd5b505afa158015612180573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610799919081019061334b565b60006107997f45786368616e6765720000000000000000000000000000000000000000000000612a51565b60006107996524b9b9bab2b960d11b612a51565b60006107997f436f6c6c61746572616c4d616e61676572000000000000000000000000000000612a51565b60006107997f4574686572577261707065720000000000000000000000000000000000000000612a51565b60006107997f57726170706572466163746f7279000000000000000000000000000000000000612a51565b60008083612277575060009050806122fe565b8385156122a257600061229160016105ed60018a03611ec4565b905061229e818787611f41565b9150505b60006122c1826122b189611ec4565b600101549063ffffffff61296816565b905060006122e2836122d28a611ec4565b600301549063ffffffff61296816565b90506122ed82612b0b565b6122f682612b0b565b945094505050505b935093915050565b60006107997f53797374656d5374617475730000000000000000000000000000000000000000612a51565b6000816123505760405162461bcd60e51b8152600401610582906140d2565b81838161235957fe5b069392505050565b60006107997f53796e7468657469785374617465000000000000000000000000000000000000612a51565b6002546040516001600160a01b039091169063907dff97906123b2908490602001613f40565b60405160208183030381529060405260016040516123cf90613e35565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261241693929160009081908190600401613f8a565b600060405180830381600087803b15801561243057600080fd5b505af1158015611709573d6000803e3d6000fd5b6000806000806124526121cf565b6001600160a01b031663ae3bbbbb866040518263ffffffff1660e01b815260040161247d9190613e40565b604080518083038186803b15801561249457600080fd5b505afa1580156124a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124cc91908101906133a5565b9150915060006124da6128f1565b9050808310156124f2575060019350915061072c9050565b600061250f612502611aa261287a565b839063ffffffff61296816565b90508084111561252957600083955095505050505061072c565b50600194509092505050915091565b6002546001600160a01b0316331480159061255e57506003546001600160a01b03163314155b156120db57600380546001600160a01b03191633179055565b60006107997f44656c6567617465417070726f76616c73000000000000000000000000000000612a51565b60008080808080806125b388612444565b91509150816125d45760405162461bcd60e51b815260040161058290614112565b80156125f25760405162461bcd60e51b8152600401610582906140c2565b6125fb886106af565b90945092508315158061260e5750600083115b61262a5760405162461bcd60e51b8152600401610582906140b2565b612648886126386001611ec4565b5467ffffffffffffffff16612b2d565b83156126635761265784612be0565b94506126638886612cbc565b821561267e5761267283612e58565b955061267e8887612f32565b612689888688612fac565b506001979650505050505050565b6002546040516001600160a01b039091169063907dff97906126c1908690869086906020016141b2565b60405160208183030381529060405260026040516126de90613dff565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261272e9392916001600160a01b038b16906000908190600401613fe9565b600060405180830381600087803b15801561274857600080fd5b505af115801561275c573d6000803e3d6000fd5b5050505050505050565b604080516001808252818301909252606091602080830190803883390190505090507f466c657869626c6553746f726167650000000000000000000000000000000000816000815181106127b657fe5b60200260200101818152505090565b606081518351016040519080825280602002602001820160405280156127f5578160200160208202803883390190505b50905060005b83518110156128375783818151811061281057fe5b602002602001015182828151811061282457fe5b60209081029190910101526001016127fb565b5060005b82518110156112365782818151811061285057fe5b602002602001015182828651018151811061286757fe5b602090810291909101015260010161283b565b6000612884612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f7461726765745468726573686f6c6400000000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b60006128fb612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f69737375616e6365526174696f000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b6000670de0b6b3a7640000612983848463ffffffff61307116565b8161298a57fe5b049392505050565b6002546001600160a01b031633148015906129b857506003546001600160a01b03163314155b156129d057600380546001600160a01b031916331790555b6000546003546001600160a01b039081169116146120db5760405162461bcd60e51b815260040161058290614072565b6002546001600160a01b031633146120db5760405162461bcd60e51b815260040161058290614172565b60006107997f52657761726473446973747269627574696f6e000000000000000000000000005b60008181526006602090815260408083205490516001600160a01b039091169182151591612a8191869101613e0a565b604051602081830303815290604052906112365760405162461bcd60e51b81526004016105829190614031565b600061208583836b033b2e3c9fd0803ce80000006130ab565b600061208583836b033b2e3c9fd0803ce80000006130ef565b60006107997f466c657869626c6553746f726167650000000000000000000000000000000000612a51565b60006305f5e10082046005600a820610612b2357600a015b600a900492915050565b612b35611e99565b6001600160a01b0316633562fd207f6c6173745f6665655f7769746864726177616c0000000000000000000000000084604051602001612b76929190613dce565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b8152600401612baa929190613f5c565b600060405180830381600087803b158015612bc457600080fd5b505af1158015612bd8573d6000803e3d6000fd5b505050505050565b6000818160015b6002811015612cb4576000612bfb82611ec4565b6002015490506000612c2082612c1085611ec4565b600101549063ffffffff611eee16565b90508015612ca9576000858210612c375785612c39565b815b9050612c4b838263ffffffff61208c16565b612c5485611ec4565b60020155612c68868263ffffffff611eee16565b9550612c7a858263ffffffff61208c16565b945085612c8f5784965050505050505061055e565b83158015612c9d5750600086115b15612ca757600095505b505b505060001901612be7565b509392505050565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612cfa5760405162461bcd60e51b815260040161058290614162565b6000612d046121cf565b6001600160a01b031663326080396007546040518263ffffffff1660e01b8152600401612d319190613f40565b60206040518083038186803b158015612d4957600080fd5b505afa158015612d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d819190810190613369565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081529091506001600160a01b03821690639dc29fac90612ddf9073feefeefeefeefeefeefeefeefeefeefeefeefeef908790600401613e92565b600060405180830381600087803b158015612df957600080fd5b505af1158015612e0d573d6000803e3d6000fd5b50506040517f867904b40000000000000000000000000000000000000000000000000000000081526001600160a01b038416925063867904b4915061272e9087908790600401613e92565b6000818160015b6002811015612cb4576000612e93612e7683611ec4565b60040154612e8384611ec4565b600301549063ffffffff611eee16565b90508015612f28576000848210612eaa5784612eac565b815b9050612ecb81612ebb85611ec4565b600401549063ffffffff61208c16565b612ed484611ec4565b60040155612ee8858263ffffffff611eee16565b9450612efa848263ffffffff61208c16565b935084612f0e57839550505050505061055e565b82158015612f1c5750600085115b15612f2657600094505b505b5060001901612e5f565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612f705760405162461bcd60e51b815260040161058290614162565b6301dfe200612f7d61311a565b6001600160a01b0316631bb47b448585846040518463ffffffff1660e01b815260040161272e93929190613ead565b6002546040516001600160a01b039091169063907dff9790612fd690869086908690602001613ead565b6040516020818303038152906040526001604051612ff390613df4565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261303a93929160009081908190600401613f8a565b600060405180830381600087803b15801561305457600080fd5b505af1158015613068573d6000803e3d6000fd5b50505050505050565b600082613080575060006106a9565b8282028284828161308d57fe5b04146120855760405162461bcd60e51b815260040161058290614122565b6000806130d1846130c587600a870263ffffffff61307116565b9063ffffffff61314516565b90506005600a825b06106130e357600a015b600a9004949350505050565b600080600a8304613106868663ffffffff61307116565b8161310d57fe5b0490506005600a826130d9565b60006107997f526577617264457363726f775632000000000000000000000000000000000000612a51565b60008082116131665760405162461bcd60e51b8152600401610582906140a2565b600082848161317157fe5b04949350505050565b60405180604001604052806002905b613191613202565b8152602001906001900390816131895790505090565b6040518060e00160405280600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b80356106a981614309565b80516106a981614309565b80516106a981614320565b80516106a981614329565b80516106a981614332565b80356106a981614329565b60006020828403121561327457600080fd5b60006132808484613220565b949350505050565b60006020828403121561329a57600080fd5b6000613280848461322b565b600080604083850312156132b957600080fd5b60006132c58585613220565b92505060206132d685828601613257565b9150509250929050565b6000806000606084860312156132f557600080fd5b60006133018686613220565b935050602061331286828701613257565b925050604061332386828701613257565b9150509250925092565b60006020828403121561333f57600080fd5b60006132808484613236565b60006020828403121561335d57600080fd5b60006132808484613241565b60006020828403121561337b57600080fd5b6000613280848461324c565b60006020828403121561339957600080fd5b60006132808484613257565b600080604083850312156133b857600080fd5b60006133c48585613241565b92505060206132d685828601613236565b600080604083850312156133e857600080fd5b60006133f48585613241565b92505060206132d685828601613241565b600080600080600080600080610100898b03121561342257600080fd5b600061342e8b8b613257565b985050602061343f8b828c01613257565b97505060406134508b828c01613257565b96505060606134618b828c01613257565b95505060806134728b828c01613257565b94505060a06134838b828c01613257565b93505060c06134948b828c01613257565b92505060e06134a58b828c01613257565b9150509295985092959890939650565b60006134c183836135ab565b505060400190565b60006134d58383613600565b505060200190565b6134e681614289565b82525050565b6134e68161424f565b6134e66135018261424f565b6142e8565b61350f8161423c565b613519818461055e565b92506135248261079c565b8060005b83811015612bd857815161353c87826134b5565b965061354783614236565b925050600101613528565b600061355d82614242565b6135678185614246565b935061357283614236565b8060005b838110156135a057815161358a88826134c9565b975061359583614236565b925050600101613576565b509495945050505050565b6135b48161423c565b6135be818461055e565b92506135c98261079c565b8060005b83811015612bd85781516135e187826134c9565b96506135ec83614236565b9250506001016135cd565b6134e68161425a565b6134e68161079c565b6134e66136158261079c565b61079c565b600061362582614242565b61362f8185614246565b935061363f8185602086016142b8565b613648816142f9565b9093019392505050565b6134e68161425f565b6134e681614294565b6134e6816142a2565b600061367a601783614246565b7f4f6e6c7920496e7465726e616c20436f6e747261637473000000000000000000815260200192915050565b60006136b3603583614246565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015260400192915050565b6000613712601d83614246565b7f546f6f206561726c7920746f20636c6f73652066656520706572696f64000000815260200192915050565b600061374b601383614246565b7f4f776e6572206f6e6c792066756e6374696f6e00000000000000000000000000815260200192915050565b600061378460248361055e565b7f46656573436c61696d656428616464726573732c75696e743235362c75696e7481527f3235362900000000000000000000000000000000000000000000000000000000602082015260240192915050565b60006137e360378361055e565b7f49737375616e636544656274526174696f456e74727928616464726573732c7581527f696e743235362c75696e743235362c75696e7432353629000000000000000000602082015260370192915050565b6000613842601b83614246565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061387b601e83614246565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b60006138b4601a83614246565b7f536166654d6174683a206469766973696f6e206279207a65726f000000000000815260200192915050565b60006138ed604083614246565b7f4e6f2066656573206f72207265776172647320617661696c61626c6520666f7281527f20706572696f642c206f72206665657320616c726561647920636c61696d6564602082015260400192915050565b600061394c60118361055e565b7f4d697373696e6720616464726573733a20000000000000000000000000000000815260110192915050565b6000613985601e83614246565b7f412073796e7468206f7220534e58207261746520697320696e76616c69640000815260200192915050565b60006139be601883614246565b7f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815260200192915050565b60006139f7601f83614246565b7f4e6f7420617070726f76656420746f20636c61696d206f6e20626568616c6600815260200192915050565b6000613a30601e83614246565b7f43616c6c6572206973206e6f742072657761726473417574686f726974790000815260200192915050565b6000613a69602f83614246565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015260400192915050565b6000613ac8601f83614246565b7f432d526174696f2062656c6f772070656e616c7479207468726573686f6c6400815260200192915050565b6000613b01602183614246565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613b60601683614246565b7f43616e6e6f7420696d706f727420626164206461746100000000000000000000815260200192915050565b6000613b99601d83614246565b7f4578636565647320746865204645455f504552494f445f4c454e475448000000815260200192915050565b6000613bd2602983614246565b7f43616e206f6e6c7920706572666f726d207468697320616374696f6e2064757281527f696e672073657475700000000000000000000000000000000000000000000000602082015260400192915050565b6000613c3160198361055e565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000613c6a601783614246565b7f4665652061646472657373206e6f7420616c6c6f776564000000000000000000815260200192915050565b6000613ca360188361055e565b7f466565506572696f64436c6f7365642875696e74323536290000000000000000815260180192915050565b6000613cdc601783614246565b7f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000815260200192915050565b6000613d15601e83614246565b7f49737375657220616e642053796e7468657469785374617465206f6e6c790000815260200192915050565b6000613d4e602083614246565b7f43757272656e7420706572696f64206973206e6f7420636c6f73656420796574815260200192915050565b6000613d87601b83614246565b7f46656520506572696f64204475726174696f6e206e6f74207365740000000000815260200192915050565b6134e6816142ad565b6134e681614276565b6134e681614283565b6000613dda8285613609565b602082019150613dea82846134f5565b5060140192915050565b60006106a982613777565b60006106a9826137d6565b6000613e158261393f565b9150613e218284613609565b50602001919050565b6000613e1582613c24565b60006106a982613c96565b602081016106a982846134ec565b602081016106a982846134dd565b60408101613e6a82856134ec565b61208560208301846134ec565b60408101613e8582856134ec565b6120856020830184613664565b60408101613ea082856134ec565b6120856020830184613600565b60608101613ebb82866134ec565b613ec86020830185613600565b6132806040830184613600565b60808101613ee382876134ec565b613ef06020830186613600565b613efd6040830185613600565b613f0a6060830184613db3565b95945050505050565b608081016106a98284613506565b602080825281016120858184613552565b602081016106a982846135f7565b602081016106a98284613600565b60408101613e6a8285613600565b60408101613ea08285613600565b60408101613f788285613600565b8181036020830152613280818461361a565b60c08082528101613f9b818961361a565b9050613faa6020830188613664565b613fb76040830187613600565b613fc4606083018661365b565b613fd1608083018561365b565b613fde60a083018461365b565b979650505050505050565b60c08082528101613ffa818961361a565b90506140096020830188613664565b6140166040830187613600565b613fc46060830186613600565b602081016106a98284613652565b60208082528101612085818461361a565b6020808252810161055b8161366d565b6020808252810161055b816136a6565b6020808252810161055b81613705565b6020808252810161055b8161373e565b6020808252810161055b81613835565b6020808252810161055b8161386e565b6020808252810161055b816138a7565b6020808252810161055b816138e0565b6020808252810161055b81613978565b6020808252810161055b816139b1565b6020808252810161055b816139ea565b6020808252810161055b81613a23565b6020808252810161055b81613a5c565b6020808252810161055b81613abb565b6020808252810161055b81613af4565b6020808252810161055b81613b53565b6020808252810161055b81613b8c565b6020808252810161055b81613bc5565b6020808252810161055b81613c5d565b6020808252810161055b81613ccf565b6020808252810161055b81613d08565b6020808252810161055b81613d41565b6020808252810161055b81613d7a565b60608101613ebb8286613600565b60e081016141ce828a613dbc565b6141db6020830189613dbc565b6141e86040830188613dbc565b6141f56060830187613600565b6142026080830186613600565b61420f60a0830185613600565b61421c60c0830184613600565b98975050505050505050565b602081016106a98284613dc5565b60200190565b50600290565b5190565b90815260200190565b600061055b8261426a565b151590565b600061055b8261424f565b6001600160a01b031690565b67ffffffffffffffff1690565b60ff1690565b600061055b8261425f565b600061055b6136158361079c565b600061055b8261079c565b600061055b82614276565b60005b838110156142d35781810151838201526020016142bb565b838111156142e2576000848401525b50505050565b600061055b82600061055b82614303565b601f01601f191690565b60601b90565b6143128161424f565b811461431d57600080fd5b50565b6143128161425a565b6143128161079c565b6143128161425f56fea365627a7a723158201b892453f68c9598ad9df24178184e6cf66b8aa9419177fdf7a3c0c46b5c23e46c6578706572696d656e74616cf564736f6c63430005100040", + "bytecode": "6080604052631cd554d160e21b6007553480156200001c57600080fd5b506040516200471b3803806200471b8339810160408190526200003f9162000221565b8080621baf8085856001600160a01b038116620000795760405162461bcd60e51b8152600401620000709062000343565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620000c69184906200030b565b60405180910390a1506000546001600160a01b0316620000fa5760405162461bcd60e51b8152600401620000709062000331565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9062000147908390620002fb565b60405180910390a1504201600455600580546001600160a01b0319166001600160a01b0392909216919091179055506001620001846000620001e2565b80546001600160401b0319166001600160401b039290921691909117905542620001af6000620001e2565b80546001600160401b0392909216600160801b02600160801b600160c01b0319909216919091179055506200039e915050565b60006008600260ff16836012540181620001f857fe5b06600281106200020457fe5b6005020192915050565b80516200021b8162000384565b92915050565b6000806000606084860312156200023757600080fd5b60006200024586866200020e565b935050602062000258868287016200020e565b92505060406200026b868287016200020e565b9150509250925092565b620002808162000370565b82525050565b62000280816200035e565b6000620002a060118362000355565b7013dddb995c881b5d5cdd081899481cd95d607a1b815260200192915050565b6000620002cf60198362000355565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b602081016200021b828462000275565b604081016200031b828562000275565b6200032a602083018462000286565b9392505050565b602080825281016200021b8162000291565b602080825281016200021b81620002c0565b90815260200190565b60006001600160a01b0382166200021b565b60006200021b8260006200021b826200035e565b6200038f816200035e565b81146200039b57600080fd5b50565b61436d80620003ae6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80636de813f111610145578063b410a034116100bd578063d67bdd251161008c578063eb1edd6111610071578063eb1edd611461045c578063ec55688914610464578063fd1f498d1461046c57610241565b8063d67bdd251461044c578063e0e6393d1461045457610241565b8063b410a03414610414578063bc67f8321461041c578063cff2ddad1461042f578063d294f0931461044457610241565b8063899ffef41161011457806397107d6d116100f957806397107d6d146103e6578063ac834193146103f9578063b10090b81461040157610241565b8063899ffef4146103c95780638da5cb5b146103de57610241565b80636de813f11461039e57806374185360146103a657806379ba5097146103ae57806386645274146103b657610241565b806333140016116101d857806353a47bb7116101a757806359a2f19f1161018c57806359a2f19f14610370578063614d08f8146103835780636466f45e1461038b57610241565b806353a47bb714610353578063569249d01461036857610241565b806333140016146102fd5780633ebc457a1461031d5780633fcd22401461032557806346ba2d901461034b57610241565b80631627540c116102145780631627540c146102b857806322425fa4146102cd57806322bf55ef146102d55780632af64bd3146102e857610241565b806304f3bcec1461024657806307ea50cd146102645780630813071c146102845780630de5861514610297575b600080fd5b61024e61047f565b60405161025b9190614012565b60405180910390f35b610277610272366004613251565b61048e565b60405161025b9190613f2f565b610277610292366004613295565b610563565b6102aa6102a5366004613251565b6106af565b60405161025b929190613f4b565b6102cb6102c6366004613251565b610731565b005b61027761078f565b6102cb6102e3366004613376565b61079f565b6102f0610978565b60405161025b9190613f21565b61031061030b366004613251565b610aa8565b60405161025b9190613f02565b6102cb610d0c565b610338610333366004613376565b611112565b60405161025b97969594939291906141af565b6102776111bb565b61035b6111c1565b60405161025b9190613e2f565b6102776111d0565b6102f061037e366004613251565b61122b565b61027761123d565b6102f0610399366004613251565b611261565b61027761138d565b6102cb6113e2565b6102cb611534565b6102cb6103c43660046132cf565b6115d0565b6103d1611710565b60405161025b9190613f10565b61035b611a30565b6102cb6103f4366004613251565b611a3f565b610277611a92565b6102cb61040f3660046133f4565b611b32565b610277611d2c565b6102cb61042a366004613251565b611d36565b610437611d60565b60405161025b9190614217565b6102f0611d65565b61035b611ddc565b610277611deb565b61035b611df5565b61024e611e0d565b6102cb61047a366004613376565b611e1c565b6005546001600160a01b031681565b6000610498611e88565b6001600160a01b031663bdc963d87f6c6173745f6665655f7769746864726177616c00000000000000000000000000846040516020016104d9929190613dbd565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161050b9190613f2f565b60206040518083038186803b15801561052357600080fd5b505afa158015610537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061055b919081019061333a565b90505b919050565b60008161058b5760405162461bcd60e51b815260040161058290614181565b60405180910390fd5b600282106105ab5760405162461bcd60e51b815260040161058290614131565b6105b760018303611eb3565b5468010000000000000000900467ffffffffffffffff166105da575060006106a9565b600061060a60016105ed60018603611eb3565b5468010000000000000000900467ffffffffffffffff1690611edd565b9050600080610617611f05565b6001600160a01b031663d29c000a87856040518363ffffffff1660e01b8152600401610644929190613e81565b604080518083038186803b15801561065b57600080fd5b505afa15801561066f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061069391908101906133c4565b90925090506106a3838383611f30565b93505050505b92915050565b6000806106ba613169565b6106c384610aa8565b905060008060015b6002811015610724576106f08482600281106106e357fe5b602002015151849061207b565b925061071a84826002811061070157fe5b602002015160016020020151839063ffffffff61207b16565b91506001016106cb565b509093509150505b915091565b6107396120a0565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610784908390613e2f565b60405180910390a150565b60006107996120cc565b90505b90565b60006107a9612193565b6001600160a01b0316331490506000806107c16121be565b6001600160a01b03166316b2213f336040518263ffffffff1660e01b81526004016107ec9190613e3d565b60206040518083038186803b15801561080457600080fd5b505afa158015610818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061083c919081019061333a565b14159050600061084a6121d2565b6001600160a01b031663b38988f7336040518263ffffffff1660e01b81526004016108759190613e3d565b60206040518083038186803b15801561088d57600080fd5b505afa1580156108a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108c5919081019061331c565b905060006108d16121fd565b6001600160a01b0316336001600160a01b031614905060006108f1612228565b6001600160a01b0316336001600160a01b031614905084806109105750835b806109185750825b806109205750815b806109285750805b6109445760405162461bcd60e51b815260040161058290614031565b610962866109526000611eb3565b600101549063ffffffff61207b16565b61096c6000611eb3565b60010155505050505050565b60006060610984611710565b905060005b8151811015610a9f5760008282815181106109a057fe5b602090810291909101810151600081815260069092526040918290205460055492517f21f8a7210000000000000000000000000000000000000000000000000000000081529193506001600160a01b039081169216906321f8a72190610a0a908590600401613f2f565b60206040518083038186803b158015610a2257600080fd5b505afa158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a5a9190810190613277565b6001600160a01b0316141580610a8557506000818152600660205260409020546001600160a01b0316155b15610a96576000935050505061079c565b50600101610989565b50600191505090565b610ab0613169565b6000806000610abd611f05565b6040517fb326f84e0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0382169063b326f84e90610b08908890600090600401613e66565b604080518083038186803b158015610b1f57600080fd5b505afa158015610b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b5791908101906133c4565b909350915081158015610b68575082155b15610b8057610b75613169565b935061055e92505050565b600080610b8f60008686612253565b8751829052875160200181905290925090506000610bac8861048e565b905060015b8015610d005760001981016000610bc782611eb3565b5468010000000000000000900467ffffffffffffffff1690508015801590610c015750610bf383611eb3565b5467ffffffffffffffff1684105b15610cf5576000610c1982600163ffffffff611edd16565b6040517fd29c000a0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0389169063d29c000a90610c63908f908590600401613e81565b604080518083038186803b158015610c7a57600080fd5b505afa158015610c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610cb291908101906133c4565b909a509850610cc2848b8b612253565b9097509550868b8560028110610cd457fe5b602002015152858b8560028110610ce757fe5b602002015160016020020152505b505060001901610bb1565b50505050505050919050565b610d146122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015610d4c57600080fd5b505afa158015610d60573d6000803e3d6000fd5b505050506000610d6e6120cc565b11610d8b5760405162461bcd60e51b815260040161058290614191565b610d936120cc565b4203610d9f6000611eb3565b54600160801b900467ffffffffffffffff161115610dcf5760405162461bcd60e51b815260040161058290614051565b610dd76121fd565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e1157600080fd5b505af1158015610e25573d6000803e3d6000fd5b50505050610e31612228565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e6b57600080fd5b505af1158015610e7f573d6000803e3d6000fd5b5060009250610e919150829050611eb3565b90506000610e9f6001611eb3565b9050610ed08260010154610ec483600201548460010154611edd90919063ffffffff16565b9063ffffffff61207b16565b610eda6000611eb3565b60010155600380830154600483015491830154610f0192610ec4919063ffffffff611edd16565b610f0b6000611eb3565b60030155601254610f4890600290610f3c90600190610f30908463ffffffff61207b16565b9063ffffffff611edd16565b9063ffffffff61232016565b601281905560089060028110610f5a57fe5b6005020180547fffffffffffffffff000000000000000000000000000000000000000000000000168155600060018083018290556002830182905560038301829055600490920155610fc690610faf81611eb3565b5467ffffffffffffffff169063ffffffff61207b16565b610fd06000611eb3565b805467ffffffffffffffff191667ffffffffffffffff92909216919091179055610ff8612350565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561103057600080fd5b505afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611068919081019061333a565b6110726000611eb3565b805467ffffffffffffffff9290921668010000000000000000026fffffffffffffffff000000000000000019909216919091179055426110b26000611eb3565b805467ffffffffffffffff92909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905561110e6110fe6001611eb3565b5467ffffffffffffffff1661237b565b5050565b6000806000806000806000611125613196565b61112e89611eb3565b6040805160e081018252825467ffffffffffffffff808216808452680100000000000000008304821660208501819052600160801b909304909116938301849052600185015460608401819052600286015460808501819052600387015460a0860181905260049097015460c0909501859052919f929e50939c50929a5091985091965090945092505050565b60045481565b6001546001600160a01b031681565b60008060015b6002811015611225576111fc6111eb82611eb3565b60010154839063ffffffff61207b16565b915061121b61120a82611eb3565b60020154839063ffffffff611edd16565b91506001016111d6565b50905090565b600061123682612433565b5092915050565b7f466565506f6f6c0000000000000000000000000000000000000000000000000081565b600061126b6122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156112a357600080fd5b505afa1580156112b7573d6000803e3d6000fd5b505050506112c3612527565b6112cb612566565b6003546040517f21f4ae570000000000000000000000000000000000000000000000000000000081526001600160a01b03928316926321f4ae579261131892879290911690600401613e4b565b60206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611368919081019061331c565b6113845760405162461bcd60e51b8152600401610582906140e1565b61055b82612591565b60008060015b6002811015611225576113b96113a882611eb3565b60030154839063ffffffff61207b16565b91506113d86113c782611eb3565b60040154839063ffffffff611edd16565b9150600101611393565b60606113ec611710565b905060005b815181101561110e57600082828151811061140857fe5b602002602001015190506000600560009054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200161144a9190613e19565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611476929190613f59565b60206040518083038186803b15801561148e57600080fd5b505afa1580156114a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114c69190810190613277565b6000838152600660205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906115229084908490613f3d565b60405180910390a150506001016113f1565b6001546001600160a01b0316331461155e5760405162461bcd60e51b815260040161058290614041565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c926115a1926001600160a01b0391821692911690613e4b565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006115da6121be565b6001600160a01b0316336001600160a01b031614905060006115fa612350565b6001600160a01b0316336001600160a01b031614905081806116195750805b6116355760405162461bcd60e51b815260040161058290614171565b61163d611f05565b6001600160a01b03166394e1a4488686866116586000611eb3565b5460405160e086901b7fffffffff000000000000000000000000000000000000000000000000000000001681526116ab9493929168010000000000000000900467ffffffffffffffff1690600401613ec4565b600060405180830381600087803b1580156116c557600080fd5b505af11580156116d9573d6000803e3d6000fd5b505050506117098585856116ed6000611eb3565b5468010000000000000000900467ffffffffffffffff16612686565b5050505050565b60608061171b612755565b60408051600d8082526101c0820190925291925060609190602082016101a0803883390190505090507f53797374656d53746174757300000000000000000000000000000000000000008160008151811061177257fe5b6020026020010181815250507f53796e7468657469780000000000000000000000000000000000000000000000816001815181106117ac57fe5b6020026020010181815250507f466565506f6f6c53746174650000000000000000000000000000000000000000816002815181106117e657fe5b6020026020010181815250507f466565506f6f6c457465726e616c53746f7261676500000000000000000000008160038151811061182057fe5b6020026020010181815250507f45786368616e67657200000000000000000000000000000000000000000000008160048151811061185a57fe5b6020026020010181815250506524b9b9bab2b960d11b8160058151811061187d57fe5b6020026020010181815250507f53796e7468657469785374617465000000000000000000000000000000000000816006815181106118b757fe5b6020026020010181815250507f526577617264457363726f775632000000000000000000000000000000000000816007815181106118f157fe5b6020026020010181815250507f44656c6567617465417070726f76616c730000000000000000000000000000008160088151811061192b57fe5b6020026020010181815250507f52657761726473446973747269627574696f6e000000000000000000000000008160098151811061196557fe5b6020026020010181815250507f436f6c6c61746572616c4d616e6167657200000000000000000000000000000081600a8151811061199f57fe5b6020026020010181815250507f57726170706572466163746f727900000000000000000000000000000000000081600b815181106119d957fe5b6020026020010181815250507f457468657257726170706572000000000000000000000000000000000000000081600c81518110611a1357fe5b602002602001018181525050611a2982826127b4565b9250505090565b6000546001600160a01b031681565b611a476120a0565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e90610784908390613e3d565b6000610799611b1e611aa2612869565b73__$f9217daff40bcb29719cec84f7ab900933$__63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611ae657600080fd5b505af4158015611afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ec4919081019061333a565b611b266128e0565b9063ffffffff61295716565b611b3a612981565b6004544210611b5b5760405162461bcd60e51b815260040161058290614141565b611b63612350565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b9b57600080fd5b505afa158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611bd3919081019061333a565b861115611bf25760405162461bcd60e51b815260040161058290614121565b6040518060e001604052808867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018667ffffffffffffffff168152602001858152602001848152602001838152602001828152506008611c62600260ff16610f3c8c60125461207b90919063ffffffff16565b60028110611c6c57fe5b82516005919091029190910180546020840151604085015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff000000000000000019166801000000000000000091851691909102177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b9390911692909202919091178155606082015160018201556080820151600282015560a0820151600382015560c0909101516004909101555050505050505050565b60006107996128e0565b611d3e6129ef565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600281565b6000611d6f6122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611da757600080fd5b505afa158015611dbb573d6000803e3d6000fd5b50505050611dc7612527565b600354610799906001600160a01b0316612591565b6003546001600160a01b031681565b6000610799612869565b73feefeefeefeefeefeefeefeefeefeefeefeefeef81565b6002546001600160a01b031681565b611e24612527565b611e2c612a19565b6003546001600160a01b03908116911614611e595760405162461bcd60e51b8152600401610582906140b1565b611e7781611e676000611eb3565b600301549063ffffffff61207b16565b611e816000611eb3565b6003015550565b60006107997f466565506f6f6c457465726e616c53746f726167650000000000000000000000612a40565b60006008600260ff16836012540181611ec857fe5b0660028110611ed357fe5b6005020192915050565b600082821115611eff5760405162461bcd60e51b815260040161058290614081565b50900390565b60006107997f466565506f6f6c53746174650000000000000000000000000000000000000000612a40565b600080611f3b612350565b9050600061206f85612063846001600160a01b03166308d95cd5886040518263ffffffff1660e01b8152600401611f729190613f2f565b60206040518083038186803b158015611f8a57600080fd5b505afa158015611f9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611fc2919081019061333a565b6040517f08d95cd50000000000000000000000000000000000000000000000000000000081526001600160a01b038716906308d95cd590612007908d90600401613f2f565b60206040518083038186803b15801561201f57600080fd5b505afa158015612033573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612057919081019061333a565b9063ffffffff612a9d16565b9063ffffffff612ab616565b925050505b9392505050565b6000828201838110156120745760405162461bcd60e51b815260040161058290614071565b6000546001600160a01b031633146120ca5760405162461bcd60e51b8152600401610582906140f1565b565b60006120d6612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f666565506572696f644475726174696f6e0000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b60206040518083038186803b15801561215b57600080fd5b505afa15801561216f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610799919081019061333a565b60006107997f45786368616e6765720000000000000000000000000000000000000000000000612a40565b60006107996524b9b9bab2b960d11b612a40565b60006107997f436f6c6c61746572616c4d616e61676572000000000000000000000000000000612a40565b60006107997f4574686572577261707065720000000000000000000000000000000000000000612a40565b60006107997f57726170706572466163746f7279000000000000000000000000000000000000612a40565b60008083612266575060009050806122ed565b83851561229157600061228060016105ed60018a03611eb3565b905061228d818787611f30565b9150505b60006122b0826122a089611eb3565b600101549063ffffffff61295716565b905060006122d1836122c18a611eb3565b600301549063ffffffff61295716565b90506122dc82612afa565b6122e582612afa565b945094505050505b935093915050565b60006107997f53797374656d5374617475730000000000000000000000000000000000000000612a40565b60008161233f5760405162461bcd60e51b8152600401610582906140d1565b81838161234857fe5b069392505050565b60006107997f53796e7468657469785374617465000000000000000000000000000000000000612a40565b6002546040516001600160a01b039091169063907dff97906123a1908490602001613f2f565b60405160208183030381529060405260016040516123be90613e24565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261240593929160009081908190600401613f79565b600060405180830381600087803b15801561241f57600080fd5b505af1158015611709573d6000803e3d6000fd5b6000806000806124416121be565b6001600160a01b031663ae3bbbbb866040518263ffffffff1660e01b815260040161246c9190613e2f565b604080518083038186803b15801561248357600080fd5b505afa158015612497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124bb9190810190613394565b9150915060006124c96128e0565b9050808310156124e1575060019350915061072c9050565b60006124fe6124f1611aa2612869565b839063ffffffff61295716565b90508084111561251857600083955095505050505061072c565b50600194509092505050915091565b6002546001600160a01b0316331480159061254d57506003546001600160a01b03163314155b156120ca57600380546001600160a01b03191633179055565b60006107997f44656c6567617465417070726f76616c73000000000000000000000000000000612a40565b60008080808080806125a288612433565b91509150816125c35760405162461bcd60e51b815260040161058290614101565b80156125e15760405162461bcd60e51b8152600401610582906140c1565b6125ea886106af565b9094509250831515806125fd5750600083115b6126195760405162461bcd60e51b8152600401610582906140a1565b612637886126276001611eb3565b5467ffffffffffffffff16612b1c565b83156126525761264684612bcf565b94506126528886612cab565b821561266d5761266183612e47565b955061266d8887612f21565b612678888688612f9b565b506001979650505050505050565b6002546040516001600160a01b039091169063907dff97906126b0908690869086906020016141a1565b60405160208183030381529060405260026040516126cd90613dee565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261271d9392916001600160a01b038b16906000908190600401613fd8565b600060405180830381600087803b15801561273757600080fd5b505af115801561274b573d6000803e3d6000fd5b5050505050505050565b604080516001808252818301909252606091602080830190803883390190505090507f466c657869626c6553746f726167650000000000000000000000000000000000816000815181106127a557fe5b60200260200101818152505090565b606081518351016040519080825280602002602001820160405280156127e4578160200160208202803883390190505b50905060005b8351811015612826578381815181106127ff57fe5b602002602001015182828151811061281357fe5b60209081029190910101526001016127ea565b5060005b82518110156112365782818151811061283f57fe5b602002602001015182828651018151811061285657fe5b602090810291909101015260010161282a565b6000612873612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f7461726765745468726573686f6c6400000000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b60006128ea612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f69737375616e6365526174696f000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b6000670de0b6b3a7640000612972848463ffffffff61306016565b8161297957fe5b049392505050565b6002546001600160a01b031633148015906129a757506003546001600160a01b03163314155b156129bf57600380546001600160a01b031916331790555b6000546003546001600160a01b039081169116146120ca5760405162461bcd60e51b815260040161058290614061565b6002546001600160a01b031633146120ca5760405162461bcd60e51b815260040161058290614161565b60006107997f52657761726473446973747269627574696f6e000000000000000000000000005b60008181526006602090815260408083205490516001600160a01b039091169182151591612a7091869101613df9565b604051602081830303815290604052906112365760405162461bcd60e51b81526004016105829190614020565b600061207483836b033b2e3c9fd0803ce800000061309a565b600061207483836b033b2e3c9fd0803ce80000006130de565b60006107997f466c657869626c6553746f726167650000000000000000000000000000000000612a40565b60006305f5e10082046005600a820610612b1257600a015b600a900492915050565b612b24611e88565b6001600160a01b0316633562fd207f6c6173745f6665655f7769746864726177616c0000000000000000000000000084604051602001612b65929190613dbd565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b8152600401612b99929190613f4b565b600060405180830381600087803b158015612bb357600080fd5b505af1158015612bc7573d6000803e3d6000fd5b505050505050565b6000818160015b6002811015612ca3576000612bea82611eb3565b6002015490506000612c0f82612bff85611eb3565b600101549063ffffffff611edd16565b90508015612c98576000858210612c265785612c28565b815b9050612c3a838263ffffffff61207b16565b612c4385611eb3565b60020155612c57868263ffffffff611edd16565b9550612c69858263ffffffff61207b16565b945085612c7e5784965050505050505061055e565b83158015612c8c5750600086115b15612c9657600095505b505b505060001901612bd6565b509392505050565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612ce95760405162461bcd60e51b815260040161058290614151565b6000612cf36121be565b6001600160a01b031663326080396007546040518263ffffffff1660e01b8152600401612d209190613f2f565b60206040518083038186803b158015612d3857600080fd5b505afa158015612d4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d709190810190613358565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081529091506001600160a01b03821690639dc29fac90612dce9073feefeefeefeefeefeefeefeefeefeefeefeefeef908790600401613e81565b600060405180830381600087803b158015612de857600080fd5b505af1158015612dfc573d6000803e3d6000fd5b50506040517f867904b40000000000000000000000000000000000000000000000000000000081526001600160a01b038416925063867904b4915061271d9087908790600401613e81565b6000818160015b6002811015612ca3576000612e82612e6583611eb3565b60040154612e7284611eb3565b600301549063ffffffff611edd16565b90508015612f17576000848210612e995784612e9b565b815b9050612eba81612eaa85611eb3565b600401549063ffffffff61207b16565b612ec384611eb3565b60040155612ed7858263ffffffff611edd16565b9450612ee9848263ffffffff61207b16565b935084612efd57839550505050505061055e565b82158015612f0b5750600085115b15612f1557600094505b505b5060001901612e4e565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612f5f5760405162461bcd60e51b815260040161058290614151565b6301dfe200612f6c613109565b6001600160a01b0316631bb47b448585846040518463ffffffff1660e01b815260040161271d93929190613e9c565b6002546040516001600160a01b039091169063907dff9790612fc590869086908690602001613e9c565b6040516020818303038152906040526001604051612fe290613de3565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261302993929160009081908190600401613f79565b600060405180830381600087803b15801561304357600080fd5b505af1158015613057573d6000803e3d6000fd5b50505050505050565b60008261306f575060006106a9565b8282028284828161307c57fe5b04146120745760405162461bcd60e51b815260040161058290614111565b6000806130c0846130b487600a870263ffffffff61306016565b9063ffffffff61313416565b90506005600a825b06106130d257600a015b600a9004949350505050565b600080600a83046130f5868663ffffffff61306016565b816130fc57fe5b0490506005600a826130c8565b60006107997f526577617264457363726f775632000000000000000000000000000000000000612a40565b60008082116131555760405162461bcd60e51b815260040161058290614091565b600082848161316057fe5b04949350505050565b60405180604001604052806002905b6131806131f1565b8152602001906001900390816131785790505090565b6040518060e00160405280600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b80356106a9816142f8565b80516106a9816142f8565b80516106a98161430f565b80516106a981614318565b80516106a981614321565b80356106a981614318565b60006020828403121561326357600080fd5b600061326f848461320f565b949350505050565b60006020828403121561328957600080fd5b600061326f848461321a565b600080604083850312156132a857600080fd5b60006132b4858561320f565b92505060206132c585828601613246565b9150509250929050565b6000806000606084860312156132e457600080fd5b60006132f0868661320f565b935050602061330186828701613246565b925050604061331286828701613246565b9150509250925092565b60006020828403121561332e57600080fd5b600061326f8484613225565b60006020828403121561334c57600080fd5b600061326f8484613230565b60006020828403121561336a57600080fd5b600061326f848461323b565b60006020828403121561338857600080fd5b600061326f8484613246565b600080604083850312156133a757600080fd5b60006133b38585613230565b92505060206132c585828601613225565b600080604083850312156133d757600080fd5b60006133e38585613230565b92505060206132c585828601613230565b600080600080600080600080610100898b03121561341157600080fd5b600061341d8b8b613246565b985050602061342e8b828c01613246565b975050604061343f8b828c01613246565b96505060606134508b828c01613246565b95505060806134618b828c01613246565b94505060a06134728b828c01613246565b93505060c06134838b828c01613246565b92505060e06134948b828c01613246565b9150509295985092959890939650565b60006134b0838361359a565b505060400190565b60006134c483836135ef565b505060200190565b6134d581614278565b82525050565b6134d58161423e565b6134d56134f08261423e565b6142d7565b6134fe8161422b565b613508818461055e565b92506135138261079c565b8060005b83811015612bc757815161352b87826134a4565b965061353683614225565b925050600101613517565b600061354c82614231565b6135568185614235565b935061356183614225565b8060005b8381101561358f57815161357988826134b8565b975061358483614225565b925050600101613565565b509495945050505050565b6135a38161422b565b6135ad818461055e565b92506135b88261079c565b8060005b83811015612bc75781516135d087826134b8565b96506135db83614225565b9250506001016135bc565b6134d581614249565b6134d58161079c565b6134d56136048261079c565b61079c565b600061361482614231565b61361e8185614235565b935061362e8185602086016142a7565b613637816142e8565b9093019392505050565b6134d58161424e565b6134d581614283565b6134d581614291565b6000613669601783614235565b7f4f6e6c7920496e7465726e616c20436f6e747261637473000000000000000000815260200192915050565b60006136a2603583614235565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015260400192915050565b6000613701601d83614235565b7f546f6f206561726c7920746f20636c6f73652066656520706572696f64000000815260200192915050565b600061373a601383614235565b7f4f776e6572206f6e6c792066756e6374696f6e00000000000000000000000000815260200192915050565b600061377360248361055e565b7f46656573436c61696d656428616464726573732c75696e743235362c75696e7481527f3235362900000000000000000000000000000000000000000000000000000000602082015260240192915050565b60006137d260378361055e565b7f49737375616e636544656274526174696f456e74727928616464726573732c7581527f696e743235362c75696e743235362c75696e7432353629000000000000000000602082015260370192915050565b6000613831601b83614235565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061386a601e83614235565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b60006138a3601a83614235565b7f536166654d6174683a206469766973696f6e206279207a65726f000000000000815260200192915050565b60006138dc604083614235565b7f4e6f2066656573206f72207265776172647320617661696c61626c6520666f7281527f20706572696f642c206f72206665657320616c726561647920636c61696d6564602082015260400192915050565b600061393b60118361055e565b7f4d697373696e6720616464726573733a20000000000000000000000000000000815260110192915050565b6000613974601883614235565b7f52657761726473446973747269627574696f6e206f6e6c790000000000000000815260200192915050565b60006139ad601e83614235565b7f412073796e7468206f7220534e58207261746520697320696e76616c69640000815260200192915050565b60006139e6601883614235565b7f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815260200192915050565b6000613a1f601f83614235565b7f4e6f7420617070726f76656420746f20636c61696d206f6e20626568616c6600815260200192915050565b6000613a58602f83614235565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015260400192915050565b6000613ab7601f83614235565b7f432d526174696f2062656c6f772070656e616c7479207468726573686f6c6400815260200192915050565b6000613af0602183614235565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613b4f601683614235565b7f43616e6e6f7420696d706f727420626164206461746100000000000000000000815260200192915050565b6000613b88601d83614235565b7f4578636565647320746865204645455f504552494f445f4c454e475448000000815260200192915050565b6000613bc1602983614235565b7f43616e206f6e6c7920706572666f726d207468697320616374696f6e2064757281527f696e672073657475700000000000000000000000000000000000000000000000602082015260400192915050565b6000613c2060198361055e565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000613c59601783614235565b7f4665652061646472657373206e6f7420616c6c6f776564000000000000000000815260200192915050565b6000613c9260188361055e565b7f466565506572696f64436c6f7365642875696e74323536290000000000000000815260180192915050565b6000613ccb601783614235565b7f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000815260200192915050565b6000613d04601e83614235565b7f49737375657220616e642053796e7468657469785374617465206f6e6c790000815260200192915050565b6000613d3d602083614235565b7f43757272656e7420706572696f64206973206e6f7420636c6f73656420796574815260200192915050565b6000613d76601b83614235565b7f46656520506572696f64204475726174696f6e206e6f74207365740000000000815260200192915050565b6134d58161429c565b6134d581614265565b6134d581614272565b6000613dc982856135f8565b602082019150613dd982846134e4565b5060140192915050565b60006106a982613766565b60006106a9826137c5565b6000613e048261392e565b9150613e1082846135f8565b50602001919050565b6000613e0482613c13565b60006106a982613c85565b602081016106a982846134db565b602081016106a982846134cc565b60408101613e5982856134db565b61207460208301846134db565b60408101613e7482856134db565b6120746020830184613653565b60408101613e8f82856134db565b61207460208301846135ef565b60608101613eaa82866134db565b613eb760208301856135ef565b61326f60408301846135ef565b60808101613ed282876134db565b613edf60208301866135ef565b613eec60408301856135ef565b613ef96060830184613da2565b95945050505050565b608081016106a982846134f5565b602080825281016120748184613541565b602081016106a982846135e6565b602081016106a982846135ef565b60408101613e5982856135ef565b60408101613e8f82856135ef565b60408101613f6782856135ef565b818103602083015261326f8184613609565b60c08082528101613f8a8189613609565b9050613f996020830188613653565b613fa660408301876135ef565b613fb3606083018661364a565b613fc0608083018561364a565b613fcd60a083018461364a565b979650505050505050565b60c08082528101613fe98189613609565b9050613ff86020830188613653565b61400560408301876135ef565b613fb360608301866135ef565b602081016106a98284613641565b602080825281016120748184613609565b6020808252810161055b8161365c565b6020808252810161055b81613695565b6020808252810161055b816136f4565b6020808252810161055b8161372d565b6020808252810161055b81613824565b6020808252810161055b8161385d565b6020808252810161055b81613896565b6020808252810161055b816138cf565b6020808252810161055b81613967565b6020808252810161055b816139a0565b6020808252810161055b816139d9565b6020808252810161055b81613a12565b6020808252810161055b81613a4b565b6020808252810161055b81613aaa565b6020808252810161055b81613ae3565b6020808252810161055b81613b42565b6020808252810161055b81613b7b565b6020808252810161055b81613bb4565b6020808252810161055b81613c4c565b6020808252810161055b81613cbe565b6020808252810161055b81613cf7565b6020808252810161055b81613d30565b6020808252810161055b81613d69565b60608101613eaa82866135ef565b60e081016141bd828a613dab565b6141ca6020830189613dab565b6141d76040830188613dab565b6141e460608301876135ef565b6141f160808301866135ef565b6141fe60a08301856135ef565b61420b60c08301846135ef565b98975050505050505050565b602081016106a98284613db4565b60200190565b50600290565b5190565b90815260200190565b600061055b82614259565b151590565b600061055b8261423e565b6001600160a01b031690565b67ffffffffffffffff1690565b60ff1690565b600061055b8261424e565b600061055b6136048361079c565b600061055b8261079c565b600061055b82614265565b60005b838110156142c25781810151838201526020016142aa565b838111156142d1576000848401525b50505050565b600061055b82600061055b826142f2565b601f01601f191690565b60601b90565b6143018161423e565b811461430c57600080fd5b50565b61430181614249565b6143018161079c565b6143018161424e56fea365627a7a72315820311ca67b066d8aa30c5fc3e5d4e569051e36efc62ebf3c8ccc4f5172288bdb2b6c6578706572696d656e74616cf564736f6c63430005100040", "abi": [ { "inputs": [ @@ -12690,10 +12699,10 @@ } ], "source": { - "keccak256": "0xb89f33e39e3b4c3f010dd3f4ee922c00778b73845226e3edd97715ead2888cd5", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914", "urls": [ - "bzz-raw://f50538229bc9b24d1a27335c8735bf3f2ade7121798c896268025fbff68b9789", - "dweb:/ipfs/Qmaty5Nuxxu3kfLZmVUy3xVL7VrQSeRjpy8GHEcrqdBCr5" + "bzz-raw://d45068f4b97b8568117b6c095694b7270cad2b0337ea0c2b8b24550dfa93fdbc", + "dweb:/ipfs/QmWYtWcqTszbsZ6tJTg6GcDWdWdGcnNkALBgzRpYPL3EH7" ] }, "metadata": { @@ -12715,10 +12724,10 @@ }, "sources": { "FeePool.sol": { - "keccak256": "0xb89f33e39e3b4c3f010dd3f4ee922c00778b73845226e3edd97715ead2888cd5", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914", "urls": [ - "bzz-raw://f50538229bc9b24d1a27335c8735bf3f2ade7121798c896268025fbff68b9789", - "dweb:/ipfs/Qmaty5Nuxxu3kfLZmVUy3xVL7VrQSeRjpy8GHEcrqdBCr5" + "bzz-raw://d45068f4b97b8568117b6c095694b7270cad2b0337ea0c2b8b24550dfa93fdbc", + "dweb:/ipfs/QmWYtWcqTszbsZ6tJTg6GcDWdWdGcnNkALBgzRpYPL3EH7" ] } }, @@ -30959,6 +30968,696 @@ }, "version": 1 } + }, + "StakingRewards": { + "bytecode": "60806040526000600755600060085562093a8060095534801561002157600080fd5b506040516118453803806118458339818101604052608081101561004457600080fd5b5080516020820151604083015160609093015191929091836001600160a01b0381166100b7576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a15060016003556000546001600160a01b0316610166576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b600580546001600160a01b0393841661010002610100600160a81b0319909116179055600680549183166001600160a01b03199283161790556002805493909216921691909117905550611686806101bf6000396000f3fe608060405234801561001057600080fd5b50600436106101e45760003560e01c806372f702f31161010f578063a694fc3a116100a2578063d1af0c7d11610071578063d1af0c7d14610448578063df136d6514610450578063e9fad8ee14610458578063ebe2b12b14610460576101e4565b8063a694fc3a146103fe578063c8f33c911461041b578063cc1a378f14610423578063cd3daf9d14610440576101e4565b80638980f11f116100de5780638980f11f1461039c5780638b876347146103c85780638da5cb5b146103ee57806391b4ded9146103f6576101e4565b806372f702f31461037c57806379ba5097146103845780637b0a47ee1461038c57806380faa57d14610394576101e4565b80632e1a7d4d116101875780633fc6df6e116101565780633fc6df6e1461030e57806353a47bb7146103325780635c975abb1461033a57806370a0823114610356576101e4565b80632e1a7d4d146102c4578063386a9525146102e15780633c6b16ab146102e95780633d18b91214610306576101e4565b806316c38b3c116101c357806316c38b3c1461026f57806318160ddd1461028e57806319762143146102965780631c1f78eb146102bc576101e4565b80628cc262146101e95780630700037d146102215780631627540c14610247575b600080fd5b61020f600480360360208110156101ff57600080fd5b50356001600160a01b0316610468565b60408051918252519081900360200190f35b61020f6004803603602081101561023757600080fd5b50356001600160a01b03166104fe565b61026d6004803603602081101561025d57600080fd5b50356001600160a01b0316610510565b005b61026d6004803603602081101561028557600080fd5b5035151561056c565b61020f6105e6565b61026d600480360360208110156102ac57600080fd5b50356001600160a01b03166105ed565b61020f610617565b61026d600480360360208110156102da57600080fd5b5035610635565b61020f6107d7565b61026d600480360360208110156102ff57600080fd5b50356107dd565b61026d610a33565b610316610b71565b604080516001600160a01b039092168252519081900360200190f35b610316610b80565b610342610b8f565b604080519115158252519081900360200190f35b61020f6004803603602081101561036c57600080fd5b50356001600160a01b0316610b98565b610316610bb3565b61026d610bc2565b61020f610c7e565b61020f610c84565b61026d600480360360408110156103b257600080fd5b506001600160a01b038135169060200135610c9c565b61020f600480360360208110156103de57600080fd5b50356001600160a01b0316610d59565b610316610d6b565b61020f610d7a565b61026d6004803603602081101561041457600080fd5b5035610d80565b61020f610f5e565b61026d6004803603602081101561043957600080fd5b5035610f64565b61020f610fe7565b610316611041565b61020f611055565b61026d61105b565b61020f61107e565b6001600160a01b0381166000908152600d6020908152604080832054600c9092528220546104f891906104ec90670de0b6b3a7640000906104e0906104bb906104af610fe7565b9063ffffffff61108416565b6001600160a01b0388166000908152600f60205260409020549063ffffffff6110e116565b9063ffffffff61114116565b9063ffffffff6111ab16565b92915050565b600d6020526000908152604090205481565b610518611205565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b610574611205565b60055460ff161515811515141561058a576105e3565b6005805460ff1916821515179081905560ff16156105a757426004555b6005546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b600e545b90565b6105f5611205565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60006106306009546008546110e190919063ffffffff16565b905090565b600380546001019081905533610649610fe7565b600b55610654610c84565b600a556001600160a01b0381161561069b5761066f81610468565b6001600160a01b0382166000908152600d6020908152604080832093909355600b54600c909152919020555b600083116106e4576040805162461bcd60e51b8152602060048201526011602482015270043616e6e6f74207769746864726177203607c1b604482015290519081900360640190fd5b600e546106f7908463ffffffff61108416565b600e55336000908152600f602052604090205461071a908463ffffffff61108416565b336000818152600f6020526040902091909155600654610746916001600160a01b03909116908561124e565b60408051848152905133917f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5919081900360200190a25060035481146107d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b5050565b60095481565b6002546001600160a01b031633146108265760405162461bcd60e51b815260040180806020018281038252602a8152602001806115dd602a913960400191505060405180910390fd5b6000610830610fe7565b600b5561083b610c84565b600a556001600160a01b038116156108825761085681610468565b6001600160a01b0382166000908152600d6020908152604080832093909355600b54600c909152919020555b60075442106108a75760095461089f90839063ffffffff61114116565b6008556108f6565b6007546000906108bd904263ffffffff61108416565b905060006108d6600854836110e190919063ffffffff16565b6009549091506108f0906104e0868463ffffffff6111ab16565b60085550505b600554604080516370a0823160e01b8152306004820152905160009261010090046001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561094657600080fd5b505afa15801561095a573d6000803e3d6000fd5b505050506040513d602081101561097057600080fd5b505160095490915061098990829063ffffffff61114116565b60085411156109df576040805162461bcd60e51b815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015290519081900360640190fd5b42600a8190556009546109f8919063ffffffff6111ab16565b6007556040805184815290517fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9181900360200190a1505050565b600380546001019081905533610a47610fe7565b600b55610a52610c84565b600a556001600160a01b03811615610a9957610a6d81610468565b6001600160a01b0382166000908152600d6020908152604080832093909355600b54600c909152919020555b336000908152600d60205260409020548015610b1957336000818152600d6020526040812055600554610ae2916101009091046001600160a01b0316908363ffffffff61124e16565b60408051828152905133917fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486919081900360200190a25b505060035481146105e3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002546001600160a01b031681565b6001546001600160a01b031681565b60055460ff1681565b6001600160a01b03166000908152600f602052604090205490565b6006546001600160a01b031681565b6001546001600160a01b03163314610c0b5760405162461bcd60e51b815260040180806020018281038252603581526020018061151c6035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60085481565b60006007544210610c9757600754610630565b504290565b610ca4611205565b6006546001600160a01b0383811691161415610cf15760405162461bcd60e51b81526004018080602001828103825260218152602001806116316021913960400191505060405180910390fd5b600054610d11906001600160a01b0384811691168363ffffffff61124e16565b604080516001600160a01b03841681526020810183905281517f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa28929181900390910190a15050565b600c6020526000908152604090205481565b6000546001600160a01b031681565b60045481565b600380546001019081905560055460ff1615610dcd5760405162461bcd60e51b815260040180806020018281038252603c8152602001806115a1603c913960400191505060405180910390fd5b33610dd6610fe7565b600b55610de1610c84565b600a556001600160a01b03811615610e2857610dfc81610468565b6001600160a01b0382166000908152600d6020908152604080832093909355600b54600c909152919020555b60008311610e6e576040805162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b604482015290519081900360640190fd5b600e54610e81908463ffffffff6111ab16565b600e55336000908152600f6020526040902054610ea4908463ffffffff6111ab16565b336000818152600f6020526040902091909155600654610ed1916001600160a01b039091169030866112a5565b60408051848152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a25060035481146107d3576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600a5481565b610f6c611205565b6007544211610fac5760405162461bcd60e51b81526004018080602001828103825260588152602001806114c46058913960600191505060405180910390fd5b60098190556040805182815290517ffb46ca5a5e06d4540d6387b930a7c978bce0db5f449ec6b3f5d07c6e1d44f2d39181900360200190a150565b6000600e5460001415610ffd5750600b546105ea565b610630611032600e546104e0670de0b6b3a7640000611026600854611026600a546104af610c84565b9063ffffffff6110e116565b600b549063ffffffff6111ab16565b60055461010090046001600160a01b031681565b600b5481565b336000908152600f602052604090205461107490610635565b61107c610a33565b565b60075481565b6000828211156110db576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826110f0575060006104f8565b828202828482816110fd57fe5b041461113a5760405162461bcd60e51b81526004018080602001828103825260218152602001806115806021913960400191505060405180910390fd5b9392505050565b6000808211611197576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816111a257fe5b04949350505050565b60008282018381101561113a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000546001600160a01b0316331461107c5760405162461bcd60e51b815260040180806020018281038252602f815260200180611551602f913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526112a0908490611305565b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526112ff908590611305565b50505050565b611317826001600160a01b03166114bd565b611368576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106113a65780518252601f199092019160209182019101611387565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611408576040519150601f19603f3d011682016040523d82523d6000602084013e61140d565b606091505b509150915081611464576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156112ff5780806020019051602081101561148057600080fd5b50516112ff5760405162461bcd60e51b815260040180806020018281038252602a815260200180611607602a913960400191505060405180910390fd5b3b15159056fe50726576696f7573207265776172647320706572696f64206d75737420626520636f6d706c657465206265666f7265206368616e67696e6720746865206475726174696f6e20666f7220746865206e657720706572696f64596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e6572736869704f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e74726163742069732070617573656443616c6c6572206973206e6f742052657761726473446973747269627574696f6e20636f6e74726163745361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656443616e6e6f7420776974686472617720746865207374616b696e6720746f6b656ea265627a7a7231582005c1c4d787ed4117d99706d539a422c50d928e74cd456ccfd64dcca42841eb8964736f6c63430005100032", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_rewardsDistribution", + "type": "address" + }, + { + "internalType": "address", + "name": "_rewardsToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_stakingToken", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "bool", + "name": "isPaused", + "type": "bool" + } + ], + "name": "PauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Recovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "RewardAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "RewardPaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newDuration", + "type": "uint256" + } + ], + "name": "RewardsDurationUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Staked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "earned", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "exit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "getReward", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getRewardForDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lastPauseTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lastTimeRewardApplicable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "lastUpdateTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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": false, + "inputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "periodFinish", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + } + ], + "name": "recoverERC20", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "rewardPerToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "rewardPerTokenStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "rewardRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "rewardsDistribution", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "rewardsDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "rewardsToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "bool", + "name": "_paused", + "type": "bool" + } + ], + "name": "setPaused", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardsDistribution", + "type": "address" + } + ], + "name": "setRewardsDistribution", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_rewardsDuration", + "type": "uint256" + } + ], + "name": "setRewardsDuration", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "stakingToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userRewardPerTokenPaid", + "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" + } + ], + "source": { + "keccak256": "0x9841ea1c48ac32392a4bfd0ed581d0950963aa09e866407736fc8b2adb6a25dd", + "urls": [ + "bzz-raw://5140b93a58005ca48177234e633b53d8d1634d8a9d03672ca5e7bafa760c8342", + "dweb:/ipfs/QmTsD5urBFpTFz8i5AqNsX3U4Tw5BHRiq4eyjBEiiKkBL1" + ] + }, + "metadata": { + "compiler": { + "version": "0.5.16+commit.9c3226ce" + }, + "language": "Solidity", + "settings": { + "compilationTarget": { + "StakingRewards.sol": "StakingRewards" + }, + "evmVersion": "istanbul", + "libraries": {}, + "optimizer": { + "enabled": true, + "runs": 200 + }, + "remappings": [] + }, + "sources": { + "StakingRewards.sol": { + "keccak256": "0x9841ea1c48ac32392a4bfd0ed581d0950963aa09e866407736fc8b2adb6a25dd", + "urls": [ + "bzz-raw://5140b93a58005ca48177234e633b53d8d1634d8a9d03672ca5e7bafa760c8342", + "dweb:/ipfs/QmTsD5urBFpTFz8i5AqNsX3U4Tw5BHRiq4eyjBEiiKkBL1" + ] + } + }, + "version": 1 + } } } } diff --git a/publish/deployed/mainnet-ovm/params.json b/publish/deployed/mainnet-ovm/params.json index ee856ec252..579ffad2e1 100644 --- a/publish/deployed/mainnet-ovm/params.json +++ b/publish/deployed/mainnet-ovm/params.json @@ -32,14 +32,5 @@ "INTERACTION_DELAY": "0", "COLLAPSE_FEE_RATE": "0" } - }, - { - "name": "COLLATERAL_ETH", - "value": { - "SYNTHS": ["sUSD"], - "MIN_CRATIO": "1200000000000000000", - "MIN_COLLATERAL": "100000000000000000", - "ISSUE_FEE_RATE": "0" - } } ] diff --git a/publish/deployed/mainnet-ovm/rewards.json b/publish/deployed/mainnet-ovm/rewards.json index fe51488c70..1391bc3bd2 100644 --- a/publish/deployed/mainnet-ovm/rewards.json +++ b/publish/deployed/mainnet-ovm/rewards.json @@ -1 +1,12 @@ -[] +[ + { + "name": "sUSDDAIUniswapV3", + "stakingToken": "0x88ccdbba89e073c5dc08b9c84dfc1fdc152c0dac", + "rewardsToken": "ProxyERC20" + }, + { + "name": "SNXWETHUniswapV3", + "stakingToken": "0x83beefb4ca39af649d03969b442c0e9f4e1732d8", + "rewardsToken": "ProxyERC20" + } +] diff --git a/publish/deployed/mainnet-ovm/versions.json b/publish/deployed/mainnet-ovm/versions.json index b1a2558460..36508843f4 100644 --- a/publish/deployed/mainnet-ovm/versions.json +++ b/publish/deployed/mainnet-ovm/versions.json @@ -581,8 +581,9 @@ "contracts": { "FeePool": { "address": "0xbc12131c93Da011B2844FA76c373A8cf5b0db4B5", - "status": "current", - "keccak256": "0xb89f33e39e3b4c3f010dd3f4ee922c00778b73845226e3edd97715ead2888cd5" + "status": "replaced", + "keccak256": "0xb89f33e39e3b4c3f010dd3f4ee922c00778b73845226e3edd97715ead2888cd5", + "replaced_in": "v2.57.1" }, "WrapperFactory": { "address": "0x27be2EFAd45DeBd732C1EBf5C9F7b49D498D4a93", @@ -610,5 +611,20 @@ "keccak256": "0xd83c3667bcacd4d33cf0fc649cee03d85e7d3914abb7ce6c9898e6ee1d66da81" } } + }, + "v2.57.1": { + "tag": "v2.57.1", + "fulltag": "v2.57.1", + "release": "Peacock", + "network": "mainnet", + "date": "2022-01-19T13:57:54-08:00", + "commit": "a13d8b6fc913901b542a7db01729930930495543", + "contracts": { + "FeePool": { + "address": "0xFDf3Be612c65464AEB4859047350a6220F304F52", + "status": "current", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914" + } + } } } diff --git a/publish/deployed/mainnet/deployment.json b/publish/deployed/mainnet/deployment.json index 2faa3ddc2f..6c99c407d5 100644 --- a/publish/deployed/mainnet/deployment.json +++ b/publish/deployed/mainnet/deployment.json @@ -29,11 +29,11 @@ }, "FeePool": { "name": "FeePool", - "address": "0xc398406FFfBEd5B0680e706634490062CB1DB579", + "address": "0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd", "source": "FeePool", - "link": "https://etherscan.io/address/0xc398406FFfBEd5B0680e706634490062CB1DB579", - "timestamp": "2021-11-16T18:47:58.000Z", - "txn": "https://etherscan.io/tx/0xa78df7d0c41537c664f0db651d7190b64a5733a8919aec2e9d93c99f23db32bd", + "link": "https://etherscan.io/address/0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd", + "timestamp": "2022-01-18T20:26:24.000Z", + "txn": "https://etherscan.io/tx/0x52c785f93a5b076568c12936a604c99e4e5454656e322f1a23f0febd4db9be0a", "network": "mainnet" }, "ProxyFeePool": { @@ -6649,7 +6649,7 @@ ] }, "FeePool": { - "bytecode": "6080604052631cd554d160e21b6007553480156200001c57600080fd5b506040516200472c3803806200472c8339810160408190526200003f9162000221565b8080621baf8085856001600160a01b038116620000795760405162461bcd60e51b8152600401620000709062000343565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620000c69184906200030b565b60405180910390a1506000546001600160a01b0316620000fa5760405162461bcd60e51b8152600401620000709062000331565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9062000147908390620002fb565b60405180910390a1504201600455600580546001600160a01b0319166001600160a01b0392909216919091179055506001620001846000620001e2565b80546001600160401b0319166001600160401b039290921691909117905542620001af6000620001e2565b80546001600160401b0392909216600160801b02600160801b600160c01b0319909216919091179055506200039e915050565b60006008600260ff16836012540181620001f857fe5b06600281106200020457fe5b6005020192915050565b80516200021b8162000384565b92915050565b6000806000606084860312156200023757600080fd5b60006200024586866200020e565b935050602062000258868287016200020e565b92505060406200026b868287016200020e565b9150509250925092565b620002808162000370565b82525050565b62000280816200035e565b6000620002a060118362000355565b7013dddb995c881b5d5cdd081899481cd95d607a1b815260200192915050565b6000620002cf60198362000355565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b602081016200021b828462000275565b604081016200031b828562000275565b6200032a602083018462000286565b9392505050565b602080825281016200021b8162000291565b602080825281016200021b81620002c0565b90815260200190565b60006001600160a01b0382166200021b565b60006200021b8260006200021b826200035e565b6200038f816200035e565b81146200039b57600080fd5b50565b61437e80620003ae6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80636de813f111610145578063b410a034116100bd578063d67bdd251161008c578063eb1edd6111610071578063eb1edd611461045c578063ec55688914610464578063fd1f498d1461046c57610241565b8063d67bdd251461044c578063e0e6393d1461045457610241565b8063b410a03414610414578063bc67f8321461041c578063cff2ddad1461042f578063d294f0931461044457610241565b8063899ffef41161011457806397107d6d116100f957806397107d6d146103e6578063ac834193146103f9578063b10090b81461040157610241565b8063899ffef4146103c95780638da5cb5b146103de57610241565b80636de813f11461039e57806374185360146103a657806379ba5097146103ae57806386645274146103b657610241565b806333140016116101d857806353a47bb7116101a757806359a2f19f1161018c57806359a2f19f14610370578063614d08f8146103835780636466f45e1461038b57610241565b806353a47bb714610353578063569249d01461036857610241565b806333140016146102fd5780633ebc457a1461031d5780633fcd22401461032557806346ba2d901461034b57610241565b80631627540c116102145780631627540c146102b857806322425fa4146102cd57806322bf55ef146102d55780632af64bd3146102e857610241565b806304f3bcec1461024657806307ea50cd146102645780630813071c146102845780630de5861514610297575b600080fd5b61024e61047f565b60405161025b9190614023565b60405180910390f35b610277610272366004613262565b61048e565b60405161025b9190613f40565b6102776102923660046132a6565b610563565b6102aa6102a5366004613262565b6106af565b60405161025b929190613f5c565b6102cb6102c6366004613262565b610731565b005b61027761078f565b6102cb6102e3366004613387565b61079f565b6102f0610978565b60405161025b9190613f32565b61031061030b366004613262565b610aa8565b60405161025b9190613f13565b6102cb610d0c565b610338610333366004613387565b611112565b60405161025b97969594939291906141c0565b6102776111bb565b61035b6111c1565b60405161025b9190613e40565b6102776111d0565b6102f061037e366004613262565b61122b565b61027761123d565b6102f0610399366004613262565b611261565b61027761138d565b6102cb6113e2565b6102cb611534565b6102cb6103c43660046132e0565b6115d0565b6103d1611710565b60405161025b9190613f21565b61035b611a30565b6102cb6103f4366004613262565b611a3f565b610277611a92565b6102cb61040f366004613405565b611b32565b610277611d2c565b6102cb61042a366004613262565b611d36565b610437611d60565b60405161025b9190614228565b6102f0611d65565b61035b611ddc565b610277611deb565b61035b611df5565b61024e611e0d565b6102cb61047a366004613387565b611e1c565b6005546001600160a01b031681565b6000610498611e99565b6001600160a01b031663bdc963d87f6c6173745f6665655f7769746864726177616c00000000000000000000000000846040516020016104d9929190613dce565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161050b9190613f40565b60206040518083038186803b15801561052357600080fd5b505afa158015610537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061055b919081019061334b565b90505b919050565b60008161058b5760405162461bcd60e51b815260040161058290614192565b60405180910390fd5b600282106105ab5760405162461bcd60e51b815260040161058290614142565b6105b760018303611ec4565b5468010000000000000000900467ffffffffffffffff166105da575060006106a9565b600061060a60016105ed60018603611ec4565b5468010000000000000000900467ffffffffffffffff1690611eee565b9050600080610617611f16565b6001600160a01b031663d29c000a87856040518363ffffffff1660e01b8152600401610644929190613e92565b604080518083038186803b15801561065b57600080fd5b505afa15801561066f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061069391908101906133d5565b90925090506106a3838383611f41565b93505050505b92915050565b6000806106ba61317a565b6106c384610aa8565b905060008060015b6002811015610724576106f08482600281106106e357fe5b602002015151849061208c565b925061071a84826002811061070157fe5b602002015160016020020151839063ffffffff61208c16565b91506001016106cb565b509093509150505b915091565b6107396120b1565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610784908390613e40565b60405180910390a150565b60006107996120dd565b90505b90565b60006107a96121a4565b6001600160a01b0316331490506000806107c16121cf565b6001600160a01b03166316b2213f336040518263ffffffff1660e01b81526004016107ec9190613e4e565b60206040518083038186803b15801561080457600080fd5b505afa158015610818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061083c919081019061334b565b14159050600061084a6121e3565b6001600160a01b031663b38988f7336040518263ffffffff1660e01b81526004016108759190613e4e565b60206040518083038186803b15801561088d57600080fd5b505afa1580156108a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108c5919081019061332d565b905060006108d161220e565b6001600160a01b0316336001600160a01b031614905060006108f1612239565b6001600160a01b0316336001600160a01b031614905084806109105750835b806109185750825b806109205750815b806109285750805b6109445760405162461bcd60e51b815260040161058290614042565b610962866109526000611ec4565b600101549063ffffffff61208c16565b61096c6000611ec4565b60010155505050505050565b60006060610984611710565b905060005b8151811015610a9f5760008282815181106109a057fe5b602090810291909101810151600081815260069092526040918290205460055492517f21f8a7210000000000000000000000000000000000000000000000000000000081529193506001600160a01b039081169216906321f8a72190610a0a908590600401613f40565b60206040518083038186803b158015610a2257600080fd5b505afa158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a5a9190810190613288565b6001600160a01b0316141580610a8557506000818152600660205260409020546001600160a01b0316155b15610a96576000935050505061079c565b50600101610989565b50600191505090565b610ab061317a565b6000806000610abd611f16565b6040517fb326f84e0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0382169063b326f84e90610b08908890600090600401613e77565b604080518083038186803b158015610b1f57600080fd5b505afa158015610b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b5791908101906133d5565b909350915081158015610b68575082155b15610b8057610b7561317a565b935061055e92505050565b600080610b8f60008686612264565b8751829052875160200181905290925090506000610bac8861048e565b905060015b8015610d005760001981016000610bc782611ec4565b5468010000000000000000900467ffffffffffffffff1690508015801590610c015750610bf383611ec4565b5467ffffffffffffffff1684105b15610cf5576000610c1982600163ffffffff611eee16565b6040517fd29c000a0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0389169063d29c000a90610c63908f908590600401613e92565b604080518083038186803b158015610c7a57600080fd5b505afa158015610c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610cb291908101906133d5565b909a509850610cc2848b8b612264565b9097509550868b8560028110610cd457fe5b602002015152858b8560028110610ce757fe5b602002015160016020020152505b505060001901610bb1565b50505050505050919050565b610d14612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015610d4c57600080fd5b505afa158015610d60573d6000803e3d6000fd5b505050506000610d6e6120dd565b11610d8b5760405162461bcd60e51b8152600401610582906141a2565b610d936120dd565b4203610d9f6000611ec4565b54600160801b900467ffffffffffffffff161115610dcf5760405162461bcd60e51b815260040161058290614062565b610dd761220e565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e1157600080fd5b505af1158015610e25573d6000803e3d6000fd5b50505050610e31612239565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e6b57600080fd5b505af1158015610e7f573d6000803e3d6000fd5b5060009250610e919150829050611ec4565b90506000610e9f6001611ec4565b9050610ed08260010154610ec483600201548460010154611eee90919063ffffffff16565b9063ffffffff61208c16565b610eda6000611ec4565b60010155600380830154600483015491830154610f0192610ec4919063ffffffff611eee16565b610f0b6000611ec4565b60030155601254610f4890600290610f3c90600190610f30908463ffffffff61208c16565b9063ffffffff611eee16565b9063ffffffff61233116565b601281905560089060028110610f5a57fe5b6005020180547fffffffffffffffff000000000000000000000000000000000000000000000000168155600060018083018290556002830182905560038301829055600490920155610fc690610faf81611ec4565b5467ffffffffffffffff169063ffffffff61208c16565b610fd06000611ec4565b805467ffffffffffffffff191667ffffffffffffffff92909216919091179055610ff8612361565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561103057600080fd5b505afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611068919081019061334b565b6110726000611ec4565b805467ffffffffffffffff9290921668010000000000000000026fffffffffffffffff000000000000000019909216919091179055426110b26000611ec4565b805467ffffffffffffffff92909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905561110e6110fe6001611ec4565b5467ffffffffffffffff1661238c565b5050565b60008060008060008060006111256131a7565b61112e89611ec4565b6040805160e081018252825467ffffffffffffffff808216808452680100000000000000008304821660208501819052600160801b909304909116938301849052600185015460608401819052600286015460808501819052600387015460a0860181905260049097015460c0909501859052919f929e50939c50929a5091985091965090945092505050565b60045481565b6001546001600160a01b031681565b60008060015b6002811015611225576111fc6111eb82611ec4565b60010154839063ffffffff61208c16565b915061121b61120a82611ec4565b60020154839063ffffffff611eee16565b91506001016111d6565b50905090565b600061123682612444565b5092915050565b7f466565506f6f6c0000000000000000000000000000000000000000000000000081565b600061126b612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156112a357600080fd5b505afa1580156112b7573d6000803e3d6000fd5b505050506112c3612538565b6112cb612577565b6003546040517f21f4ae570000000000000000000000000000000000000000000000000000000081526001600160a01b03928316926321f4ae579261131892879290911690600401613e5c565b60206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611368919081019061332d565b6113845760405162461bcd60e51b8152600401610582906140e2565b61055b826125a2565b60008060015b6002811015611225576113b96113a882611ec4565b60030154839063ffffffff61208c16565b91506113d86113c782611ec4565b60040154839063ffffffff611eee16565b9150600101611393565b60606113ec611710565b905060005b815181101561110e57600082828151811061140857fe5b602002602001015190506000600560009054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200161144a9190613e2a565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611476929190613f6a565b60206040518083038186803b15801561148e57600080fd5b505afa1580156114a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114c69190810190613288565b6000838152600660205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906115229084908490613f4e565b60405180910390a150506001016113f1565b6001546001600160a01b0316331461155e5760405162461bcd60e51b815260040161058290614052565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c926115a1926001600160a01b0391821692911690613e5c565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006115da6121cf565b6001600160a01b0316336001600160a01b031614905060006115fa612361565b6001600160a01b0316336001600160a01b031614905081806116195750805b6116355760405162461bcd60e51b815260040161058290614182565b61163d611f16565b6001600160a01b03166394e1a4488686866116586000611ec4565b5460405160e086901b7fffffffff000000000000000000000000000000000000000000000000000000001681526116ab9493929168010000000000000000900467ffffffffffffffff1690600401613ed5565b600060405180830381600087803b1580156116c557600080fd5b505af11580156116d9573d6000803e3d6000fd5b505050506117098585856116ed6000611ec4565b5468010000000000000000900467ffffffffffffffff16612697565b5050505050565b60608061171b612766565b60408051600d8082526101c0820190925291925060609190602082016101a0803883390190505090507f53797374656d53746174757300000000000000000000000000000000000000008160008151811061177257fe5b6020026020010181815250507f53796e7468657469780000000000000000000000000000000000000000000000816001815181106117ac57fe5b6020026020010181815250507f466565506f6f6c53746174650000000000000000000000000000000000000000816002815181106117e657fe5b6020026020010181815250507f466565506f6f6c457465726e616c53746f7261676500000000000000000000008160038151811061182057fe5b6020026020010181815250507f45786368616e67657200000000000000000000000000000000000000000000008160048151811061185a57fe5b6020026020010181815250506524b9b9bab2b960d11b8160058151811061187d57fe5b6020026020010181815250507f53796e7468657469785374617465000000000000000000000000000000000000816006815181106118b757fe5b6020026020010181815250507f526577617264457363726f775632000000000000000000000000000000000000816007815181106118f157fe5b6020026020010181815250507f44656c6567617465417070726f76616c730000000000000000000000000000008160088151811061192b57fe5b6020026020010181815250507f52657761726473446973747269627574696f6e000000000000000000000000008160098151811061196557fe5b6020026020010181815250507f436f6c6c61746572616c4d616e6167657200000000000000000000000000000081600a8151811061199f57fe5b6020026020010181815250507f57726170706572466163746f727900000000000000000000000000000000000081600b815181106119d957fe5b6020026020010181815250507f457468657257726170706572000000000000000000000000000000000000000081600c81518110611a1357fe5b602002602001018181525050611a2982826127c5565b9250505090565b6000546001600160a01b031681565b611a476120b1565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e90610784908390613e4e565b6000610799611b1e611aa261287a565b73__$f9217daff40bcb29719cec84f7ab900933$__63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611ae657600080fd5b505af4158015611afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ec4919081019061334b565b611b266128f1565b9063ffffffff61296816565b611b3a612992565b6004544210611b5b5760405162461bcd60e51b815260040161058290614152565b611b63612361565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b9b57600080fd5b505afa158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611bd3919081019061334b565b861115611bf25760405162461bcd60e51b815260040161058290614132565b6040518060e001604052808867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018667ffffffffffffffff168152602001858152602001848152602001838152602001828152506008611c62600260ff16610f3c8c60125461208c90919063ffffffff16565b60028110611c6c57fe5b82516005919091029190910180546020840151604085015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff000000000000000019166801000000000000000091851691909102177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b9390911692909202919091178155606082015160018201556080820151600282015560a0820151600382015560c0909101516004909101555050505050505050565b60006107996128f1565b611d3e612a00565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600281565b6000611d6f612306565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611da757600080fd5b505afa158015611dbb573d6000803e3d6000fd5b50505050611dc7612538565b600354610799906001600160a01b03166125a2565b6003546001600160a01b031681565b600061079961287a565b73feefeefeefeefeefeefeefeefeefeefeefeefeef81565b6002546001600160a01b031681565b6000611e26612a2a565b6003549091506001600160a01b0380831691161480611e4d5750336001600160a01b038216145b611e695760405162461bcd60e51b8152600401610582906140f2565b611e8782611e776000611ec4565b600301549063ffffffff61208c16565b611e916000611ec4565b600301555050565b60006107997f466565506f6f6c457465726e616c53746f726167650000000000000000000000612a51565b60006008600260ff16836012540181611ed957fe5b0660028110611ee457fe5b6005020192915050565b600082821115611f105760405162461bcd60e51b815260040161058290614092565b50900390565b60006107997f466565506f6f6c53746174650000000000000000000000000000000000000000612a51565b600080611f4c612361565b9050600061208085612074846001600160a01b03166308d95cd5886040518263ffffffff1660e01b8152600401611f839190613f40565b60206040518083038186803b158015611f9b57600080fd5b505afa158015611faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611fd3919081019061334b565b6040517f08d95cd50000000000000000000000000000000000000000000000000000000081526001600160a01b038716906308d95cd590612018908d90600401613f40565b60206040518083038186803b15801561203057600080fd5b505afa158015612044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612068919081019061334b565b9063ffffffff612aae16565b9063ffffffff612ac716565b925050505b9392505050565b6000828201838110156120855760405162461bcd60e51b815260040161058290614082565b6000546001600160a01b031633146120db5760405162461bcd60e51b815260040161058290614102565b565b60006120e7612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f666565506572696f644475726174696f6e0000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b60206040518083038186803b15801561216c57600080fd5b505afa158015612180573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610799919081019061334b565b60006107997f45786368616e6765720000000000000000000000000000000000000000000000612a51565b60006107996524b9b9bab2b960d11b612a51565b60006107997f436f6c6c61746572616c4d616e61676572000000000000000000000000000000612a51565b60006107997f4574686572577261707065720000000000000000000000000000000000000000612a51565b60006107997f57726170706572466163746f7279000000000000000000000000000000000000612a51565b60008083612277575060009050806122fe565b8385156122a257600061229160016105ed60018a03611ec4565b905061229e818787611f41565b9150505b60006122c1826122b189611ec4565b600101549063ffffffff61296816565b905060006122e2836122d28a611ec4565b600301549063ffffffff61296816565b90506122ed82612b0b565b6122f682612b0b565b945094505050505b935093915050565b60006107997f53797374656d5374617475730000000000000000000000000000000000000000612a51565b6000816123505760405162461bcd60e51b8152600401610582906140d2565b81838161235957fe5b069392505050565b60006107997f53796e7468657469785374617465000000000000000000000000000000000000612a51565b6002546040516001600160a01b039091169063907dff97906123b2908490602001613f40565b60405160208183030381529060405260016040516123cf90613e35565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261241693929160009081908190600401613f8a565b600060405180830381600087803b15801561243057600080fd5b505af1158015611709573d6000803e3d6000fd5b6000806000806124526121cf565b6001600160a01b031663ae3bbbbb866040518263ffffffff1660e01b815260040161247d9190613e40565b604080518083038186803b15801561249457600080fd5b505afa1580156124a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124cc91908101906133a5565b9150915060006124da6128f1565b9050808310156124f2575060019350915061072c9050565b600061250f612502611aa261287a565b839063ffffffff61296816565b90508084111561252957600083955095505050505061072c565b50600194509092505050915091565b6002546001600160a01b0316331480159061255e57506003546001600160a01b03163314155b156120db57600380546001600160a01b03191633179055565b60006107997f44656c6567617465417070726f76616c73000000000000000000000000000000612a51565b60008080808080806125b388612444565b91509150816125d45760405162461bcd60e51b815260040161058290614112565b80156125f25760405162461bcd60e51b8152600401610582906140c2565b6125fb886106af565b90945092508315158061260e5750600083115b61262a5760405162461bcd60e51b8152600401610582906140b2565b612648886126386001611ec4565b5467ffffffffffffffff16612b2d565b83156126635761265784612be0565b94506126638886612cbc565b821561267e5761267283612e58565b955061267e8887612f32565b612689888688612fac565b506001979650505050505050565b6002546040516001600160a01b039091169063907dff97906126c1908690869086906020016141b2565b60405160208183030381529060405260026040516126de90613dff565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261272e9392916001600160a01b038b16906000908190600401613fe9565b600060405180830381600087803b15801561274857600080fd5b505af115801561275c573d6000803e3d6000fd5b5050505050505050565b604080516001808252818301909252606091602080830190803883390190505090507f466c657869626c6553746f726167650000000000000000000000000000000000816000815181106127b657fe5b60200260200101818152505090565b606081518351016040519080825280602002602001820160405280156127f5578160200160208202803883390190505b50905060005b83518110156128375783818151811061281057fe5b602002602001015182828151811061282457fe5b60209081029190910101526001016127fb565b5060005b82518110156112365782818151811061285057fe5b602002602001015182828651018151811061286757fe5b602090810291909101015260010161283b565b6000612884612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f7461726765745468726573686f6c6400000000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b60006128fb612ae0565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f69737375616e6365526174696f000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401612154929190613f5c565b6000670de0b6b3a7640000612983848463ffffffff61307116565b8161298a57fe5b049392505050565b6002546001600160a01b031633148015906129b857506003546001600160a01b03163314155b156129d057600380546001600160a01b031916331790555b6000546003546001600160a01b039081169116146120db5760405162461bcd60e51b815260040161058290614072565b6002546001600160a01b031633146120db5760405162461bcd60e51b815260040161058290614172565b60006107997f52657761726473446973747269627574696f6e000000000000000000000000005b60008181526006602090815260408083205490516001600160a01b039091169182151591612a8191869101613e0a565b604051602081830303815290604052906112365760405162461bcd60e51b81526004016105829190614031565b600061208583836b033b2e3c9fd0803ce80000006130ab565b600061208583836b033b2e3c9fd0803ce80000006130ef565b60006107997f466c657869626c6553746f726167650000000000000000000000000000000000612a51565b60006305f5e10082046005600a820610612b2357600a015b600a900492915050565b612b35611e99565b6001600160a01b0316633562fd207f6c6173745f6665655f7769746864726177616c0000000000000000000000000084604051602001612b76929190613dce565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b8152600401612baa929190613f5c565b600060405180830381600087803b158015612bc457600080fd5b505af1158015612bd8573d6000803e3d6000fd5b505050505050565b6000818160015b6002811015612cb4576000612bfb82611ec4565b6002015490506000612c2082612c1085611ec4565b600101549063ffffffff611eee16565b90508015612ca9576000858210612c375785612c39565b815b9050612c4b838263ffffffff61208c16565b612c5485611ec4565b60020155612c68868263ffffffff611eee16565b9550612c7a858263ffffffff61208c16565b945085612c8f5784965050505050505061055e565b83158015612c9d5750600086115b15612ca757600095505b505b505060001901612be7565b509392505050565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612cfa5760405162461bcd60e51b815260040161058290614162565b6000612d046121cf565b6001600160a01b031663326080396007546040518263ffffffff1660e01b8152600401612d319190613f40565b60206040518083038186803b158015612d4957600080fd5b505afa158015612d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d819190810190613369565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081529091506001600160a01b03821690639dc29fac90612ddf9073feefeefeefeefeefeefeefeefeefeefeefeefeef908790600401613e92565b600060405180830381600087803b158015612df957600080fd5b505af1158015612e0d573d6000803e3d6000fd5b50506040517f867904b40000000000000000000000000000000000000000000000000000000081526001600160a01b038416925063867904b4915061272e9087908790600401613e92565b6000818160015b6002811015612cb4576000612e93612e7683611ec4565b60040154612e8384611ec4565b600301549063ffffffff611eee16565b90508015612f28576000848210612eaa5784612eac565b815b9050612ecb81612ebb85611ec4565b600401549063ffffffff61208c16565b612ed484611ec4565b60040155612ee8858263ffffffff611eee16565b9450612efa848263ffffffff61208c16565b935084612f0e57839550505050505061055e565b82158015612f1c5750600085115b15612f2657600094505b505b5060001901612e5f565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612f705760405162461bcd60e51b815260040161058290614162565b6301dfe200612f7d61311a565b6001600160a01b0316631bb47b448585846040518463ffffffff1660e01b815260040161272e93929190613ead565b6002546040516001600160a01b039091169063907dff9790612fd690869086908690602001613ead565b6040516020818303038152906040526001604051612ff390613df4565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261303a93929160009081908190600401613f8a565b600060405180830381600087803b15801561305457600080fd5b505af1158015613068573d6000803e3d6000fd5b50505050505050565b600082613080575060006106a9565b8282028284828161308d57fe5b04146120855760405162461bcd60e51b815260040161058290614122565b6000806130d1846130c587600a870263ffffffff61307116565b9063ffffffff61314516565b90506005600a825b06106130e357600a015b600a9004949350505050565b600080600a8304613106868663ffffffff61307116565b8161310d57fe5b0490506005600a826130d9565b60006107997f526577617264457363726f775632000000000000000000000000000000000000612a51565b60008082116131665760405162461bcd60e51b8152600401610582906140a2565b600082848161317157fe5b04949350505050565b60405180604001604052806002905b613191613202565b8152602001906001900390816131895790505090565b6040518060e00160405280600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b80356106a981614309565b80516106a981614309565b80516106a981614320565b80516106a981614329565b80516106a981614332565b80356106a981614329565b60006020828403121561327457600080fd5b60006132808484613220565b949350505050565b60006020828403121561329a57600080fd5b6000613280848461322b565b600080604083850312156132b957600080fd5b60006132c58585613220565b92505060206132d685828601613257565b9150509250929050565b6000806000606084860312156132f557600080fd5b60006133018686613220565b935050602061331286828701613257565b925050604061332386828701613257565b9150509250925092565b60006020828403121561333f57600080fd5b60006132808484613236565b60006020828403121561335d57600080fd5b60006132808484613241565b60006020828403121561337b57600080fd5b6000613280848461324c565b60006020828403121561339957600080fd5b60006132808484613257565b600080604083850312156133b857600080fd5b60006133c48585613241565b92505060206132d685828601613236565b600080604083850312156133e857600080fd5b60006133f48585613241565b92505060206132d685828601613241565b600080600080600080600080610100898b03121561342257600080fd5b600061342e8b8b613257565b985050602061343f8b828c01613257565b97505060406134508b828c01613257565b96505060606134618b828c01613257565b95505060806134728b828c01613257565b94505060a06134838b828c01613257565b93505060c06134948b828c01613257565b92505060e06134a58b828c01613257565b9150509295985092959890939650565b60006134c183836135ab565b505060400190565b60006134d58383613600565b505060200190565b6134e681614289565b82525050565b6134e68161424f565b6134e66135018261424f565b6142e8565b61350f8161423c565b613519818461055e565b92506135248261079c565b8060005b83811015612bd857815161353c87826134b5565b965061354783614236565b925050600101613528565b600061355d82614242565b6135678185614246565b935061357283614236565b8060005b838110156135a057815161358a88826134c9565b975061359583614236565b925050600101613576565b509495945050505050565b6135b48161423c565b6135be818461055e565b92506135c98261079c565b8060005b83811015612bd85781516135e187826134c9565b96506135ec83614236565b9250506001016135cd565b6134e68161425a565b6134e68161079c565b6134e66136158261079c565b61079c565b600061362582614242565b61362f8185614246565b935061363f8185602086016142b8565b613648816142f9565b9093019392505050565b6134e68161425f565b6134e681614294565b6134e6816142a2565b600061367a601783614246565b7f4f6e6c7920496e7465726e616c20436f6e747261637473000000000000000000815260200192915050565b60006136b3603583614246565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015260400192915050565b6000613712601d83614246565b7f546f6f206561726c7920746f20636c6f73652066656520706572696f64000000815260200192915050565b600061374b601383614246565b7f4f776e6572206f6e6c792066756e6374696f6e00000000000000000000000000815260200192915050565b600061378460248361055e565b7f46656573436c61696d656428616464726573732c75696e743235362c75696e7481527f3235362900000000000000000000000000000000000000000000000000000000602082015260240192915050565b60006137e360378361055e565b7f49737375616e636544656274526174696f456e74727928616464726573732c7581527f696e743235362c75696e743235362c75696e7432353629000000000000000000602082015260370192915050565b6000613842601b83614246565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061387b601e83614246565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b60006138b4601a83614246565b7f536166654d6174683a206469766973696f6e206279207a65726f000000000000815260200192915050565b60006138ed604083614246565b7f4e6f2066656573206f72207265776172647320617661696c61626c6520666f7281527f20706572696f642c206f72206665657320616c726561647920636c61696d6564602082015260400192915050565b600061394c60118361055e565b7f4d697373696e6720616464726573733a20000000000000000000000000000000815260110192915050565b6000613985601e83614246565b7f412073796e7468206f7220534e58207261746520697320696e76616c69640000815260200192915050565b60006139be601883614246565b7f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815260200192915050565b60006139f7601f83614246565b7f4e6f7420617070726f76656420746f20636c61696d206f6e20626568616c6600815260200192915050565b6000613a30601e83614246565b7f43616c6c6572206973206e6f742072657761726473417574686f726974790000815260200192915050565b6000613a69602f83614246565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015260400192915050565b6000613ac8601f83614246565b7f432d526174696f2062656c6f772070656e616c7479207468726573686f6c6400815260200192915050565b6000613b01602183614246565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613b60601683614246565b7f43616e6e6f7420696d706f727420626164206461746100000000000000000000815260200192915050565b6000613b99601d83614246565b7f4578636565647320746865204645455f504552494f445f4c454e475448000000815260200192915050565b6000613bd2602983614246565b7f43616e206f6e6c7920706572666f726d207468697320616374696f6e2064757281527f696e672073657475700000000000000000000000000000000000000000000000602082015260400192915050565b6000613c3160198361055e565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000613c6a601783614246565b7f4665652061646472657373206e6f7420616c6c6f776564000000000000000000815260200192915050565b6000613ca360188361055e565b7f466565506572696f64436c6f7365642875696e74323536290000000000000000815260180192915050565b6000613cdc601783614246565b7f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000815260200192915050565b6000613d15601e83614246565b7f49737375657220616e642053796e7468657469785374617465206f6e6c790000815260200192915050565b6000613d4e602083614246565b7f43757272656e7420706572696f64206973206e6f7420636c6f73656420796574815260200192915050565b6000613d87601b83614246565b7f46656520506572696f64204475726174696f6e206e6f74207365740000000000815260200192915050565b6134e6816142ad565b6134e681614276565b6134e681614283565b6000613dda8285613609565b602082019150613dea82846134f5565b5060140192915050565b60006106a982613777565b60006106a9826137d6565b6000613e158261393f565b9150613e218284613609565b50602001919050565b6000613e1582613c24565b60006106a982613c96565b602081016106a982846134ec565b602081016106a982846134dd565b60408101613e6a82856134ec565b61208560208301846134ec565b60408101613e8582856134ec565b6120856020830184613664565b60408101613ea082856134ec565b6120856020830184613600565b60608101613ebb82866134ec565b613ec86020830185613600565b6132806040830184613600565b60808101613ee382876134ec565b613ef06020830186613600565b613efd6040830185613600565b613f0a6060830184613db3565b95945050505050565b608081016106a98284613506565b602080825281016120858184613552565b602081016106a982846135f7565b602081016106a98284613600565b60408101613e6a8285613600565b60408101613ea08285613600565b60408101613f788285613600565b8181036020830152613280818461361a565b60c08082528101613f9b818961361a565b9050613faa6020830188613664565b613fb76040830187613600565b613fc4606083018661365b565b613fd1608083018561365b565b613fde60a083018461365b565b979650505050505050565b60c08082528101613ffa818961361a565b90506140096020830188613664565b6140166040830187613600565b613fc46060830186613600565b602081016106a98284613652565b60208082528101612085818461361a565b6020808252810161055b8161366d565b6020808252810161055b816136a6565b6020808252810161055b81613705565b6020808252810161055b8161373e565b6020808252810161055b81613835565b6020808252810161055b8161386e565b6020808252810161055b816138a7565b6020808252810161055b816138e0565b6020808252810161055b81613978565b6020808252810161055b816139b1565b6020808252810161055b816139ea565b6020808252810161055b81613a23565b6020808252810161055b81613a5c565b6020808252810161055b81613abb565b6020808252810161055b81613af4565b6020808252810161055b81613b53565b6020808252810161055b81613b8c565b6020808252810161055b81613bc5565b6020808252810161055b81613c5d565b6020808252810161055b81613ccf565b6020808252810161055b81613d08565b6020808252810161055b81613d41565b6020808252810161055b81613d7a565b60608101613ebb8286613600565b60e081016141ce828a613dbc565b6141db6020830189613dbc565b6141e86040830188613dbc565b6141f56060830187613600565b6142026080830186613600565b61420f60a0830185613600565b61421c60c0830184613600565b98975050505050505050565b602081016106a98284613dc5565b60200190565b50600290565b5190565b90815260200190565b600061055b8261426a565b151590565b600061055b8261424f565b6001600160a01b031690565b67ffffffffffffffff1690565b60ff1690565b600061055b8261425f565b600061055b6136158361079c565b600061055b8261079c565b600061055b82614276565b60005b838110156142d35781810151838201526020016142bb565b838111156142e2576000848401525b50505050565b600061055b82600061055b82614303565b601f01601f191690565b60601b90565b6143128161424f565b811461431d57600080fd5b50565b6143128161425a565b6143128161079c565b6143128161425f56fea365627a7a7231582023fb25e610f0e82a8e13a44599008ec503839a1c5669bf3ffe153f41941fe4c36c6578706572696d656e74616cf564736f6c63430005100040", + "bytecode": "6080604052631cd554d160e21b6007553480156200001c57600080fd5b506040516200471b3803806200471b8339810160408190526200003f9162000221565b8080621baf8085856001600160a01b038116620000795760405162461bcd60e51b8152600401620000709062000343565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620000c69184906200030b565b60405180910390a1506000546001600160a01b0316620000fa5760405162461bcd60e51b8152600401620000709062000331565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e9062000147908390620002fb565b60405180910390a1504201600455600580546001600160a01b0319166001600160a01b0392909216919091179055506001620001846000620001e2565b80546001600160401b0319166001600160401b039290921691909117905542620001af6000620001e2565b80546001600160401b0392909216600160801b02600160801b600160c01b0319909216919091179055506200039e915050565b60006008600260ff16836012540181620001f857fe5b06600281106200020457fe5b6005020192915050565b80516200021b8162000384565b92915050565b6000806000606084860312156200023757600080fd5b60006200024586866200020e565b935050602062000258868287016200020e565b92505060406200026b868287016200020e565b9150509250925092565b620002808162000370565b82525050565b62000280816200035e565b6000620002a060118362000355565b7013dddb995c881b5d5cdd081899481cd95d607a1b815260200192915050565b6000620002cf60198362000355565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b602081016200021b828462000275565b604081016200031b828562000275565b6200032a602083018462000286565b9392505050565b602080825281016200021b8162000291565b602080825281016200021b81620002c0565b90815260200190565b60006001600160a01b0382166200021b565b60006200021b8260006200021b826200035e565b6200038f816200035e565b81146200039b57600080fd5b50565b61436d80620003ae6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80636de813f111610145578063b410a034116100bd578063d67bdd251161008c578063eb1edd6111610071578063eb1edd611461045c578063ec55688914610464578063fd1f498d1461046c57610241565b8063d67bdd251461044c578063e0e6393d1461045457610241565b8063b410a03414610414578063bc67f8321461041c578063cff2ddad1461042f578063d294f0931461044457610241565b8063899ffef41161011457806397107d6d116100f957806397107d6d146103e6578063ac834193146103f9578063b10090b81461040157610241565b8063899ffef4146103c95780638da5cb5b146103de57610241565b80636de813f11461039e57806374185360146103a657806379ba5097146103ae57806386645274146103b657610241565b806333140016116101d857806353a47bb7116101a757806359a2f19f1161018c57806359a2f19f14610370578063614d08f8146103835780636466f45e1461038b57610241565b806353a47bb714610353578063569249d01461036857610241565b806333140016146102fd5780633ebc457a1461031d5780633fcd22401461032557806346ba2d901461034b57610241565b80631627540c116102145780631627540c146102b857806322425fa4146102cd57806322bf55ef146102d55780632af64bd3146102e857610241565b806304f3bcec1461024657806307ea50cd146102645780630813071c146102845780630de5861514610297575b600080fd5b61024e61047f565b60405161025b9190614012565b60405180910390f35b610277610272366004613251565b61048e565b60405161025b9190613f2f565b610277610292366004613295565b610563565b6102aa6102a5366004613251565b6106af565b60405161025b929190613f4b565b6102cb6102c6366004613251565b610731565b005b61027761078f565b6102cb6102e3366004613376565b61079f565b6102f0610978565b60405161025b9190613f21565b61031061030b366004613251565b610aa8565b60405161025b9190613f02565b6102cb610d0c565b610338610333366004613376565b611112565b60405161025b97969594939291906141af565b6102776111bb565b61035b6111c1565b60405161025b9190613e2f565b6102776111d0565b6102f061037e366004613251565b61122b565b61027761123d565b6102f0610399366004613251565b611261565b61027761138d565b6102cb6113e2565b6102cb611534565b6102cb6103c43660046132cf565b6115d0565b6103d1611710565b60405161025b9190613f10565b61035b611a30565b6102cb6103f4366004613251565b611a3f565b610277611a92565b6102cb61040f3660046133f4565b611b32565b610277611d2c565b6102cb61042a366004613251565b611d36565b610437611d60565b60405161025b9190614217565b6102f0611d65565b61035b611ddc565b610277611deb565b61035b611df5565b61024e611e0d565b6102cb61047a366004613376565b611e1c565b6005546001600160a01b031681565b6000610498611e88565b6001600160a01b031663bdc963d87f6c6173745f6665655f7769746864726177616c00000000000000000000000000846040516020016104d9929190613dbd565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161050b9190613f2f565b60206040518083038186803b15801561052357600080fd5b505afa158015610537573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061055b919081019061333a565b90505b919050565b60008161058b5760405162461bcd60e51b815260040161058290614181565b60405180910390fd5b600282106105ab5760405162461bcd60e51b815260040161058290614131565b6105b760018303611eb3565b5468010000000000000000900467ffffffffffffffff166105da575060006106a9565b600061060a60016105ed60018603611eb3565b5468010000000000000000900467ffffffffffffffff1690611edd565b9050600080610617611f05565b6001600160a01b031663d29c000a87856040518363ffffffff1660e01b8152600401610644929190613e81565b604080518083038186803b15801561065b57600080fd5b505afa15801561066f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061069391908101906133c4565b90925090506106a3838383611f30565b93505050505b92915050565b6000806106ba613169565b6106c384610aa8565b905060008060015b6002811015610724576106f08482600281106106e357fe5b602002015151849061207b565b925061071a84826002811061070157fe5b602002015160016020020151839063ffffffff61207b16565b91506001016106cb565b509093509150505b915091565b6107396120a0565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610784908390613e2f565b60405180910390a150565b60006107996120cc565b90505b90565b60006107a9612193565b6001600160a01b0316331490506000806107c16121be565b6001600160a01b03166316b2213f336040518263ffffffff1660e01b81526004016107ec9190613e3d565b60206040518083038186803b15801561080457600080fd5b505afa158015610818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061083c919081019061333a565b14159050600061084a6121d2565b6001600160a01b031663b38988f7336040518263ffffffff1660e01b81526004016108759190613e3d565b60206040518083038186803b15801561088d57600080fd5b505afa1580156108a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108c5919081019061331c565b905060006108d16121fd565b6001600160a01b0316336001600160a01b031614905060006108f1612228565b6001600160a01b0316336001600160a01b031614905084806109105750835b806109185750825b806109205750815b806109285750805b6109445760405162461bcd60e51b815260040161058290614031565b610962866109526000611eb3565b600101549063ffffffff61207b16565b61096c6000611eb3565b60010155505050505050565b60006060610984611710565b905060005b8151811015610a9f5760008282815181106109a057fe5b602090810291909101810151600081815260069092526040918290205460055492517f21f8a7210000000000000000000000000000000000000000000000000000000081529193506001600160a01b039081169216906321f8a72190610a0a908590600401613f2f565b60206040518083038186803b158015610a2257600080fd5b505afa158015610a36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a5a9190810190613277565b6001600160a01b0316141580610a8557506000818152600660205260409020546001600160a01b0316155b15610a96576000935050505061079c565b50600101610989565b50600191505090565b610ab0613169565b6000806000610abd611f05565b6040517fb326f84e0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0382169063b326f84e90610b08908890600090600401613e66565b604080518083038186803b158015610b1f57600080fd5b505afa158015610b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b5791908101906133c4565b909350915081158015610b68575082155b15610b8057610b75613169565b935061055e92505050565b600080610b8f60008686612253565b8751829052875160200181905290925090506000610bac8861048e565b905060015b8015610d005760001981016000610bc782611eb3565b5468010000000000000000900467ffffffffffffffff1690508015801590610c015750610bf383611eb3565b5467ffffffffffffffff1684105b15610cf5576000610c1982600163ffffffff611edd16565b6040517fd29c000a0000000000000000000000000000000000000000000000000000000081529091506001600160a01b0389169063d29c000a90610c63908f908590600401613e81565b604080518083038186803b158015610c7a57600080fd5b505afa158015610c8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610cb291908101906133c4565b909a509850610cc2848b8b612253565b9097509550868b8560028110610cd457fe5b602002015152858b8560028110610ce757fe5b602002015160016020020152505b505060001901610bb1565b50505050505050919050565b610d146122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015610d4c57600080fd5b505afa158015610d60573d6000803e3d6000fd5b505050506000610d6e6120cc565b11610d8b5760405162461bcd60e51b815260040161058290614191565b610d936120cc565b4203610d9f6000611eb3565b54600160801b900467ffffffffffffffff161115610dcf5760405162461bcd60e51b815260040161058290614051565b610dd76121fd565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e1157600080fd5b505af1158015610e25573d6000803e3d6000fd5b50505050610e31612228565b6001600160a01b031663bb57ad206040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e6b57600080fd5b505af1158015610e7f573d6000803e3d6000fd5b5060009250610e919150829050611eb3565b90506000610e9f6001611eb3565b9050610ed08260010154610ec483600201548460010154611edd90919063ffffffff16565b9063ffffffff61207b16565b610eda6000611eb3565b60010155600380830154600483015491830154610f0192610ec4919063ffffffff611edd16565b610f0b6000611eb3565b60030155601254610f4890600290610f3c90600190610f30908463ffffffff61207b16565b9063ffffffff611edd16565b9063ffffffff61232016565b601281905560089060028110610f5a57fe5b6005020180547fffffffffffffffff000000000000000000000000000000000000000000000000168155600060018083018290556002830182905560038301829055600490920155610fc690610faf81611eb3565b5467ffffffffffffffff169063ffffffff61207b16565b610fd06000611eb3565b805467ffffffffffffffff191667ffffffffffffffff92909216919091179055610ff8612350565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561103057600080fd5b505afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611068919081019061333a565b6110726000611eb3565b805467ffffffffffffffff9290921668010000000000000000026fffffffffffffffff000000000000000019909216919091179055426110b26000611eb3565b805467ffffffffffffffff92909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905561110e6110fe6001611eb3565b5467ffffffffffffffff1661237b565b5050565b6000806000806000806000611125613196565b61112e89611eb3565b6040805160e081018252825467ffffffffffffffff808216808452680100000000000000008304821660208501819052600160801b909304909116938301849052600185015460608401819052600286015460808501819052600387015460a0860181905260049097015460c0909501859052919f929e50939c50929a5091985091965090945092505050565b60045481565b6001546001600160a01b031681565b60008060015b6002811015611225576111fc6111eb82611eb3565b60010154839063ffffffff61207b16565b915061121b61120a82611eb3565b60020154839063ffffffff611edd16565b91506001016111d6565b50905090565b600061123682612433565b5092915050565b7f466565506f6f6c0000000000000000000000000000000000000000000000000081565b600061126b6122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b1580156112a357600080fd5b505afa1580156112b7573d6000803e3d6000fd5b505050506112c3612527565b6112cb612566565b6003546040517f21f4ae570000000000000000000000000000000000000000000000000000000081526001600160a01b03928316926321f4ae579261131892879290911690600401613e4b565b60206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611368919081019061331c565b6113845760405162461bcd60e51b8152600401610582906140e1565b61055b82612591565b60008060015b6002811015611225576113b96113a882611eb3565b60030154839063ffffffff61207b16565b91506113d86113c782611eb3565b60040154839063ffffffff611edd16565b9150600101611393565b60606113ec611710565b905060005b815181101561110e57600082828151811061140857fe5b602002602001015190506000600560009054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200161144a9190613e19565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611476929190613f59565b60206040518083038186803b15801561148e57600080fd5b505afa1580156114a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114c69190810190613277565b6000838152600660205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68906115229084908490613f3d565b60405180910390a150506001016113f1565b6001546001600160a01b0316331461155e5760405162461bcd60e51b815260040161058290614041565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c926115a1926001600160a01b0391821692911690613e4b565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006115da6121be565b6001600160a01b0316336001600160a01b031614905060006115fa612350565b6001600160a01b0316336001600160a01b031614905081806116195750805b6116355760405162461bcd60e51b815260040161058290614171565b61163d611f05565b6001600160a01b03166394e1a4488686866116586000611eb3565b5460405160e086901b7fffffffff000000000000000000000000000000000000000000000000000000001681526116ab9493929168010000000000000000900467ffffffffffffffff1690600401613ec4565b600060405180830381600087803b1580156116c557600080fd5b505af11580156116d9573d6000803e3d6000fd5b505050506117098585856116ed6000611eb3565b5468010000000000000000900467ffffffffffffffff16612686565b5050505050565b60608061171b612755565b60408051600d8082526101c0820190925291925060609190602082016101a0803883390190505090507f53797374656d53746174757300000000000000000000000000000000000000008160008151811061177257fe5b6020026020010181815250507f53796e7468657469780000000000000000000000000000000000000000000000816001815181106117ac57fe5b6020026020010181815250507f466565506f6f6c53746174650000000000000000000000000000000000000000816002815181106117e657fe5b6020026020010181815250507f466565506f6f6c457465726e616c53746f7261676500000000000000000000008160038151811061182057fe5b6020026020010181815250507f45786368616e67657200000000000000000000000000000000000000000000008160048151811061185a57fe5b6020026020010181815250506524b9b9bab2b960d11b8160058151811061187d57fe5b6020026020010181815250507f53796e7468657469785374617465000000000000000000000000000000000000816006815181106118b757fe5b6020026020010181815250507f526577617264457363726f775632000000000000000000000000000000000000816007815181106118f157fe5b6020026020010181815250507f44656c6567617465417070726f76616c730000000000000000000000000000008160088151811061192b57fe5b6020026020010181815250507f52657761726473446973747269627574696f6e000000000000000000000000008160098151811061196557fe5b6020026020010181815250507f436f6c6c61746572616c4d616e6167657200000000000000000000000000000081600a8151811061199f57fe5b6020026020010181815250507f57726170706572466163746f727900000000000000000000000000000000000081600b815181106119d957fe5b6020026020010181815250507f457468657257726170706572000000000000000000000000000000000000000081600c81518110611a1357fe5b602002602001018181525050611a2982826127b4565b9250505090565b6000546001600160a01b031681565b611a476120a0565b600280546001600160a01b0319166001600160a01b0383161790556040517ffc80377ca9c49cc11ae6982f390a42db976d5530af7c43889264b13fbbd7c57e90610784908390613e3d565b6000610799611b1e611aa2612869565b73__$f9217daff40bcb29719cec84f7ab900933$__63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015611ae657600080fd5b505af4158015611afa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ec4919081019061333a565b611b266128e0565b9063ffffffff61295716565b611b3a612981565b6004544210611b5b5760405162461bcd60e51b815260040161058290614141565b611b63612350565b6001600160a01b031663cd92eba96040518163ffffffff1660e01b815260040160206040518083038186803b158015611b9b57600080fd5b505afa158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611bd3919081019061333a565b861115611bf25760405162461bcd60e51b815260040161058290614121565b6040518060e001604052808867ffffffffffffffff1681526020018767ffffffffffffffff1681526020018667ffffffffffffffff168152602001858152602001848152602001838152602001828152506008611c62600260ff16610f3c8c60125461207b90919063ffffffff16565b60028110611c6c57fe5b82516005919091029190910180546020840151604085015167ffffffffffffffff1990921667ffffffffffffffff948516176fffffffffffffffff000000000000000019166801000000000000000091851691909102177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b9390911692909202919091178155606082015160018201556080820151600282015560a0820151600382015560c0909101516004909101555050505050505050565b60006107996128e0565b611d3e6129ef565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600281565b6000611d6f6122f5565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b158015611da757600080fd5b505afa158015611dbb573d6000803e3d6000fd5b50505050611dc7612527565b600354610799906001600160a01b0316612591565b6003546001600160a01b031681565b6000610799612869565b73feefeefeefeefeefeefeefeefeefeefeefeefeef81565b6002546001600160a01b031681565b611e24612527565b611e2c612a19565b6003546001600160a01b03908116911614611e595760405162461bcd60e51b8152600401610582906140b1565b611e7781611e676000611eb3565b600301549063ffffffff61207b16565b611e816000611eb3565b6003015550565b60006107997f466565506f6f6c457465726e616c53746f726167650000000000000000000000612a40565b60006008600260ff16836012540181611ec857fe5b0660028110611ed357fe5b6005020192915050565b600082821115611eff5760405162461bcd60e51b815260040161058290614081565b50900390565b60006107997f466565506f6f6c53746174650000000000000000000000000000000000000000612a40565b600080611f3b612350565b9050600061206f85612063846001600160a01b03166308d95cd5886040518263ffffffff1660e01b8152600401611f729190613f2f565b60206040518083038186803b158015611f8a57600080fd5b505afa158015611f9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611fc2919081019061333a565b6040517f08d95cd50000000000000000000000000000000000000000000000000000000081526001600160a01b038716906308d95cd590612007908d90600401613f2f565b60206040518083038186803b15801561201f57600080fd5b505afa158015612033573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612057919081019061333a565b9063ffffffff612a9d16565b9063ffffffff612ab616565b925050505b9392505050565b6000828201838110156120745760405162461bcd60e51b815260040161058290614071565b6000546001600160a01b031633146120ca5760405162461bcd60e51b8152600401610582906140f1565b565b60006120d6612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f666565506572696f644475726174696f6e0000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b60206040518083038186803b15801561215b57600080fd5b505afa15801561216f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610799919081019061333a565b60006107997f45786368616e6765720000000000000000000000000000000000000000000000612a40565b60006107996524b9b9bab2b960d11b612a40565b60006107997f436f6c6c61746572616c4d616e61676572000000000000000000000000000000612a40565b60006107997f4574686572577261707065720000000000000000000000000000000000000000612a40565b60006107997f57726170706572466163746f7279000000000000000000000000000000000000612a40565b60008083612266575060009050806122ed565b83851561229157600061228060016105ed60018a03611eb3565b905061228d818787611f30565b9150505b60006122b0826122a089611eb3565b600101549063ffffffff61295716565b905060006122d1836122c18a611eb3565b600301549063ffffffff61295716565b90506122dc82612afa565b6122e582612afa565b945094505050505b935093915050565b60006107997f53797374656d5374617475730000000000000000000000000000000000000000612a40565b60008161233f5760405162461bcd60e51b8152600401610582906140d1565b81838161234857fe5b069392505050565b60006107997f53796e7468657469785374617465000000000000000000000000000000000000612a40565b6002546040516001600160a01b039091169063907dff97906123a1908490602001613f2f565b60405160208183030381529060405260016040516123be90613e24565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261240593929160009081908190600401613f79565b600060405180830381600087803b15801561241f57600080fd5b505af1158015611709573d6000803e3d6000fd5b6000806000806124416121be565b6001600160a01b031663ae3bbbbb866040518263ffffffff1660e01b815260040161246c9190613e2f565b604080518083038186803b15801561248357600080fd5b505afa158015612497573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506124bb9190810190613394565b9150915060006124c96128e0565b9050808310156124e1575060019350915061072c9050565b60006124fe6124f1611aa2612869565b839063ffffffff61295716565b90508084111561251857600083955095505050505061072c565b50600194509092505050915091565b6002546001600160a01b0316331480159061254d57506003546001600160a01b03163314155b156120ca57600380546001600160a01b03191633179055565b60006107997f44656c6567617465417070726f76616c73000000000000000000000000000000612a40565b60008080808080806125a288612433565b91509150816125c35760405162461bcd60e51b815260040161058290614101565b80156125e15760405162461bcd60e51b8152600401610582906140c1565b6125ea886106af565b9094509250831515806125fd5750600083115b6126195760405162461bcd60e51b8152600401610582906140a1565b612637886126276001611eb3565b5467ffffffffffffffff16612b1c565b83156126525761264684612bcf565b94506126528886612cab565b821561266d5761266183612e47565b955061266d8887612f21565b612678888688612f9b565b506001979650505050505050565b6002546040516001600160a01b039091169063907dff97906126b0908690869086906020016141a1565b60405160208183030381529060405260026040516126cd90613dee565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261271d9392916001600160a01b038b16906000908190600401613fd8565b600060405180830381600087803b15801561273757600080fd5b505af115801561274b573d6000803e3d6000fd5b5050505050505050565b604080516001808252818301909252606091602080830190803883390190505090507f466c657869626c6553746f726167650000000000000000000000000000000000816000815181106127a557fe5b60200260200101818152505090565b606081518351016040519080825280602002602001820160405280156127e4578160200160208202803883390190505b50905060005b8351811015612826578381815181106127ff57fe5b602002602001015182828151811061281357fe5b60209081029190910101526001016127ea565b5060005b82518110156112365782818151811061283f57fe5b602002602001015182828651018151811061285657fe5b602090810291909101015260010161282a565b6000612873612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f7461726765745468726573686f6c6400000000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b60006128ea612acf565b6001600160a01b03166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f69737375616e6365526174696f000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401612143929190613f4b565b6000670de0b6b3a7640000612972848463ffffffff61306016565b8161297957fe5b049392505050565b6002546001600160a01b031633148015906129a757506003546001600160a01b03163314155b156129bf57600380546001600160a01b031916331790555b6000546003546001600160a01b039081169116146120ca5760405162461bcd60e51b815260040161058290614061565b6002546001600160a01b031633146120ca5760405162461bcd60e51b815260040161058290614161565b60006107997f52657761726473446973747269627574696f6e000000000000000000000000005b60008181526006602090815260408083205490516001600160a01b039091169182151591612a7091869101613df9565b604051602081830303815290604052906112365760405162461bcd60e51b81526004016105829190614020565b600061207483836b033b2e3c9fd0803ce800000061309a565b600061207483836b033b2e3c9fd0803ce80000006130de565b60006107997f466c657869626c6553746f726167650000000000000000000000000000000000612a40565b60006305f5e10082046005600a820610612b1257600a015b600a900492915050565b612b24611e88565b6001600160a01b0316633562fd207f6c6173745f6665655f7769746864726177616c0000000000000000000000000084604051602001612b65929190613dbd565b60405160208183030381529060405280519060200120836040518363ffffffff1660e01b8152600401612b99929190613f4b565b600060405180830381600087803b158015612bb357600080fd5b505af1158015612bc7573d6000803e3d6000fd5b505050505050565b6000818160015b6002811015612ca3576000612bea82611eb3565b6002015490506000612c0f82612bff85611eb3565b600101549063ffffffff611edd16565b90508015612c98576000858210612c265785612c28565b815b9050612c3a838263ffffffff61207b16565b612c4385611eb3565b60020155612c57868263ffffffff611edd16565b9550612c69858263ffffffff61207b16565b945085612c7e5784965050505050505061055e565b83158015612c8c5750600086115b15612c9657600095505b505b505060001901612bd6565b509392505050565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612ce95760405162461bcd60e51b815260040161058290614151565b6000612cf36121be565b6001600160a01b031663326080396007546040518263ffffffff1660e01b8152600401612d209190613f2f565b60206040518083038186803b158015612d3857600080fd5b505afa158015612d4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d709190810190613358565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081529091506001600160a01b03821690639dc29fac90612dce9073feefeefeefeefeefeefeefeefeefeefeefeefeef908790600401613e81565b600060405180830381600087803b158015612de857600080fd5b505af1158015612dfc573d6000803e3d6000fd5b50506040517f867904b40000000000000000000000000000000000000000000000000000000081526001600160a01b038416925063867904b4915061271d9087908790600401613e81565b6000818160015b6002811015612ca3576000612e82612e6583611eb3565b60040154612e7284611eb3565b600301549063ffffffff611edd16565b90508015612f17576000848210612e995784612e9b565b815b9050612eba81612eaa85611eb3565b600401549063ffffffff61207b16565b612ec384611eb3565b60040155612ed7858263ffffffff611edd16565b9450612ee9848263ffffffff61207b16565b935084612efd57839550505050505061055e565b82158015612f0b5750600085115b15612f1557600094505b505b5060001901612e4e565b816001600160a01b03811673feefeefeefeefeefeefeefeefeefeefeefeefeef1415612f5f5760405162461bcd60e51b815260040161058290614151565b6301dfe200612f6c613109565b6001600160a01b0316631bb47b448585846040518463ffffffff1660e01b815260040161271d93929190613e9c565b6002546040516001600160a01b039091169063907dff9790612fc590869086908690602001613e9c565b6040516020818303038152906040526001604051612fe290613de3565b6040519081900381207fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16825261302993929160009081908190600401613f79565b600060405180830381600087803b15801561304357600080fd5b505af1158015613057573d6000803e3d6000fd5b50505050505050565b60008261306f575060006106a9565b8282028284828161307c57fe5b04146120745760405162461bcd60e51b815260040161058290614111565b6000806130c0846130b487600a870263ffffffff61306016565b9063ffffffff61313416565b90506005600a825b06106130d257600a015b600a9004949350505050565b600080600a83046130f5868663ffffffff61306016565b816130fc57fe5b0490506005600a826130c8565b60006107997f526577617264457363726f775632000000000000000000000000000000000000612a40565b60008082116131555760405162461bcd60e51b815260040161058290614091565b600082848161316057fe5b04949350505050565b60405180604001604052806002905b6131806131f1565b8152602001906001900390816131785790505090565b6040518060e00160405280600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b80356106a9816142f8565b80516106a9816142f8565b80516106a98161430f565b80516106a981614318565b80516106a981614321565b80356106a981614318565b60006020828403121561326357600080fd5b600061326f848461320f565b949350505050565b60006020828403121561328957600080fd5b600061326f848461321a565b600080604083850312156132a857600080fd5b60006132b4858561320f565b92505060206132c585828601613246565b9150509250929050565b6000806000606084860312156132e457600080fd5b60006132f0868661320f565b935050602061330186828701613246565b925050604061331286828701613246565b9150509250925092565b60006020828403121561332e57600080fd5b600061326f8484613225565b60006020828403121561334c57600080fd5b600061326f8484613230565b60006020828403121561336a57600080fd5b600061326f848461323b565b60006020828403121561338857600080fd5b600061326f8484613246565b600080604083850312156133a757600080fd5b60006133b38585613230565b92505060206132c585828601613225565b600080604083850312156133d757600080fd5b60006133e38585613230565b92505060206132c585828601613230565b600080600080600080600080610100898b03121561341157600080fd5b600061341d8b8b613246565b985050602061342e8b828c01613246565b975050604061343f8b828c01613246565b96505060606134508b828c01613246565b95505060806134618b828c01613246565b94505060a06134728b828c01613246565b93505060c06134838b828c01613246565b92505060e06134948b828c01613246565b9150509295985092959890939650565b60006134b0838361359a565b505060400190565b60006134c483836135ef565b505060200190565b6134d581614278565b82525050565b6134d58161423e565b6134d56134f08261423e565b6142d7565b6134fe8161422b565b613508818461055e565b92506135138261079c565b8060005b83811015612bc757815161352b87826134a4565b965061353683614225565b925050600101613517565b600061354c82614231565b6135568185614235565b935061356183614225565b8060005b8381101561358f57815161357988826134b8565b975061358483614225565b925050600101613565565b509495945050505050565b6135a38161422b565b6135ad818461055e565b92506135b88261079c565b8060005b83811015612bc75781516135d087826134b8565b96506135db83614225565b9250506001016135bc565b6134d581614249565b6134d58161079c565b6134d56136048261079c565b61079c565b600061361482614231565b61361e8185614235565b935061362e8185602086016142a7565b613637816142e8565b9093019392505050565b6134d58161424e565b6134d581614283565b6134d581614291565b6000613669601783614235565b7f4f6e6c7920496e7465726e616c20436f6e747261637473000000000000000000815260200192915050565b60006136a2603583614235565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527f2063616e20616363657074206f776e6572736869700000000000000000000000602082015260400192915050565b6000613701601d83614235565b7f546f6f206561726c7920746f20636c6f73652066656520706572696f64000000815260200192915050565b600061373a601383614235565b7f4f776e6572206f6e6c792066756e6374696f6e00000000000000000000000000815260200192915050565b600061377360248361055e565b7f46656573436c61696d656428616464726573732c75696e743235362c75696e7481527f3235362900000000000000000000000000000000000000000000000000000000602082015260240192915050565b60006137d260378361055e565b7f49737375616e636544656274526174696f456e74727928616464726573732c7581527f696e743235362c75696e743235362c75696e7432353629000000000000000000602082015260370192915050565b6000613831601b83614235565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061386a601e83614235565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b60006138a3601a83614235565b7f536166654d6174683a206469766973696f6e206279207a65726f000000000000815260200192915050565b60006138dc604083614235565b7f4e6f2066656573206f72207265776172647320617661696c61626c6520666f7281527f20706572696f642c206f72206665657320616c726561647920636c61696d6564602082015260400192915050565b600061393b60118361055e565b7f4d697373696e6720616464726573733a20000000000000000000000000000000815260110192915050565b6000613974601883614235565b7f52657761726473446973747269627574696f6e206f6e6c790000000000000000815260200192915050565b60006139ad601e83614235565b7f412073796e7468206f7220534e58207261746520697320696e76616c69640000815260200192915050565b60006139e6601883614235565b7f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815260200192915050565b6000613a1f601f83614235565b7f4e6f7420617070726f76656420746f20636c61696d206f6e20626568616c6600815260200192915050565b6000613a58602f83614235565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681527f6f726d207468697320616374696f6e0000000000000000000000000000000000602082015260400192915050565b6000613ab7601f83614235565b7f432d526174696f2062656c6f772070656e616c7479207468726573686f6c6400815260200192915050565b6000613af0602183614235565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f81527f7700000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000613b4f601683614235565b7f43616e6e6f7420696d706f727420626164206461746100000000000000000000815260200192915050565b6000613b88601d83614235565b7f4578636565647320746865204645455f504552494f445f4c454e475448000000815260200192915050565b6000613bc1602983614235565b7f43616e206f6e6c7920706572666f726d207468697320616374696f6e2064757281527f696e672073657475700000000000000000000000000000000000000000000000602082015260400192915050565b6000613c2060198361055e565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000613c59601783614235565b7f4665652061646472657373206e6f7420616c6c6f776564000000000000000000815260200192915050565b6000613c9260188361055e565b7f466565506572696f64436c6f7365642875696e74323536290000000000000000815260180192915050565b6000613ccb601783614235565b7f4f6e6c79207468652070726f78792063616e2063616c6c000000000000000000815260200192915050565b6000613d04601e83614235565b7f49737375657220616e642053796e7468657469785374617465206f6e6c790000815260200192915050565b6000613d3d602083614235565b7f43757272656e7420706572696f64206973206e6f7420636c6f73656420796574815260200192915050565b6000613d76601b83614235565b7f46656520506572696f64204475726174696f6e206e6f74207365740000000000815260200192915050565b6134d58161429c565b6134d581614265565b6134d581614272565b6000613dc982856135f8565b602082019150613dd982846134e4565b5060140192915050565b60006106a982613766565b60006106a9826137c5565b6000613e048261392e565b9150613e1082846135f8565b50602001919050565b6000613e0482613c13565b60006106a982613c85565b602081016106a982846134db565b602081016106a982846134cc565b60408101613e5982856134db565b61207460208301846134db565b60408101613e7482856134db565b6120746020830184613653565b60408101613e8f82856134db565b61207460208301846135ef565b60608101613eaa82866134db565b613eb760208301856135ef565b61326f60408301846135ef565b60808101613ed282876134db565b613edf60208301866135ef565b613eec60408301856135ef565b613ef96060830184613da2565b95945050505050565b608081016106a982846134f5565b602080825281016120748184613541565b602081016106a982846135e6565b602081016106a982846135ef565b60408101613e5982856135ef565b60408101613e8f82856135ef565b60408101613f6782856135ef565b818103602083015261326f8184613609565b60c08082528101613f8a8189613609565b9050613f996020830188613653565b613fa660408301876135ef565b613fb3606083018661364a565b613fc0608083018561364a565b613fcd60a083018461364a565b979650505050505050565b60c08082528101613fe98189613609565b9050613ff86020830188613653565b61400560408301876135ef565b613fb360608301866135ef565b602081016106a98284613641565b602080825281016120748184613609565b6020808252810161055b8161365c565b6020808252810161055b81613695565b6020808252810161055b816136f4565b6020808252810161055b8161372d565b6020808252810161055b81613824565b6020808252810161055b8161385d565b6020808252810161055b81613896565b6020808252810161055b816138cf565b6020808252810161055b81613967565b6020808252810161055b816139a0565b6020808252810161055b816139d9565b6020808252810161055b81613a12565b6020808252810161055b81613a4b565b6020808252810161055b81613aaa565b6020808252810161055b81613ae3565b6020808252810161055b81613b42565b6020808252810161055b81613b7b565b6020808252810161055b81613bb4565b6020808252810161055b81613c4c565b6020808252810161055b81613cbe565b6020808252810161055b81613cf7565b6020808252810161055b81613d30565b6020808252810161055b81613d69565b60608101613eaa82866135ef565b60e081016141bd828a613dab565b6141ca6020830189613dab565b6141d76040830188613dab565b6141e460608301876135ef565b6141f160808301866135ef565b6141fe60a08301856135ef565b61420b60c08301846135ef565b98975050505050505050565b602081016106a98284613db4565b60200190565b50600290565b5190565b90815260200190565b600061055b82614259565b151590565b600061055b8261423e565b6001600160a01b031690565b67ffffffffffffffff1690565b60ff1690565b600061055b8261424e565b600061055b6136048361079c565b600061055b8261079c565b600061055b82614265565b60005b838110156142c25781810151838201526020016142aa565b838111156142d1576000848401525b50505050565b600061055b82600061055b826142f2565b601f01601f191690565b60601b90565b6143018161423e565b811461430c57600080fd5b50565b61430181614249565b6143018161079c565b6143018161424e56fea365627a7a72315820311ca67b066d8aa30c5fc3e5d4e569051e36efc62ebf3c8ccc4f5172288bdb2b6c6578706572696d656e74616cf564736f6c63430005100040", "abi": [ { "inputs": [ @@ -7442,10 +7442,10 @@ } ], "source": { - "keccak256": "0x9e381069cb34a10eb54ca9fb651d514a2cbcdcb328adfe943956b9d759c5ebac", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914", "urls": [ - "bzz-raw://c8d6ae1feaa83b97ed46b18a34b336e2014ebbe064b07276bd35c33f8000aa71", - "dweb:/ipfs/QmUECjHzMVyjue53V4xAvbmXThvvxChgJg5FkVSZfs8Zam" + "bzz-raw://d45068f4b97b8568117b6c095694b7270cad2b0337ea0c2b8b24550dfa93fdbc", + "dweb:/ipfs/QmWYtWcqTszbsZ6tJTg6GcDWdWdGcnNkALBgzRpYPL3EH7" ] }, "metadata": { @@ -7467,10 +7467,10 @@ }, "sources": { "FeePool.sol": { - "keccak256": "0x9e381069cb34a10eb54ca9fb651d514a2cbcdcb328adfe943956b9d759c5ebac", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914", "urls": [ - "bzz-raw://c8d6ae1feaa83b97ed46b18a34b336e2014ebbe064b07276bd35c33f8000aa71", - "dweb:/ipfs/QmUECjHzMVyjue53V4xAvbmXThvvxChgJg5FkVSZfs8Zam" + "bzz-raw://d45068f4b97b8568117b6c095694b7270cad2b0337ea0c2b8b24550dfa93fdbc", + "dweb:/ipfs/QmWYtWcqTszbsZ6tJTg6GcDWdWdGcnNkALBgzRpYPL3EH7" ] } }, diff --git a/publish/deployed/mainnet/params.json b/publish/deployed/mainnet/params.json index 54a6aab3b2..55615d3800 100644 --- a/publish/deployed/mainnet/params.json +++ b/publish/deployed/mainnet/params.json @@ -1,4 +1,8 @@ [ + { + "name": "EXCHANGE_DYNAMIC_FEE_ROUNDS", + "value": "0" + }, { "name": "DEX_PRICE_AGGREGATOR", "value": "0xf120F029Ac143633d1942e48aE2Dfa2036C5786c" diff --git a/publish/deployed/mainnet/versions.json b/publish/deployed/mainnet/versions.json index d55965b4c7..2d04fb944d 100644 --- a/publish/deployed/mainnet/versions.json +++ b/publish/deployed/mainnet/versions.json @@ -3749,8 +3749,9 @@ }, "FeePool": { "address": "0xc398406FFfBEd5B0680e706634490062CB1DB579", - "status": "current", - "keccak256": "0x9e381069cb34a10eb54ca9fb651d514a2cbcdcb328adfe943956b9d759c5ebac" + "status": "replaced", + "keccak256": "0x9e381069cb34a10eb54ca9fb651d514a2cbcdcb328adfe943956b9d759c5ebac", + "replaced_in": "v2.57.1" }, "Synthetix": { "address": "0xDC01020857afbaE65224CfCeDb265d1216064c59", @@ -3915,5 +3916,20 @@ "keccak256": "0x77d6d75f0faee02ff7a6bae37e0aa47e6afb849484a1f4ea6794131ffc5c77b8" } } + }, + "v2.57.1": { + "tag": "v2.57.1", + "fulltag": "v2.57.1", + "release": "Peacock", + "network": "mainnet", + "date": "2022-01-19T13:57:54-08:00", + "commit": "a13d8b6fc913901b542a7db01729930930495543", + "contracts": { + "FeePool": { + "address": "0xF66d34426C10CE91cDBcd86F8e9594AfB83049bd", + "status": "current", + "keccak256": "0xdb500335962961757d10ccbded7e9de457824b4c2d428c8c9aa63f18a5ca3914" + } + } } } diff --git a/publish/releases.json b/publish/releases.json index 5eb764ab8b..de3d48d7fa 100644 --- a/publish/releases.json +++ b/publish/releases.json @@ -402,6 +402,11 @@ ], "released": "both" }, + { + "sip": 184, + "layer": "both", + "sources": ["Exchanger", "ExchangeRates", "SystemSettings"] + }, { "sip": 187, "layer": "both", @@ -441,6 +446,12 @@ "sip": 196, "layer": "both", "sources": ["ExchangeRates"] + }, + { + "sip": 200, + "layer": "both", + "sources": ["FeePool"], + "released": "both" } ], "releases": [ @@ -773,22 +784,22 @@ }, { "name": "Peacock", - "released": false, + "released": true, "version": { "major": 2, "minor": 57 }, - "sips": [] + "sips": [200] }, { "name": "Peacock (Optimism)", "ovm": true, - "released": false, + "released": true, "version": { "major": 2, "minor": 57 }, - "sips": [] + "sips": [200] }, { "name": "Alsephina", diff --git a/publish/src/Deployer.js b/publish/src/Deployer.js index b89db223ce..5c27f6eaec 100644 --- a/publish/src/Deployer.js +++ b/publish/src/Deployer.js @@ -48,7 +48,7 @@ class Deployer { // use the default owner when in a fork or in local mode and no private key supplied if ((useFork || network === 'local') && !privateKey) { - const ownerAddress = getUsers({ network, user: 'owner' }).address; // protocolDAO + const ownerAddress = getUsers({ network, useOvm, user: 'owner' }).address; this.signer = this.provider.getSigner(ownerAddress); this.signer.address = ownerAddress; } else { diff --git a/publish/src/commands/deploy-staking-rewards.js b/publish/src/commands/deploy-staking-rewards.js index 1ee18ce748..33baa93841 100644 --- a/publish/src/commands/deploy-staking-rewards.js +++ b/publish/src/commands/deploy-staking-rewards.js @@ -43,10 +43,11 @@ const deployStakingRewards = async ({ deploymentPath, privateKey, yes, + useOvm, dryRun = false, } = {}) => { ensureNetwork(network); - deploymentPath = deploymentPath || getDeploymentPathForNetwork({ network }); + deploymentPath = deploymentPath || getDeploymentPathForNetwork({ network, useOvm }); ensureDeploymentPath(deploymentPath); const { @@ -112,6 +113,7 @@ const deployStakingRewards = async ({ const { providerUrl, privateKey: envPrivateKey, explorerLinkPrefix } = loadConnections({ network, + useOvm, }); // allow local deployments to use the private key passed as a CLI option @@ -139,6 +141,7 @@ const deployStakingRewards = async ({ privateKey, providerUrl, dryRun, + useOvm, }); const { account } = deployer; @@ -308,6 +311,7 @@ module.exports = { '-v, --private-key [value]', 'The private key to deploy with (only works in local mode, otherwise set in .env).' ) + .option('-z, --use-ovm', 'Target deployment for the OVM (Optimism).') .option('-y, --yes', 'Dont prompt, just reply yes.') .action(deployStakingRewards), }; diff --git a/publish/src/commands/deploy/configure-system-settings.js b/publish/src/commands/deploy/configure-system-settings.js index 78efa75de7..819f54602d 100644 --- a/publish/src/commands/deploy/configure-system-settings.js +++ b/publish/src/commands/deploy/configure-system-settings.js @@ -368,6 +368,54 @@ module.exports = async ({ comment: 'Set the fee rate for burning sETH for ETH in the EtherWrapper (SIP-112)', }); + // SIP-184 Exchange Dynamic Fee Rate + const exchangeDynamicFeeThreshold = await getDeployParameter('EXCHANGE_DYNAMIC_FEE_THRESHOLD'); + await runStep({ + contract: 'SystemSettings', + target: SystemSettings, + read: 'exchangeDynamicFeeThreshold', + readTarget: previousSystemSettings, + expected: allowZeroOrUpdateIfNonZero(exchangeDynamicFeeThreshold), + write: 'setExchangeDynamicFeeThreshold', + writeArg: exchangeDynamicFeeThreshold, + comment: 'Set exchange dynamic fee threshold (SIP-184)', + }); + const exchangeDynamicFeeWeightDecay = await getDeployParameter( + 'EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY' + ); + await runStep({ + contract: 'SystemSettings', + target: SystemSettings, + read: 'exchangeDynamicFeeWeightDecay', + readTarget: previousSystemSettings, + expected: allowZeroOrUpdateIfNonZero(exchangeDynamicFeeWeightDecay), + write: 'setExchangeDynamicFeeWeightDecay', + writeArg: exchangeDynamicFeeWeightDecay, + comment: 'Set exchange dynamic fee weight decay (SIP-184)', + }); + const exchangeDynamicFeeRounds = await getDeployParameter('EXCHANGE_DYNAMIC_FEE_ROUNDS'); + await runStep({ + contract: 'SystemSettings', + target: SystemSettings, + read: 'exchangeDynamicFeeRounds', + readTarget: previousSystemSettings, + expected: allowZeroOrUpdateIfNonZero(exchangeDynamicFeeRounds), + write: 'setExchangeDynamicFeeRounds', + writeArg: exchangeDynamicFeeRounds, + comment: 'Set exchange dynamic fee rounds (SIP-184)', + }); + const exchangeMaxDynamicFee = await getDeployParameter('EXCHANGE_MAX_DYNAMIC_FEE'); + await runStep({ + contract: 'SystemSettings', + target: SystemSettings, + read: 'exchangeMaxDynamicFee', + readTarget: previousSystemSettings, + expected: allowZeroOrUpdateIfNonZero(exchangeMaxDynamicFee), + write: 'setExchangeMaxDynamicFee', + writeArg: exchangeMaxDynamicFee, + comment: 'Set exchange max dynamic fee (SIP-184)', + }); + // SIP-120 Atomic swap settings if (SystemSettings.atomicMaxVolumePerBlock) { // TODO (SIP-120): finish configuring new atomic exchange system settings diff --git a/test/contracts/BaseSynthetix.js b/test/contracts/BaseSynthetix.js index c9a78e39ca..18959c8ae1 100644 --- a/test/contracts/BaseSynthetix.js +++ b/test/contracts/BaseSynthetix.js @@ -820,6 +820,9 @@ contract('BaseSynthetix', async accounts => { }); it("should lock newly received synthetix if the user's collaterisation is too high", async () => { + // Disable Dynamic fee so that we can neglect it. + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); + // Set sEUR for purposes of this test await updateAggregatorRates(exchangeRates, [sEUR], [toUnit('0.75')]); await debtCache.takeDebtSnapshot(); @@ -860,6 +863,9 @@ contract('BaseSynthetix', async accounts => { }); it('should unlock synthetix when collaterisation ratio changes', async () => { + // Disable Dynamic fee so that we can neglect it. + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); + // prevent circuit breaker from firing by upping the threshold to factor 5 await systemSettings.setPriceDeviationThresholdFactor(toUnit('5'), { from: owner }); diff --git a/test/contracts/CollateralShort.js b/test/contracts/CollateralShort.js index 3e9afb874a..eb2c937cfa 100644 --- a/test/contracts/CollateralShort.js +++ b/test/contracts/CollateralShort.js @@ -59,6 +59,8 @@ contract('CollateralShort', async accounts => { }; const updateRatesWithDefaults = async () => { + const sBTC = toBytes32('sBTC'); + await updateAggregatorRates(exchangeRates, [sETH, sBTC], [100, 10000].map(toUnit)); }; diff --git a/test/contracts/DebtCache.js b/test/contracts/DebtCache.js index 438e780324..2b08083b50 100644 --- a/test/contracts/DebtCache.js +++ b/test/contracts/DebtCache.js @@ -297,7 +297,6 @@ contract('DebtCache', async accounts => { ['0.5', '1.25', '10', '200', '200', '200'].map(toUnit) ); - // set a 0.3% default exchange fee rate const exchangeFeeRate = toUnit('0.003'); await setExchangeFeeRateForSynths({ owner, @@ -989,6 +988,9 @@ contract('DebtCache', async accounts => { }); it('exchanging between synths updates sUSD debt total due to fees', async () => { + // Disable Dynamic fee so that we can neglect it. + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); + await systemSettings.setExchangeFeeRateForSynths( [sAUD, sUSD, sEUR], [toUnit(0.1), toUnit(0.1), toUnit(0.1)], @@ -1011,9 +1013,12 @@ contract('DebtCache', async accounts => { }); it('exchanging between synths updates debt properly when prices have changed', async () => { + // Zero exchange fees so that we can neglect them. await systemSettings.setExchangeFeeRateForSynths([sAUD, sUSD], [toUnit(0), toUnit(0)], { from: owner, }); + // Disable Dynamic fee so that we can neglect it. + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); await sEURContract.issue(account1, toUnit(20)); await debtCache.takeDebtSnapshot(); @@ -1035,9 +1040,13 @@ contract('DebtCache', async accounts => { }); it('settlement updates debt totals', async () => { + // Zero exchange fees so that we can neglect them. await systemSettings.setExchangeFeeRateForSynths([sAUD, sEUR], [toUnit(0), toUnit(0)], { from: owner, }); + // Disable Dynamic fee so that we can neglect it. + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); + await sAUDContract.issue(account1, toUnit(100)); await debtCache.takeDebtSnapshot(); diff --git a/test/contracts/DynamicFee.js b/test/contracts/DynamicFee.js new file mode 100644 index 0000000000..e10799661a --- /dev/null +++ b/test/contracts/DynamicFee.js @@ -0,0 +1,149 @@ +const { contract, artifacts } = require('hardhat'); +const { assert } = require('./common'); +const { toUnit, toBN } = require('../utils')(); +const SafeDecimalMath = artifacts.require('SafeDecimalMath'); +const TestableDynamicFee = artifacts.require('TestableDynamicFee'); + +contract('DynamicFee', accounts => { + const [, owner, account1] = accounts; + + let testableDynamicFee; + + const threshold = toUnit('0.004'); + const weightDecay = toUnit('0.9'); + + before(async () => { + const safeDecimalMath = await SafeDecimalMath.new(); + TestableDynamicFee.link(safeDecimalMath); + const addressResolver = account1; // is not important for these tests + testableDynamicFee = await TestableDynamicFee.new(owner, addressResolver); + }); + + it('Can get price differential', async () => { + const priceDiff1 = await testableDynamicFee.thresholdedAbsDeviationRatio( + toUnit('8'), + toUnit('10'), + threshold + ); + assert.bnEqual(priceDiff1, '196000000000000000'); + const priceDiff2 = await testableDynamicFee.thresholdedAbsDeviationRatio( + toUnit('12'), + toUnit('10'), + threshold + ); + assert.bnEqual(priceDiff2, '196000000000000000'); + assert.bnEqual(priceDiff1, priceDiff2); + }); + + it('Fee is similar to dynamic-fee-calc.csv rounds 22-11, all below threshold', async () => { + const prices = [ + toUnit('49535.05178912'), + toUnit('49714.05205647'), + toUnit('49691.8024553899'), + toUnit('49714.05205647'), + toUnit('49722.83886705'), + toUnit('49838.87627216'), + toUnit('49842.74988613'), + toUnit('49933.34034209'), + toUnit('49871.92313713'), + toUnit('49981'), + toUnit('49960.65493467'), + toUnit('49994'), + ]; + const dynamicFee = await testableDynamicFee.dynamicFeeCalculation( + prices, + threshold, + weightDecay + ); + assert.bnEqual(dynamicFee, '0'); + }); + + it('Fee is similar to dynamic-fee-calc.csv rounds 23-14, last one above threshold', async () => { + const prices = [ + toUnit('49234.65005734'), + toUnit('49535.05178912'), + toUnit('49714.05205647'), + toUnit('49691.8024553899'), + toUnit('49714.05205647'), + toUnit('49722.83886705'), + toUnit('49838.87627216'), + toUnit('49842.74988613'), + toUnit('49933.34034209'), + toUnit('49871.92313713'), + toUnit('49981'), + ]; + const dynamicFee = await testableDynamicFee.dynamicFeeCalculation( + prices, + threshold, + weightDecay + ); + assert.bnClose(dynamicFee, toUnit(20.6442753020364).div(toBN(10000)), 1e4); + }); + + it('Fee is similar to dynamic-fee-calc.csv rounds 32-22, first one above threshold', async () => { + const prices = [ + toUnit('49198.77'), + toUnit('49143.5399999999'), + toUnit('49096.77'), + toUnit('49131.10261767'), + toUnit('49088.63670793'), + toUnit('49046.17079819'), + toUnit('49088.63670793'), + toUnit('49234.65005734'), + toUnit('49190.99117585'), + toUnit('49234.65005734'), + toUnit('49535.05178912'), + ]; + const dynamicFee = await testableDynamicFee.dynamicFeeCalculation( + prices, + threshold, + weightDecay + ); + assert.bnClose(dynamicFee, toUnit(7.99801523256557).div(toBN(10000)), 1e4); + }); + + it('Fee is similar to dynamic-fee-calc.csv rounds 72-63, 70% above threshold', async () => { + const prices = [ + toUnit('44661.70868763'), + toUnit('44672.6561639399'), + toUnit('45483.8961602099'), + toUnit('45586.5085919099'), + toUnit('45919.00562933'), + toUnit('46183.17440371'), + toUnit('46217.7336139799'), + toUnit('46463.74676537'), + toUnit('46675.18493538'), + toUnit('46948.76815888'), + toUnit('47222.35138239'), + toUnit('47382.88726893'), + ]; + const dynamicFee = await testableDynamicFee.dynamicFeeCalculation( + prices, + threshold, + weightDecay + ); + assert.bnClose(dynamicFee, toUnit(183.663338097394).div(toBN(10000)), 1e4); + }); + + it('Fee is similar to dynamic-fee-calc.csv rounds 67-58, 50% above threshold', async () => { + const prices = [ + toUnit('46183.17440371'), + toUnit('46217.7336139799'), + toUnit('46463.74676537'), + toUnit('46675.18493538'), + toUnit('46948.76815888'), + toUnit('47222.35138239'), + toUnit('47382.88726893'), + toUnit('47449.76309439'), + toUnit('47580.67384441'), + toUnit('47670.81054939'), + toUnit('47911.8471578599'), + ]; + const dynamicFee = await testableDynamicFee.dynamicFeeCalculation( + prices, + threshold, + weightDecay + ); + assert.bnClose(dynamicFee, toUnit(45.0272321178039).div(toBN(10000)), 1e4); + }); +}); diff --git a/test/contracts/ExchangeRates.js b/test/contracts/ExchangeRates.js index c5a78a4cfb..7ef19f9ac6 100644 --- a/test/contracts/ExchangeRates.js +++ b/test/contracts/ExchangeRates.js @@ -949,7 +949,7 @@ contract('Exchange Rates', async accounts => { }); it('ratesAndUpdatedTimeForCurrencyLastNRounds() shows first entry for sUSD', async () => { - assert.deepEqual(await instance.ratesAndUpdatedTimeForCurrencyLastNRounds(sUSD, '3'), [ + assert.deepEqual(await instance.ratesAndUpdatedTimeForCurrencyLastNRounds(sUSD, '3', '0'), [ [toUnit('1'), '0', '0'], [0, 0, 0], ]); @@ -957,7 +957,7 @@ contract('Exchange Rates', async accounts => { it('ratesAndUpdatedTimeForCurrencyLastNRounds() returns 0s for other currencies without updates', async () => { const fiveZeros = new Array(5).fill('0'); await setupAggregators([sJPY]); - assert.deepEqual(await instance.ratesAndUpdatedTimeForCurrencyLastNRounds(sJPY, '5'), [ + assert.deepEqual(await instance.ratesAndUpdatedTimeForCurrencyLastNRounds(sJPY, '5', '0'), [ fiveZeros, fiveZeros, ]); @@ -1012,7 +1012,7 @@ contract('Exchange Rates', async accounts => { it('then it returns zeros', async () => { const fiveZeros = new Array(5).fill('0'); assert.deepEqual( - await instance.ratesAndUpdatedTimeForCurrencyLastNRounds(sAUD, '5'), + await instance.ratesAndUpdatedTimeForCurrencyLastNRounds(sAUD, '5', '0'), [fiveZeros, fiveZeros] ); }); @@ -1020,7 +1020,7 @@ contract('Exchange Rates', async accounts => { describe('when invoked for an aggregated price', () => { it('then it returns the rates as expected', async () => { assert.deepEqual( - await instance.ratesAndUpdatedTimeForCurrencyLastNRounds(sJPY, '3'), + await instance.ratesAndUpdatedTimeForCurrencyLastNRounds(sJPY, '3', '0'), [ [toUnit('102'), toUnit('101'), toUnit('100')], ['1002', '1001', '1000'], @@ -1030,7 +1030,7 @@ contract('Exchange Rates', async accounts => { it('then it returns the rates as expected, even over the edge', async () => { assert.deepEqual( - await instance.ratesAndUpdatedTimeForCurrencyLastNRounds(sJPY, '5'), + await instance.ratesAndUpdatedTimeForCurrencyLastNRounds(sJPY, '5', '0'), [ [toUnit('102'), toUnit('101'), toUnit('100'), '0', '0'], ['1002', '1001', '1000', '0', '0'], @@ -1111,7 +1111,7 @@ contract('Exchange Rates', async accounts => { }); }); - describe('effectiveValueAtRound()', () => { + describe('effectiveValueAndRatesAtRound()', () => { describe('when both aggregated prices have been given three rates with current timestamps', () => { beforeEach(async () => { await setupAggregators([sBNB]); @@ -1126,43 +1126,61 @@ contract('Exchange Rates', async accounts => { }); it('accepts various changes to src roundId', async () => { assert.bnEqual( - await instance.effectiveValueAtRound(sJPY, toUnit('1'), sBNB, '1', '1'), + ( + await instance.effectiveValueAndRatesAtRound(sJPY, toUnit('1'), sBNB, '1', '1') + )[0], toUnit('0.1') ); assert.bnEqual( - await instance.effectiveValueAtRound(sJPY, toUnit('1'), sBNB, '2', '1'), + ( + await instance.effectiveValueAndRatesAtRound(sJPY, toUnit('1'), sBNB, '2', '1') + )[0], toUnit('0.2') ); assert.bnEqual( - await instance.effectiveValueAtRound(sJPY, toUnit('1'), sBNB, '3', '1'), + ( + await instance.effectiveValueAndRatesAtRound(sJPY, toUnit('1'), sBNB, '3', '1') + )[0], toUnit('0.3') ); }); it('accepts various changes to dest roundId', async () => { assert.bnEqual( - await instance.effectiveValueAtRound(sJPY, toUnit('1'), sBNB, '1', '1'), + ( + await instance.effectiveValueAndRatesAtRound(sJPY, toUnit('1'), sBNB, '1', '1') + )[0], toUnit('0.1') ); assert.bnEqual( - await instance.effectiveValueAtRound(sJPY, toUnit('1'), sBNB, '1', '2'), + ( + await instance.effectiveValueAndRatesAtRound(sJPY, toUnit('1'), sBNB, '1', '2') + )[0], toUnit('0.05') ); assert.bnEqual( - await instance.effectiveValueAtRound(sJPY, toUnit('1'), sBNB, '1', '3'), + ( + await instance.effectiveValueAndRatesAtRound(sJPY, toUnit('1'), sBNB, '1', '3') + )[0], toUnit('0.025') ); }); it('and combinations therein', async () => { assert.bnEqual( - await instance.effectiveValueAtRound(sJPY, toUnit('1'), sBNB, '2', '2'), + ( + await instance.effectiveValueAndRatesAtRound(sJPY, toUnit('1'), sBNB, '2', '2') + )[0], toUnit('0.1') ); assert.bnEqual( - await instance.effectiveValueAtRound(sJPY, toUnit('1'), sBNB, '3', '3'), + ( + await instance.effectiveValueAndRatesAtRound(sJPY, toUnit('1'), sBNB, '3', '3') + )[0], toUnit('0.075') ); assert.bnEqual( - await instance.effectiveValueAtRound(sJPY, toUnit('1'), sBNB, '3', '2'), + ( + await instance.effectiveValueAndRatesAtRound(sJPY, toUnit('1'), sBNB, '3', '2') + )[0], toUnit('0.15') ); }); diff --git a/test/contracts/Exchanger.spec.js b/test/contracts/Exchanger.spec.js index 7164a8fbba..119fabd10c 100644 --- a/test/contracts/Exchanger.spec.js +++ b/test/contracts/Exchanger.spec.js @@ -5,7 +5,14 @@ const { smockit } = require('@eth-optimism/smock'); const BN = require('bn.js'); const { assert, addSnapshotBeforeRestoreAfterEach } = require('./common'); -const { currentTime, fastForward, multiplyDecimal, divideDecimal, toUnit } = require('../utils')(); +const { + currentTime, + fastForward, + multiplyDecimal, + divideDecimal, + toUnit, + toBN, +} = require('../utils')(); const { setupAllContracts } = require('./setup'); @@ -24,7 +31,15 @@ const { const { toBytes32, - defaults: { WAITING_PERIOD_SECS, PRICE_DEVIATION_THRESHOLD_FACTOR, ATOMIC_MAX_VOLUME_PER_BLOCK }, + defaults: { + WAITING_PERIOD_SECS, + PRICE_DEVIATION_THRESHOLD_FACTOR, + ATOMIC_MAX_VOLUME_PER_BLOCK, + EXCHANGE_DYNAMIC_FEE_ROUNDS, + EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY, + EXCHANGE_DYNAMIC_FEE_THRESHOLD, + EXCHANGE_MAX_DYNAMIC_FEE, + }, } = require('../..'); const bnCloseVariance = '30'; @@ -127,6 +142,9 @@ contract('Exchanger (spec tests)', async accounts => { let initialWaitingPeriod; beforeEach(async () => { + // disable dynamic fee here as it's testing settlement + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); + initialWaitingPeriod = await systemSettings.waitingPeriodSecs(); await systemSettings.setWaitingPeriodSecs('0', { from: owner }); }); @@ -209,6 +227,7 @@ contract('Exchanger (spec tests)', async accounts => { new web3.utils.BN(1), new web3.utils.BN(2), ], + bnCloseVariance, }); }); @@ -443,7 +462,7 @@ contract('Exchanger (spec tests)', async accounts => { const itCalculatesFeeRateForExchange = () => { describe('Given exchangeFeeRates are configured and when calling feeRateForExchange()', () => { it('for two long synths, returns the regular exchange fee', async () => { - const actualFeeRate = await exchanger.feeRateForExchange(sEUR, sBTC); + const actualFeeRate = (await exchanger.feeRateForExchange(sEUR, sBTC))[0]; assert.bnEqual(actualFeeRate, exchangeFeeRate, 'Rate must be the exchange fee rate'); }); }); @@ -488,7 +507,7 @@ contract('Exchanger (spec tests)', async accounts => { assert.bnEqual(destinationFee, exchangeFeeIncurred(effectiveValue, bipsCrypto)); }); it('then return the feeRate', async () => { - const exchangeFeeRate = await exchanger.feeRateForExchange(sUSD, sBTC); + const exchangeFeeRate = (await exchanger.feeRateForExchange(sUSD, sBTC))[0]; assert.bnEqual(feeRate, exchangeFeeRate); }); }); @@ -517,7 +536,7 @@ contract('Exchanger (spec tests)', async accounts => { assert.bnEqual(destinationFee, exchangeFeeIncurred(effectiveValue, bipsFX)); }); it('then return the feeRate', async () => { - const exchangeFeeRate = await exchanger.feeRateForExchange(sUSD, sEUR); + const exchangeFeeRate = (await exchanger.feeRateForExchange(sUSD, sEUR))[0]; assert.bnEqual(feeRate, exchangeFeeRate); }); }); @@ -560,6 +579,280 @@ contract('Exchanger (spec tests)', async accounts => { assert.bnEqual(amountReceived, effectiveValue.sub(tripleFee)); }); }); + + describe('dynamic fee when rates change', () => { + const threshold = toBN(EXCHANGE_DYNAMIC_FEE_THRESHOLD); + const maxDynamicFeeRate = toBN(EXCHANGE_MAX_DYNAMIC_FEE); + + it('initial fee is correct', async () => { + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sBTC), [bipsCrypto, false]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sBTC), [0, false]); + }); + + describe('fee is caluclated correctly when rates spike or drop', () => { + it('.3% spike is below threshold', async () => { + await updateRates([sETH], [toUnit(100.3)]); + // spike + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [bipsCrypto, false]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [0, false]); + // control + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sBTC), [bipsCrypto, false]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sBTC, sBTC), [0, false]); + }); + + it('.3% drop is below threshold', async () => { + await updateRates([sETH], [toUnit(99.7)]); + // spike + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [bipsCrypto, false]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [0, false]); + // control + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sBTC), [bipsCrypto, false]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sBTC, sBTC), [0, false]); + }); + + it('1% spike result in correct dynamic fee', async () => { + await updateRates([sETH], [toUnit(101)]); + // price diff ratio (1%)- threshold + const expectedDynamicFee = toUnit(0.01).sub(threshold); + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [ + bipsCrypto.add(expectedDynamicFee), + false, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [ + expectedDynamicFee, + false, + ]); + // control + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sBTC), [bipsCrypto, false]); + }); + + it('1% drop result in correct dynamic fee', async () => { + await updateRates([sETH], [toUnit(99)]); + // price diff ratio (1%)- threshold + const expectedDynamicFee = toUnit(0.01).sub(threshold); + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [ + bipsCrypto.add(expectedDynamicFee), + false, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [ + expectedDynamicFee, + false, + ]); + // control + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sBTC), [bipsCrypto, false]); + }); + + it('5% spike result in correct dynamic fee', async () => { + await updateRates([sETH], [toUnit(105)]); + // price diff ratio (5%)- threshold + const expectedDynamicFee = toUnit(0.05).sub(threshold); + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [ + bipsCrypto.add(expectedDynamicFee), + false, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [ + expectedDynamicFee, + false, + ]); + // control + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sBTC), [bipsCrypto, false]); + }); + + it('5% drop result in correct dynamic fee', async () => { + await updateRates([sETH], [toUnit(95)]); + // price diff ratio (5%)- threshold + const expectedDynamicFee = toUnit(0.05).sub(threshold); + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [ + bipsCrypto.add(expectedDynamicFee), + false, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [ + expectedDynamicFee, + false, + ]); + // control + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sBTC), [bipsCrypto, false]); + }); + + it('10% spike is over the max and is too volatile', async () => { + await updateRates([sETH], [toUnit(110)]); + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [ + bipsCrypto.add(maxDynamicFeeRate), + true, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [ + maxDynamicFeeRate, + true, + ]); + // view reverts + await assert.revert( + exchanger.getAmountsForExchange(toUnit('1'), sUSD, sETH), + 'too volatile' + ); + // control + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sBTC), [bipsCrypto, false]); + }); + + it('10% drop result in correct dynamic fee', async () => { + await updateRates([sETH], [toUnit(90)]); + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [ + bipsCrypto.add(maxDynamicFeeRate), + true, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [ + maxDynamicFeeRate, + true, + ]); + // view reverts + await assert.revert( + exchanger.getAmountsForExchange(toUnit('1'), sUSD, sETH), + 'too volatile' + ); + // control + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sBTC), [bipsCrypto, false]); + }); + + it('trading between two spiked rates is correctly calculated ', async () => { + await updateRates([sETH, sBTC], [toUnit(102), toUnit(5100)]); + // base fee + (price diff ratio (2%)- threshold) * 2 + const expectedDynamicFee = toUnit(0.02) + .sub(threshold) + .mul(toBN(2)); + assert.deepEqual(await exchanger.feeRateForExchange(sBTC, sETH), [ + bipsCrypto.add(expectedDynamicFee), + false, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sBTC, sETH), [ + expectedDynamicFee, + false, + ]); + // reverse direction is the same + assert.deepEqual(await exchanger.feeRateForExchange(sETH, sBTC), [ + bipsCrypto.add(expectedDynamicFee), + false, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sETH, sBTC), [ + expectedDynamicFee, + false, + ]); + }); + + it('trading between two spiked respects max fee and volatility flag', async () => { + // spike each 3% so that total dynamic fee is 6% which is more than the max + await updateRates([sETH, sBTC], [toUnit(103), toUnit(5150)]); + assert.deepEqual(await exchanger.feeRateForExchange(sBTC, sETH), [ + bipsCrypto.add(maxDynamicFeeRate), + true, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sBTC, sETH), [ + maxDynamicFeeRate, + true, + ]); + // reverse direction is the same + assert.deepEqual(await exchanger.feeRateForExchange(sETH, sBTC), [ + bipsCrypto.add(maxDynamicFeeRate), + true, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sETH, sBTC), [ + maxDynamicFeeRate, + true, + ]); + // view reverts + await assert.revert( + exchanger.getAmountsForExchange(toUnit('1'), sETH, sBTC), + 'too volatile' + ); + await assert.revert( + exchanger.getAmountsForExchange(toUnit('1'), sBTC, sETH), + 'too volatile' + ); + }); + }); + + it('no exchange happens when dynamic fee is too high', async () => { + await sETHContract.issue(account1, toUnit('10')); + + async function echangeSuccessful() { + // this should work + const txn = await synthetix.exchange(sETH, toUnit('1'), sUSD, { from: account1 }); + const logs = await getDecodedLogs({ + hash: txn.tx, + contracts: [synthetix, exchanger, systemStatus], + }); + // some exchange took place (this is just to control for correct assertion) + return logs.some(({ name } = {}) => name === 'SynthExchange'); + } + + // should work for no change + assert.ok(await echangeSuccessful()); + // view doesn't revert + await exchanger.getAmountsForExchange(toUnit('1'), sETH, sUSD); + + // spike the rate a little + await updateRates([sETH], [toUnit(103)]); + // should still work + assert.ok(await echangeSuccessful()); + // view doesn't revert + await exchanger.getAmountsForExchange(toUnit('1'), sETH, sUSD); + + // spike the rate too much + await updateRates([sETH], [toUnit(110)]); + // should not work now + assert.notOk(await echangeSuccessful()); + // view reverts + await assert.revert( + exchanger.getAmountsForExchange(toUnit('1'), sETH, sUSD), + 'too volatile' + ); + }); + + it('dynamic fee decays with time', async () => { + await updateRates([sETH], [toUnit(105)]); + // (price diff ratio (5%)- threshold) + let expectedDynamicFee = toUnit(0.05).sub(threshold); + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [ + bipsCrypto.add(expectedDynamicFee), + false, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [ + expectedDynamicFee, + false, + ]); + + const decay = toBN(EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY); + + // next round + await updateRates([sETH], [toUnit(105)]); + expectedDynamicFee = multiplyDecimal(expectedDynamicFee, decay); + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [ + bipsCrypto.add(expectedDynamicFee), + false, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [ + expectedDynamicFee, + false, + ]); + + // another round + await updateRates([sETH], [toUnit(105)]); + expectedDynamicFee = multiplyDecimal(expectedDynamicFee, decay); + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [ + bipsCrypto.add(expectedDynamicFee), + false, + ]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [ + expectedDynamicFee, + false, + ]); + + // EXCHANGE_DYNAMIC_FEE_ROUNDS after spike dynamic fee is 0 + for (let i = 0; i < EXCHANGE_DYNAMIC_FEE_ROUNDS - 3; i++) { + await updateRates([sETH], [toUnit(105)]); + } + assert.deepEqual(await exchanger.feeRateForExchange(sUSD, sETH), [bipsCrypto, false]); + assert.deepEqual(await exchanger.dynamicFeeRateForExchange(sUSD, sETH), [0, false]); + }); + }); }); }); }; @@ -615,6 +908,8 @@ contract('Exchanger (spec tests)', async accounts => { describe(`when ${section} is suspended`, () => { beforeEach(async () => { await setStatus({ owner, systemStatus, section, suspend: true, synth }); + // Disable Dynamic Fee here as settlement is L1 and Dynamic fee is on L2 + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); }); it('then calling settle() reverts', async () => { await assert.revert( @@ -660,6 +955,8 @@ contract('Exchanger (spec tests)', async accounts => { beforeEach(async () => { // set sUSD:sEUR as 2:1, sUSD:sETH at 100:1, sUSD:sBTC at 9000:1 await updateRates([sEUR, sETH, sBTC], ['2', '100', '9000'].map(toUnit)); + // Disable Dynamic Fee by setting rounds to 0 + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); }); describe('and the exchange fee rate is 1% for easier human consumption', () => { beforeEach(async () => { @@ -1860,7 +2157,12 @@ contract('Exchanger (spec tests)', async accounts => { it(`attempting to ${type} from sUSD into sAUD reverts with dest stale`, async () => { await assert.revert( exchange({ from: sUSD, amount: amountIssued, to: sAUD }), - 'Src/dest rate invalid or not found' + 'src/dest rate stale or flagged' + ); + // view reverts + await assert.revert( + exchanger.getAmountsForExchange(toUnit('1'), sUSD, sAUD), + 'stale' ); }); it('settling still works ', async () => { @@ -1883,7 +2185,7 @@ contract('Exchanger (spec tests)', async accounts => { it(`${type} back to sUSD fails as the source has no rate`, async () => { await assert.revert( exchange({ from: sAUD, amount: amountIssued, to: sUSD }), - 'Src/dest rate invalid or not found' + 'src/dest rate stale or flagged' ); }); }); @@ -2151,6 +2453,13 @@ contract('Exchanger (spec tests)', async accounts => { }); describe('when exchanging into that synth', () => { + it('getAmountsForExchange reverts due to invalid rate', async () => { + await assert.revert( + exchanger.getAmountsForExchange(toUnit('1'), sUSD, sETH), + 'synth rate invalid' + ); + }); + it('then it causes a suspension from price deviation as the price is 9', async () => { const { tx: hash } = await synthetix.exchange(sUSD, toUnit('1'), sETH, { from: account1, @@ -2168,6 +2477,12 @@ contract('Exchanger (spec tests)', async accounts => { const { suspended, reason } = await systemStatus.synthSuspension(sETH); assert.ok(suspended); assert.equal(reason, '65'); + + // check view reverts since synth is now suspended + await assert.revert( + exchanger.getAmountsForExchange(toUnit('1'), sUSD, sETH), + 'suspended' + ); }); }); describe('when exchanging out of that synth', () => { @@ -2175,6 +2490,12 @@ contract('Exchanger (spec tests)', async accounts => { // give the user some sETH await sETHContract.issue(account1, toUnit('1')); }); + it('getAmountsForExchange reverts due to invalid rate', async () => { + await assert.revert( + exchanger.getAmountsForExchange(toUnit('1'), sETH, sUSD), + 'synth rate invalid' + ); + }); it('then it causes a suspension from price deviation', async () => { // await assert.revert( const { tx: hash } = await synthetix.exchange(sETH, toUnit('1'), sUSD, { @@ -2193,6 +2514,12 @@ contract('Exchanger (spec tests)', async accounts => { const { suspended, reason } = await systemStatus.synthSuspension(sETH); assert.ok(suspended); assert.equal(reason, '65'); + + // check view reverts since synth is now suspended + await assert.revert( + exchanger.getAmountsForExchange(toUnit('1'), sETH, sUSD), + 'suspended' + ); }); }); }); @@ -2478,11 +2805,10 @@ contract('Exchanger (spec tests)', async accounts => { // CL aggregator with past price data const aggregator = await MockAggregator.new({ from: owner }); await exchangeRates.addAggregator(sETH, aggregator.address, { from: owner }); - // set prices with no valatility - await aggregator.setLatestAnswer(ethOnCL, (await currentTime()) - 20 * 60); - await aggregator.setLatestAnswer(ethOnCL, (await currentTime()) - 15 * 60); - await aggregator.setLatestAnswer(ethOnCL, (await currentTime()) - 10 * 60); - await aggregator.setLatestAnswer(ethOnCL, (await currentTime()) - 5 * 60); + // set prices with no volatility over the course of last 20 minutes + for (let i = 4; i > 0; i--) { + await aggregator.setLatestAnswer(ethOnCL, (await currentTime()) - i * 5 * 60); + } // DexPriceAggregator const dexPriceAggregator = await MockDexPriceAggregator.new(); @@ -2688,6 +3014,12 @@ contract('Exchanger (spec tests)', async accounts => { describe('priceSpikeDeviation', () => { const baseRate = 100; + beforeEach(async () => { + // disable dynamic fee here as it will not let trades get through at smaller deviations + // than required for suspension + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); + }); + const updateRate = ({ target, rate }) => { beforeEach(async () => { await fastForward(10); @@ -3046,6 +3378,8 @@ contract('Exchanger (spec tests)', async accounts => { describe('settlement ignores deviations', () => { describe('when a user exchange 100 sUSD into sETH', () => { beforeEach(async () => { + // Disable Dynamic Fee in settlement by setting rounds to 0 + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); await synthetix.exchange(sUSD, toUnit('100'), sETH, { from: account1 }); }); describe('and the sETH rate moves up by a factor of 2 to 200', () => { @@ -3332,6 +3666,9 @@ contract('Exchanger (spec tests)', async accounts => { const newCryptoBIPS = toUnit('0.04'); beforeEach(async () => { + // Disable Dynamic Fee here as it's testing for the base exchange fee rate + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); + // Store multiple rates await systemSettings.setExchangeFeeRateForSynths( [sUSD, sAUD, sBTC, sETH], @@ -3346,7 +3683,7 @@ contract('Exchanger (spec tests)', async accounts => { await systemSettings.setExchangeFeeRateForSynths([sUSD], [newFxBIPS], { from: owner, }); - const sUSDRate = await exchanger.feeRateForExchange(empty, sUSD); + const sUSDRate = (await exchanger.feeRateForExchange(empty, sUSD))[0]; assert.bnEqual(sUSDRate, newFxBIPS); }); @@ -3360,13 +3697,13 @@ contract('Exchanger (spec tests)', async accounts => { } ); // Read all rates - const sAUDRate = await exchanger.feeRateForExchange(empty, sAUD); + const sAUDRate = (await exchanger.feeRateForExchange(empty, sAUD))[0]; assert.bnEqual(sAUDRate, newFxBIPS); - const sUSDRate = await exchanger.feeRateForExchange(empty, sUSD); + const sUSDRate = (await exchanger.feeRateForExchange(empty, sUSD))[0]; assert.bnEqual(sUSDRate, newFxBIPS); - const sBTCRate = await exchanger.feeRateForExchange(empty, sBTC); + const sBTCRate = (await exchanger.feeRateForExchange(empty, sBTC))[0]; assert.bnEqual(sBTCRate, newCryptoBIPS); - const sETHRate = await exchanger.feeRateForExchange(empty, sETH); + const sETHRate = (await exchanger.feeRateForExchange(empty, sETH))[0]; assert.bnEqual(sETHRate, newCryptoBIPS); }); }); @@ -3443,7 +3780,6 @@ contract('Exchanger (spec tests)', async accounts => { await setupPriceAggregators(exchangeRates, owner, keys); await updateRates(keys, rates); - // set a 0.5% exchange fee rate (1/200) exchangeFeeRate = toUnit('0.005'); await setExchangeFeeRateForSynths({ owner, diff --git a/test/contracts/ExchangerWithFeeRecAlternatives.behaviors.js b/test/contracts/ExchangerWithFeeRecAlternatives.behaviors.js index edf64001fe..07734a921e 100644 --- a/test/contracts/ExchangerWithFeeRecAlternatives.behaviors.js +++ b/test/contracts/ExchangerWithFeeRecAlternatives.behaviors.js @@ -21,7 +21,8 @@ module.exports = function({ accounts }) { }); before(async () => { - ExchangerWithFeeRecAlternatives.link(await artifacts.require('SafeDecimalMath').new()); + const safeDecimalMath = await artifacts.require('SafeDecimalMath').new(); + ExchangerWithFeeRecAlternatives.link(safeDecimalMath); }); beforeEach(async () => { @@ -110,6 +111,14 @@ module.exports = function({ accounts }) { cb(); }); }, + whenMockedWithExchangeRatesValidityAtRound: ({ valid = true }, cb) => { + describe(`when mocked with ${valid ? 'valid' : 'invalid'} exchange rates`, () => { + beforeEach(async () => { + this.mocks.ExchangeRates.smocked.anyRateIsInvalidAtRound.will.return.with(!valid); + }); + cb(); + }); + }, whenMockedWithNoPriorExchangesToSettle: cb => { describe(`when mocked with no prior exchanges to settle`, () => { beforeEach(async () => { @@ -135,6 +144,14 @@ module.exports = function({ accounts }) { cb(); }); }, + whenMockedWithUintsSystemSetting: ({ setting, value }, cb) => { + describe(`when SystemSetting.${setting} is mocked to ${value}`, () => { + beforeEach(async () => { + this.flexibleStorageMock.mockSystemSetting({ setting, value, type: 'uints' }); + }); + cb(); + }); + }, whenMockedWithSynthUintSystemSetting: ({ setting, synth, value }, cb) => { const settingForSynth = web3.utils.soliditySha3( { type: 'bytes32', value: toBytes32(setting) }, @@ -162,6 +179,16 @@ module.exports = function({ accounts }) { cb(); }); }, + whenMockedEffectiveRateAsEqualAtRound: cb => { + describe(`when mocked with exchange rates giving an effective value of 1:1`, () => { + beforeEach(async () => { + this.mocks.ExchangeRates.smocked.effectiveValueAndRatesAtRound.will.return.with( + (srcKey, amount, destKey) => [amount, (1e18).toString(), (1e18).toString()] + ); + }); + cb(); + }); + }, whenMockedLastNRates: cb => { describe(`when mocked 1e18 as last n rates`, () => { beforeEach(async () => { diff --git a/test/contracts/ExchangerWithFeeRecAlternatives.unit.js b/test/contracts/ExchangerWithFeeRecAlternatives.unit.js index 9302e3f68f..17b91432f0 100644 --- a/test/contracts/ExchangerWithFeeRecAlternatives.unit.js +++ b/test/contracts/ExchangerWithFeeRecAlternatives.unit.js @@ -70,38 +70,21 @@ contract('ExchangerWithFeeRecAlternatives (unit tests)', async accounts => { ); }); - describe('feeRateForAtomicExchange()', () => { - // Mimic settings not being configured - behaviors.whenMockedWithSynthUintSystemSetting( - { setting: 'exchangeFeeRate', synth: sETH, value: '0' }, - () => { - it('is set to 0', async () => { - assert.bnEqual(await this.instance.feeRateForAtomicExchange(sUSD, sETH), '0'); - }); - } - ); - - // With configured override value - behaviors.whenMockedWithSynthUintSystemSetting( - { setting: 'atomicExchangeFeeRate', synth: sETH, value: overrideFeeRate }, - () => { - it('is set to the configured atomic override value', async () => { - assert.bnEqual( - await this.instance.feeRateForAtomicExchange(sUSD, sETH), - overrideFeeRate - ); - }); - } - ); - - // With configured base and override values - behaviors.whenMockedWithSynthUintSystemSetting( - { setting: 'exchangeFeeRate', synth: sETH, value: baseFeeRate }, - () => { - it('is set to the configured base value', async () => { - assert.bnEqual(await this.instance.feeRateForAtomicExchange(sUSD, sETH), baseFeeRate); - }); + behaviors.whenMockedWithUintSystemSetting( + { setting: 'exchangeMaxDynamicFee', value: toUnit('1') }, + () => { + describe('feeRateForAtomicExchange()', () => { + // Mimic settings not being configured + behaviors.whenMockedWithSynthUintSystemSetting( + { setting: 'exchangeFeeRate', synth: sETH, value: '0' }, + () => { + it('is set to 0', async () => { + assert.bnEqual(await this.instance.feeRateForAtomicExchange(sUSD, sETH), '0'); + }); + } + ); + // With configured override value behaviors.whenMockedWithSynthUintSystemSetting( { setting: 'atomicExchangeFeeRate', synth: sETH, value: overrideFeeRate }, () => { @@ -113,9 +96,34 @@ contract('ExchangerWithFeeRecAlternatives (unit tests)', async accounts => { }); } ); - } - ); - }); + + // With configured base and override values + behaviors.whenMockedWithSynthUintSystemSetting( + { setting: 'exchangeFeeRate', synth: sETH, value: baseFeeRate }, + () => { + it('is set to the configured base value', async () => { + assert.bnEqual( + await this.instance.feeRateForAtomicExchange(sUSD, sETH), + baseFeeRate + ); + }); + + behaviors.whenMockedWithSynthUintSystemSetting( + { setting: 'atomicExchangeFeeRate', synth: sETH, value: overrideFeeRate }, + () => { + it('is set to the configured atomic override value', async () => { + assert.bnEqual( + await this.instance.feeRateForAtomicExchange(sUSD, sETH), + overrideFeeRate + ); + }); + } + ); + } + ); + }); + } + ); describe('getAmountsForAtomicExchange()', () => { const atomicRate = toUnit('0.01'); @@ -233,11 +241,11 @@ contract('ExchangerWithFeeRecAlternatives (unit tests)', async accounts => { }; describe('failure modes', () => { - behaviors.whenMockedWithExchangeRatesValidity({ valid: false }, () => { + behaviors.whenMockedWithExchangeRatesValidityAtRound({ valid: false }, () => { it('reverts when either rate is invalid', async () => { await assert.revert( this.instance.exchange(...getExchangeArgs()), - 'Src/dest rate invalid or not found' + 'src/dest rate stale or flagged' ); }); }); @@ -247,7 +255,7 @@ contract('ExchangerWithFeeRecAlternatives (unit tests)', async accounts => { behaviors.whenMockedWithUintSystemSetting( { setting: 'waitingPeriodSecs', value: '0' }, () => { - behaviors.whenMockedEffectiveRateAsEqual(() => { + behaviors.whenMockedEffectiveRateAsEqualAtRound(() => { behaviors.whenMockedLastNRates(() => { behaviors.whenMockedASingleSynthToIssueAndBurn(() => { behaviors.whenMockedExchangeStatePersistance(() => { @@ -283,7 +291,7 @@ contract('ExchangerWithFeeRecAlternatives (unit tests)', async accounts => { behaviors.whenMockedWithUintSystemSetting( { setting: 'waitingPeriodSecs', value: '0' }, () => { - behaviors.whenMockedEffectiveRateAsEqual(() => { + behaviors.whenMockedEffectiveRateAsEqualAtRound(() => { behaviors.whenMockedLastNRates(() => { behaviors.whenMockedASingleSynthToIssueAndBurn(() => { behaviors.whenMockedExchangeStatePersistance(() => { @@ -409,7 +417,7 @@ contract('ExchangerWithFeeRecAlternatives (unit tests)', async accounts => { it('reverts when either rate is invalid', async () => { await assert.revert( this.instance.exchangeAtomically(...getExchangeArgs()), - 'Src/dest rate invalid or not found' + 'src/dest rate stale or flagged' ); }); }); @@ -605,224 +613,246 @@ contract('ExchangerWithFeeRecAlternatives (unit tests)', async accounts => { }, () => { behaviors.whenMockedWithUintSystemSetting( - { setting: 'atomicMaxVolumePerBlock', value: maxAtomicValuePerBlock }, + { setting: 'exchangeMaxDynamicFee', value: toUnit('1') }, () => { - const itExchangesCorrectly = ({ - exchangeFeeRate, - setAsOverrideRate, - tradingRewardsEnabled, - trackingCode, - }) => { - behaviors.whenMockedWithBoolSystemSetting( - { - setting: 'tradingRewardsEnabled', - value: !!tradingRewardsEnabled, - }, - () => { - behaviors.whenMockedWithSynthUintSystemSetting( + behaviors.whenMockedWithUintSystemSetting( + { setting: 'atomicMaxVolumePerBlock', value: maxAtomicValuePerBlock }, + () => { + const itExchangesCorrectly = ({ + exchangeFeeRate, + setAsOverrideRate, + tradingRewardsEnabled, + trackingCode, + }) => { + behaviors.whenMockedWithBoolSystemSetting( { - setting: setAsOverrideRate - ? 'atomicExchangeFeeRate' - : 'exchangeFeeRate', - synth: sETH, - value: exchangeFeeRate, + setting: 'tradingRewardsEnabled', + value: !!tradingRewardsEnabled, }, () => { - let expectedAmountReceived; - let expectedFee; - beforeEach('attempt exchange', async () => { - expectedFee = multiplyDecimal(amountIn, exchangeFeeRate); - expectedAmountReceived = divideDecimal( - amountIn.sub(expectedFee), - lastEthRate - ); - - await this.instance.exchangeAtomically( - ...getExchangeArgs({ - trackingCode, - }) - ); - }); - it('burned correct amount of sUSD', () => { - assert.equal( - this.mocks.sUSD.smocked.burn.calls[0][0], - owner - ); - assert.bnEqual( - this.mocks.sUSD.smocked.burn.calls[0][1], - amountIn - ); - }); - it('issued correct amount of sETH', () => { - assert.equal( - this.mocks.sETH.smocked.issue.calls[0][0], - owner - ); - assert.bnEqual( - this.mocks.sETH.smocked.issue.calls[0][1], - expectedAmountReceived - ); - }); - it('tracked atomic volume', async () => { - assert.bnEqual( - (await this.instance.lastAtomicVolume()).volume, - amountIn - ); - }); - it('updated debt cache', () => { - const debtCacheUpdateCall = this.mocks.DebtCache.smocked - .updateCachedSynthDebtsWithRates; - assert.deepEqual(debtCacheUpdateCall.calls[0][0], [ - sUSD, - sETH, - ]); - assert.deepEqual(debtCacheUpdateCall.calls[0][1], [ - lastUsdRate, - lastEthRate, - ]); - }); - it('asked Synthetix to emit an exchange event', () => { - const synthetixEmitExchangeCall = this.mocks.Synthetix - .smocked.emitSynthExchange; - assert.equal(synthetixEmitExchangeCall.calls[0][0], owner); - assert.equal(synthetixEmitExchangeCall.calls[0][1], sUSD); - assert.bnEqual( - synthetixEmitExchangeCall.calls[0][2], - amountIn - ); - assert.equal(synthetixEmitExchangeCall.calls[0][3], sETH); - assert.bnEqual( - synthetixEmitExchangeCall.calls[0][4], - expectedAmountReceived - ); - assert.equal(synthetixEmitExchangeCall.calls[0][5], owner); - }); - it('asked Synthetix to emit an atomic exchange event', () => { - const synthetixEmitAtomicExchangeCall = this.mocks.Synthetix - .smocked.emitAtomicSynthExchange; - assert.equal( - synthetixEmitAtomicExchangeCall.calls[0][0], - owner - ); - assert.equal( - synthetixEmitAtomicExchangeCall.calls[0][1], - sUSD - ); - assert.bnEqual( - synthetixEmitAtomicExchangeCall.calls[0][2], - amountIn - ); - assert.equal( - synthetixEmitAtomicExchangeCall.calls[0][3], - sETH - ); - assert.bnEqual( - synthetixEmitAtomicExchangeCall.calls[0][4], - expectedAmountReceived - ); - assert.equal( - synthetixEmitAtomicExchangeCall.calls[0][5], - owner - ); - }); - it('did not add any fee reclamation entries to exchange state', () => { - assert.equal( - this.mocks.ExchangeState.smocked.appendExchangeEntry.calls - .length, - 0 - ); - }); - - // Conditional based on test settings - if (toBN(exchangeFeeRate).isZero()) { - it('did not report a fee', () => { - assert.equal( - this.mocks.FeePool.smocked.recordFeePaid.calls.length, - 0 - ); - }); - } else { - it('remitted correct fee to fee pool', () => { - assert.equal( - this.mocks.sUSD.smocked.issue.calls[0][0], - getUsers({ network: 'mainnet', user: 'fee' }).address - ); - assert.bnEqual( - this.mocks.sUSD.smocked.issue.calls[0][1], - expectedFee - ); - assert.bnEqual( - this.mocks.FeePool.smocked.recordFeePaid.calls[0], - expectedFee - ); - }); - } - if (!tradingRewardsEnabled) { - it('did not report trading rewards', () => { - assert.equal( - this.mocks.TradingRewards.smocked - .recordExchangeFeeForAccount.calls.length, - 0 - ); - }); - } else { - it('reported trading rewards', () => { - const trRecordCall = this.mocks.TradingRewards.smocked - .recordExchangeFeeForAccount; - assert.bnEqual(trRecordCall.calls[0][0], expectedFee); - assert.equal(trRecordCall.calls[0][1], owner); - }); - } - if (!trackingCode) { - it('did not ask Synthetix to emit tracking event', () => { - assert.equal( - this.mocks.Synthetix.smocked.emitExchangeTracking.calls - .length, - 0 - ); - }); - } else { - it('asked Synthetix to emit tracking event', () => { - const synthetixEmitTrackingCall = this.mocks.Synthetix - .smocked.emitExchangeTracking; - assert.equal( - synthetixEmitTrackingCall.calls[0][0], - trackingCode - ); - }); - } + behaviors.whenMockedWithSynthUintSystemSetting( + { + setting: setAsOverrideRate + ? 'atomicExchangeFeeRate' + : 'exchangeFeeRate', + synth: sETH, + value: exchangeFeeRate, + }, + () => { + let expectedAmountReceived; + let expectedFee; + beforeEach('attempt exchange', async () => { + expectedFee = multiplyDecimal( + amountIn, + exchangeFeeRate + ); + expectedAmountReceived = divideDecimal( + amountIn.sub(expectedFee), + lastEthRate + ); + + await this.instance.exchangeAtomically( + ...getExchangeArgs({ + trackingCode, + }) + ); + }); + it('burned correct amount of sUSD', () => { + assert.equal( + this.mocks.sUSD.smocked.burn.calls[0][0], + owner + ); + assert.bnEqual( + this.mocks.sUSD.smocked.burn.calls[0][1], + amountIn + ); + }); + it('issued correct amount of sETH', () => { + assert.equal( + this.mocks.sETH.smocked.issue.calls[0][0], + owner + ); + assert.bnEqual( + this.mocks.sETH.smocked.issue.calls[0][1], + expectedAmountReceived + ); + }); + it('tracked atomic volume', async () => { + assert.bnEqual( + (await this.instance.lastAtomicVolume()).volume, + amountIn + ); + }); + it('updated debt cache', () => { + const debtCacheUpdateCall = this.mocks.DebtCache.smocked + .updateCachedSynthDebtsWithRates; + assert.deepEqual(debtCacheUpdateCall.calls[0][0], [ + sUSD, + sETH, + ]); + assert.deepEqual(debtCacheUpdateCall.calls[0][1], [ + lastUsdRate, + lastEthRate, + ]); + }); + it('asked Synthetix to emit an exchange event', () => { + const synthetixEmitExchangeCall = this.mocks.Synthetix + .smocked.emitSynthExchange; + assert.equal( + synthetixEmitExchangeCall.calls[0][0], + owner + ); + assert.equal( + synthetixEmitExchangeCall.calls[0][1], + sUSD + ); + assert.bnEqual( + synthetixEmitExchangeCall.calls[0][2], + amountIn + ); + assert.equal( + synthetixEmitExchangeCall.calls[0][3], + sETH + ); + assert.bnEqual( + synthetixEmitExchangeCall.calls[0][4], + expectedAmountReceived + ); + assert.equal( + synthetixEmitExchangeCall.calls[0][5], + owner + ); + }); + it('asked Synthetix to emit an atomic exchange event', () => { + const synthetixEmitAtomicExchangeCall = this.mocks + .Synthetix.smocked.emitAtomicSynthExchange; + assert.equal( + synthetixEmitAtomicExchangeCall.calls[0][0], + owner + ); + assert.equal( + synthetixEmitAtomicExchangeCall.calls[0][1], + sUSD + ); + assert.bnEqual( + synthetixEmitAtomicExchangeCall.calls[0][2], + amountIn + ); + assert.equal( + synthetixEmitAtomicExchangeCall.calls[0][3], + sETH + ); + assert.bnEqual( + synthetixEmitAtomicExchangeCall.calls[0][4], + expectedAmountReceived + ); + assert.equal( + synthetixEmitAtomicExchangeCall.calls[0][5], + owner + ); + }); + it('did not add any fee reclamation entries to exchange state', () => { + assert.equal( + this.mocks.ExchangeState.smocked.appendExchangeEntry + .calls.length, + 0 + ); + }); + + // Conditional based on test settings + if (toBN(exchangeFeeRate).isZero()) { + it('did not report a fee', () => { + assert.equal( + this.mocks.FeePool.smocked.recordFeePaid.calls + .length, + 0 + ); + }); + } else { + it('remitted correct fee to fee pool', () => { + assert.equal( + this.mocks.sUSD.smocked.issue.calls[0][0], + getUsers({ network: 'mainnet', user: 'fee' }) + .address + ); + assert.bnEqual( + this.mocks.sUSD.smocked.issue.calls[0][1], + expectedFee + ); + assert.bnEqual( + this.mocks.FeePool.smocked.recordFeePaid.calls[0], + expectedFee + ); + }); + } + if (!tradingRewardsEnabled) { + it('did not report trading rewards', () => { + assert.equal( + this.mocks.TradingRewards.smocked + .recordExchangeFeeForAccount.calls.length, + 0 + ); + }); + } else { + it('reported trading rewards', () => { + const trRecordCall = this.mocks.TradingRewards.smocked + .recordExchangeFeeForAccount; + assert.bnEqual(trRecordCall.calls[0][0], expectedFee); + assert.equal(trRecordCall.calls[0][1], owner); + }); + } + if (!trackingCode) { + it('did not ask Synthetix to emit tracking event', () => { + assert.equal( + this.mocks.Synthetix.smocked.emitExchangeTracking + .calls.length, + 0 + ); + }); + } else { + it('asked Synthetix to emit tracking event', () => { + const synthetixEmitTrackingCall = this.mocks.Synthetix + .smocked.emitExchangeTracking; + assert.equal( + synthetixEmitTrackingCall.calls[0][0], + trackingCode + ); + }); + } + } + ); } ); - } - ); - }; - - describe('when no exchange fees are configured', () => { - itExchangesCorrectly({ - exchangeFeeRate: '0', - }); - }); - - describe('with tracking code', () => { - itExchangesCorrectly({ - exchangeFeeRate: '0', - trackingCode: toBytes32('TRACKING'), - }); - }); - - describe('when an exchange fee is configured', () => { - itExchangesCorrectly({ - exchangeFeeRate: baseFeeRate, - tradingRewardsEnabled: true, - }); - }); - describe('when an exchange fee override for atomic exchanges is configured', () => { - itExchangesCorrectly({ - exchangeFeeRate: overrideFeeRate, - setAsOverrideRate: true, - tradingRewardsEnabled: true, - }); - }); + }; + + describe('when no exchange fees are configured', () => { + itExchangesCorrectly({ + exchangeFeeRate: '0', + }); + }); + + describe('with tracking code', () => { + itExchangesCorrectly({ + exchangeFeeRate: '0', + trackingCode: toBytes32('TRACKING'), + }); + }); + + describe('when an exchange fee is configured', () => { + itExchangesCorrectly({ + exchangeFeeRate: baseFeeRate, + tradingRewardsEnabled: true, + }); + }); + describe('when an exchange fee override for atomic exchanges is configured', () => { + itExchangesCorrectly({ + exchangeFeeRate: overrideFeeRate, + setAsOverrideRate: true, + tradingRewardsEnabled: true, + }); + }); + } + ); } ); } diff --git a/test/contracts/FeePool.js b/test/contracts/FeePool.js index f951ddc5c7..07a6cd881c 100644 --- a/test/contracts/FeePool.js +++ b/test/contracts/FeePool.js @@ -767,13 +767,9 @@ contract('FeePool', async accounts => { }); it('should disallow closing the current fee period too early', async () => { - const feePeriodDuration = await feePool.feePeriodDuration(); - // Close the current one so we know exactly what we're dealing with await closeFeePeriod(); - // Try to close the new fee period 5 seconds early - await fastForward(feePeriodDuration.sub(web3.utils.toBN('5'))); await assert.revert( feePool.closeCurrentFeePeriod({ from: account1 }), 'Too early to close fee period' diff --git a/test/contracts/Issuer.js b/test/contracts/Issuer.js index fdf8c432d2..da91822355 100644 --- a/test/contracts/Issuer.js +++ b/test/contracts/Issuer.js @@ -2051,6 +2051,9 @@ contract('Issuer (via Synthetix)', async accounts => { // **************************************** it("should prevent more issuance if the user's collaterisation changes to be insufficient", async () => { + // disable dynamic fee here as it will prevent exchange due to fees spiking too much + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); + // Set sEUR for purposes of this test await updateAggregatorRates(exchangeRates, [sEUR], [toUnit('0.75')]); await debtCache.takeDebtSnapshot(); diff --git a/test/contracts/PurgeableSynth.js b/test/contracts/PurgeableSynth.js index 7d8508bf00..9e1067af4c 100644 --- a/test/contracts/PurgeableSynth.js +++ b/test/contracts/PurgeableSynth.js @@ -208,7 +208,7 @@ contract('PurgeableSynth', accounts => { it('then purge() reverts', async () => { await assert.revert( iETHContract.purge([account1], { from: owner }), - 'Src/dest rate invalid or not found' + 'src/dest rate stale or flagged' ); }); describe('when rates are received', () => { diff --git a/test/contracts/RewardsIntegrationTests.js b/test/contracts/RewardsIntegrationTests.js index f50af7f70c..546d3757c5 100644 --- a/test/contracts/RewardsIntegrationTests.js +++ b/test/contracts/RewardsIntegrationTests.js @@ -559,8 +559,8 @@ contract('Rewards Integration Tests', accounts => { assert.bnClose(account3Rewards[1], rewardsAmount, '1'); // Accounts 2 & 3 claim + await updateRatesWithDefaults({ exchangeRates, owner, debtCache }); await feePool.claimFees({ from: account2 }); - // updateRatesWithDefaults(); await feePool.claimFees({ from: account3 }); // Accounts 2 & 3 now have the rewards escrowed @@ -635,6 +635,9 @@ contract('Rewards Integration Tests', accounts => { await synthetix.mint({ from: owner }); // Do some exchanging to generateFees + // disable dynamic fee here otherwise it will flag rates as too volatile + await systemSettings.setExchangeDynamicFeeRounds('0', { from: owner }); + const { amountReceived } = await exchanger.getAmountsForExchange(tenK, sUSD, sBTC); await synthetix.exchange(sBTC, amountReceived, sUSD, { from: account1 }); await synthetix.exchange(sBTC, amountReceived, sUSD, { from: account2 }); diff --git a/test/contracts/SystemSettings.js b/test/contracts/SystemSettings.js index a1ec5c00b8..1da3cc4c4b 100644 --- a/test/contracts/SystemSettings.js +++ b/test/contracts/SystemSettings.js @@ -85,6 +85,10 @@ contract('SystemSettings', async accounts => { 'setWrapperBurnFeeRate', 'setWrapperMaxTokenAmount', 'setWrapperMintFeeRate', + 'setExchangeDynamicFeeThreshold', + 'setExchangeDynamicFeeWeightDecay', + 'setExchangeDynamicFeeRounds', + 'setExchangeMaxDynamicFee', ], }); }); @@ -1483,4 +1487,96 @@ contract('SystemSettings', async accounts => { }); }); }); + + describe('setExchangeDynamicFeeThreshold()', () => { + const threshold = toUnit('0.004'); + it('only owner can invoke', async () => { + await onlyGivenAddressCanInvoke({ + fnc: systemSettings.setExchangeDynamicFeeThreshold, + args: [threshold], + accounts, + address: owner, + reason: 'Only the contract owner may perform this action', + }); + }); + it('the owner can invoke and replace with emitted event', async () => { + const txn = await systemSettings.setExchangeDynamicFeeThreshold(threshold, { from: owner }); + const actual = await systemSettings.exchangeDynamicFeeThreshold(); + assert.bnEqual( + actual, + threshold, + 'Configured exchange dynamic fee threshold is set correctly' + ); + assert.eventEqual(txn, 'ExchangeDynamicFeeThresholdUpdated', [threshold]); + }); + }); + + describe('setExchangeDynamicFeeWeightDecay()', () => { + const weightDecay = toUnit('0.9'); + it('only owner can invoke', async () => { + await onlyGivenAddressCanInvoke({ + fnc: systemSettings.setExchangeDynamicFeeWeightDecay, + args: [weightDecay], + accounts, + address: owner, + reason: 'Only the contract owner may perform this action', + }); + }); + it('the owner can invoke and replace with emitted event', async () => { + const txn = await systemSettings.setExchangeDynamicFeeWeightDecay(weightDecay, { + from: owner, + }); + const actual = await systemSettings.exchangeDynamicFeeWeightDecay(); + assert.bnEqual( + actual, + weightDecay, + 'Configured exchange dynamic fee weight decay is set correctly' + ); + assert.eventEqual(txn, 'ExchangeDynamicFeeWeightDecayUpdated', [weightDecay]); + }); + }); + + describe('setExchangeDynamicFeeRounds()', () => { + const rounds = '10'; + it('only owner can invoke', async () => { + await onlyGivenAddressCanInvoke({ + fnc: systemSettings.setExchangeDynamicFeeRounds, + args: [rounds], + accounts, + address: owner, + reason: 'Only the contract owner may perform this action', + }); + }); + it('the owner can invoke and replace with emitted event', async () => { + const txn = await systemSettings.setExchangeDynamicFeeRounds(rounds, { from: owner }); + const actual = await systemSettings.exchangeDynamicFeeRounds(); + assert.equal(actual, rounds, 'Configured exchange dynamic fee rounds is set correctly'); + assert.eventEqual(txn, 'ExchangeDynamicFeeRoundsUpdated', [rounds]); + }); + }); + + describe('setExchangeMaxDynamicFee()', () => { + const maxDynamicFee = toUnit('0.05'); + it('only owner can invoke', async () => { + await onlyGivenAddressCanInvoke({ + fnc: systemSettings.setExchangeMaxDynamicFee, + args: [maxDynamicFee], + accounts, + address: owner, + reason: 'Only the contract owner may perform this action', + }); + }); + it('the owner can invoke and replace with emitted event', async () => { + const txn = await systemSettings.setExchangeMaxDynamicFee(maxDynamicFee, { from: owner }); + const actual = await systemSettings.exchangeMaxDynamicFee(); + assert.bnEqual(actual, maxDynamicFee, 'Configured exchange max dynamic fee is set correctly'); + assert.eventEqual(txn, 'ExchangeMaxDynamicFeeUpdated', [maxDynamicFee]); + }); + it('when owner sets a value higher than MAX_EXCHANGE_FEE_RATE then revert', async () => { + await assert.revert( + systemSettings.setExchangeMaxDynamicFee(toUnit('11'), { from: owner }), + 'MAX_EXCHANGE_FEE_RATE exceeded' + ); + }); + }); }); diff --git a/test/contracts/helpers.js b/test/contracts/helpers.js index 8d9db9fd6f..59dea94025 100644 --- a/test/contracts/helpers.js +++ b/test/contracts/helpers.js @@ -336,6 +336,7 @@ module.exports = { const flexibleStorageTypes = [ ['uint', 'getUIntValue', '0'], + ['uints', 'getUIntValues', ['0', '0', '0', '0']], ['int', 'getIntValue', '0'], ['address', 'getAddressValue', ZERO_ADDRESS], ['bool', 'getBoolValue', false], diff --git a/test/contracts/setup.js b/test/contracts/setup.js index 9c0db8bc55..4351472c31 100644 --- a/test/contracts/setup.js +++ b/test/contracts/setup.js @@ -20,6 +20,10 @@ const { LIQUIDATION_RATIO, LIQUIDATION_PENALTY, RATE_STALE_PERIOD, + EXCHANGE_DYNAMIC_FEE_THRESHOLD, + EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY, + EXCHANGE_DYNAMIC_FEE_ROUNDS, + EXCHANGE_MAX_DYNAMIC_FEE, MINIMUM_STAKE_TIME, DEBT_SNAPSHOT_STALE_TIME, ATOMIC_MAX_VOLUME_PER_BLOCK, @@ -131,10 +135,12 @@ const setupContract = async ({ if (Object.keys((await artifacts.readArtifact(source || contract)).linkReferences).length > 0) { const safeDecimalMath = await artifacts.require('SafeDecimalMath').new(); if (artifact._json.contractName === 'SystemSettings') { + // SafeDecimalMath -> SystemSettingsLib -> SystemSettings const SystemSettingsLib = artifacts.require('SystemSettingsLib'); SystemSettingsLib.link(safeDecimalMath); artifact.link(await SystemSettingsLib.new()); } else { + // SafeDecimalMath -> anything else that expects linking artifact.link(safeDecimalMath); } } @@ -612,7 +618,7 @@ const setupContract = async ({ instance, mock, fncName: 'feeRateForExchange', - returns: [toWei('0.0030')], + returns: [toWei('0.0030'), '0'], }), ]); } else if (mock === 'ExchangeState') { @@ -1221,6 +1227,21 @@ const setupAllContracts = async ({ returnObj['SystemSettings'].setLiquidationRatio(LIQUIDATION_RATIO, { from: owner }), returnObj['SystemSettings'].setLiquidationPenalty(LIQUIDATION_PENALTY, { from: owner }), returnObj['SystemSettings'].setRateStalePeriod(RATE_STALE_PERIOD, { from: owner }), + returnObj['SystemSettings'].setExchangeDynamicFeeThreshold(EXCHANGE_DYNAMIC_FEE_THRESHOLD, { + from: owner, + }), + returnObj['SystemSettings'].setExchangeDynamicFeeWeightDecay( + EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY, + { + from: owner, + } + ), + returnObj['SystemSettings'].setExchangeDynamicFeeRounds(EXCHANGE_DYNAMIC_FEE_ROUNDS, { + from: owner, + }), + returnObj['SystemSettings'].setExchangeMaxDynamicFee(EXCHANGE_MAX_DYNAMIC_FEE, { + from: owner, + }), returnObj['SystemSettings'].setMinimumStakeTime(MINIMUM_STAKE_TIME, { from: owner }), returnObj['SystemSettings'].setDebtSnapshotStaleTime(DEBT_SNAPSHOT_STALE_TIME, { from: owner, diff --git a/test/dynamic-fee-calc.csv b/test/dynamic-fee-calc.csv new file mode 100644 index 0000000000..bbbf2b3086 --- /dev/null +++ b/test/dynamic-fee-calc.csv @@ -0,0 +1,125 @@ +To recreate / alter see formulas at the bottom,,,,,,, +,round,price,ΔP (bp),boost,dynamic_fee (bp),,deviation threshold (bp) +,1,50007.73057899,,,,,20 +,2,49953.81262846,10.7819230958361,0,,, +,3,50051.305,19.5165026271593,0,,,exchange fee (bp) +,4,50069.7111646299,3.67745948480325,0,,,20 +,5,50070.40589905,0.13875343075398,0,,, +,6,50078.36597318,1.58977623349932,0,,,boost threshold (bp) +,7,50080.61,0.448103043377834,0,,,40 +,8,50070.3465,2.04939596382681,0,0,, +,9,50074.192,0.768019450394508,0,0,,boost decay constant +,10,50076.03,0.367055348591272,0,0,,0.9 +,11,49994,16.3810909131568,0,0,, +,12,49960.65493467,6.66981344361384,0,0,, +,13,49981,4.07221749927134,0,0,, +,14,49871.92313713,21.8236655669157,0,0,, +,15,49933.34034209,12.3149862882022,0,0,,max weight +,16,49842.74988613,18.1422783533758,0,0,,1 +,17,49838.87627216,0.777166985940214,0,0,, +,18,49722.83886705,23.2825083126564,0,0,,decay constant +,19,49714.05205647,1.76715786552206,0,0,,0.9 +,20,49691.8024553899,4.47551550511793,0,0,, +,21,49714.05205647,4.47751942587837,0,0,,0.387420489 +,22,49535.05178912,36.0059701322823,0,0,,0.43046721 +,23,49234.65005734,60.6442753020364,20.6442753020364,20.6442753020364,,0.4782969 +,24,49190.99117585,8.86751128303942,0,18.5798477718328,,0.531441 +,25,49234.65005734,8.8753815376319,0,16.7218629946495,,0.59049 +,26,49088.63670793,29.6566237883167,0,15.0496766951846,,0.6561 +,27,49046.17079819,8.65086353745492,0,13.5447090256661,,0.729 +,28,49088.63670793,8.65835376113955,0,12.1902381230995,,0.81 +,29,49131.10261767,8.65086353745381,0,10.9712143107895,,0.9 +,30,49096.77,6.9879599359246,0,9.87409287971058,,1 +,31,49143.5399999999,9.52608491350926,0,8.88668359173952,, +,32,49198.77,11.2385066277465,0,7.99801523256557,, +,33,49254,11.2258904033591,0,0,, +,34,49208,9.33934299752304,0,0,, +,35,49101.41,21.6611120143062,0,0,, +,36,49095.24231598,1.2561113866183,0,0,, +,37,49093.89744338,0.273931349873413,0,0,, +,38,49054.03062906,8.12052340435687,0,0,, +,39,49009.46274509,9.08546828843004,0,0,, +,40,49054.03062906,9.09373036831695,0,0,, +,41,48964.89486113,18.1709365748206,0,0,, +,42,48954.93260767,2.03457058128076,0,0,, +,43,48364.4121895,120.625315308367,80.625315308367,80.625315308367,, +,44,48342.34371195,4.56295787562344,0,72.5627837775303,, +,45,48267.37667219,15.5075310801422,0,65.3065053997772,, +,46,48225.00037245,8.77949096504738,0,58.7758548597995,, +,47,47783.75,91.4982621134564,51.4982621134564,104.396531487276,, +,48,48198.4621158,86.7893616135196,46.7893616135196,140.746239952068,, +,49,48043.1218078999,32.2293079656533,0,126.671615956861,, +,50,48198.4621158,32.3335166522343,0,114.004454361175,, +,51,48044.80901916,31.8792529667944,0,102.604008925058,, +,52,48108.4029515399,13.236379471202,0,92.3436080325518,, +,53,48112,0.747696501943729,0,54.9969380550045,, +,54,48056.45718986,11.5444816553045,0,49.4972442495041,, +,55,47988.17926024,14.2078575102289,0,44.5475198245537,, +,56,47902.24487106,17.9074077209684,0,40.0927678420983,, +,57,47911.8471578599,2.0045588313744,0,18.1271573563076,, +,58,47670.81054939,50.3083522694781,10.3083522694781,10.3083522694781,, +,59,47580.67384441,18.9081544746583,0,9.27751704253025,, +,60,47449.76309439,27.5134291809487,0,8.34976533827722,, +,61,47382.88726893,14.0940272614154,0,7.5147888044495,, +,62,47222.35138239,33.8805623280924,0,6.76330992400455,, +,63,46948.76815888,57.9351123993432,17.9351123993432,24.0220913309473,, +,64,46675.18493538,58.2727160325403,18.2727160325403,39.8925982303928,, +,65,46463.74676537,45.2999104990637,5.29991049906368,41.2032489064172,, +,66,46217.7336139799,52.9473338928954,12.9473338928954,50.0302579086709,, +,67,46183.17440371,7.47747835463941,0,45.0272321178038,, +,68,45919.00562933,57.2002201647659,17.2002201647659,54.1304288814665,, +,69,45586.5085919099,72.4094594086167,32.4094594086167,81.1268454019365,, +,70,45483.8961602099,22.509385971754,0,73.0141608617428,, +,71,44672.6561639399,178.357630888202,138.357630888202,204.07037566377,, +,72,44661.70868763,2.4505989233603,0,183.663338097393,, +,73,44650.76121132,2.45119961409634,0,159.043417273233,, +,74,44668.7953606,4.03893434081759,0,136.767773423293,, +,75,44774.49388229,23.6627204375495,0,121.243031555481,, +,76,44853.05,17.5448365572861,0,104.604272214704,, +,77,45204.4549999999,78.345842701868,38.345842701868,132.489687695102,, +,78,45231.276,5.93326476341804,0,113.243372989164,, +,79,45477.5075,54.4383271433691,14.4383271433691,105.056883082536,, +,80,45568.3515,19.9755890315667,0,94.5511947742825,, +,81,45468.09,22.0024417604836,0,36.8537523828245,, +,82,45757.7,63.6952200983143,23.6952200983143,56.8635972428563,, +,83,45846.1785,19.3363084245934,0,51.1772375185707,, +,84,46060.93771094,46.8434268605389,6.84342686053888,52.9029406272525,, +,85,46081.215,4.40227447978669,0,47.6126465645273,, +,86,46167.82,18.7939923025038,0,42.8513819080745,, +,87,45860.8944999999,66.480396951838,26.4803969518379,51.6762720514978,, +,88,45844.31854774,3.61439793981844,0,46.508644846348,, +,89,46040.66042188,42.8279621902417,2.82796219024165,39.6514091659514,, +,90,45975.5952109399,14.1321193796728,0,35.6862682493563,, +,91,45942.48948481,7.20071724531368,0,32.1176414244206,, +,92,46040.66042188,21.3682232223089,0,20.6438649002722,, +,93,46090.3302109399,10.7882442616525,0,18.579478410245,, +,94,46132.86,9.2274863003694,0,14.3353751665493,, +,95,45874.42216374,56.0203369702217,16.0203369702217,28.9221746201161,, +,96,45830.84933011,9.49828500824923,0,26.0299571581045,, +,97,45888.1962499999,12.5127333942343,0,14.1938179398984,, +,98,46038.42444459,32.7378731061145,0,12.7744361459085,, +,99,46039.54243323,0.242838162576309,0,10.5109430861624,, +,100,46218.23018745,38.8118006340177,0,9.4598487775462,, +,101,46213.94,0.928245723083032,0,8.51386389979158,, +,102,46437.773,48.4340872039901,8.43408720399012,16.0965647138025,, +,103,46506.479,14.7952831415932,0,14.4869082424223,, +,104,46519.9745,2.90185373956087,0,13.0382174181801,, +,105,46533.47,2.90101190833836,0,6.1484495717088,, +,106,46622.632,19.1608319774983,0,5.53360461453792,, +,107,46619.216,0.732691367574256,0,4.98024415308413,, +,108,46615.8,0.732745055171957,0,4.48221973777571,, +,109,46707.1025,19.5861703542577,0,4.03399776399814,, +,110,46826.18,25.4945165994824,0,3.63059798759833,, +,111,46819.33062006,1.46272447165252,0,3.26753818883849,, +,112,46826.18,1.46293845924239,0,0,, +,113,46961.35210329,28.8667799273834,0,0,, +,114,47001.22734027,8.4910751488354,0,0,, +,115,46829.45375,36.5466180332763,0,0,, +,116,46796.05875,7.13119571675636,0,0,, +,117,46903.6069999999,22.9823307502164,0,0,, +,118,46789.378,24.3539905150381,0,0,, +,119,46752.593,7.86182710101335,0,0,, +,120,46766.34475,2.94138765736474,0,0,, +,121,46780.0965,2.94052273563716,0,0,, +,122,46946.0995,35.4858182047568,0,0,, +formulas (apply from bottom up),,,"""=ABS(C125/C124-1)*10000”","""=IF(D125-$H$9>0,D125-$H$9,0)”","""=SUMPRODUCT(E116:E125,$H$23:$H$32)”",, diff --git a/test/integration/behaviors/liquidations.behavior.js b/test/integration/behaviors/liquidations.behavior.js index 55990c819b..b40b730c09 100644 --- a/test/integration/behaviors/liquidations.behavior.js +++ b/test/integration/behaviors/liquidations.behavior.js @@ -1,7 +1,7 @@ const ethers = require('ethers'); const { toBytes32 } = require('../../../index'); const { assert } = require('../../contracts/common'); -const { getRate, setRate } = require('../utils/rates'); +const { getRate, addAggregatorAndSetRate } = require('../utils/rates'); const { ensureBalance } = require('../utils/balances'); const { skipLiquidationDelay } = require('../utils/skip'); @@ -46,7 +46,11 @@ function itCanLiquidate({ ctx }) { before('exchange rate is set', async () => { exchangeRate = await getRate({ ctx, symbol: 'SNX' }); - await setRate({ ctx, symbol: 'SNX', rate: '1000000000000000000' }); + await addAggregatorAndSetRate({ + ctx, + currencyKey: toBytes32('SNX'), + rate: '1000000000000000000', + }); }); before('someUser stakes their SNX', async () => { @@ -59,7 +63,11 @@ function itCanLiquidate({ ctx }) { describe('getting marked', () => { before('exchange rate changes to allow liquidation', async () => { - await setRate({ ctx, symbol: 'SNX', rate: '200000000000000000' }); + await addAggregatorAndSetRate({ + ctx, + currencyKey: toBytes32('SNX'), + rate: '200000000000000000', + }); }); before('liquidation is marked', async () => { @@ -67,7 +75,11 @@ function itCanLiquidate({ ctx }) { }); after('restore exchange rate', async () => { - await setRate({ ctx, symbol: 'SNX', rate: exchangeRate.toString() }); + await addAggregatorAndSetRate({ + ctx, + currencyKey: toBytes32('SNX'), + rate: exchangeRate.toString(), + }); }); it('still not open for liquidation', async () => { diff --git a/test/integration/behaviors/redeem.behavior.js b/test/integration/behaviors/redeem.behavior.js index 4e855ce62c..edc65af5cb 100644 --- a/test/integration/behaviors/redeem.behavior.js +++ b/test/integration/behaviors/redeem.behavior.js @@ -18,8 +18,8 @@ function itCanRedeem({ ctx }) { before('target contracts and users', () => { const { addedSynths } = ctx; - // when no added synths, then just use sDEFI for testing (useful for the simulation) - synth = addedSynths.length ? addedSynths[0].name : 'sDEFI'; + // when no added synths, then just use sETH for testing (useful for the simulation) + synth = addedSynths.length ? addedSynths[0].name : 'sBTC'; ({ Synthetix, diff --git a/test/integration/behaviors/short.behavior.js b/test/integration/behaviors/short.behavior.js index cc96ee365d..32d208280e 100644 --- a/test/integration/behaviors/short.behavior.js +++ b/test/integration/behaviors/short.behavior.js @@ -14,7 +14,7 @@ const { skipWaitingPeriod } = require('../utils/skip'); function itCanOpenAndCloseShort({ ctx }) { describe('shorting', () => { - const amountOfsUSDRequired = parseEther('2000'); // sUSD + const amountOfsUSDRequired = parseEther('5000'); // sUSD const amountToDeposit = parseEther('1000'); // sUSD const amountToBorrow = parseEther('0.000001'); // sETH const amountToExchange = parseEther('100'); // sUSD diff --git a/test/integration/l1/Liquidations.l1.integrations.js b/test/integration/l1/Liquidations.l1.integrations.js index 1027828391..e382b86573 100644 --- a/test/integration/l1/Liquidations.l1.integrations.js +++ b/test/integration/l1/Liquidations.l1.integrations.js @@ -1,31 +1,9 @@ const { bootstrapL1 } = require('../utils/bootstrap'); const { itCanLiquidate } = require('../behaviors/liquidations.behavior'); -const { ethers } = require('hardhat'); - -// Load Compiled -const path = require('path'); -const { - constants: { BUILD_FOLDER }, -} = require('../../..'); -const buildPath = path.join(__dirname, '..', '..', '..', `${BUILD_FOLDER}`); -const { loadCompiledFiles } = require('../../../publish/src/solidity'); -const { compiled } = loadCompiledFiles({ buildPath }); describe('Liquidations (L1)', () => { const ctx = this; bootstrapL1({ ctx }); - before(async () => { - const { - abi, - evm: { - bytecode: { object: bytecode }, - }, - } = compiled.MockAggregatorV2V3; - const MockAggregatorFactory = new ethers.ContractFactory(abi, bytecode, ctx.users.owner); - const MockAggregator = await MockAggregatorFactory.deploy(); - ctx.contracts.MockAggregator = MockAggregator; - }); - itCanLiquidate({ ctx }); }); diff --git a/test/integration/l2/Liquidations.l2.integration.js b/test/integration/l2/Liquidations.l2.integration.js index 34bb13634f..6a0c7a15ad 100644 --- a/test/integration/l2/Liquidations.l2.integration.js +++ b/test/integration/l2/Liquidations.l2.integration.js @@ -1,31 +1,9 @@ const { bootstrapL2 } = require('../utils/bootstrap'); const { itCanLiquidate } = require('../behaviors/liquidations.behavior'); -const { ethers } = require('hardhat'); - -// Load Compiled -const path = require('path'); -const { - constants: { BUILD_FOLDER }, -} = require('../../..'); -const buildPath = path.join(__dirname, '..', '..', '..', `${BUILD_FOLDER}`); -const { loadCompiledFiles } = require('../../../publish/src/solidity'); -const { compiled } = loadCompiledFiles({ buildPath }); describe('Liquidations (L2)', () => { const ctx = this; bootstrapL2({ ctx }); - before(async () => { - const { - abi, - evm: { - bytecode: { object: bytecode }, - }, - } = compiled.MockAggregatorV2V3; - const MockAggregatorFactory = new ethers.ContractFactory(abi, bytecode, ctx.users.owner); - const MockAggregator = await MockAggregatorFactory.deploy(); - ctx.contracts.MockAggregator = MockAggregator; - }); - itCanLiquidate({ ctx }); }); diff --git a/test/integration/l2/WrapperFactory.l2.integration.js b/test/integration/l2/WrapperFactory.l2.integration.js index 1dec85fcb0..60d9e4f0c7 100644 --- a/test/integration/l2/WrapperFactory.l2.integration.js +++ b/test/integration/l2/WrapperFactory.l2.integration.js @@ -10,7 +10,7 @@ const path = require('path'); const { constants: { BUILD_FOLDER }, } = require('../../..'); -const buildPath = path.join(__dirname, '..', '..', '..', `${BUILD_FOLDER}-ovm`); +const buildPath = path.join(__dirname, '..', '..', '..', BUILD_FOLDER); const { loadCompiledFiles } = require('../../../publish/src/solidity'); const { compiled } = loadCompiledFiles({ buildPath }); diff --git a/test/integration/l2/directRelay.l2.integration.js b/test/integration/l2/directRelay.l2.integration.js index 0cfe06f0bb..0c25f6f8ea 100644 --- a/test/integration/l2/directRelay.l2.integration.js +++ b/test/integration/l2/directRelay.l2.integration.js @@ -1,10 +1,7 @@ const { assert } = require('../../contracts/common'); const { bootstrapL2 } = require('../utils/bootstrap'); -const { - defaults: { TEMP_OWNER_DEFAULT_DURATION }, -} = require('../../..'); - +// skipped because tempOwner no longer will work for fork tests describe('tempOwner directRelay integration tests (L2)', () => { const ctx = this; bootstrapL2({ ctx }); @@ -15,6 +12,13 @@ describe('tempOwner directRelay integration tests (L2)', () => { // Contracts let AddressResolverL2, OwnerRelayOnOptimism, SystemSettingsL2; + before('check fork', async function() { + // on fork, directRelay doesn't work + if (ctx.fork) { + this.skip(); + } + }); + before('target contracts and users', () => { ({ OwnerRelayOnOptimism, @@ -22,17 +26,12 @@ describe('tempOwner directRelay integration tests (L2)', () => { ReadProxyAddressResolver: AddressResolverL2, } = ctx.contracts); - ownerL2 = ctx.users.owner; + ownerL2 = ctx.users.deployer; }); it('shows that the L2 relay was deployed with the correct parameters', async () => { assert.equal(AddressResolverL2.address, await OwnerRelayOnOptimism.resolver()); assert.equal(ownerL2.address, await OwnerRelayOnOptimism.temporaryOwner()); - - // Accept results within two hours (TODO: check why the time difference almost doubled) - const expectedExpiry = (await ctx.provider.getBlock()).timestamp + TEMP_OWNER_DEFAULT_DURATION; - const expiryTime = (await OwnerRelayOnOptimism.expiryTime()).toString(); - assert.bnClose(expectedExpiry, expiryTime, '7200'); }); describe('when SystemSettings on L2 is owned by an EOA', () => { diff --git a/test/integration/utils/balances.js b/test/integration/utils/balances.js index 18689c0735..6bfc8923a1 100644 --- a/test/integration/utils/balances.js +++ b/test/integration/utils/balances.js @@ -36,6 +36,12 @@ async function _getAmount({ ctx, symbol, user, amount }) { `Symbol ${symbol} not yet supported. TODO: Support via exchanging sUSD to other Synths.` ); } + + // sanity check + const newBalance = await _readBalance({ ctx, symbol, user }); + if (newBalance.lt(amount)) { + throw new Error(`Failed to get required ${amount} ${symbol} for ${user.address}`); + } } async function _getETHFromOtherUsers({ ctx, user, amount }) { diff --git a/test/integration/utils/bootstrap.js b/test/integration/utils/bootstrap.js index c905e731e5..365456f39d 100644 --- a/test/integration/utils/bootstrap.js +++ b/test/integration/utils/bootstrap.js @@ -33,7 +33,7 @@ function bootstrapL1({ ctx }) { function bootstrapL2({ ctx }) { before('bootstrap layer 2 instance', async () => { ctx.useOvm = true; - ctx.l1mock = { useOvm: false }; + ctx.fork = hre.config.fork; ctx.addedSynths = hre.config.addedSynths || []; @@ -44,15 +44,22 @@ function bootstrapL2({ ctx }) { * the L1 chain and waiting for the L2 chain to sync. * Direct fast forwarding on the L2 chain is not possible because the rpc does not support * the method evm_increaseTime. + * + * L1 provider is not needed when fork testing * */ - ctx.l1mock.provider = _setupProvider({ - url: `${hre.config.providerUrl}:${hre.config.providerPortL1}`, - }); + if (!ctx.fork) { + ctx.l1mock = { useOvm: false }; + ctx.l1mock.provider = _setupProvider({ + url: `${hre.config.providerUrl}:${hre.config.providerPortL1}`, + }); + + await loadUsers({ ctx: ctx.l1mock }); + } + ctx.provider = _setupProvider({ url: `${hre.config.providerUrl}:${hre.config.providerPortL2}`, }); - await loadUsers({ ctx: ctx.l1mock }); await loadUsers({ ctx }); connectContracts({ ctx }); @@ -66,10 +73,12 @@ function bootstrapL2({ ctx }) { balance: ethers.utils.parseEther('1000000'), }); - startOpsHeartbeat({ - l1Wallet: ctx.l1mock.users.user9, - l2Wallet: ctx.users.user9, - }); + if (!ctx.fork) { + startOpsHeartbeat({ + l1Wallet: ctx.l1mock.users.user9, + l2Wallet: ctx.users.user9, + }); + } }); } diff --git a/test/integration/utils/contracts.js b/test/integration/utils/contracts.js index e9d07a6757..3cdef9eaa5 100644 --- a/test/integration/utils/contracts.js +++ b/test/integration/utils/contracts.js @@ -25,12 +25,11 @@ function _ensureWETH({ ctx }) { if (!ctx.contracts.WETH) { if (ctx.useOvm) { ctx.contracts.WETH = new ethers.Contract( - '0x4200000000000000000000000000000000000000', + '0x4200000000000000000000000000000000000006', _loadCustomAbi({ name: 'WETH' }), ctx.provider ); - } - if (ctx.fork) { + } else if (ctx.fork) { ctx.contracts.WETH = new ethers.Contract( '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH on mainnet L1 _loadCustomAbi({ name: 'WETH' }), diff --git a/test/integration/utils/rates.js b/test/integration/utils/rates.js index 7692b017d1..386553796c 100644 --- a/test/integration/utils/rates.js +++ b/test/integration/utils/rates.js @@ -25,6 +25,26 @@ async function increaseStalePeriodAndCheckRatesAndCache({ ctx }) { } } +/// this creates and adds a new aggregator (even if a previous one exists) and sets the latest rate in it +async function addAggregatorAndSetRate({ ctx, currencyKey, rate }) { + const owner = ctx.users.owner; + const exchangeRates = ctx.contracts.ExchangeRates.connect(owner); + + // factory for price aggregators contracts + const MockAggregatorFactory = await createMockAggregatorFactory(owner); + + // deploy an aggregator + const aggregator = (await MockAggregatorFactory.deploy()).connect(owner); + + // set decimals + await (await aggregator.setDecimals(18)).wait(); + // push the new price + const { timestamp } = await ctx.provider.getBlock(); + await (await aggregator.setLatestAnswer(rate, timestamp)).wait(); + // set the aggregator in ExchangeRates + await (await exchangeRates.addAggregator(currencyKey, aggregator.address)).wait(); +} + async function _isCacheInvalid({ ctx }) { const { DebtCache } = ctx.contracts; @@ -86,26 +106,11 @@ async function _setMissingRates({ ctx }) { currencyKeys = await _getAvailableCurrencyKeys({ ctx }); } - const owner = ctx.users.owner; - const ExchangeRates = ctx.contracts.ExchangeRates.connect(owner); - - // factory for price aggregators contracts - const MockAggregatorFactory = await createMockAggregatorFactory(owner); - - // got over all rates and add aggregators - const { timestamp } = await ctx.provider.getBlock(); + // got over all rates and add aggregators if rate is missing for (const currencyKey of currencyKeys) { - const rate = await ExchangeRates.rateForCurrency(currencyKey); + const rate = await ctx.contracts.ExchangeRates.rateForCurrency(currencyKey); if (rate.toString() === '0') { - // deploy an aggregator - let aggregator = await MockAggregatorFactory.deploy(); - aggregator = aggregator.connect(owner); - // set decimals - await (await aggregator.setDecimals(18)).wait(); - // push the new price - await (await aggregator.setLatestAnswer(ethers.utils.parseEther('1'), timestamp)).wait(); - // set the aggregator in ExchangeRates - await (await ExchangeRates.addAggregator(currencyKey, aggregator.address)).wait(); + await addAggregatorAndSetRate({ ctx, currencyKey, rate: ethers.utils.parseEther('1') }); } } } @@ -129,21 +134,9 @@ async function getRate({ ctx, symbol }) { return ExchangeRates.rateForCurrency(toBytes32(symbol)); } -async function setRate({ ctx, symbol, rate }) { - const ExchangeRates = ctx.contracts.ExchangeRates.connect(ctx.users.owner); - const MockAggregator = ctx.contracts.MockAggregator.connect(ctx.users.owner); - - const { timestamp } = await ctx.provider.getBlock(); - - await (await MockAggregator.setDecimals(18)).wait(); - await (await MockAggregator.setLatestAnswer(ethers.utils.parseEther(rate), timestamp)).wait(); - await (await ExchangeRates.addAggregator(toBytes32(symbol), MockAggregator.address)).wait(); - await MockAggregator.setLatestAnswer(rate, timestamp); -} - module.exports = { increaseStalePeriodAndCheckRatesAndCache, + addAggregatorAndSetRate, getRate, - setRate, updateCache, }; diff --git a/test/integration/utils/users.js b/test/integration/utils/users.js index 42918b0658..e3ad6312dc 100644 --- a/test/integration/utils/users.js +++ b/test/integration/utils/users.js @@ -1,39 +1,50 @@ +const ethers = require('ethers'); const { getUsers } = require('../../../index'); const { loadLocalWallets } = require('../../test-utils/wallets'); -async function loadUsers({ ctx, network }) { +async function loadUsers({ ctx }) { + ctx.users = {}; let wallets = []; // Retrieve and create wallets - if (ctx.fork) { - wallets = wallets.concat(_getWallets({ provider: ctx.provider })); - } wallets = wallets.concat(loadLocalWallets({ provider: ctx.provider })); // Build ctx.users - ctx.users = {}; ctx.users.owner = wallets[0]; + ctx.users.deployer = ctx.users.owner; ctx.users.someUser = wallets[1]; ctx.users.otherUser = wallets[2]; for (let i = 3; i < wallets.length; i++) { ctx.users[`user${i}`] = wallets[i]; } -} -function _getWallets({ provider }) { - const users = getUsers({ network: 'mainnet' }); + if (ctx.fork) { + ctx.users = { ...ctx.users, ..._getWallets({ ctx, provider: ctx.provider }) }; + } else if (ctx.useOvm) { + // Here we set a default private key for local-ovm deployment, as the + // OVM geth node has no notion of local/unlocked accounts. + // Deploying without a private key will give the error "OVM: Unsupported RPC method", + // as the OVM node does not support eth_sendTransaction, which inherently relies on + // the unlocked accounts on the node. + // Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + const privateKey = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'; + + ctx.users.owner = new ethers.Wallet(privateKey, ctx.provider); + ctx.users.owner.address = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'; + ctx.users.deployer = ctx.users.owner; + } +} - const signers = users - .filter(user => user.name !== 'fee') - .filter(user => user.name !== 'zero') - .map(user => { - const signer = provider.getSigner(user.address); - signer.address = signer._address; +function _getWallets({ ctx, provider }) { + const usersArray = getUsers(ctx); - return signer; - }); + const usersObj = {}; + for (const user of usersArray) { + usersObj[user.name] = provider.getSigner(user.address); + usersObj[user.name].address = user.address; + } - return signers; + return usersObj; } module.exports = { diff --git a/test/publish/index.js b/test/publish/index.js index 46fa1250fd..f26ff15ed7 100644 --- a/test/publish/index.js +++ b/test/publish/index.js @@ -309,7 +309,7 @@ describe('publish scripts', () => { assert.strictEqual( ( await Exchanger.feeRateForExchange(toBytes32('(ignored)'), toBytes32(synth.name)) - ).toString(), + )[0].toString(), rate ); } @@ -466,7 +466,7 @@ describe('publish scripts', () => { assert.strictEqual( ( await Exchanger.feeRateForExchange(toBytes32('(ignored)'), toBytes32('sUSD')) - ).toString(), + )[0].toString(), newRateForsUSD ); }); diff --git a/test/utils/index.js b/test/utils/index.js index 877bdb28cc..111bcdb6e2 100644 --- a/test/utils/index.js +++ b/test/utils/index.js @@ -371,11 +371,11 @@ module.exports = ({ web3 } = {}) => { assert.ok( actual.gte(expected.sub(variance)), - `Number is too small to be close (Delta between actual and expected is ${actualDelta.toString()}, but variance was only ${variance.toString()}` + `Number is too small to be close (actual is ${actualDelta.toString()}, but variance was only ${variance.toString()}` ); assert.ok( actual.lte(expected.add(variance)), - `Number is too large to be close (Delta between actual and expected is ${actualDelta.toString()}, but variance was only ${variance.toString()})` + `Number is too large to be close (actual is ${actualDelta.toString()}, but variance was only ${variance.toString()})` ); }; @@ -592,9 +592,9 @@ module.exports = ({ web3 } = {}) => { divideDecimalRound, powerToDecimal, + toBN, toUnit, fromUnit, - toBN, toPreciseUnit, fromPreciseUnit,