My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x980e97853f57286f084538e807f1ca89e70c3b1b68c99fce54738988242a76a8 | Nominate New Own... | 701569 | 846 days 6 hrs ago | 0x3c05b1239b223c969540fefc0270227a2b00e047 | IN | Synthetix: Wrapper Factory | 0 ETH | 0.000692107635 | |
0xb8b6fc36b7cb72f52654255e77079e4cde9879626145c0342c39693ec1c5e7c9 | 0x60806040 | 701057 | 846 days 7 hrs ago | 0x3c05b1239b223c969540fefc0270227a2b00e047 | IN | Create: WrapperFactory | 0 ETH | 0.042033191775 |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
WrapperFactory
Compiler Version
v0.5.16+commit.9c3226ce
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Optimistic.Etherscan.io on 2021-12-03 */ /* ____ __ __ __ _ / __/__ __ ___ / /_ / / ___ / /_ (_)__ __ _\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ / /___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\ /___/ * Synthetix: WrapperFactory.sol * * Latest source (may be newer): https://github.com/Synthetixio/synthetix/blob/master/contracts/WrapperFactory.sol * Docs: https://docs.synthetix.io/contracts/WrapperFactory * * Contract Dependencies: * - IAddressResolver * - IWrapper * - IWrapperFactory * - MixinResolver * - MixinSystemSettings * - Owned * - Pausable * Libraries: * - SafeDecimalMath * - SafeMath * * MIT License * =========== * * Copyright (c) 2021 Synthetix * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ pragma solidity ^0.5.16; // https://docs.synthetix.io/contracts/source/contracts/owned contract Owned { address public owner; address public nominatedOwner; constructor(address _owner) public { require(_owner != address(0), "Owner address cannot be 0"); owner = _owner; emit OwnerChanged(address(0), _owner); } function nominateNewOwner(address _owner) external onlyOwner { nominatedOwner = _owner; emit OwnerNominated(_owner); } function acceptOwnership() external { require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); emit OwnerChanged(owner, nominatedOwner); owner = nominatedOwner; nominatedOwner = address(0); } modifier onlyOwner { _onlyOwner(); _; } function _onlyOwner() private view { require(msg.sender == owner, "Only the contract owner may perform this action"); } event OwnerNominated(address newOwner); event OwnerChanged(address oldOwner, address newOwner); } // https://docs.synthetix.io/contracts/source/interfaces/iaddressresolver interface IAddressResolver { function getAddress(bytes32 name) external view returns (address); function getSynth(bytes32 key) external view returns (address); function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address); } // https://docs.synthetix.io/contracts/source/interfaces/isynth interface ISynth { // Views function currencyKey() external view returns (bytes32); function transferableSynths(address account) external view returns (uint); // Mutative functions function transferAndSettle(address to, uint value) external returns (bool); function transferFromAndSettle( address from, address to, uint value ) external returns (bool); // Restricted: used internally to Synthetix function burn(address account, uint amount) external; function issue(address account, uint amount) external; } // https://docs.synthetix.io/contracts/source/interfaces/iissuer interface IIssuer { // Views function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid); function availableCurrencyKeys() external view returns (bytes32[] memory); function availableSynthCount() external view returns (uint); function availableSynths(uint index) external view returns (ISynth); function canBurnSynths(address account) external view returns (bool); function collateral(address account) external view returns (uint); function collateralisationRatio(address issuer) external view returns (uint); function collateralisationRatioAndAnyRatesInvalid(address _issuer) external view returns (uint cratio, bool anyRateIsInvalid); function debtBalanceOf(address issuer, bytes32 currencyKey) external view returns (uint debtBalance); function issuanceRatio() external view returns (uint); function lastIssueEvent(address account) external view returns (uint); function maxIssuableSynths(address issuer) external view returns (uint maxIssuable); function minimumStakeTime() external view returns (uint); function remainingIssuableSynths(address issuer) external view returns ( uint maxIssuable, uint alreadyIssued, uint totalSystemDebt ); function synths(bytes32 currencyKey) external view returns (ISynth); function getSynths(bytes32[] calldata currencyKeys) external view returns (ISynth[] memory); function synthsByAddress(address synthAddress) external view returns (bytes32); function totalIssuedSynths(bytes32 currencyKey, bool excludeOtherCollateral) external view returns (uint); function transferableSynthetixAndAnyRateIsInvalid(address account, uint balance) external view returns (uint transferable, bool anyRateIsInvalid); // Restricted: used internally to Synthetix function issueSynths(address from, uint amount) external; function issueSynthsOnBehalf( address issueFor, address from, uint amount ) external; function issueMaxSynths(address from) external; function issueMaxSynthsOnBehalf(address issueFor, address from) external; function burnSynths(address from, uint amount) external; function burnSynthsOnBehalf( address burnForAddress, address from, uint amount ) external; function burnSynthsToTarget(address from) external; function burnSynthsToTargetOnBehalf(address burnForAddress, address from) external; function burnForRedemption( address deprecatedSynthProxy, address account, uint balance ) external; function liquidateDelinquentAccount( address account, uint susdAmount, address liquidator ) external returns (uint totalRedeemed, uint amountToLiquidate); } // Inheritance // Internal references // https://docs.synthetix.io/contracts/source/contracts/addressresolver contract AddressResolver is Owned, IAddressResolver { mapping(bytes32 => address) public repository; constructor(address _owner) public Owned(_owner) {} /* ========== RESTRICTED FUNCTIONS ========== */ function importAddresses(bytes32[] calldata names, address[] calldata destinations) external onlyOwner { require(names.length == destinations.length, "Input lengths must match"); for (uint i = 0; i < names.length; i++) { bytes32 name = names[i]; address destination = destinations[i]; repository[name] = destination; emit AddressImported(name, destination); } } /* ========= PUBLIC FUNCTIONS ========== */ function rebuildCaches(MixinResolver[] calldata destinations) external { for (uint i = 0; i < destinations.length; i++) { destinations[i].rebuildCache(); } } /* ========== VIEWS ========== */ function areAddressesImported(bytes32[] calldata names, address[] calldata destinations) external view returns (bool) { for (uint i = 0; i < names.length; i++) { if (repository[names[i]] != destinations[i]) { return false; } } return true; } function getAddress(bytes32 name) external view returns (address) { return repository[name]; } function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address) { address _foundAddress = repository[name]; require(_foundAddress != address(0), reason); return _foundAddress; } function getSynth(bytes32 key) external view returns (address) { IIssuer issuer = IIssuer(repository["Issuer"]); require(address(issuer) != address(0), "Cannot find Issuer address"); return address(issuer.synths(key)); } /* ========== EVENTS ========== */ event AddressImported(bytes32 name, address destination); } // Internal references // https://docs.synthetix.io/contracts/source/contracts/mixinresolver contract MixinResolver { AddressResolver public resolver; mapping(bytes32 => address) private addressCache; constructor(address _resolver) internal { resolver = AddressResolver(_resolver); } /* ========== INTERNAL FUNCTIONS ========== */ function combineArrays(bytes32[] memory first, bytes32[] memory second) internal pure returns (bytes32[] memory combination) { combination = new bytes32[](first.length + second.length); for (uint i = 0; i < first.length; i++) { combination[i] = first[i]; } for (uint j = 0; j < second.length; j++) { combination[first.length + j] = second[j]; } } /* ========== PUBLIC FUNCTIONS ========== */ // Note: this function is public not external in order for it to be overridden and invoked via super in subclasses function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {} function rebuildCache() public { bytes32[] memory requiredAddresses = resolverAddressesRequired(); // The resolver must call this function whenver it updates its state for (uint i = 0; i < requiredAddresses.length; i++) { bytes32 name = requiredAddresses[i]; // Note: can only be invoked once the resolver has all the targets needed added address destination = resolver.requireAndGetAddress(name, string(abi.encodePacked("Resolver missing target: ", name))); addressCache[name] = destination; emit CacheUpdated(name, destination); } } /* ========== VIEWS ========== */ function isResolverCached() external view returns (bool) { bytes32[] memory requiredAddresses = resolverAddressesRequired(); for (uint i = 0; i < requiredAddresses.length; i++) { bytes32 name = requiredAddresses[i]; // false if our cache is invalid or if the resolver doesn't have the required address if (resolver.getAddress(name) != addressCache[name] || addressCache[name] == address(0)) { return false; } } return true; } /* ========== INTERNAL FUNCTIONS ========== */ function requireAndGetAddress(bytes32 name) internal view returns (address) { address _foundAddress = addressCache[name]; require(_foundAddress != address(0), string(abi.encodePacked("Missing address: ", name))); return _foundAddress; } /* ========== EVENTS ========== */ event CacheUpdated(bytes32 name, address destination); } // Inheritance // https://docs.synthetix.io/contracts/source/contracts/pausable contract Pausable is Owned { uint public lastPauseTime; bool public paused; constructor() internal { // This contract is abstract, and thus cannot be instantiated directly require(owner != address(0), "Owner must be set"); // Paused will be false, and lastPauseTime will be 0 upon initialisation } /** * @notice Change the paused state of the contract * @dev Only the contract owner may call this. */ function setPaused(bool _paused) external onlyOwner { // Ensure we're actually changing the state before we do anything if (_paused == paused) { return; } // Set our paused state. paused = _paused; // If applicable, set the last pause time. if (paused) { lastPauseTime = now; } // Let everyone know that our pause state has changed. emit PauseChanged(paused); } event PauseChanged(bool isPaused); modifier notPaused { require(!paused, "This action cannot be performed while the contract is paused"); _; } } // https://docs.synthetix.io/contracts/source/interfaces/ierc20 interface IERC20 { // ERC20 Optional Views function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); // Views function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); // Mutative functions function transfer(address to, uint value) external returns (bool); function approve(address spender, uint value) external returns (bool); function transferFrom( address from, address to, uint value ) external returns (bool); // Events event Transfer(address indexed from, address indexed to, uint value); event Approval(address indexed owner, address indexed spender, uint value); } // https://docs.synthetix.io/contracts/source/interfaces/iwrapper interface IWrapper { function mint(uint amount) external; function burn(uint amount) external; function capacity() external view returns (uint); function totalIssuedSynths() external view returns (uint); function calculateMintFee(uint amount) external view returns (uint, bool); function calculateBurnFee(uint amount) external view returns (uint, bool); function maxTokenAmount() external view returns (uint256); function mintFeeRate() external view returns (int256); function burnFeeRate() external view returns (int256); } // https://docs.synthetix.io/contracts/source/interfaces/iexchangerates interface IExchangeRates { // Structs struct RateAndUpdatedTime { uint216 rate; uint40 time; } // Views function aggregators(bytes32 currencyKey) external view returns (address); function aggregatorWarningFlags() external view returns (address); function anyRateIsInvalid(bytes32[] calldata currencyKeys) external view returns (bool); function currentRoundForRate(bytes32 currencyKey) external view returns (uint); function currenciesUsingAggregator(address aggregator) external view returns (bytes32[] memory); function effectiveValue( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external view returns (uint value); function effectiveValueAndRates( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external view returns ( uint value, uint sourceRate, uint destinationRate ); function effectiveAtomicValueAndRates( bytes32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey ) external view returns ( uint value, uint systemValue, uint systemSourceRate, 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( bytes32 currencyKey, uint startingRoundId, uint startingTimestamp, uint timediff ) external view returns (uint); function lastRateUpdateTimes(bytes32 currencyKey) external view returns (uint256); function oracle() external view returns (address); function rateAndTimestampAtRound(bytes32 currencyKey, uint roundId) external view returns (uint rate, uint time); function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time); function rateAndInvalid(bytes32 currencyKey) external view returns (uint rate, bool isInvalid); function rateForCurrency(bytes32 currencyKey) external view returns (uint); function rateIsFlagged(bytes32 currencyKey) external view returns (bool); function rateIsInvalid(bytes32 currencyKey) external view returns (bool); function rateIsStale(bytes32 currencyKey) external view returns (bool); function rateStalePeriod() external view returns (uint); function ratesAndUpdatedTimeForCurrencyLastNRounds(bytes32 currencyKey, uint numRounds) external view returns (uint[] memory rates, uint[] memory times); function ratesAndInvalidForCurrencies(bytes32[] calldata currencyKeys) external view returns (uint[] memory rates, bool anyRateInvalid); function ratesForCurrencies(bytes32[] calldata currencyKeys) external view returns (uint[] memory); function synthTooVolatileForAtomicExchange(bytes32 currencyKey) external view returns (bool); } interface IDebtCache { // Views function cachedDebt() external view returns (uint); function cachedSynthDebt(bytes32 currencyKey) external view returns (uint); function cacheTimestamp() external view returns (uint); function cacheInvalid() external view returns (bool); function cacheStale() external view returns (bool); function currentSynthDebts(bytes32[] calldata currencyKeys) external view returns ( uint[] memory debtValues, uint excludedDebt, bool anyRateIsInvalid ); function cachedSynthDebts(bytes32[] calldata currencyKeys) external view returns (uint[] memory debtValues); function totalNonSnxBackedDebt() external view returns (uint excludedDebt, bool isInvalid); function currentDebt() external view returns (uint debt, bool anyRateIsInvalid); function cacheInfo() external view returns ( uint debt, uint timestamp, bool isInvalid, bool isStale ); // Mutative functions function updateCachedSynthDebts(bytes32[] calldata currencyKeys) external; function updateCachedSynthDebtWithRate(bytes32 currencyKey, uint currencyRate) external; function updateCachedSynthDebtsWithRates(bytes32[] calldata currencyKeys, uint[] calldata currencyRates) external; function updateDebtCacheValidity(bool currentlyInvalid) external; function purgeCachedSynthDebt(bytes32 currencyKey) external; function takeDebtSnapshot() external; function recordExcludedDebtChange(bytes32 currencyKey, int256 delta) external; function updateCachedsUSDDebt(int amount) external; } // https://docs.synthetix.io/contracts/source/interfaces/isystemstatus interface ISystemStatus { struct Status { bool canSuspend; bool canResume; } struct Suspension { bool suspended; // reason is an integer code, // 0 => no reason, 1 => upgrading, 2+ => defined by system usage uint248 reason; } // Views function accessControl(bytes32 section, address account) external view returns (bool canSuspend, bool canResume); function requireSystemActive() external view; function requireIssuanceActive() external view; function requireExchangeActive() external view; function requireExchangeBetweenSynthsAllowed(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view; function requireSynthActive(bytes32 currencyKey) external view; function requireSynthsActive(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view; function systemSuspension() external view returns (bool suspended, uint248 reason); function issuanceSuspension() external view returns (bool suspended, uint248 reason); function exchangeSuspension() external view returns (bool suspended, uint248 reason); function synthExchangeSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason); function synthSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason); function getSynthExchangeSuspensions(bytes32[] calldata synths) external view returns (bool[] memory exchangeSuspensions, uint256[] memory reasons); function getSynthSuspensions(bytes32[] calldata synths) external view returns (bool[] memory suspensions, uint256[] memory reasons); // Restricted functions function suspendSynth(bytes32 currencyKey, uint256 reason) external; function updateAccessControl( bytes32 section, address account, bool canSuspend, bool canResume ) external; } // https://docs.synthetix.io/contracts/source/interfaces/iwrapperfactory interface IWrapperFactory { function isWrapper(address possibleWrapper) external view returns (bool); function createWrapper( IERC20 token, bytes32 currencyKey, bytes32 synthContractName ) external returns (address); function distributeFees() external; } // https://docs.synthetix.io/contracts/source/interfaces/iflexiblestorage interface IFlexibleStorage { // Views function getUIntValue(bytes32 contractName, bytes32 record) external view returns (uint); function getUIntValues(bytes32 contractName, bytes32[] calldata records) external view returns (uint[] memory); function getIntValue(bytes32 contractName, bytes32 record) external view returns (int); function getIntValues(bytes32 contractName, bytes32[] calldata records) external view returns (int[] memory); function getAddressValue(bytes32 contractName, bytes32 record) external view returns (address); function getAddressValues(bytes32 contractName, bytes32[] calldata records) external view returns (address[] memory); function getBoolValue(bytes32 contractName, bytes32 record) external view returns (bool); function getBoolValues(bytes32 contractName, bytes32[] calldata records) external view returns (bool[] memory); function getBytes32Value(bytes32 contractName, bytes32 record) external view returns (bytes32); function getBytes32Values(bytes32 contractName, bytes32[] calldata records) external view returns (bytes32[] memory); // Mutative functions function deleteUIntValue(bytes32 contractName, bytes32 record) external; function deleteIntValue(bytes32 contractName, bytes32 record) external; function deleteAddressValue(bytes32 contractName, bytes32 record) external; function deleteBoolValue(bytes32 contractName, bytes32 record) external; function deleteBytes32Value(bytes32 contractName, bytes32 record) external; function setUIntValue( bytes32 contractName, bytes32 record, uint value ) external; function setUIntValues( bytes32 contractName, bytes32[] calldata records, uint[] calldata values ) external; function setIntValue( bytes32 contractName, bytes32 record, int value ) external; function setIntValues( bytes32 contractName, bytes32[] calldata records, int[] calldata values ) external; function setAddressValue( bytes32 contractName, bytes32 record, address value ) external; function setAddressValues( bytes32 contractName, bytes32[] calldata records, address[] calldata values ) external; function setBoolValue( bytes32 contractName, bytes32 record, bool value ) external; function setBoolValues( bytes32 contractName, bytes32[] calldata records, bool[] calldata values ) external; function setBytes32Value( bytes32 contractName, bytes32 record, bytes32 value ) external; function setBytes32Values( bytes32 contractName, bytes32[] calldata records, bytes32[] calldata values ) external; } // Internal references // https://docs.synthetix.io/contracts/source/contracts/mixinsystemsettings contract MixinSystemSettings is MixinResolver { bytes32 internal constant SETTING_CONTRACT_NAME = "SystemSettings"; bytes32 internal constant SETTING_WAITING_PERIOD_SECS = "waitingPeriodSecs"; bytes32 internal constant SETTING_PRICE_DEVIATION_THRESHOLD_FACTOR = "priceDeviationThresholdFactor"; bytes32 internal constant SETTING_ISSUANCE_RATIO = "issuanceRatio"; bytes32 internal constant SETTING_FEE_PERIOD_DURATION = "feePeriodDuration"; bytes32 internal constant SETTING_TARGET_THRESHOLD = "targetThreshold"; bytes32 internal constant SETTING_LIQUIDATION_DELAY = "liquidationDelay"; bytes32 internal constant SETTING_LIQUIDATION_RATIO = "liquidationRatio"; bytes32 internal constant SETTING_LIQUIDATION_PENALTY = "liquidationPenalty"; bytes32 internal constant SETTING_RATE_STALE_PERIOD = "rateStalePeriod"; bytes32 internal constant SETTING_EXCHANGE_FEE_RATE = "exchangeFeeRate"; bytes32 internal constant SETTING_MINIMUM_STAKE_TIME = "minimumStakeTime"; bytes32 internal constant SETTING_AGGREGATOR_WARNING_FLAGS = "aggregatorWarningFlags"; bytes32 internal constant SETTING_TRADING_REWARDS_ENABLED = "tradingRewardsEnabled"; bytes32 internal constant SETTING_DEBT_SNAPSHOT_STALE_TIME = "debtSnapshotStaleTime"; bytes32 internal constant SETTING_CROSS_DOMAIN_DEPOSIT_GAS_LIMIT = "crossDomainDepositGasLimit"; bytes32 internal constant SETTING_CROSS_DOMAIN_ESCROW_GAS_LIMIT = "crossDomainEscrowGasLimit"; bytes32 internal constant SETTING_CROSS_DOMAIN_REWARD_GAS_LIMIT = "crossDomainRewardGasLimit"; bytes32 internal constant SETTING_CROSS_DOMAIN_WITHDRAWAL_GAS_LIMIT = "crossDomainWithdrawalGasLimit"; bytes32 internal constant SETTING_CROSS_DOMAIN_RELAY_GAS_LIMIT = "crossDomainRelayGasLimit"; bytes32 internal constant SETTING_ETHER_WRAPPER_MAX_ETH = "etherWrapperMaxETH"; bytes32 internal constant SETTING_ETHER_WRAPPER_MINT_FEE_RATE = "etherWrapperMintFeeRate"; bytes32 internal constant SETTING_ETHER_WRAPPER_BURN_FEE_RATE = "etherWrapperBurnFeeRate"; bytes32 internal constant SETTING_WRAPPER_MAX_TOKEN_AMOUNT = "wrapperMaxTokens"; bytes32 internal constant SETTING_WRAPPER_MINT_FEE_RATE = "wrapperMintFeeRate"; bytes32 internal constant SETTING_WRAPPER_BURN_FEE_RATE = "wrapperBurnFeeRate"; bytes32 internal constant SETTING_MIN_CRATIO = "minCratio"; bytes32 internal constant SETTING_NEW_COLLATERAL_MANAGER = "newCollateralManager"; bytes32 internal constant SETTING_INTERACTION_DELAY = "interactionDelay"; bytes32 internal constant SETTING_COLLAPSE_FEE_RATE = "collapseFeeRate"; bytes32 internal constant SETTING_ATOMIC_MAX_VOLUME_PER_BLOCK = "atomicMaxVolumePerBlock"; bytes32 internal constant SETTING_ATOMIC_TWAP_WINDOW = "atomicTwapWindow"; bytes32 internal constant SETTING_ATOMIC_EQUIVALENT_FOR_DEX_PRICING = "atomicEquivalentForDexPricing"; bytes32 internal constant SETTING_ATOMIC_EXCHANGE_FEE_RATE = "atomicExchangeFeeRate"; bytes32 internal constant SETTING_ATOMIC_PRICE_BUFFER = "atomicPriceBuffer"; bytes32 internal constant SETTING_ATOMIC_VOLATILITY_CONSIDERATION_WINDOW = "atomicVolConsiderationWindow"; bytes32 internal constant SETTING_ATOMIC_VOLATILITY_UPDATE_THRESHOLD = "atomicVolUpdateThreshold"; bytes32 internal constant CONTRACT_FLEXIBLESTORAGE = "FlexibleStorage"; enum CrossDomainMessageGasLimits {Deposit, Escrow, Reward, Withdrawal, Relay} constructor(address _resolver) internal MixinResolver(_resolver) {} function resolverAddressesRequired() public view returns (bytes32[] memory addresses) { addresses = new bytes32[](1); addresses[0] = CONTRACT_FLEXIBLESTORAGE; } function flexibleStorage() internal view returns (IFlexibleStorage) { return IFlexibleStorage(requireAndGetAddress(CONTRACT_FLEXIBLESTORAGE)); } function _getGasLimitSetting(CrossDomainMessageGasLimits gasLimitType) internal pure returns (bytes32) { if (gasLimitType == CrossDomainMessageGasLimits.Deposit) { return SETTING_CROSS_DOMAIN_DEPOSIT_GAS_LIMIT; } else if (gasLimitType == CrossDomainMessageGasLimits.Escrow) { return SETTING_CROSS_DOMAIN_ESCROW_GAS_LIMIT; } else if (gasLimitType == CrossDomainMessageGasLimits.Reward) { return SETTING_CROSS_DOMAIN_REWARD_GAS_LIMIT; } else if (gasLimitType == CrossDomainMessageGasLimits.Withdrawal) { return SETTING_CROSS_DOMAIN_WITHDRAWAL_GAS_LIMIT; } else if (gasLimitType == CrossDomainMessageGasLimits.Relay) { return SETTING_CROSS_DOMAIN_RELAY_GAS_LIMIT; } else { revert("Unknown gas limit type"); } } function getCrossDomainMessageGasLimit(CrossDomainMessageGasLimits gasLimitType) internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, _getGasLimitSetting(gasLimitType)); } function getTradingRewardsEnabled() internal view returns (bool) { return flexibleStorage().getBoolValue(SETTING_CONTRACT_NAME, SETTING_TRADING_REWARDS_ENABLED); } function getWaitingPeriodSecs() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_WAITING_PERIOD_SECS); } function getPriceDeviationThresholdFactor() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_PRICE_DEVIATION_THRESHOLD_FACTOR); } function getIssuanceRatio() internal view returns (uint) { // lookup on flexible storage directly for gas savings (rather than via SystemSettings) return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ISSUANCE_RATIO); } function getFeePeriodDuration() internal view returns (uint) { // lookup on flexible storage directly for gas savings (rather than via SystemSettings) return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_FEE_PERIOD_DURATION); } function getTargetThreshold() internal view returns (uint) { // lookup on flexible storage directly for gas savings (rather than via SystemSettings) return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_TARGET_THRESHOLD); } function getLiquidationDelay() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_DELAY); } function getLiquidationRatio() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_RATIO); } function getLiquidationPenalty() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_PENALTY); } function getRateStalePeriod() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_RATE_STALE_PERIOD); } function getExchangeFeeRate(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_EXCHANGE_FEE_RATE, currencyKey)) ); } function getMinimumStakeTime() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_MINIMUM_STAKE_TIME); } function getAggregatorWarningFlags() internal view returns (address) { return flexibleStorage().getAddressValue(SETTING_CONTRACT_NAME, SETTING_AGGREGATOR_WARNING_FLAGS); } function getDebtSnapshotStaleTime() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_DEBT_SNAPSHOT_STALE_TIME); } function getEtherWrapperMaxETH() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ETHER_WRAPPER_MAX_ETH); } function getEtherWrapperMintFeeRate() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ETHER_WRAPPER_MINT_FEE_RATE); } function getEtherWrapperBurnFeeRate() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ETHER_WRAPPER_BURN_FEE_RATE); } function getWrapperMaxTokenAmount(address wrapper) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_WRAPPER_MAX_TOKEN_AMOUNT, wrapper)) ); } function getWrapperMintFeeRate(address wrapper) internal view returns (int) { return flexibleStorage().getIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_WRAPPER_MINT_FEE_RATE, wrapper)) ); } function getWrapperBurnFeeRate(address wrapper) internal view returns (int) { return flexibleStorage().getIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_WRAPPER_BURN_FEE_RATE, wrapper)) ); } function getMinCratio(address collateral) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_MIN_CRATIO, collateral)) ); } function getNewCollateralManager(address collateral) internal view returns (address) { return flexibleStorage().getAddressValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_NEW_COLLATERAL_MANAGER, collateral)) ); } function getInteractionDelay(address collateral) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_INTERACTION_DELAY, collateral)) ); } function getCollapseFeeRate(address collateral) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_COLLAPSE_FEE_RATE, collateral)) ); } function getAtomicMaxVolumePerBlock() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ATOMIC_MAX_VOLUME_PER_BLOCK); } function getAtomicTwapWindow() internal view returns (uint) { return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ATOMIC_TWAP_WINDOW); } function getAtomicEquivalentForDexPricing(bytes32 currencyKey) internal view returns (address) { return flexibleStorage().getAddressValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_ATOMIC_EQUIVALENT_FOR_DEX_PRICING, currencyKey)) ); } function getAtomicExchangeFeeRate(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_ATOMIC_EXCHANGE_FEE_RATE, currencyKey)) ); } function getAtomicPriceBuffer(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_ATOMIC_PRICE_BUFFER, currencyKey)) ); } function getAtomicVolatilityConsiderationWindow(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_ATOMIC_VOLATILITY_CONSIDERATION_WINDOW, currencyKey)) ); } function getAtomicVolatilityUpdateThreshold(bytes32 currencyKey) internal view returns (uint) { return flexibleStorage().getUIntValue( SETTING_CONTRACT_NAME, keccak256(abi.encodePacked(SETTING_ATOMIC_VOLATILITY_UPDATE_THRESHOLD, currencyKey)) ); } } /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, "SafeMath: modulo by zero"); return a % b; } } // Libraries // https://docs.synthetix.io/contracts/source/libraries/safedecimalmath library SafeDecimalMath { using SafeMath for uint; /* Number of decimal places in the representations. */ uint8 public constant decimals = 18; uint8 public constant highPrecisionDecimals = 27; /* The number representing 1.0. */ uint public constant UNIT = 10**uint(decimals); /* The number representing 1.0 for higher fidelity numbers. */ uint public constant PRECISE_UNIT = 10**uint(highPrecisionDecimals); uint private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10**uint(highPrecisionDecimals - decimals); /** * @return Provides an interface to UNIT. */ function unit() external pure returns (uint) { return UNIT; } /** * @return Provides an interface to PRECISE_UNIT. */ function preciseUnit() external pure returns (uint) { return PRECISE_UNIT; } /** * @return The result of multiplying x and y, interpreting the operands as fixed-point * decimals. * * @dev A unit factor is divided out after the product of x and y is evaluated, * so that product must be less than 2**256. As this is an integer division, * the internal division always rounds down. This helps save on gas. Rounding * is more expensive on gas. */ function multiplyDecimal(uint x, uint y) internal pure returns (uint) { /* Divide by UNIT to remove the extra factor introduced by the product. */ return x.mul(y) / UNIT; } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of the specified precision unit. * * @dev The operands should be in the form of a the specified unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function _multiplyDecimalRound( uint x, uint y, uint precisionUnit ) private pure returns (uint) { /* Divide by UNIT to remove the extra factor introduced by the product. */ uint quotientTimesTen = x.mul(y) / (precisionUnit / 10); if (quotientTimesTen % 10 >= 5) { quotientTimesTen += 10; } return quotientTimesTen / 10; } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of a precise unit. * * @dev The operands should be in the precise unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function multiplyDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) { return _multiplyDecimalRound(x, y, PRECISE_UNIT); } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of a standard unit. * * @dev The operands should be in the standard unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function multiplyDecimalRound(uint x, uint y) internal pure returns (uint) { return _multiplyDecimalRound(x, y, UNIT); } /** * @return The result of safely dividing x and y. The return value is a high * precision decimal. * * @dev y is divided after the product of x and the standard precision unit * is evaluated, so the product of x and UNIT must be less than 2**256. As * this is an integer division, the result is always rounded down. * This helps save on gas. Rounding is more expensive on gas. */ function divideDecimal(uint x, uint y) internal pure returns (uint) { /* Reintroduce the UNIT factor that will be divided out by y. */ return x.mul(UNIT).div(y); } /** * @return The result of safely dividing x and y. The return value is as a rounded * decimal in the precision unit specified in the parameter. * * @dev y is divided after the product of x and the specified precision unit * is evaluated, so the product of x and the specified precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function _divideDecimalRound( uint x, uint y, uint precisionUnit ) private pure returns (uint) { uint resultTimesTen = x.mul(precisionUnit * 10).div(y); if (resultTimesTen % 10 >= 5) { resultTimesTen += 10; } return resultTimesTen / 10; } /** * @return The result of safely dividing x and y. The return value is as a rounded * standard precision decimal. * * @dev y is divided after the product of x and the standard precision unit * is evaluated, so the product of x and the standard precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function divideDecimalRound(uint x, uint y) internal pure returns (uint) { return _divideDecimalRound(x, y, UNIT); } /** * @return The result of safely dividing x and y. The return value is as a rounded * high precision decimal. * * @dev y is divided after the product of x and the high precision unit * is evaluated, so the product of x and the high precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function divideDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) { return _divideDecimalRound(x, y, PRECISE_UNIT); } /** * @dev Convert a standard decimal representation to a high precision one. */ function decimalToPreciseDecimal(uint i) internal pure returns (uint) { return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR); } /** * @dev Convert a high precision decimal to a standard decimal representation. */ function preciseDecimalToDecimal(uint i) internal pure returns (uint) { uint quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10); if (quotientTimesTen % 10 >= 5) { quotientTimesTen += 10; } return quotientTimesTen / 10; } // Computes `a - b`, setting the value to 0 if b > a. function floorsub(uint a, uint b) internal pure returns (uint) { return b >= a ? 0 : a - b; } /* ---------- Utilities ---------- */ /* * Absolute value of the input, returned as a signed number. */ function signedAbs(int x) internal pure returns (int) { return x < 0 ? -x : x; } /* * Absolute value of the input, returned as an unsigned number. */ function abs(int x) internal pure returns (uint) { return uint(signedAbs(x)); } } // Inheritance // Internal references // Libraries // https://docs.synthetix.io/contracts/source/contracts/wrapper contract Wrapper is Owned, Pausable, MixinResolver, MixinSystemSettings, IWrapper { using SafeMath for uint; using SafeDecimalMath for uint; /* ========== ENCODED NAMES ========== */ bytes32 internal constant sUSD = "sUSD"; /* ========== ADDRESS RESOLVER CONFIGURATION ========== */ bytes32 private constant CONTRACT_SYNTH_SUSD = "SynthsUSD"; bytes32 private constant CONTRACT_EXRATES = "ExchangeRates"; bytes32 private constant CONTRACT_DEBTCACHE = "DebtCache"; bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus"; bytes32 private constant CONTRACT_WRAPPERFACTORY = "WrapperFactory"; // ========== STATE VARIABLES ========== // NOTE: these values should ideally be `immutable` instead of public IERC20 public token; bytes32 public currencyKey; bytes32 public synthContractName; uint public targetSynthIssued; constructor( address _owner, address _resolver, IERC20 _token, bytes32 _currencyKey, bytes32 _synthContractName ) public Owned(_owner) MixinSystemSettings(_resolver) { token = _token; currencyKey = _currencyKey; synthContractName = _synthContractName; targetSynthIssued = 0; token.approve(address(this), uint256(-1)); } /* ========== VIEWS ========== */ function resolverAddressesRequired() public view returns (bytes32[] memory addresses) { bytes32[] memory existingAddresses = MixinSystemSettings.resolverAddressesRequired(); bytes32[] memory newAddresses = new bytes32[](6); newAddresses[0] = CONTRACT_SYNTH_SUSD; newAddresses[1] = synthContractName; newAddresses[2] = CONTRACT_EXRATES; newAddresses[3] = CONTRACT_DEBTCACHE; newAddresses[4] = CONTRACT_SYSTEMSTATUS; newAddresses[5] = CONTRACT_WRAPPERFACTORY; addresses = combineArrays(existingAddresses, newAddresses); return addresses; } /* ========== INTERNAL VIEWS ========== */ function synthsUSD() internal view returns (ISynth) { return ISynth(requireAndGetAddress(CONTRACT_SYNTH_SUSD)); } function synth() internal view returns (ISynth) { return ISynth(requireAndGetAddress(synthContractName)); } function exchangeRates() internal view returns (IExchangeRates) { return IExchangeRates(requireAndGetAddress(CONTRACT_EXRATES)); } function debtCache() internal view returns (IDebtCache) { return IDebtCache(requireAndGetAddress(CONTRACT_DEBTCACHE)); } function systemStatus() internal view returns (ISystemStatus) { return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS)); } function wrapperFactory() internal view returns (IWrapperFactory) { return IWrapperFactory(requireAndGetAddress(CONTRACT_WRAPPERFACTORY)); } /* ========== PUBLIC FUNCTIONS ========== */ // ========== VIEWS ========== function capacity() public view returns (uint _capacity) { // capacity = max(maxETH - balance, 0) uint balance = getReserves(); uint maxToken = maxTokenAmount(); if (balance >= maxToken) { return 0; } return maxToken.sub(balance); } function totalIssuedSynths() public view returns (uint) { // synths issued by this contract is always exactly equal to the balance of reserves return exchangeRates().effectiveValue(currencyKey, targetSynthIssued, sUSD); } function getReserves() public view returns (uint) { return token.balanceOf(address(this)); } function calculateMintFee(uint amount) public view returns (uint, bool) { int r = mintFeeRate(); if (r < 0) { return (amount.multiplyDecimalRound(uint(-r)), true); } else { return (amount.multiplyDecimalRound(uint(r)), false); } } function calculateBurnFee(uint amount) public view returns (uint, bool) { int r = burnFeeRate(); if (r < 0) { return (amount.multiplyDecimalRound(uint(-r)), true); } else { return (amount.multiplyDecimalRound(uint(r)), false); } } function maxTokenAmount() public view returns (uint256) { return getWrapperMaxTokenAmount(address(this)); } function mintFeeRate() public view returns (int256) { return getWrapperMintFeeRate(address(this)); } function burnFeeRate() public view returns (int256) { return getWrapperBurnFeeRate(address(this)); } /* ========== MUTATIVE FUNCTIONS ========== */ // Transfers `amountIn` token to mint `amountIn - fees` of currencyKey. // `amountIn` is inclusive of fees, calculable via `calculateMintFee`. function mint(uint amountIn) external notPaused issuanceActive { require(amountIn <= token.allowance(msg.sender, address(this)), "Allowance not high enough"); require(amountIn <= token.balanceOf(msg.sender), "Balance is too low"); require(!exchangeRates().rateIsInvalid(currencyKey), "Currency rate is invalid"); uint currentCapacity = capacity(); require(currentCapacity > 0, "Contract has no spare capacity to mint"); uint actualAmountIn = currentCapacity < amountIn ? currentCapacity : amountIn; (uint feeAmountTarget, bool negative) = calculateMintFee(actualAmountIn); uint mintAmount = negative ? actualAmountIn.add(feeAmountTarget) : actualAmountIn.sub(feeAmountTarget); // Transfer token from user. bool success = _safeTransferFrom(address(token), msg.sender, address(this), actualAmountIn); require(success, "Transfer did not succeed"); // Mint tokens to user _mint(mintAmount); emit Minted(msg.sender, mintAmount, negative ? 0 : feeAmountTarget, actualAmountIn); } // Burns `amountIn` synth for `amountIn - fees` amount of token. // `amountIn` is inclusive of fees, calculable via `calculateBurnFee`. function burn(uint amountIn) external notPaused issuanceActive { require(amountIn <= IERC20(address(synth())).balanceOf(msg.sender), "Balance is too low"); require(!exchangeRates().rateIsInvalid(currencyKey), "Currency rate is invalid"); require(totalIssuedSynths() > 0, "Contract cannot burn for token, token balance is zero"); (uint burnFee, bool negative) = calculateBurnFee(targetSynthIssued); uint burnAmount; uint amountOut; if (negative) { burnAmount = targetSynthIssued < amountIn ? targetSynthIssued.sub(burnFee) : amountIn; amountOut = burnAmount.multiplyDecimal( // -1e18 <= burnFeeRate <= 1e18 so this operation is safe uint(int(SafeDecimalMath.unit()) - burnFeeRate()) ); } else { burnAmount = targetSynthIssued.add(burnFee) < amountIn ? targetSynthIssued.add(burnFee) : amountIn; amountOut = burnAmount.divideDecimal( // -1e18 <= burnFeeRate <= 1e18 so this operation is safe uint(int(SafeDecimalMath.unit()) + burnFeeRate()) ); } uint feeAmountTarget = negative ? 0 : burnAmount.sub(amountOut); // Transfer token to user. bool success = _safeTransferFrom(address(token), address(this), msg.sender, amountOut); require(success, "Transfer did not succeed"); // Burn _burn(burnAmount); emit Burned(msg.sender, amountOut, feeAmountTarget, burnAmount); } // ========== RESTRICTED ========== /** * @notice Fallback function */ function() external payable { revert("Fallback disabled, use mint()"); } /* ========== INTERNAL FUNCTIONS ========== */ function _mint(uint amount) internal { uint reserves = getReserves(); uint excessAmount = reserves > targetSynthIssued.add(amount) ? reserves.sub(targetSynthIssued.add(amount)) : 0; uint excessAmountUsd = exchangeRates().effectiveValue(currencyKey, excessAmount, sUSD); // Mint `amount` to user. synth().issue(msg.sender, amount); // Escrow fee. if (excessAmountUsd > 0) { synthsUSD().issue(address(wrapperFactory()), excessAmountUsd); } // in the case of a negative fee extra synths will be issued, billed to the snx stakers _setTargetSynthIssued(reserves); } function _burn(uint amount) internal { uint reserves = getReserves(); // this is logically equivalent to getReserves() - (targetSynthIssued - amount), without going negative uint excessAmount = reserves.add(amount) > targetSynthIssued ? reserves.add(amount).sub(targetSynthIssued) : 0; uint excessAmountUsd = exchangeRates().effectiveValue(currencyKey, excessAmount, sUSD); // Burn `amount` of currencyKey from user. synth().burn(msg.sender, amount); // We use burn/issue instead of burning the principal and transferring the fee. // This saves an approval and is cheaper. // Escrow fee. if (excessAmountUsd > 0) { synthsUSD().issue(address(wrapperFactory()), excessAmountUsd); } // in the case of a negative fee fewer synths will be burned, billed to the snx stakers _setTargetSynthIssued(reserves); } function _setTargetSynthIssued(uint _targetSynthIssued) internal { debtCache().recordExcludedDebtChange(currencyKey, int256(_targetSynthIssued) - int256(targetSynthIssued)); targetSynthIssued = _targetSynthIssued; } function _safeTransferFrom( address _tokenAddress, address _from, address _to, uint256 _value ) internal returns (bool success) { // note: both of these could be replaced with manual mstore's to reduce cost if desired bytes memory msgData = abi.encodeWithSignature("transferFrom(address,address,uint256)", _from, _to, _value); uint msgSize = msgData.length; assembly { // pre-set scratch space to all bits set mstore(0x00, 0xff) // note: this requires tangerine whistle compatible EVM if iszero(call(gas(), _tokenAddress, 0, add(msgData, 0x20), msgSize, 0x00, 0x20)) { revert(0, 0) } switch mload(0x00) case 0xff { // token is not fully ERC20 compatible, didn't return anything, assume it was successful success := 1 } case 0x01 { success := 1 } case 0x00 { success := 0 } default { // unexpected value, what could this be? revert(0, 0) } } } modifier issuanceActive { systemStatus().requireIssuanceActive(); _; } /* ========== EVENTS ========== */ event Minted(address indexed account, uint principal, uint fee, uint amountIn); event Burned(address indexed account, uint principal, uint fee, uint amountIn); } // https://docs.synthetix.io/contracts/source/interfaces/ifeepool interface IFeePool { // Views // solhint-disable-next-line func-name-mixedcase function FEE_ADDRESS() external view returns (address); function feesAvailable(address account) external view returns (uint, uint); function feePeriodDuration() external view returns (uint); function isFeesClaimable(address account) external view returns (bool); function targetThreshold() external view returns (uint); function totalFeesAvailable() external view returns (uint); function totalRewardsAvailable() external view returns (uint); // Mutative Functions function claimFees() external returns (bool); function claimOnBehalf(address claimingForAddress) external returns (bool); function closeCurrentFeePeriod() external; // Restricted: used internally to Synthetix function appendAccountIssuanceRecord( address account, uint lockedAmount, uint debtEntryIndex ) external; function recordFeePaid(uint sUSDAmount) external; function setRewardsToDistribute(uint amount) external; } // Inheritance // Internal references // https://docs.synthetix.io/contracts/source/contracts/wrapperfactory contract WrapperFactory is Owned, MixinResolver, IWrapperFactory { bytes32 public constant CONTRACT_NAME = "WrapperFactory"; bytes32 internal constant CONTRACT_FLEXIBLESTORAGE = "FlexibleStorage"; bytes32 internal constant CONTRACT_SYNTH_SUSD = "SynthsUSD"; bytes32 internal constant CONTRACT_FEEPOOL = "FeePool"; uint internal constant WRAPPER_VERSION = 1; /* ========== CONSTRUCTOR ========== */ constructor(address _owner, address _resolver) public Owned(_owner) MixinResolver(_resolver) {} function resolverAddressesRequired() public view returns (bytes32[] memory addresses) { addresses = new bytes32[](3); addresses[0] = CONTRACT_SYNTH_SUSD; addresses[1] = CONTRACT_FLEXIBLESTORAGE; addresses[2] = CONTRACT_FEEPOOL; } /* ========== INTERNAL VIEWS ========== */ function synthsUSD() internal view returns (IERC20) { return IERC20(requireAndGetAddress(CONTRACT_SYNTH_SUSD)); } function flexibleStorage() internal view returns (IFlexibleStorage) { return IFlexibleStorage(requireAndGetAddress(CONTRACT_FLEXIBLESTORAGE)); } function feePool() internal view returns (IFeePool) { return IFeePool(requireAndGetAddress(CONTRACT_FEEPOOL)); } // ========== VIEWS ========== // Returns the version of a wrapper created by this wrapper factory // Used by MultiCollateralSynth to know if it should trust the wrapper contract function isWrapper(address possibleWrapper) external view returns (bool) { return flexibleStorage().getUIntValue(CONTRACT_NAME, bytes32(uint(address(possibleWrapper)))) > 0; } function feesEscrowed() public view returns (uint) { return synthsUSD().balanceOf(address(this)); } // ========== RESTRICTED ========== /** * @notice Fallback function */ function() external payable { revert("Contract is not payable"); } /* ========== MUTATIVE FUNCTIONS ========== */ function createWrapper( IERC20 token, bytes32 currencyKey, bytes32 synthContractName ) external onlyOwner returns (address) { // Create the wrapper instance Wrapper wrapper = new Wrapper(owner, address(resolver), token, currencyKey, synthContractName); // Rebuild caches immediately since it will almost certainly need to be done wrapper.rebuildCache(); // Register it so that MultiCollateralSynth knows to trust it flexibleStorage().setUIntValue(CONTRACT_NAME, bytes32(uint(address(wrapper))), WRAPPER_VERSION); emit WrapperCreated(address(token), currencyKey, address(wrapper)); return address(wrapper); } function distributeFees() external { // Normalize fee to sUSD uint amountSUSD = feesEscrowed(); if (amountSUSD > 0) { // Transfer sUSD to the fee pool bool success = synthsUSD().transfer(feePool().FEE_ADDRESS(), amountSUSD); require(success, "Transfer did not succeed"); } } event WrapperCreated(address indexed token, bytes32 indexed currencyKey, address wrapperAddress); }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_resolver","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"CacheUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":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":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"indexed":false,"internalType":"address","name":"wrapperAddress","type":"address"}],"name":"WrapperCreated","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[],"name":"CONTRACT_NAME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"internalType":"bytes32","name":"synthContractName","type":"bytes32"}],"name":"createWrapper","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"distributeFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"feesEscrowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isResolverCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"possibleWrapper","type":"address"}],"name":"isWrapper","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"rebuildCache","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"resolver","outputs":[{"internalType":"contract AddressResolver","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32[]","name":"addresses","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506040516135553803806135558339818101604052604081101561003357600080fd5b50805160209091015180826001600160a01b038116610099576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150600280546001600160a01b039092166001600160a01b03199092169190911790555050613431806101246000396000f3fe608060405260043610620000d45760003560e01c806375d920a9116200008b5780638da5cb5b11620000615780638da5cb5b14620002ae578063a106935d14620002c6578063bb57ad201462000309578063e0aa2797146200032157620000d4565b806375d920a9146200021457806379ba5097146200022c578063899ffef4146200024457620000d4565b806304f3bcec14620001215780631627540c14620001555780632af64bd3146200018e57806353a47bb714620001ba578063614d08f814620001d25780637418536014620001fc575b6040805162461bcd60e51b815260206004820152601760248201527f436f6e7472616374206973206e6f742070617961626c65000000000000000000604482015290519081900360640190fd5b3480156200012e57600080fd5b506200013962000358565b604080516001600160a01b039092168252519081900360200190f35b3480156200016257600080fd5b506200018c600480360360208110156200017b57600080fd5b50356001600160a01b031662000367565b005b3480156200019b57600080fd5b50620001a6620003c5565b604080519115158252519081900360200190f35b348015620001c757600080fd5b5062000139620004db565b348015620001df57600080fd5b50620001ea620004ea565b60408051918252519081900360200190f35b3480156200020957600080fd5b506200018c620004ff565b3480156200022157600080fd5b50620001ea620006d2565b3480156200023957600080fd5b506200018c62000767565b3480156200025157600080fd5b506200025c62000825565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156200029a57818101518382015260200162000280565b505050509050019250505060405180910390f35b348015620002bb57600080fd5b5062000139620008c3565b348015620002d357600080fd5b506200013960048036036060811015620002ec57600080fd5b506001600160a01b038135169060208101359060400135620008d2565b3480156200031657600080fd5b506200018c62000a8a565b3480156200032e57600080fd5b50620001a6600480360360208110156200034757600080fd5b50356001600160a01b031662000bff565b6002546001600160a01b031681565b6200037162000caa565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b60006060620003d362000825565b905060005b8151811015620004d1576000828281518110620003f157fe5b6020908102919091018101516000818152600383526040908190205460025482516321f8a72160e01b81526004810185905292519395506001600160a01b03918216949116926321f8a721926024808201939291829003018186803b1580156200045a57600080fd5b505afa1580156200046f573d6000803e3d6000fd5b505050506040513d60208110156200048657600080fd5b50516001600160a01b0316141580620004b457506000818152600360205260409020546001600160a01b0316155b15620004c75760009350505050620004d8565b50600101620003d8565b5060019150505b90565b6001546001600160a01b031681565b6d57726170706572466163746f727960901b81565b60606200050b62000825565b905060005b8151811015620006ce5760008282815181106200052957fe5b602090810291909101810151600254604080517f5265736f6c766572206d697373696e67207461726765743a2000000000000000818601526039808201859052825180830390910181526059820180845263dacb2d0160e01b9052605d8201858152607d83019384528151609d84015281519597506000966001600160a01b039095169563dacb2d01958995939492939260bd0191908501908083838c5b83811015620005e1578181015183820152602001620005c7565b50505050905090810190601f1680156200060f5780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b1580156200062e57600080fd5b505afa15801562000643573d6000803e3d6000fd5b505050506040513d60208110156200065a57600080fd5b505160008381526003602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518681529182015281519293507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68929081900390910190a1505060010162000510565b5050565b6000620006de62000cf7565b6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156200073457600080fd5b505afa15801562000749573d6000803e3d6000fd5b505050506040513d60208110156200076057600080fd5b5051905090565b6001546001600160a01b03163314620007b25760405162461bcd60e51b8152600401808060200182810382526035815260200180620033996035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b604080516003808252608082019092526060916020820183803883390190505090506814de5b9d1a1cd554d160ba1b816000815181106200086257fe5b6020026020010181815250506e466c657869626c6553746f7261676560881b816001815181106200088f57fe5b60200260200101818152505066119959541bdbdb60ca1b81600281518110620008b457fe5b60200260200101818152505090565b6000546001600160a01b031681565b6000620008de62000caa565b600080546002546040516001600160a01b039283169290911690879087908790620009099062000e2e565b6001600160a01b0395861681529385166020850152919093166040808401919091526060830193909352608082015290519081900360a001906000f08015801562000958573d6000803e3d6000fd5b509050806001600160a01b031663741853606040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200099757600080fd5b505af1158015620009ac573d6000803e3d6000fd5b50505050620009ba62000d15565b60408051631d5b277f60e01b81526d57726170706572466163746f727960901b60048201526001600160a01b0384811660248301526001604483015291519290911691631d5b277f9160648082019260009290919082900301818387803b15801562000a2557600080fd5b505af115801562000a3a573d6000803e3d6000fd5b5050604080516001600160a01b038581168252915188945091891692507f8aba3d0a3cbd86bcfc8d4d553823cb5030939fb35208794c1ca597046b2b561e919081900360200190a3949350505050565b600062000a96620006d2565b9050801562000bfc57600062000aab62000cf7565b6001600160a01b031663a9059cbb62000ac362000d34565b6001600160a01b031663eb1edd616040518163ffffffff1660e01b815260040160206040518083038186803b15801562000afc57600080fd5b505afa15801562000b11573d6000803e3d6000fd5b505050506040513d602081101562000b2857600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482018690525160448083019260209291908290030181600087803b15801562000b7957600080fd5b505af115801562000b8e573d6000803e3d6000fd5b505050506040513d602081101562000ba557600080fd5b5051905080620006ce576040805162461bcd60e51b815260206004820152601860248201527f5472616e7366657220646964206e6f7420737563636565640000000000000000604482015290519081900360640190fd5b50565b60008062000c0c62000d15565b6001600160a01b03166323257c2b6d57726170706572466163746f727960901b856001600160a01b031660001b6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801562000c7557600080fd5b505afa15801562000c8a573d6000803e3d6000fd5b505050506040513d602081101562000ca157600080fd5b50511192915050565b6000546001600160a01b0316331462000cf55760405162461bcd60e51b815260040180806020018281038252602f815260200180620033ce602f913960400191505060405180910390fd5b565b600062000d106814de5b9d1a1cd554d160ba1b62000d46565b905090565b600062000d106e466c657869626c6553746f7261676560881b62000d46565b600062000d1066119959541bdbdb60ca1b5b600081815260036020908152604080832054815170026b4b9b9b4b7339030b2323932b9b99d1607d1b9381019390935260318084018690528251808503909101815260519093019091526001600160a01b0316908162000e275760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101562000deb57818101518382015260200162000dd1565b50505050905090810190601f16801562000e195780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5092915050565b61255c8062000e3d8339019056fe60806040523480156200001157600080fd5b506040516200255c3803806200255c833981810160405260a08110156200003757600080fd5b508051602082015160408301516060840151608090940151929391929091908380866001600160a01b038116620000b5576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a1506000546001600160a01b031662000160576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b60038054610100600160a81b0319166101006001600160a01b0393841602179055600580546001600160a01b031916868316179081905560068590556007849055600060088190556040805163095ea7b360e01b81523060048201526000196024820152905192909316935063095ea7b392604480820193602093909283900390910190829087803b158015620001f657600080fd5b505af11580156200020b573d6000803e3d6000fd5b505050506040513d60208110156200022257600080fd5b5050505050505061232380620002396000396000f3fe6080604052600436106101665760003560e01c80635c975abb116100d15780638a926d0f1161008a578063a0712d6811610064578063a0712d681461048d578063dbd06c85146104b7578063ee5f3f5c146104cc578063fc0c546a146104e157610166565b80638a926d0f1461044e5780638da5cb5b1461046357806391b4ded91461047857610166565b80635c975abb1461036b5780635cfc1a51146103805780636ad882691461039557806374185360146103bf57806379ba5097146103d4578063899ffef4146103e957610166565b80631f23a352116101235780631f23a352146102965780632af64bd3146102ab57806342966c68146102d4578063509bf42a146102fe57806353a47bb7146103135780635c095e541461032857610166565b806304f3bcec146101b35780630902f1ac146101e45780631627540c1461020b57806316c38b3c1461024057806317c943bc1461026c57806318819a3114610281575b6040805162461bcd60e51b815260206004820152601d60248201527f46616c6c6261636b2064697361626c65642c20757365206d696e742829000000604482015290519081900360640190fd5b3480156101bf57600080fd5b506101c86104f6565b604080516001600160a01b039092168252519081900360200190f35b3480156101f057600080fd5b506101f961050a565b60408051918252519081900360200190f35b34801561021757600080fd5b5061023e6004803603602081101561022e57600080fd5b50356001600160a01b0316610587565b005b34801561024c57600080fd5b5061023e6004803603602081101561026357600080fd5b503515156105e3565b34801561027857600080fd5b506101f961065d565b34801561028d57600080fd5b506101f9610663565b3480156102a257600080fd5b506101f9610673565b3480156102b757600080fd5b506102c0610679565b604080519115158252519081900360200190f35b3480156102e057600080fd5b5061023e600480360360208110156102f757600080fd5b5035610789565b34801561030a57600080fd5b506101f9610c73565b34801561031f57600080fd5b506101c8610c7e565b34801561033457600080fd5b506103526004803603602081101561034b57600080fd5b5035610c8d565b6040805192835290151560208301528051918290030190f35b34801561037757600080fd5b506102c0610ce2565b34801561038c57600080fd5b506101f9610ceb565b3480156103a157600080fd5b50610352600480360360208110156103b857600080fd5b5035610d2d565b3480156103cb57600080fd5b5061023e610d3a565b3480156103e057600080fd5b5061023e610f17565b3480156103f557600080fd5b506103fe610fd3565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561043a578181015183820152602001610422565b505050509050019250505060405180910390f35b34801561045a57600080fd5b506101f96110f5565b34801561046f57600080fd5b506101c8611100565b34801561048457600080fd5b506101f961110f565b34801561049957600080fd5b5061023e600480360360208110156104b057600080fd5b5035611115565b3480156104c357600080fd5b506101f961156f565b3480156104d857600080fd5b506101f9611575565b3480156104ed57600080fd5b506101c86115dd565b60035461010090046001600160a01b031681565b600554604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561055557600080fd5b505afa158015610569573d6000803e3d6000fd5b505050506040513d602081101561057f57600080fd5b505190505b90565b61058f6115ec565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b6105eb6115ec565b60035460ff16151581151514156106015761065a565b6003805460ff1916821515179081905560ff161561061e57426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b60085481565b600061066e30611637565b905090565b60075481565b60006060610685610fd3565b905060005b81518110156107805760008282815181106106a157fe5b602090810291909101810151600081815260048084526040918290205460035483516321f8a72160e01b815292830185905292519395506001600160a01b039081169461010090930416926321f8a72192602480840193919291829003018186803b15801561070f57600080fd5b505afa158015610723573d6000803e3d6000fd5b505050506040513d602081101561073957600080fd5b50516001600160a01b031614158061076657506000818152600460205260409020546001600160a01b0316155b156107775760009350505050610584565b5060010161068a565b50600191505090565b60035460ff16156107cb5760405162461bcd60e51b815260040180806020018281038252603c815260200180612258603c913960400191505060405180910390fd5b6107d3611727565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b15801561080b57600080fd5b505afa15801561081f573d6000803e3d6000fd5b5050505061082b611741565b6001600160a01b03166370a08231336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561088057600080fd5b505afa158015610894573d6000803e3d6000fd5b505050506040513d60208110156108aa57600080fd5b50518111156108f5576040805162461bcd60e51b815260206004820152601260248201527142616c616e636520697320746f6f206c6f7760701b604482015290519081900360640190fd5b6108fd61174e565b6001600160a01b0316632528f0fe6006546040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561094257600080fd5b505afa158015610956573d6000803e3d6000fd5b505050506040513d602081101561096c57600080fd5b5051156109bb576040805162461bcd60e51b815260206004820152601860248201527710dd5c9c995b98de481c985d19481a5cc81a5b9d985b1a5960421b604482015290519081900360640190fd5b60006109c5611575565b11610a015760405162461bcd60e51b81526004018080602001828103825260358152602001806122ba6035913960400191505060405180910390fd5b600080610a0f600854610d2d565b915091506000808215610ad1578460085410610a2b5784610a3e565b600854610a3e908563ffffffff61176916565b9150610aca610a4b610c73565b730142f40c25ce1f1177ed131101fa19217396cb8863907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015610a8f57600080fd5b505af4158015610aa3573d6000803e3d6000fd5b505050506040513d6020811015610ab957600080fd5b50518491900363ffffffff6117cb16565b9050610b92565b6008548590610ae6908663ffffffff6117f516565b10610af15784610b04565b600854610b04908563ffffffff6117f516565b9150610b8f610b11610c73565b730142f40c25ce1f1177ed131101fa19217396cb8863907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015610b5557600080fd5b505af4158015610b69573d6000803e3d6000fd5b505050506040513d6020811015610b7f57600080fd5b505184910163ffffffff61185616565b90505b600083610bae57610ba9838363ffffffff61176916565b610bb1565b60005b600554909150600090610bcf906001600160a01b0316303386611880565b905080610c1e576040805162461bcd60e51b8152602060048201526018602482015277151c985b9cd9995c88191a59081b9bdd081cdd58d8d9595960421b604482015290519081900360640190fd5b610c2784611925565b6040805184815260208101849052808201869052905133917f4c60206a5c1de41f3376d1d60f0949d96cb682033c90b1c2d9d9a62d4c4120c0919081900360600190a250505050505050565b600061066e30611b2b565b6001546001600160a01b031681565b6000806000610c9a610663565b90506000811215610cc557610cb984600083900363ffffffff611be916565b60019250925050610cdd565b610cd5848263ffffffff611be916565b600092509250505b915091565b60035460ff1681565b600080610cf661050a565b90506000610d026110f5565b9050808210610d1657600092505050610584565b610d26818363ffffffff61176916565b9250505090565b6000806000610c9a610c73565b6060610d44610fd3565b905060005b8151811015610f13576000828281518110610d6057fe5b602002602001015190506000600360019054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200180807f5265736f6c766572206d697373696e67207461726765743a20000000000000008152506019018281526020019150506040516020818303038152906040526040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610e2b578181015183820152602001610e13565b50505050905090810190601f168015610e585780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b158015610e7657600080fd5b505afa158015610e8a573d6000803e3d6000fd5b505050506040513d6020811015610ea057600080fd5b505160008381526004602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518681529182015281519293507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68929081900390910190a15050600101610d49565b5050565b6001546001600160a01b03163314610f605760405162461bcd60e51b81526004018080602001828103825260358152602001806121d36035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b606080610fde611bfe565b60408051600680825260e08201909252919250606091906020820160c0803883390190505090506814de5b9d1a1cd554d160ba1b8160008151811061101f57fe5b6020026020010181815250506007548160018151811061103b57fe5b6020026020010181815250506c45786368616e6765526174657360981b8160028151811061106557fe5b6020026020010181815250506844656274436163686560b81b8160038151811061108b57fe5b6020026020010181815250506b53797374656d53746174757360a01b816004815181106110b457fe5b6020026020010181815250506d57726170706572466163746f727960901b816005815181106110df57fe5b602002602001018181525050610d268282611c4f565b600061066e30611d0b565b6000546001600160a01b031681565b60025481565b60035460ff16156111575760405162461bcd60e51b815260040180806020018281038252603c815260200180612258603c913960400191505060405180910390fd5b61115f611727565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b15801561119757600080fd5b505afa1580156111ab573d6000803e3d6000fd5b505060055460408051636eb1769f60e11b815233600482015230602482015290516001600160a01b03909216935063dd62ed3e9250604480820192602092909190829003018186803b15801561120057600080fd5b505afa158015611214573d6000803e3d6000fd5b505050506040513d602081101561122a57600080fd5b5051811115611280576040805162461bcd60e51b815260206004820152601960248201527f416c6c6f77616e6365206e6f74206869676820656e6f75676800000000000000604482015290519081900360640190fd5b600554604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d60208110156112f557600080fd5b5051811115611340576040805162461bcd60e51b815260206004820152601260248201527142616c616e636520697320746f6f206c6f7760701b604482015290519081900360640190fd5b61134861174e565b6001600160a01b0316632528f0fe6006546040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561138d57600080fd5b505afa1580156113a1573d6000803e3d6000fd5b505050506040513d60208110156113b757600080fd5b505115611406576040805162461bcd60e51b815260206004820152601860248201527710dd5c9c995b98de481c985d19481a5cc81a5b9d985b1a5960421b604482015290519081900360640190fd5b6000611410610ceb565b9050600081116114515760405162461bcd60e51b81526004018080602001828103825260268152602001806122946026913960400191505060405180910390fd5b60008282106114605782611462565b815b905060008061147083610c8d565b915091506000816114905761148b848463ffffffff61176916565b6114a0565b6114a0848463ffffffff6117f516565b6005549091506000906114be906001600160a01b0316333088611880565b90508061150d576040805162461bcd60e51b8152602060048201526018602482015277151c985b9cd9995c88191a59081b9bdd081cdd58d8d9595960421b604482015290519081900360640190fd5b61151682611dc7565b337f5a3358a3d27a5373c0df2604662088d37894d56b7cfd27f315770440f4e0d91983856115445786611547565b60005b604080519283526020830191909152818101899052519081900360600190a250505050505050565b60065481565b600061157f61174e565b6001600160a01b031663654a60ac600654600854631cd554d160e21b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b15801561055557600080fd5b6005546001600160a01b031681565b6000546001600160a01b031633146116355760405162461bcd60e51b815260040180806020018281038252602f815260200180612208602f913960400191505060405180910390fd5b565b6000611641611f18565b6001600160a01b031663c4f610ed6d53797374656d53657474696e677360901b71777261707065724d696e744665655261746560701b8560405160200180838152602001826001600160a01b03166001600160a01b031660601b815260140192505050604051602081830303815290604052805190602001206040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156116f557600080fd5b505afa158015611709573d6000803e3d6000fd5b505050506040513d602081101561171f57600080fd5b505192915050565b600061066e6b53797374656d53746174757360a01b611f31565b600061066e600754611f31565b600061066e6c45786368616e6765526174657360981b611f31565b6000828211156117c0576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000670de0b6b3a76400006117e6848463ffffffff61200e16565b816117ed57fe5b049392505050565b60008282018381101561184f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b600061184f8261187485670de0b6b3a764000063ffffffff61200e16565b9063ffffffff61206716565b604080516001600160a01b038086166024830152841660448201526064808201849052825180830390910181526084909101909152602081810180516001600160e01b03166323b872dd60e01b178152825160ff60009081529392909184908390828b5af16118ee57600080fd5b60005160ff811461190c576001811461190c57801561191557600080fd5b6001935061191a565b600093505b505050949350505050565b600061192f61050a565b600854909150600090611948838563ffffffff6117f516565b11611954576000611977565b6008546119779061196b848663ffffffff6117f516565b9063ffffffff61176916565b9050600061198361174e565b6001600160a01b031663654a60ac60065484631cd554d160e21b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b1580156119df57600080fd5b505afa1580156119f3573d6000803e3d6000fd5b505050506040513d6020811015611a0957600080fd5b50519050611a15611741565b6001600160a01b0316639dc29fac33866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611a7457600080fd5b505af1158015611a88573d6000803e3d6000fd5b505050506000811115611b1c57611a9d6120d1565b6001600160a01b031663867904b4611ab36120e8565b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611b0357600080fd5b505af1158015611b17573d6000803e3d6000fd5b505050505b611b2583612104565b50505050565b6000611b35611f18565b6001600160a01b031663c4f610ed6d53797374656d53657474696e677360901b71777261707065724275726e4665655261746560701b8560405160200180838152602001826001600160a01b03166001600160a01b031660601b815260140192505050604051602081830303815290604052805190602001206040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156116f557600080fd5b600061184f8383670de0b6b3a764000061217f565b604080516001808252818301909252606091602080830190803883390190505090506e466c657869626c6553746f7261676560881b81600081518110611c4057fe5b60200260200101818152505090565b60608151835101604051908082528060200260200182016040528015611c7f578160200160208202803883390190505b50905060005b8351811015611cc157838181518110611c9a57fe5b6020026020010151828281518110611cae57fe5b6020908102919091010152600101611c85565b5060005b8251811015611d0457828181518110611cda57fe5b6020026020010151828286510181518110611cf157fe5b6020908102919091010152600101611cc5565b5092915050565b6000611d15611f18565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b6f777261707065724d6178546f6b656e7360801b8560405160200180838152602001826001600160a01b03166001600160a01b031660601b815260140192505050604051602081830303815290604052805190602001206040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156116f557600080fd5b6000611dd161050a565b90506000611dea836008546117f590919063ffffffff16565b8211611df7576000611e1b565b600854611e1b90611e0e908563ffffffff6117f516565b839063ffffffff61176916565b90506000611e2761174e565b6001600160a01b031663654a60ac60065484631cd554d160e21b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b158015611e8357600080fd5b505afa158015611e97573d6000803e3d6000fd5b505050506040513d6020811015611ead57600080fd5b50519050611eb9611741565b6001600160a01b031663867904b433866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611a7457600080fd5b600061066e6e466c657869626c6553746f7261676560881b5b600081815260046020908152604080832054815170026b4b9b9b4b7339030b2323932b9b99d1607d1b9381019390935260318084018690528251808503909101815260519093019091526001600160a01b03169081611d045760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611fd3578181015183820152602001611fbb565b50505050905090810190601f1680156120005780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60008261201d575060006117c5565b8282028284828161202a57fe5b041461184f5760405162461bcd60e51b81526004018080602001828103825260218152602001806122376021913960400191505060405180910390fd5b60008082116120bd576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816120c857fe5b04949350505050565b600061066e6814de5b9d1a1cd554d160ba1b611f31565b600061066e6d57726170706572466163746f727960901b611f31565b61210c6121bb565b6001600160a01b0316639e3b92ca60065460085484036040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b15801561215f57600080fd5b505af1158015612173573d6000803e3d6000fd5b50505060089190915550565b600080600a8304612196868663ffffffff61200e16565b8161219d57fe5b0490506005600a8206106121af57600a015b600a9004949350505050565b600061066e6844656274436163686560b81b611f3156fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e6572736869704f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564436f6e747261637420686173206e6f20737061726520636170616369747920746f206d696e74436f6e74726163742063616e6e6f74206275726e20666f7220746f6b656e2c20746f6b656e2062616c616e6365206973207a65726fa265627a7a72315820a4a10d85c707bcbaf53a80a679c2465266162fe35b377e6b8360036004afc38e64736f6c63430005100032596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e6572736869704f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6ea265627a7a72315820389b20616fbd648646f2eabc9039e3a34d21fd0baea43bc61609f135762f668f64736f6c634300051000320000000000000000000000003c05b1239b223c969540fefc0270227a2b00e0470000000000000000000000001cb059b7e74fd21665968c908806143e744d5f30
Deployed Bytecode
0x608060405260043610620000d45760003560e01c806375d920a9116200008b5780638da5cb5b11620000615780638da5cb5b14620002ae578063a106935d14620002c6578063bb57ad201462000309578063e0aa2797146200032157620000d4565b806375d920a9146200021457806379ba5097146200022c578063899ffef4146200024457620000d4565b806304f3bcec14620001215780631627540c14620001555780632af64bd3146200018e57806353a47bb714620001ba578063614d08f814620001d25780637418536014620001fc575b6040805162461bcd60e51b815260206004820152601760248201527f436f6e7472616374206973206e6f742070617961626c65000000000000000000604482015290519081900360640190fd5b3480156200012e57600080fd5b506200013962000358565b604080516001600160a01b039092168252519081900360200190f35b3480156200016257600080fd5b506200018c600480360360208110156200017b57600080fd5b50356001600160a01b031662000367565b005b3480156200019b57600080fd5b50620001a6620003c5565b604080519115158252519081900360200190f35b348015620001c757600080fd5b5062000139620004db565b348015620001df57600080fd5b50620001ea620004ea565b60408051918252519081900360200190f35b3480156200020957600080fd5b506200018c620004ff565b3480156200022157600080fd5b50620001ea620006d2565b3480156200023957600080fd5b506200018c62000767565b3480156200025157600080fd5b506200025c62000825565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156200029a57818101518382015260200162000280565b505050509050019250505060405180910390f35b348015620002bb57600080fd5b5062000139620008c3565b348015620002d357600080fd5b506200013960048036036060811015620002ec57600080fd5b506001600160a01b038135169060208101359060400135620008d2565b3480156200031657600080fd5b506200018c62000a8a565b3480156200032e57600080fd5b50620001a6600480360360208110156200034757600080fd5b50356001600160a01b031662000bff565b6002546001600160a01b031681565b6200037162000caa565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b60006060620003d362000825565b905060005b8151811015620004d1576000828281518110620003f157fe5b6020908102919091018101516000818152600383526040908190205460025482516321f8a72160e01b81526004810185905292519395506001600160a01b03918216949116926321f8a721926024808201939291829003018186803b1580156200045a57600080fd5b505afa1580156200046f573d6000803e3d6000fd5b505050506040513d60208110156200048657600080fd5b50516001600160a01b0316141580620004b457506000818152600360205260409020546001600160a01b0316155b15620004c75760009350505050620004d8565b50600101620003d8565b5060019150505b90565b6001546001600160a01b031681565b6d57726170706572466163746f727960901b81565b60606200050b62000825565b905060005b8151811015620006ce5760008282815181106200052957fe5b602090810291909101810151600254604080517f5265736f6c766572206d697373696e67207461726765743a2000000000000000818601526039808201859052825180830390910181526059820180845263dacb2d0160e01b9052605d8201858152607d83019384528151609d84015281519597506000966001600160a01b039095169563dacb2d01958995939492939260bd0191908501908083838c5b83811015620005e1578181015183820152602001620005c7565b50505050905090810190601f1680156200060f5780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b1580156200062e57600080fd5b505afa15801562000643573d6000803e3d6000fd5b505050506040513d60208110156200065a57600080fd5b505160008381526003602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518681529182015281519293507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68929081900390910190a1505060010162000510565b5050565b6000620006de62000cf7565b6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156200073457600080fd5b505afa15801562000749573d6000803e3d6000fd5b505050506040513d60208110156200076057600080fd5b5051905090565b6001546001600160a01b03163314620007b25760405162461bcd60e51b8152600401808060200182810382526035815260200180620033996035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b604080516003808252608082019092526060916020820183803883390190505090506814de5b9d1a1cd554d160ba1b816000815181106200086257fe5b6020026020010181815250506e466c657869626c6553746f7261676560881b816001815181106200088f57fe5b60200260200101818152505066119959541bdbdb60ca1b81600281518110620008b457fe5b60200260200101818152505090565b6000546001600160a01b031681565b6000620008de62000caa565b600080546002546040516001600160a01b039283169290911690879087908790620009099062000e2e565b6001600160a01b0395861681529385166020850152919093166040808401919091526060830193909352608082015290519081900360a001906000f08015801562000958573d6000803e3d6000fd5b509050806001600160a01b031663741853606040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200099757600080fd5b505af1158015620009ac573d6000803e3d6000fd5b50505050620009ba62000d15565b60408051631d5b277f60e01b81526d57726170706572466163746f727960901b60048201526001600160a01b0384811660248301526001604483015291519290911691631d5b277f9160648082019260009290919082900301818387803b15801562000a2557600080fd5b505af115801562000a3a573d6000803e3d6000fd5b5050604080516001600160a01b038581168252915188945091891692507f8aba3d0a3cbd86bcfc8d4d553823cb5030939fb35208794c1ca597046b2b561e919081900360200190a3949350505050565b600062000a96620006d2565b9050801562000bfc57600062000aab62000cf7565b6001600160a01b031663a9059cbb62000ac362000d34565b6001600160a01b031663eb1edd616040518163ffffffff1660e01b815260040160206040518083038186803b15801562000afc57600080fd5b505afa15801562000b11573d6000803e3d6000fd5b505050506040513d602081101562000b2857600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482018690525160448083019260209291908290030181600087803b15801562000b7957600080fd5b505af115801562000b8e573d6000803e3d6000fd5b505050506040513d602081101562000ba557600080fd5b5051905080620006ce576040805162461bcd60e51b815260206004820152601860248201527f5472616e7366657220646964206e6f7420737563636565640000000000000000604482015290519081900360640190fd5b50565b60008062000c0c62000d15565b6001600160a01b03166323257c2b6d57726170706572466163746f727960901b856001600160a01b031660001b6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801562000c7557600080fd5b505afa15801562000c8a573d6000803e3d6000fd5b505050506040513d602081101562000ca157600080fd5b50511192915050565b6000546001600160a01b0316331462000cf55760405162461bcd60e51b815260040180806020018281038252602f815260200180620033ce602f913960400191505060405180910390fd5b565b600062000d106814de5b9d1a1cd554d160ba1b62000d46565b905090565b600062000d106e466c657869626c6553746f7261676560881b62000d46565b600062000d1066119959541bdbdb60ca1b5b600081815260036020908152604080832054815170026b4b9b9b4b7339030b2323932b9b99d1607d1b9381019390935260318084018690528251808503909101815260519093019091526001600160a01b0316908162000e275760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101562000deb57818101518382015260200162000dd1565b50505050905090810190601f16801562000e195780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5092915050565b61255c8062000e3d8339019056fe60806040523480156200001157600080fd5b506040516200255c3803806200255c833981810160405260a08110156200003757600080fd5b508051602082015160408301516060840151608090940151929391929091908380866001600160a01b038116620000b5576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a1506000546001600160a01b031662000160576040805162461bcd60e51b815260206004820152601160248201527013dddb995c881b5d5cdd081899481cd95d607a1b604482015290519081900360640190fd5b60038054610100600160a81b0319166101006001600160a01b0393841602179055600580546001600160a01b031916868316179081905560068590556007849055600060088190556040805163095ea7b360e01b81523060048201526000196024820152905192909316935063095ea7b392604480820193602093909283900390910190829087803b158015620001f657600080fd5b505af11580156200020b573d6000803e3d6000fd5b505050506040513d60208110156200022257600080fd5b5050505050505061232380620002396000396000f3fe6080604052600436106101665760003560e01c80635c975abb116100d15780638a926d0f1161008a578063a0712d6811610064578063a0712d681461048d578063dbd06c85146104b7578063ee5f3f5c146104cc578063fc0c546a146104e157610166565b80638a926d0f1461044e5780638da5cb5b1461046357806391b4ded91461047857610166565b80635c975abb1461036b5780635cfc1a51146103805780636ad882691461039557806374185360146103bf57806379ba5097146103d4578063899ffef4146103e957610166565b80631f23a352116101235780631f23a352146102965780632af64bd3146102ab57806342966c68146102d4578063509bf42a146102fe57806353a47bb7146103135780635c095e541461032857610166565b806304f3bcec146101b35780630902f1ac146101e45780631627540c1461020b57806316c38b3c1461024057806317c943bc1461026c57806318819a3114610281575b6040805162461bcd60e51b815260206004820152601d60248201527f46616c6c6261636b2064697361626c65642c20757365206d696e742829000000604482015290519081900360640190fd5b3480156101bf57600080fd5b506101c86104f6565b604080516001600160a01b039092168252519081900360200190f35b3480156101f057600080fd5b506101f961050a565b60408051918252519081900360200190f35b34801561021757600080fd5b5061023e6004803603602081101561022e57600080fd5b50356001600160a01b0316610587565b005b34801561024c57600080fd5b5061023e6004803603602081101561026357600080fd5b503515156105e3565b34801561027857600080fd5b506101f961065d565b34801561028d57600080fd5b506101f9610663565b3480156102a257600080fd5b506101f9610673565b3480156102b757600080fd5b506102c0610679565b604080519115158252519081900360200190f35b3480156102e057600080fd5b5061023e600480360360208110156102f757600080fd5b5035610789565b34801561030a57600080fd5b506101f9610c73565b34801561031f57600080fd5b506101c8610c7e565b34801561033457600080fd5b506103526004803603602081101561034b57600080fd5b5035610c8d565b6040805192835290151560208301528051918290030190f35b34801561037757600080fd5b506102c0610ce2565b34801561038c57600080fd5b506101f9610ceb565b3480156103a157600080fd5b50610352600480360360208110156103b857600080fd5b5035610d2d565b3480156103cb57600080fd5b5061023e610d3a565b3480156103e057600080fd5b5061023e610f17565b3480156103f557600080fd5b506103fe610fd3565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561043a578181015183820152602001610422565b505050509050019250505060405180910390f35b34801561045a57600080fd5b506101f96110f5565b34801561046f57600080fd5b506101c8611100565b34801561048457600080fd5b506101f961110f565b34801561049957600080fd5b5061023e600480360360208110156104b057600080fd5b5035611115565b3480156104c357600080fd5b506101f961156f565b3480156104d857600080fd5b506101f9611575565b3480156104ed57600080fd5b506101c86115dd565b60035461010090046001600160a01b031681565b600554604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561055557600080fd5b505afa158015610569573d6000803e3d6000fd5b505050506040513d602081101561057f57600080fd5b505190505b90565b61058f6115ec565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b6105eb6115ec565b60035460ff16151581151514156106015761065a565b6003805460ff1916821515179081905560ff161561061e57426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b60085481565b600061066e30611637565b905090565b60075481565b60006060610685610fd3565b905060005b81518110156107805760008282815181106106a157fe5b602090810291909101810151600081815260048084526040918290205460035483516321f8a72160e01b815292830185905292519395506001600160a01b039081169461010090930416926321f8a72192602480840193919291829003018186803b15801561070f57600080fd5b505afa158015610723573d6000803e3d6000fd5b505050506040513d602081101561073957600080fd5b50516001600160a01b031614158061076657506000818152600460205260409020546001600160a01b0316155b156107775760009350505050610584565b5060010161068a565b50600191505090565b60035460ff16156107cb5760405162461bcd60e51b815260040180806020018281038252603c815260200180612258603c913960400191505060405180910390fd5b6107d3611727565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b15801561080b57600080fd5b505afa15801561081f573d6000803e3d6000fd5b5050505061082b611741565b6001600160a01b03166370a08231336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561088057600080fd5b505afa158015610894573d6000803e3d6000fd5b505050506040513d60208110156108aa57600080fd5b50518111156108f5576040805162461bcd60e51b815260206004820152601260248201527142616c616e636520697320746f6f206c6f7760701b604482015290519081900360640190fd5b6108fd61174e565b6001600160a01b0316632528f0fe6006546040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561094257600080fd5b505afa158015610956573d6000803e3d6000fd5b505050506040513d602081101561096c57600080fd5b5051156109bb576040805162461bcd60e51b815260206004820152601860248201527710dd5c9c995b98de481c985d19481a5cc81a5b9d985b1a5960421b604482015290519081900360640190fd5b60006109c5611575565b11610a015760405162461bcd60e51b81526004018080602001828103825260358152602001806122ba6035913960400191505060405180910390fd5b600080610a0f600854610d2d565b915091506000808215610ad1578460085410610a2b5784610a3e565b600854610a3e908563ffffffff61176916565b9150610aca610a4b610c73565b730142f40c25ce1f1177ed131101fa19217396cb8863907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015610a8f57600080fd5b505af4158015610aa3573d6000803e3d6000fd5b505050506040513d6020811015610ab957600080fd5b50518491900363ffffffff6117cb16565b9050610b92565b6008548590610ae6908663ffffffff6117f516565b10610af15784610b04565b600854610b04908563ffffffff6117f516565b9150610b8f610b11610c73565b730142f40c25ce1f1177ed131101fa19217396cb8863907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b158015610b5557600080fd5b505af4158015610b69573d6000803e3d6000fd5b505050506040513d6020811015610b7f57600080fd5b505184910163ffffffff61185616565b90505b600083610bae57610ba9838363ffffffff61176916565b610bb1565b60005b600554909150600090610bcf906001600160a01b0316303386611880565b905080610c1e576040805162461bcd60e51b8152602060048201526018602482015277151c985b9cd9995c88191a59081b9bdd081cdd58d8d9595960421b604482015290519081900360640190fd5b610c2784611925565b6040805184815260208101849052808201869052905133917f4c60206a5c1de41f3376d1d60f0949d96cb682033c90b1c2d9d9a62d4c4120c0919081900360600190a250505050505050565b600061066e30611b2b565b6001546001600160a01b031681565b6000806000610c9a610663565b90506000811215610cc557610cb984600083900363ffffffff611be916565b60019250925050610cdd565b610cd5848263ffffffff611be916565b600092509250505b915091565b60035460ff1681565b600080610cf661050a565b90506000610d026110f5565b9050808210610d1657600092505050610584565b610d26818363ffffffff61176916565b9250505090565b6000806000610c9a610c73565b6060610d44610fd3565b905060005b8151811015610f13576000828281518110610d6057fe5b602002602001015190506000600360019054906101000a90046001600160a01b03166001600160a01b031663dacb2d01838460405160200180807f5265736f6c766572206d697373696e67207461726765743a20000000000000008152506019018281526020019150506040516020818303038152906040526040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610e2b578181015183820152602001610e13565b50505050905090810190601f168015610e585780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b158015610e7657600080fd5b505afa158015610e8a573d6000803e3d6000fd5b505050506040513d6020811015610ea057600080fd5b505160008381526004602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518681529182015281519293507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68929081900390910190a15050600101610d49565b5050565b6001546001600160a01b03163314610f605760405162461bcd60e51b81526004018080602001828103825260358152602001806121d36035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b606080610fde611bfe565b60408051600680825260e08201909252919250606091906020820160c0803883390190505090506814de5b9d1a1cd554d160ba1b8160008151811061101f57fe5b6020026020010181815250506007548160018151811061103b57fe5b6020026020010181815250506c45786368616e6765526174657360981b8160028151811061106557fe5b6020026020010181815250506844656274436163686560b81b8160038151811061108b57fe5b6020026020010181815250506b53797374656d53746174757360a01b816004815181106110b457fe5b6020026020010181815250506d57726170706572466163746f727960901b816005815181106110df57fe5b602002602001018181525050610d268282611c4f565b600061066e30611d0b565b6000546001600160a01b031681565b60025481565b60035460ff16156111575760405162461bcd60e51b815260040180806020018281038252603c815260200180612258603c913960400191505060405180910390fd5b61115f611727565b6001600160a01b0316637c3125416040518163ffffffff1660e01b815260040160006040518083038186803b15801561119757600080fd5b505afa1580156111ab573d6000803e3d6000fd5b505060055460408051636eb1769f60e11b815233600482015230602482015290516001600160a01b03909216935063dd62ed3e9250604480820192602092909190829003018186803b15801561120057600080fd5b505afa158015611214573d6000803e3d6000fd5b505050506040513d602081101561122a57600080fd5b5051811115611280576040805162461bcd60e51b815260206004820152601960248201527f416c6c6f77616e6365206e6f74206869676820656e6f75676800000000000000604482015290519081900360640190fd5b600554604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d60208110156112f557600080fd5b5051811115611340576040805162461bcd60e51b815260206004820152601260248201527142616c616e636520697320746f6f206c6f7760701b604482015290519081900360640190fd5b61134861174e565b6001600160a01b0316632528f0fe6006546040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561138d57600080fd5b505afa1580156113a1573d6000803e3d6000fd5b505050506040513d60208110156113b757600080fd5b505115611406576040805162461bcd60e51b815260206004820152601860248201527710dd5c9c995b98de481c985d19481a5cc81a5b9d985b1a5960421b604482015290519081900360640190fd5b6000611410610ceb565b9050600081116114515760405162461bcd60e51b81526004018080602001828103825260268152602001806122946026913960400191505060405180910390fd5b60008282106114605782611462565b815b905060008061147083610c8d565b915091506000816114905761148b848463ffffffff61176916565b6114a0565b6114a0848463ffffffff6117f516565b6005549091506000906114be906001600160a01b0316333088611880565b90508061150d576040805162461bcd60e51b8152602060048201526018602482015277151c985b9cd9995c88191a59081b9bdd081cdd58d8d9595960421b604482015290519081900360640190fd5b61151682611dc7565b337f5a3358a3d27a5373c0df2604662088d37894d56b7cfd27f315770440f4e0d91983856115445786611547565b60005b604080519283526020830191909152818101899052519081900360600190a250505050505050565b60065481565b600061157f61174e565b6001600160a01b031663654a60ac600654600854631cd554d160e21b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b15801561055557600080fd5b6005546001600160a01b031681565b6000546001600160a01b031633146116355760405162461bcd60e51b815260040180806020018281038252602f815260200180612208602f913960400191505060405180910390fd5b565b6000611641611f18565b6001600160a01b031663c4f610ed6d53797374656d53657474696e677360901b71777261707065724d696e744665655261746560701b8560405160200180838152602001826001600160a01b03166001600160a01b031660601b815260140192505050604051602081830303815290604052805190602001206040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156116f557600080fd5b505afa158015611709573d6000803e3d6000fd5b505050506040513d602081101561171f57600080fd5b505192915050565b600061066e6b53797374656d53746174757360a01b611f31565b600061066e600754611f31565b600061066e6c45786368616e6765526174657360981b611f31565b6000828211156117c0576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b6000670de0b6b3a76400006117e6848463ffffffff61200e16565b816117ed57fe5b049392505050565b60008282018381101561184f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b600061184f8261187485670de0b6b3a764000063ffffffff61200e16565b9063ffffffff61206716565b604080516001600160a01b038086166024830152841660448201526064808201849052825180830390910181526084909101909152602081810180516001600160e01b03166323b872dd60e01b178152825160ff60009081529392909184908390828b5af16118ee57600080fd5b60005160ff811461190c576001811461190c57801561191557600080fd5b6001935061191a565b600093505b505050949350505050565b600061192f61050a565b600854909150600090611948838563ffffffff6117f516565b11611954576000611977565b6008546119779061196b848663ffffffff6117f516565b9063ffffffff61176916565b9050600061198361174e565b6001600160a01b031663654a60ac60065484631cd554d160e21b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b1580156119df57600080fd5b505afa1580156119f3573d6000803e3d6000fd5b505050506040513d6020811015611a0957600080fd5b50519050611a15611741565b6001600160a01b0316639dc29fac33866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611a7457600080fd5b505af1158015611a88573d6000803e3d6000fd5b505050506000811115611b1c57611a9d6120d1565b6001600160a01b031663867904b4611ab36120e8565b836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611b0357600080fd5b505af1158015611b17573d6000803e3d6000fd5b505050505b611b2583612104565b50505050565b6000611b35611f18565b6001600160a01b031663c4f610ed6d53797374656d53657474696e677360901b71777261707065724275726e4665655261746560701b8560405160200180838152602001826001600160a01b03166001600160a01b031660601b815260140192505050604051602081830303815290604052805190602001206040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156116f557600080fd5b600061184f8383670de0b6b3a764000061217f565b604080516001808252818301909252606091602080830190803883390190505090506e466c657869626c6553746f7261676560881b81600081518110611c4057fe5b60200260200101818152505090565b60608151835101604051908082528060200260200182016040528015611c7f578160200160208202803883390190505b50905060005b8351811015611cc157838181518110611c9a57fe5b6020026020010151828281518110611cae57fe5b6020908102919091010152600101611c85565b5060005b8251811015611d0457828181518110611cda57fe5b6020026020010151828286510181518110611cf157fe5b6020908102919091010152600101611cc5565b5092915050565b6000611d15611f18565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b6f777261707065724d6178546f6b656e7360801b8560405160200180838152602001826001600160a01b03166001600160a01b031660601b815260140192505050604051602081830303815290604052805190602001206040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156116f557600080fd5b6000611dd161050a565b90506000611dea836008546117f590919063ffffffff16565b8211611df7576000611e1b565b600854611e1b90611e0e908563ffffffff6117f516565b839063ffffffff61176916565b90506000611e2761174e565b6001600160a01b031663654a60ac60065484631cd554d160e21b6040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b158015611e8357600080fd5b505afa158015611e97573d6000803e3d6000fd5b505050506040513d6020811015611ead57600080fd5b50519050611eb9611741565b6001600160a01b031663867904b433866040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611a7457600080fd5b600061066e6e466c657869626c6553746f7261676560881b5b600081815260046020908152604080832054815170026b4b9b9b4b7339030b2323932b9b99d1607d1b9381019390935260318084018690528251808503909101815260519093019091526001600160a01b03169081611d045760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611fd3578181015183820152602001611fbb565b50505050905090810190601f1680156120005780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60008261201d575060006117c5565b8282028284828161202a57fe5b041461184f5760405162461bcd60e51b81526004018080602001828103825260218152602001806122376021913960400191505060405180910390fd5b60008082116120bd576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816120c857fe5b04949350505050565b600061066e6814de5b9d1a1cd554d160ba1b611f31565b600061066e6d57726170706572466163746f727960901b611f31565b61210c6121bb565b6001600160a01b0316639e3b92ca60065460085484036040518363ffffffff1660e01b81526004018083815260200182815260200192505050600060405180830381600087803b15801561215f57600080fd5b505af1158015612173573d6000803e3d6000fd5b50505060089190915550565b600080600a8304612196868663ffffffff61200e16565b8161219d57fe5b0490506005600a8206106121af57600a015b600a9004949350505050565b600061066e6844656274436163686560b81b611f3156fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e6572736869704f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564436f6e747261637420686173206e6f20737061726520636170616369747920746f206d696e74436f6e74726163742063616e6e6f74206275726e20666f7220746f6b656e2c20746f6b656e2062616c616e6365206973207a65726fa265627a7a72315820a4a10d85c707bcbaf53a80a679c2465266162fe35b377e6b8360036004afc38e64736f6c63430005100032596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e6572736869704f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6ea265627a7a72315820389b20616fbd648646f2eabc9039e3a34d21fd0baea43bc61609f135762f668f64736f6c63430005100032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003c05b1239b223c969540fefc0270227a2b00e0470000000000000000000000001cb059b7e74fd21665968c908806143e744d5f30
-----Decoded View---------------
Arg [0] : _owner (address): 0x3C05B1239B223c969540FeFc0270227a2B00e047
Arg [1] : _resolver (address): 0x1Cb059b7e74fD21665968C908806143E744D5F30
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000003c05b1239b223c969540fefc0270227a2b00e047
Arg [1] : 0000000000000000000000001cb059b7e74fd21665968c908806143e744d5f30
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.