Latest 25 from a total of 5,309 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Deposit | 23800978 | 1 hr ago | IN | 0 ETH | 0.00034568 | ||||
| Deposit | 23793819 | 25 hrs ago | IN | 0 ETH | 0.00069741 | ||||
| Initiate Synth T... | 23793190 | 27 hrs ago | IN | 0 ETH | 0.00294556 | ||||
| Initiate Synth T... | 23787528 | 46 hrs ago | IN | 0 ETH | 0.00034769 | ||||
| Deposit | 23786684 | 2 days ago | IN | 0 ETH | 0.00029335 | ||||
| Initiate Synth T... | 23782349 | 2 days ago | IN | 0 ETH | 0.00041571 | ||||
| Deposit | 23779533 | 3 days ago | IN | 0 ETH | 0.00034993 | ||||
| Deposit | 23772400 | 4 days ago | IN | 0 ETH | 0.00035921 | ||||
| Deposit | 23765258 | 5 days ago | IN | 0 ETH | 0.00060153 | ||||
| Initiate Synth T... | 23760974 | 5 days ago | IN | 0 ETH | 0.00032359 | ||||
| Deposit | 23758098 | 6 days ago | IN | 0 ETH | 0.00028746 | ||||
| Initiate Synth T... | 23751590 | 6 days ago | IN | 0 ETH | 0.00048789 | ||||
| Deposit | 23750942 | 7 days ago | IN | 0 ETH | 0.00089116 | ||||
| Initiate Synth T... | 23747721 | 7 days ago | IN | 0 ETH | 0.00379968 | ||||
| Deposit | 23743792 | 8 days ago | IN | 0 ETH | 0.00103594 | ||||
| Deposit | 23736634 | 9 days ago | IN | 0 ETH | 0.00116658 | ||||
| Deposit | 23729499 | 10 days ago | IN | 0 ETH | 0.00269696 | ||||
| Deposit | 23722347 | 11 days ago | IN | 0 ETH | 0.00087454 | ||||
| Deposit | 23715188 | 12 days ago | IN | 0 ETH | 0.00024257 | ||||
| Deposit | 23708034 | 13 days ago | IN | 0 ETH | 0.00028858 | ||||
| Initiate Synth T... | 23700928 | 14 days ago | IN | 0 ETH | 0.00029733 | ||||
| Deposit | 23700880 | 14 days ago | IN | 0 ETH | 0.00029413 | ||||
| Deposit | 23693744 | 15 days ago | IN | 0 ETH | 0.00046199 | ||||
| Deposit | 23686600 | 16 days ago | IN | 0 ETH | 0.00050478 | ||||
| Deposit | 23679454 | 17 days ago | IN | 0 ETH | 0.00030131 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SynthetixBridgeToOptimism
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 Etherscan.io on 2022-05-10
*/
/*
____ __ __ __ _
/ __/__ __ ___ / /_ / / ___ / /_ (_)__ __
_\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ /
/___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\
/___/
* Synthetix: SynthetixBridgeToOptimism.sol
*
* Latest source (may be newer): https://github.com/Synthetixio/synthetix/blob/master/contracts/SynthetixBridgeToOptimism.sol
* Docs: https://docs.synthetix.io/contracts/SynthetixBridgeToOptimism
*
* Contract Dependencies:
* - BaseSynthetixBridge
* - IAddressResolver
* - IBaseSynthetixBridge
* - ISynthetixBridgeToOptimism
* - MixinResolver
* - MixinSystemSettings
* - Owned
* - iOVM_L1TokenGateway
* Libraries:
* - Address
* - Math
* - SafeDecimalMath
* - SafeERC20
* - SafeMath
* - VestingEntries
*
* MIT License
* ===========
*
* Copyright (c) 2022 Synthetix
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*/
pragma solidity ^0.5.16;
// https://docs.synthetix.io/contracts/source/contracts/owned
contract Owned {
address public owner;
address public nominatedOwner;
constructor(address _owner) public {
require(_owner != address(0), "Owner address cannot be 0");
owner = _owner;
emit OwnerChanged(address(0), _owner);
}
function nominateNewOwner(address _owner) external onlyOwner {
nominatedOwner = _owner;
emit OwnerNominated(_owner);
}
function acceptOwnership() external {
require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
emit OwnerChanged(owner, nominatedOwner);
owner = nominatedOwner;
nominatedOwner = address(0);
}
modifier onlyOwner {
_onlyOwner();
_;
}
function _onlyOwner() private view {
require(msg.sender == owner, "Only the contract owner may perform this action");
}
event OwnerNominated(address newOwner);
event OwnerChanged(address oldOwner, address newOwner);
}
// https://docs.synthetix.io/contracts/source/interfaces/iaddressresolver
interface IAddressResolver {
function getAddress(bytes32 name) external view returns (address);
function getSynth(bytes32 key) external view returns (address);
function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address);
}
// https://docs.synthetix.io/contracts/source/interfaces/isynth
interface ISynth {
// Views
function currencyKey() external view returns (bytes32);
function transferableSynths(address account) external view returns (uint);
// Mutative functions
function transferAndSettle(address to, uint value) external returns (bool);
function transferFromAndSettle(
address from,
address to,
uint value
) external returns (bool);
// Restricted: used internally to Synthetix
function burn(address account, uint amount) external;
function issue(address account, uint amount) external;
}
// https://docs.synthetix.io/contracts/source/interfaces/iissuer
interface IIssuer {
// Views
function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid);
function availableCurrencyKeys() external view returns (bytes32[] memory);
function availableSynthCount() external view returns (uint);
function availableSynths(uint index) external view returns (ISynth);
function canBurnSynths(address account) external view returns (bool);
function collateral(address account) external view returns (uint);
function collateralisationRatio(address issuer) external view returns (uint);
function collateralisationRatioAndAnyRatesInvalid(address _issuer)
external
view
returns (uint cratio, bool anyRateIsInvalid);
function debtBalanceOf(address issuer, bytes32 currencyKey) external view returns (uint debtBalance);
function issuanceRatio() external view returns (uint);
function lastIssueEvent(address account) external view returns (uint);
function maxIssuableSynths(address issuer) external view returns (uint maxIssuable);
function minimumStakeTime() external view returns (uint);
function remainingIssuableSynths(address issuer)
external
view
returns (
uint maxIssuable,
uint alreadyIssued,
uint totalSystemDebt
);
function synths(bytes32 currencyKey) external view returns (ISynth);
function getSynths(bytes32[] calldata currencyKeys) external view returns (ISynth[] memory);
function synthsByAddress(address synthAddress) external view returns (bytes32);
function totalIssuedSynths(bytes32 currencyKey, bool excludeOtherCollateral) external view returns (uint);
function transferableSynthetixAndAnyRateIsInvalid(address account, uint balance)
external
view
returns (uint transferable, bool anyRateIsInvalid);
// Restricted: used internally to Synthetix
function issueSynths(address from, uint amount) external;
function issueSynthsOnBehalf(
address issueFor,
address from,
uint amount
) external;
function issueMaxSynths(address from) external;
function issueMaxSynthsOnBehalf(address issueFor, address from) external;
function burnSynths(address from, uint amount) external;
function burnSynthsOnBehalf(
address burnForAddress,
address from,
uint amount
) external;
function burnSynthsToTarget(address from) external;
function burnSynthsToTargetOnBehalf(address burnForAddress, address from) external;
function burnForRedemption(
address deprecatedSynthProxy,
address account,
uint balance
) external;
function liquidateDelinquentAccount(
address account,
uint susdAmount,
address liquidator
) external returns (uint totalRedeemed, uint amountToLiquidate);
function setCurrentPeriodId(uint128 periodId) external;
function issueSynthsWithoutDebt(
bytes32 currencyKey,
address to,
uint amount
) external returns (bool rateInvalid);
function burnSynthsWithoutDebt(
bytes32 currencyKey,
address to,
uint amount
) external returns (bool rateInvalid);
}
// Inheritance
// Internal references
// https://docs.synthetix.io/contracts/source/contracts/addressresolver
contract AddressResolver is Owned, IAddressResolver {
mapping(bytes32 => address) public repository;
constructor(address _owner) public Owned(_owner) {}
/* ========== RESTRICTED FUNCTIONS ========== */
function importAddresses(bytes32[] calldata names, address[] calldata destinations) external onlyOwner {
require(names.length == destinations.length, "Input lengths must match");
for (uint i = 0; i < names.length; i++) {
bytes32 name = names[i];
address destination = destinations[i];
repository[name] = destination;
emit AddressImported(name, destination);
}
}
/* ========= PUBLIC FUNCTIONS ========== */
function rebuildCaches(MixinResolver[] calldata destinations) external {
for (uint i = 0; i < destinations.length; i++) {
destinations[i].rebuildCache();
}
}
/* ========== VIEWS ========== */
function areAddressesImported(bytes32[] calldata names, address[] calldata destinations) external view returns (bool) {
for (uint i = 0; i < names.length; i++) {
if (repository[names[i]] != destinations[i]) {
return false;
}
}
return true;
}
function getAddress(bytes32 name) external view returns (address) {
return repository[name];
}
function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address) {
address _foundAddress = repository[name];
require(_foundAddress != address(0), reason);
return _foundAddress;
}
function getSynth(bytes32 key) external view returns (address) {
IIssuer issuer = IIssuer(repository["Issuer"]);
require(address(issuer) != address(0), "Cannot find Issuer address");
return address(issuer.synths(key));
}
/* ========== EVENTS ========== */
event AddressImported(bytes32 name, address destination);
}
// Internal references
// https://docs.synthetix.io/contracts/source/contracts/mixinresolver
contract MixinResolver {
AddressResolver public resolver;
mapping(bytes32 => address) private addressCache;
constructor(address _resolver) internal {
resolver = AddressResolver(_resolver);
}
/* ========== INTERNAL FUNCTIONS ========== */
function combineArrays(bytes32[] memory first, bytes32[] memory second)
internal
pure
returns (bytes32[] memory combination)
{
combination = new bytes32[](first.length + second.length);
for (uint i = 0; i < first.length; i++) {
combination[i] = first[i];
}
for (uint j = 0; j < second.length; j++) {
combination[first.length + j] = second[j];
}
}
/* ========== PUBLIC FUNCTIONS ========== */
// Note: this function is public not external in order for it to be overridden and invoked via super in subclasses
function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {}
function rebuildCache() public {
bytes32[] memory requiredAddresses = resolverAddressesRequired();
// The resolver must call this function whenver it updates its state
for (uint i = 0; i < requiredAddresses.length; i++) {
bytes32 name = requiredAddresses[i];
// Note: can only be invoked once the resolver has all the targets needed added
address destination =
resolver.requireAndGetAddress(name, string(abi.encodePacked("Resolver missing target: ", name)));
addressCache[name] = destination;
emit CacheUpdated(name, destination);
}
}
/* ========== VIEWS ========== */
function isResolverCached() external view returns (bool) {
bytes32[] memory requiredAddresses = resolverAddressesRequired();
for (uint i = 0; i < requiredAddresses.length; i++) {
bytes32 name = requiredAddresses[i];
// false if our cache is invalid or if the resolver doesn't have the required address
if (resolver.getAddress(name) != addressCache[name] || addressCache[name] == address(0)) {
return false;
}
}
return true;
}
/* ========== INTERNAL FUNCTIONS ========== */
function requireAndGetAddress(bytes32 name) internal view returns (address) {
address _foundAddress = addressCache[name];
require(_foundAddress != address(0), string(abi.encodePacked("Missing address: ", name)));
return _foundAddress;
}
/* ========== EVENTS ========== */
event CacheUpdated(bytes32 name, address destination);
}
// https://docs.synthetix.io/contracts/source/interfaces/iflexiblestorage
interface IFlexibleStorage {
// Views
function getUIntValue(bytes32 contractName, bytes32 record) external view returns (uint);
function getUIntValues(bytes32 contractName, bytes32[] calldata records) external view returns (uint[] memory);
function getIntValue(bytes32 contractName, bytes32 record) external view returns (int);
function getIntValues(bytes32 contractName, bytes32[] calldata records) external view returns (int[] memory);
function getAddressValue(bytes32 contractName, bytes32 record) external view returns (address);
function getAddressValues(bytes32 contractName, bytes32[] calldata records) external view returns (address[] memory);
function getBoolValue(bytes32 contractName, bytes32 record) external view returns (bool);
function getBoolValues(bytes32 contractName, bytes32[] calldata records) external view returns (bool[] memory);
function getBytes32Value(bytes32 contractName, bytes32 record) external view returns (bytes32);
function getBytes32Values(bytes32 contractName, bytes32[] calldata records) external view returns (bytes32[] memory);
// Mutative functions
function deleteUIntValue(bytes32 contractName, bytes32 record) external;
function deleteIntValue(bytes32 contractName, bytes32 record) external;
function deleteAddressValue(bytes32 contractName, bytes32 record) external;
function deleteBoolValue(bytes32 contractName, bytes32 record) external;
function deleteBytes32Value(bytes32 contractName, bytes32 record) external;
function setUIntValue(
bytes32 contractName,
bytes32 record,
uint value
) external;
function setUIntValues(
bytes32 contractName,
bytes32[] calldata records,
uint[] calldata values
) external;
function setIntValue(
bytes32 contractName,
bytes32 record,
int value
) external;
function setIntValues(
bytes32 contractName,
bytes32[] calldata records,
int[] calldata values
) external;
function setAddressValue(
bytes32 contractName,
bytes32 record,
address value
) external;
function setAddressValues(
bytes32 contractName,
bytes32[] calldata records,
address[] calldata values
) external;
function setBoolValue(
bytes32 contractName,
bytes32 record,
bool value
) external;
function setBoolValues(
bytes32 contractName,
bytes32[] calldata records,
bool[] calldata values
) external;
function setBytes32Value(
bytes32 contractName,
bytes32 record,
bytes32 value
) external;
function setBytes32Values(
bytes32 contractName,
bytes32[] calldata records,
bytes32[] calldata values
) external;
}
// Internal references
// https://docs.synthetix.io/contracts/source/contracts/mixinsystemsettings
contract MixinSystemSettings is MixinResolver {
// must match the one defined SystemSettingsLib, defined in both places due to sol v0.5 limitations
bytes32 internal constant SETTING_CONTRACT_NAME = "SystemSettings";
bytes32 internal constant SETTING_WAITING_PERIOD_SECS = "waitingPeriodSecs";
bytes32 internal constant SETTING_PRICE_DEVIATION_THRESHOLD_FACTOR = "priceDeviationThresholdFactor";
bytes32 internal constant SETTING_ISSUANCE_RATIO = "issuanceRatio";
bytes32 internal constant SETTING_FEE_PERIOD_DURATION = "feePeriodDuration";
bytes32 internal constant SETTING_TARGET_THRESHOLD = "targetThreshold";
bytes32 internal constant SETTING_LIQUIDATION_DELAY = "liquidationDelay";
bytes32 internal constant SETTING_LIQUIDATION_RATIO = "liquidationRatio";
bytes32 internal constant SETTING_LIQUIDATION_PENALTY = "liquidationPenalty";
bytes32 internal constant SETTING_RATE_STALE_PERIOD = "rateStalePeriod";
/* ========== Exchange Fees Related ========== */
bytes32 internal constant SETTING_EXCHANGE_FEE_RATE = "exchangeFeeRate";
bytes32 internal constant SETTING_EXCHANGE_DYNAMIC_FEE_THRESHOLD = "exchangeDynamicFeeThreshold";
bytes32 internal constant SETTING_EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY = "exchangeDynamicFeeWeightDecay";
bytes32 internal constant SETTING_EXCHANGE_DYNAMIC_FEE_ROUNDS = "exchangeDynamicFeeRounds";
bytes32 internal constant SETTING_EXCHANGE_MAX_DYNAMIC_FEE = "exchangeMaxDynamicFee";
/* ========== End Exchange Fees Related ========== */
bytes32 internal constant SETTING_MINIMUM_STAKE_TIME = "minimumStakeTime";
bytes32 internal constant SETTING_AGGREGATOR_WARNING_FLAGS = "aggregatorWarningFlags";
bytes32 internal constant SETTING_TRADING_REWARDS_ENABLED = "tradingRewardsEnabled";
bytes32 internal constant SETTING_DEBT_SNAPSHOT_STALE_TIME = "debtSnapshotStaleTime";
bytes32 internal constant SETTING_CROSS_DOMAIN_DEPOSIT_GAS_LIMIT = "crossDomainDepositGasLimit";
bytes32 internal constant SETTING_CROSS_DOMAIN_ESCROW_GAS_LIMIT = "crossDomainEscrowGasLimit";
bytes32 internal constant SETTING_CROSS_DOMAIN_REWARD_GAS_LIMIT = "crossDomainRewardGasLimit";
bytes32 internal constant SETTING_CROSS_DOMAIN_WITHDRAWAL_GAS_LIMIT = "crossDomainWithdrawalGasLimit";
bytes32 internal constant SETTING_CROSS_DOMAIN_FEE_PERIOD_CLOSE_GAS_LIMIT = "crossDomainCloseGasLimit";
bytes32 internal constant SETTING_CROSS_DOMAIN_RELAY_GAS_LIMIT = "crossDomainRelayGasLimit";
bytes32 internal constant SETTING_ETHER_WRAPPER_MAX_ETH = "etherWrapperMaxETH";
bytes32 internal constant SETTING_ETHER_WRAPPER_MINT_FEE_RATE = "etherWrapperMintFeeRate";
bytes32 internal constant SETTING_ETHER_WRAPPER_BURN_FEE_RATE = "etherWrapperBurnFeeRate";
bytes32 internal constant SETTING_WRAPPER_MAX_TOKEN_AMOUNT = "wrapperMaxTokens";
bytes32 internal constant SETTING_WRAPPER_MINT_FEE_RATE = "wrapperMintFeeRate";
bytes32 internal constant SETTING_WRAPPER_BURN_FEE_RATE = "wrapperBurnFeeRate";
bytes32 internal constant SETTING_INTERACTION_DELAY = "interactionDelay";
bytes32 internal constant SETTING_COLLAPSE_FEE_RATE = "collapseFeeRate";
bytes32 internal constant SETTING_ATOMIC_MAX_VOLUME_PER_BLOCK = "atomicMaxVolumePerBlock";
bytes32 internal constant SETTING_ATOMIC_TWAP_WINDOW = "atomicTwapWindow";
bytes32 internal constant SETTING_ATOMIC_EQUIVALENT_FOR_DEX_PRICING = "atomicEquivalentForDexPricing";
bytes32 internal constant SETTING_ATOMIC_EXCHANGE_FEE_RATE = "atomicExchangeFeeRate";
bytes32 internal constant SETTING_ATOMIC_VOLATILITY_CONSIDERATION_WINDOW = "atomicVolConsiderationWindow";
bytes32 internal constant SETTING_ATOMIC_VOLATILITY_UPDATE_THRESHOLD = "atomicVolUpdateThreshold";
bytes32 internal constant SETTING_PURE_CHAINLINK_PRICE_FOR_ATOMIC_SWAPS_ENABLED = "pureChainlinkForAtomicsEnabled";
bytes32 internal constant SETTING_CROSS_SYNTH_TRANSFER_ENABLED = "crossChainSynthTransferEnabled";
bytes32 internal constant CONTRACT_FLEXIBLESTORAGE = "FlexibleStorage";
enum CrossDomainMessageGasLimits {Deposit, Escrow, Reward, Withdrawal, CloseFeePeriod, Relay}
struct DynamicFeeConfig {
uint threshold;
uint weightDecay;
uint rounds;
uint maxFee;
}
constructor(address _resolver) internal MixinResolver(_resolver) {}
function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
addresses = new bytes32[](1);
addresses[0] = CONTRACT_FLEXIBLESTORAGE;
}
function flexibleStorage() internal view returns (IFlexibleStorage) {
return IFlexibleStorage(requireAndGetAddress(CONTRACT_FLEXIBLESTORAGE));
}
function _getGasLimitSetting(CrossDomainMessageGasLimits gasLimitType) internal pure returns (bytes32) {
if (gasLimitType == CrossDomainMessageGasLimits.Deposit) {
return SETTING_CROSS_DOMAIN_DEPOSIT_GAS_LIMIT;
} else if (gasLimitType == CrossDomainMessageGasLimits.Escrow) {
return SETTING_CROSS_DOMAIN_ESCROW_GAS_LIMIT;
} else if (gasLimitType == CrossDomainMessageGasLimits.Reward) {
return SETTING_CROSS_DOMAIN_REWARD_GAS_LIMIT;
} else if (gasLimitType == CrossDomainMessageGasLimits.Withdrawal) {
return SETTING_CROSS_DOMAIN_WITHDRAWAL_GAS_LIMIT;
} else if (gasLimitType == CrossDomainMessageGasLimits.Relay) {
return SETTING_CROSS_DOMAIN_RELAY_GAS_LIMIT;
} else if (gasLimitType == CrossDomainMessageGasLimits.CloseFeePeriod) {
return SETTING_CROSS_DOMAIN_FEE_PERIOD_CLOSE_GAS_LIMIT;
} else {
revert("Unknown gas limit type");
}
}
function getCrossDomainMessageGasLimit(CrossDomainMessageGasLimits gasLimitType) internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, _getGasLimitSetting(gasLimitType));
}
function getTradingRewardsEnabled() internal view returns (bool) {
return flexibleStorage().getBoolValue(SETTING_CONTRACT_NAME, SETTING_TRADING_REWARDS_ENABLED);
}
function getWaitingPeriodSecs() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_WAITING_PERIOD_SECS);
}
function getPriceDeviationThresholdFactor() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_PRICE_DEVIATION_THRESHOLD_FACTOR);
}
function getIssuanceRatio() internal view returns (uint) {
// lookup on flexible storage directly for gas savings (rather than via SystemSettings)
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ISSUANCE_RATIO);
}
function getFeePeriodDuration() internal view returns (uint) {
// lookup on flexible storage directly for gas savings (rather than via SystemSettings)
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_FEE_PERIOD_DURATION);
}
function getTargetThreshold() internal view returns (uint) {
// lookup on flexible storage directly for gas savings (rather than via SystemSettings)
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_TARGET_THRESHOLD);
}
function getLiquidationDelay() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_DELAY);
}
function getLiquidationRatio() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_RATIO);
}
function getLiquidationPenalty() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_PENALTY);
}
function getRateStalePeriod() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_RATE_STALE_PERIOD);
}
/* ========== Exchange Related Fees ========== */
function getExchangeFeeRate(bytes32 currencyKey) internal view returns (uint) {
return
flexibleStorage().getUIntValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_EXCHANGE_FEE_RATE, currencyKey))
);
}
/// @notice Get exchange dynamic fee related keys
/// @return threshold, weight decay, rounds, and max fee
function getExchangeDynamicFeeConfig() internal view returns (DynamicFeeConfig memory) {
bytes32[] memory keys = new bytes32[](4);
keys[0] = SETTING_EXCHANGE_DYNAMIC_FEE_THRESHOLD;
keys[1] = SETTING_EXCHANGE_DYNAMIC_FEE_WEIGHT_DECAY;
keys[2] = SETTING_EXCHANGE_DYNAMIC_FEE_ROUNDS;
keys[3] = SETTING_EXCHANGE_MAX_DYNAMIC_FEE;
uint[] memory values = flexibleStorage().getUIntValues(SETTING_CONTRACT_NAME, keys);
return DynamicFeeConfig({threshold: values[0], weightDecay: values[1], rounds: values[2], maxFee: values[3]});
}
/* ========== End Exchange Related Fees ========== */
function getMinimumStakeTime() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_MINIMUM_STAKE_TIME);
}
function getAggregatorWarningFlags() internal view returns (address) {
return flexibleStorage().getAddressValue(SETTING_CONTRACT_NAME, SETTING_AGGREGATOR_WARNING_FLAGS);
}
function getDebtSnapshotStaleTime() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_DEBT_SNAPSHOT_STALE_TIME);
}
function getEtherWrapperMaxETH() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ETHER_WRAPPER_MAX_ETH);
}
function getEtherWrapperMintFeeRate() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ETHER_WRAPPER_MINT_FEE_RATE);
}
function getEtherWrapperBurnFeeRate() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ETHER_WRAPPER_BURN_FEE_RATE);
}
function getWrapperMaxTokenAmount(address wrapper) internal view returns (uint) {
return
flexibleStorage().getUIntValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_WRAPPER_MAX_TOKEN_AMOUNT, wrapper))
);
}
function getWrapperMintFeeRate(address wrapper) internal view returns (int) {
return
flexibleStorage().getIntValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_WRAPPER_MINT_FEE_RATE, wrapper))
);
}
function getWrapperBurnFeeRate(address wrapper) internal view returns (int) {
return
flexibleStorage().getIntValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_WRAPPER_BURN_FEE_RATE, wrapper))
);
}
function getInteractionDelay(address collateral) internal view returns (uint) {
return
flexibleStorage().getUIntValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_INTERACTION_DELAY, collateral))
);
}
function getCollapseFeeRate(address collateral) internal view returns (uint) {
return
flexibleStorage().getUIntValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_COLLAPSE_FEE_RATE, collateral))
);
}
function getAtomicMaxVolumePerBlock() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ATOMIC_MAX_VOLUME_PER_BLOCK);
}
function getAtomicTwapWindow() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_ATOMIC_TWAP_WINDOW);
}
function getAtomicEquivalentForDexPricing(bytes32 currencyKey) internal view returns (address) {
return
flexibleStorage().getAddressValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_ATOMIC_EQUIVALENT_FOR_DEX_PRICING, currencyKey))
);
}
function getAtomicExchangeFeeRate(bytes32 currencyKey) internal view returns (uint) {
return
flexibleStorage().getUIntValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_ATOMIC_EXCHANGE_FEE_RATE, currencyKey))
);
}
function getAtomicVolatilityConsiderationWindow(bytes32 currencyKey) internal view returns (uint) {
return
flexibleStorage().getUIntValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_ATOMIC_VOLATILITY_CONSIDERATION_WINDOW, currencyKey))
);
}
function getAtomicVolatilityUpdateThreshold(bytes32 currencyKey) internal view returns (uint) {
return
flexibleStorage().getUIntValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_ATOMIC_VOLATILITY_UPDATE_THRESHOLD, currencyKey))
);
}
function getPureChainlinkPriceForAtomicSwapsEnabled(bytes32 currencyKey) internal view returns (bool) {
return
flexibleStorage().getBoolValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_PURE_CHAINLINK_PRICE_FOR_ATOMIC_SWAPS_ENABLED, currencyKey))
);
}
function getCrossChainSynthTransferEnabled(bytes32 currencyKey) internal view returns (uint) {
return
flexibleStorage().getUIntValue(
SETTING_CONTRACT_NAME,
keccak256(abi.encodePacked(SETTING_CROSS_SYNTH_TRANSFER_ENABLED, currencyKey))
);
}
}
pragma experimental ABIEncoderV2;
interface IBaseSynthetixBridge {
function suspendInitiation() external;
function resumeInitiation() external;
}
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, "SafeMath: division by zero");
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
}
// Libraries
// https://docs.synthetix.io/contracts/source/libraries/safedecimalmath
library SafeDecimalMath {
using SafeMath for uint;
/* Number of decimal places in the representations. */
uint8 public constant decimals = 18;
uint8 public constant highPrecisionDecimals = 27;
/* The number representing 1.0. */
uint public constant UNIT = 10**uint(decimals);
/* The number representing 1.0 for higher fidelity numbers. */
uint public constant PRECISE_UNIT = 10**uint(highPrecisionDecimals);
uint private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10**uint(highPrecisionDecimals - decimals);
/**
* @return Provides an interface to UNIT.
*/
function unit() external pure returns (uint) {
return UNIT;
}
/**
* @return Provides an interface to PRECISE_UNIT.
*/
function preciseUnit() external pure returns (uint) {
return PRECISE_UNIT;
}
/**
* @return The result of multiplying x and y, interpreting the operands as fixed-point
* decimals.
*
* @dev A unit factor is divided out after the product of x and y is evaluated,
* so that product must be less than 2**256. As this is an integer division,
* the internal division always rounds down. This helps save on gas. Rounding
* is more expensive on gas.
*/
function multiplyDecimal(uint x, uint y) internal pure returns (uint) {
/* Divide by UNIT to remove the extra factor introduced by the product. */
return x.mul(y) / UNIT;
}
/**
* @return The result of safely multiplying x and y, interpreting the operands
* as fixed-point decimals of the specified precision unit.
*
* @dev The operands should be in the form of a the specified unit factor which will be
* divided out after the product of x and y is evaluated, so that product must be
* less than 2**256.
*
* Unlike multiplyDecimal, this function rounds the result to the nearest increment.
* Rounding is useful when you need to retain fidelity for small decimal numbers
* (eg. small fractions or percentages).
*/
function _multiplyDecimalRound(
uint x,
uint y,
uint precisionUnit
) private pure returns (uint) {
/* Divide by UNIT to remove the extra factor introduced by the product. */
uint quotientTimesTen = x.mul(y) / (precisionUnit / 10);
if (quotientTimesTen % 10 >= 5) {
quotientTimesTen += 10;
}
return quotientTimesTen / 10;
}
/**
* @return The result of safely multiplying x and y, interpreting the operands
* as fixed-point decimals of a precise unit.
*
* @dev The operands should be in the precise unit factor which will be
* divided out after the product of x and y is evaluated, so that product must be
* less than 2**256.
*
* Unlike multiplyDecimal, this function rounds the result to the nearest increment.
* Rounding is useful when you need to retain fidelity for small decimal numbers
* (eg. small fractions or percentages).
*/
function multiplyDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
return _multiplyDecimalRound(x, y, PRECISE_UNIT);
}
/**
* @return The result of safely multiplying x and y, interpreting the operands
* as fixed-point decimals of a standard unit.
*
* @dev The operands should be in the standard unit factor which will be
* divided out after the product of x and y is evaluated, so that product must be
* less than 2**256.
*
* Unlike multiplyDecimal, this function rounds the result to the nearest increment.
* Rounding is useful when you need to retain fidelity for small decimal numbers
* (eg. small fractions or percentages).
*/
function multiplyDecimalRound(uint x, uint y) internal pure returns (uint) {
return _multiplyDecimalRound(x, y, UNIT);
}
/**
* @return The result of safely dividing x and y. The return value is a high
* precision decimal.
*
* @dev y is divided after the product of x and the standard precision unit
* is evaluated, so the product of x and UNIT must be less than 2**256. As
* this is an integer division, the result is always rounded down.
* This helps save on gas. Rounding is more expensive on gas.
*/
function divideDecimal(uint x, uint y) internal pure returns (uint) {
/* Reintroduce the UNIT factor that will be divided out by y. */
return x.mul(UNIT).div(y);
}
/**
* @return The result of safely dividing x and y. The return value is as a rounded
* decimal in the precision unit specified in the parameter.
*
* @dev y is divided after the product of x and the specified precision unit
* is evaluated, so the product of x and the specified precision unit must
* be less than 2**256. The result is rounded to the nearest increment.
*/
function _divideDecimalRound(
uint x,
uint y,
uint precisionUnit
) private pure returns (uint) {
uint resultTimesTen = x.mul(precisionUnit * 10).div(y);
if (resultTimesTen % 10 >= 5) {
resultTimesTen += 10;
}
return resultTimesTen / 10;
}
/**
* @return The result of safely dividing x and y. The return value is as a rounded
* standard precision decimal.
*
* @dev y is divided after the product of x and the standard precision unit
* is evaluated, so the product of x and the standard precision unit must
* be less than 2**256. The result is rounded to the nearest increment.
*/
function divideDecimalRound(uint x, uint y) internal pure returns (uint) {
return _divideDecimalRound(x, y, UNIT);
}
/**
* @return The result of safely dividing x and y. The return value is as a rounded
* high precision decimal.
*
* @dev y is divided after the product of x and the high precision unit
* is evaluated, so the product of x and the high precision unit must
* be less than 2**256. The result is rounded to the nearest increment.
*/
function divideDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
return _divideDecimalRound(x, y, PRECISE_UNIT);
}
/**
* @dev Convert a standard decimal representation to a high precision one.
*/
function decimalToPreciseDecimal(uint i) internal pure returns (uint) {
return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR);
}
/**
* @dev Convert a high precision decimal to a standard decimal representation.
*/
function preciseDecimalToDecimal(uint i) internal pure returns (uint) {
uint quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10);
if (quotientTimesTen % 10 >= 5) {
quotientTimesTen += 10;
}
return quotientTimesTen / 10;
}
// Computes `a - b`, setting the value to 0 if b > a.
function floorsub(uint a, uint b) internal pure returns (uint) {
return b >= a ? 0 : a - b;
}
/* ---------- Utilities ---------- */
/*
* Absolute value of the input, returned as a signed number.
*/
function signedAbs(int x) internal pure returns (int) {
return x < 0 ? -x : x;
}
/*
* Absolute value of the input, returned as an unsigned number.
*/
function abs(int x) internal pure returns (uint) {
return uint(signedAbs(x));
}
}
// Libraries
// https://docs.synthetix.io/contracts/source/libraries/math
library Math {
using SafeMath for uint;
using SafeDecimalMath for uint;
/**
* @dev Uses "exponentiation by squaring" algorithm where cost is 0(logN)
* vs 0(N) for naive repeated multiplication.
* Calculates x^n with x as fixed-point and n as regular unsigned int.
* Calculates to 18 digits of precision with SafeDecimalMath.unit()
*/
function powDecimal(uint x, uint n) internal pure returns (uint) {
// https://mpark.github.io/programming/2014/08/18/exponentiation-by-squaring/
uint result = SafeDecimalMath.unit();
while (n > 0) {
if (n % 2 != 0) {
result = result.multiplyDecimal(x);
}
x = x.multiplyDecimal(x);
n /= 2;
}
return result;
}
}
interface IVirtualSynth {
// Views
function balanceOfUnderlying(address account) external view returns (uint);
function rate() external view returns (uint);
function readyToSettle() external view returns (bool);
function secsLeftInWaitingPeriod() external view returns (uint);
function settled() external view returns (bool);
function synth() external view returns (ISynth);
// Mutative functions
function settle(address account) external;
}
// https://docs.synthetix.io/contracts/source/interfaces/isynthetix
interface ISynthetix {
// Views
function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid);
function availableCurrencyKeys() external view returns (bytes32[] memory);
function availableSynthCount() external view returns (uint);
function availableSynths(uint index) external view returns (ISynth);
function collateral(address account) external view returns (uint);
function collateralisationRatio(address issuer) external view returns (uint);
function debtBalanceOf(address issuer, bytes32 currencyKey) external view returns (uint);
function isWaitingPeriod(bytes32 currencyKey) external view returns (bool);
function maxIssuableSynths(address issuer) external view returns (uint maxIssuable);
function remainingIssuableSynths(address issuer)
external
view
returns (
uint maxIssuable,
uint alreadyIssued,
uint totalSystemDebt
);
function synths(bytes32 currencyKey) external view returns (ISynth);
function synthsByAddress(address synthAddress) external view returns (bytes32);
function totalIssuedSynths(bytes32 currencyKey) external view returns (uint);
function totalIssuedSynthsExcludeOtherCollateral(bytes32 currencyKey) external view returns (uint);
function transferableSynthetix(address account) external view returns (uint transferable);
// Mutative Functions
function burnSynths(uint amount) external;
function burnSynthsOnBehalf(address burnForAddress, uint amount) external;
function burnSynthsToTarget() external;
function burnSynthsToTargetOnBehalf(address burnForAddress) external;
function exchange(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey
) external returns (uint amountReceived);
function exchangeOnBehalf(
address exchangeForAddress,
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey
) external returns (uint amountReceived);
function exchangeWithTracking(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey,
address rewardAddress,
bytes32 trackingCode
) external returns (uint amountReceived);
function exchangeWithTrackingForInitiator(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey,
address rewardAddress,
bytes32 trackingCode
) external returns (uint amountReceived);
function exchangeOnBehalfWithTracking(
address exchangeForAddress,
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey,
address rewardAddress,
bytes32 trackingCode
) external returns (uint amountReceived);
function exchangeWithVirtual(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey,
bytes32 trackingCode
) external returns (uint amountReceived, IVirtualSynth vSynth);
function exchangeAtomically(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey,
bytes32 trackingCode,
uint minAmount
) external returns (uint amountReceived);
function issueMaxSynths() external;
function issueMaxSynthsOnBehalf(address issueForAddress) external;
function issueSynths(uint amount) external;
function issueSynthsOnBehalf(address issueForAddress, uint amount) external;
function mint() external returns (bool);
function settle(bytes32 currencyKey)
external
returns (
uint reclaimed,
uint refunded,
uint numEntries
);
// Liquidations
function liquidateDelinquentAccount(address account, uint susdAmount) external returns (bool);
// Restricted Functions
function mintSecondary(address account, uint amount) external;
function mintSecondaryRewards(uint amount) external;
function burnSecondary(address account, uint amount) external;
}
library VestingEntries {
struct VestingEntry {
uint64 endTime;
uint256 escrowAmount;
}
struct VestingEntryWithID {
uint64 endTime;
uint256 escrowAmount;
uint256 entryID;
}
}
interface IRewardEscrowV2 {
// Views
function balanceOf(address account) external view returns (uint);
function numVestingEntries(address account) external view returns (uint);
function totalEscrowedAccountBalance(address account) external view returns (uint);
function totalVestedAccountBalance(address account) external view returns (uint);
function getVestingQuantity(address account, uint256[] calldata entryIDs) external view returns (uint);
function getVestingSchedules(
address account,
uint256 index,
uint256 pageSize
) external view returns (VestingEntries.VestingEntryWithID[] memory);
function getAccountVestingEntryIDs(
address account,
uint256 index,
uint256 pageSize
) external view returns (uint256[] memory);
function getVestingEntryClaimable(address account, uint256 entryID) external view returns (uint);
function getVestingEntry(address account, uint256 entryID) external view returns (uint64, uint256);
// Mutative functions
function vest(uint256[] calldata entryIDs) external;
function createEscrowEntry(
address beneficiary,
uint256 deposit,
uint256 duration
) external;
function appendVestingEntry(
address account,
uint256 quantity,
uint256 duration
) external;
function migrateVestingSchedule(address _addressToMigrate) external;
function migrateAccountEscrowBalances(
address[] calldata accounts,
uint256[] calldata escrowBalances,
uint256[] calldata vestedBalances
) external;
// Account Merging
function startMergingWindow() external;
function mergeAccount(address accountToMerge, uint256[] calldata entryIDs) external;
function nominateAccountToMerge(address account) external;
function accountMergingIsOpen() external view returns (bool);
// L2 Migration
function importVestingEntries(
address account,
uint256 escrowedAmount,
VestingEntries.VestingEntry[] calldata vestingEntries
) external;
// Return amount of SNX transfered to SynthetixBridgeToOptimism deposit contract
function burnForMigration(address account, uint256[] calldata entryIDs)
external
returns (uint256 escrowedAccountBalance, VestingEntries.VestingEntry[] memory vestingEntries);
}
// https://docs.synthetix.io/contracts/source/interfaces/ifeepool
interface IFeePool {
// Views
// solhint-disable-next-line func-name-mixedcase
function FEE_ADDRESS() external view returns (address);
function feesAvailable(address account) external view returns (uint, uint);
function feePeriodDuration() external view returns (uint);
function isFeesClaimable(address account) external view returns (bool);
function targetThreshold() external view returns (uint);
function totalFeesAvailable() external view returns (uint);
function totalRewardsAvailable() external view returns (uint);
// Mutative Functions
function claimFees() external returns (bool);
function claimOnBehalf(address claimingForAddress) external returns (bool);
function closeCurrentFeePeriod() external;
function closeSecondary(uint snxBackedDebt, uint debtShareSupply) external;
function recordFeePaid(uint sUSDAmount) external;
function setRewardsToDistribute(uint amount) external;
}
// https://docs.synthetix.io/contracts/source/interfaces/iexchangerates
interface IExchangeRates {
// Structs
struct RateAndUpdatedTime {
uint216 rate;
uint40 time;
}
// Views
function aggregators(bytes32 currencyKey) external view returns (address);
function aggregatorWarningFlags() external view returns (address);
function anyRateIsInvalid(bytes32[] calldata currencyKeys) external view returns (bool);
function anyRateIsInvalidAtRound(bytes32[] calldata currencyKeys, uint[] calldata roundIds) external view returns (bool);
function currenciesUsingAggregator(address aggregator) external view returns (bytes32[] memory);
function effectiveValue(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey
) external view returns (uint value);
function effectiveValueAndRates(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey
)
external
view
returns (
uint value,
uint sourceRate,
uint destinationRate
);
function effectiveValueAndRatesAtRound(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey,
uint roundIdForSrc,
uint roundIdForDest
)
external
view
returns (
uint value,
uint sourceRate,
uint destinationRate
);
function effectiveAtomicValueAndRates(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey
)
external
view
returns (
uint value,
uint systemValue,
uint systemSourceRate,
uint systemDestinationRate
);
function getCurrentRoundId(bytes32 currencyKey) external view returns (uint);
function getLastRoundIdBeforeElapsedSecs(
bytes32 currencyKey,
uint startingRoundId,
uint startingTimestamp,
uint timediff
) external view returns (uint);
function lastRateUpdateTimes(bytes32 currencyKey) external view returns (uint256);
function rateAndTimestampAtRound(bytes32 currencyKey, uint roundId) external view returns (uint rate, uint time);
function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time);
function rateAndInvalid(bytes32 currencyKey) external view returns (uint rate, bool isInvalid);
function rateForCurrency(bytes32 currencyKey) external view returns (uint);
function rateIsFlagged(bytes32 currencyKey) external view returns (bool);
function rateIsInvalid(bytes32 currencyKey) external view returns (bool);
function rateIsStale(bytes32 currencyKey) external view returns (bool);
function rateStalePeriod() external view returns (uint);
function ratesAndUpdatedTimeForCurrencyLastNRounds(
bytes32 currencyKey,
uint numRounds,
uint roundId
) external view returns (uint[] memory rates, uint[] memory times);
function ratesAndInvalidForCurrencies(bytes32[] calldata currencyKeys)
external
view
returns (uint[] memory rates, bool anyRateInvalid);
function ratesForCurrencies(bytes32[] calldata currencyKeys) external view returns (uint[] memory);
function synthTooVolatileForAtomicExchange(bytes32 currencyKey) external view returns (bool);
}
// https://docs.synthetix.io/contracts/source/interfaces/isystemstatus
interface ISystemStatus {
struct Status {
bool canSuspend;
bool canResume;
}
struct Suspension {
bool suspended;
// reason is an integer code,
// 0 => no reason, 1 => upgrading, 2+ => defined by system usage
uint248 reason;
}
// Views
function accessControl(bytes32 section, address account) external view returns (bool canSuspend, bool canResume);
function requireSystemActive() external view;
function systemSuspended() external view returns (bool);
function requireIssuanceActive() external view;
function requireExchangeActive() external view;
function requireFuturesActive() external view;
function requireFuturesMarketActive(bytes32 marketKey) external view;
function requireExchangeBetweenSynthsAllowed(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view;
function requireSynthActive(bytes32 currencyKey) external view;
function synthSuspended(bytes32 currencyKey) external view returns (bool);
function requireSynthsActive(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view;
function systemSuspension() external view returns (bool suspended, uint248 reason);
function issuanceSuspension() external view returns (bool suspended, uint248 reason);
function exchangeSuspension() external view returns (bool suspended, uint248 reason);
function futuresSuspension() external view returns (bool suspended, uint248 reason);
function synthExchangeSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason);
function synthSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason);
function futuresMarketSuspension(bytes32 marketKey) external view returns (bool suspended, uint248 reason);
function getSynthExchangeSuspensions(bytes32[] calldata synths)
external
view
returns (bool[] memory exchangeSuspensions, uint256[] memory reasons);
function getSynthSuspensions(bytes32[] calldata synths)
external
view
returns (bool[] memory suspensions, uint256[] memory reasons);
function getFuturesMarketSuspensions(bytes32[] calldata marketKeys)
external
view
returns (bool[] memory suspensions, uint256[] memory reasons);
// Restricted functions
function suspendIssuance(uint256 reason) external;
function suspendSynth(bytes32 currencyKey, uint256 reason) external;
function suspendFuturesMarket(bytes32 marketKey, uint256 reason) external;
function updateAccessControl(
bytes32 section,
address account,
bool canSuspend,
bool canResume
) external;
}
// SPDX-License-Identifier: MIT
/**
* @title iAbs_BaseCrossDomainMessenger
*/
interface iAbs_BaseCrossDomainMessenger {
/**********
* Events *
**********/
event SentMessage(bytes message);
event RelayedMessage(bytes32 msgHash);
event FailedRelayedMessage(bytes32 msgHash);
/*************
* Variables *
*************/
function xDomainMessageSender() external view returns (address);
/********************
* Public Functions *
********************/
/**
* Sends a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _message Message to send to the target.
* @param _gasLimit Gas limit for the provided message.
*/
function sendMessage(
address _target,
bytes calldata _message,
uint32 _gasLimit
) external;
}
// Inheritance
// Libraries
// Internal references
contract BaseSynthetixBridge is Owned, MixinSystemSettings, IBaseSynthetixBridge {
using SafeMath for uint;
using SafeDecimalMath for uint;
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
bytes32 private constant CONTRACT_EXT_MESSENGER = "ext:Messenger";
bytes32 internal constant CONTRACT_SYNTHETIX = "Synthetix";
bytes32 private constant CONTRACT_REWARDESCROW = "RewardEscrowV2";
bytes32 private constant CONTRACT_ISSUER = "Issuer";
bytes32 private constant CONTRACT_FEEPOOL = "FeePool";
bytes32 private constant CONTRACT_FLEXIBLESTORAGE = "FlexibleStorage";
bytes32 private constant CONTRACT_EXCHANGERATES = "ExchangeRates";
bytes32 private constant CONTRACT_SYSTEM_STATUS = "SystemStatus";
// have to define this function like this here because contract name is required for FlexibleStorage
function CONTRACT_NAME() public pure returns (bytes32);
bool public initiationActive;
bytes32 private constant SYNTH_TRANSFER_NAMESPACE = "SynthTransfer";
bytes32 private constant SYNTH_TRANSFER_SENT = "Sent";
bytes32 private constant SYNTH_TRANSFER_RECV = "Recv";
// ========== CONSTRUCTOR ==========
constructor(address _owner, address _resolver) public Owned(_owner) MixinSystemSettings(_resolver) {
initiationActive = true;
}
// ========== INTERNALS ============
function messenger() internal view returns (iAbs_BaseCrossDomainMessenger) {
return iAbs_BaseCrossDomainMessenger(requireAndGetAddress(CONTRACT_EXT_MESSENGER));
}
function synthetix() internal view returns (ISynthetix) {
return ISynthetix(requireAndGetAddress(CONTRACT_SYNTHETIX));
}
function rewardEscrowV2() internal view returns (IRewardEscrowV2) {
return IRewardEscrowV2(requireAndGetAddress(CONTRACT_REWARDESCROW));
}
function issuer() internal view returns (IIssuer) {
return IIssuer(requireAndGetAddress(CONTRACT_ISSUER));
}
function feePool() internal view returns (IFeePool) {
return IFeePool(requireAndGetAddress(CONTRACT_FEEPOOL));
}
function flexibleStorage() internal view returns (IFlexibleStorage) {
return IFlexibleStorage(requireAndGetAddress(CONTRACT_FLEXIBLESTORAGE));
}
function exchangeRates() internal view returns (IExchangeRates) {
return IExchangeRates(requireAndGetAddress(CONTRACT_EXCHANGERATES));
}
function systemStatus() internal view returns (ISystemStatus) {
return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEM_STATUS));
}
function initiatingActive() internal view {
require(initiationActive, "Initiation deactivated");
}
function counterpart() internal view returns (address);
function onlyAllowFromCounterpart() internal view {
// ensure function only callable from the L2 bridge via messenger (aka relayer)
iAbs_BaseCrossDomainMessenger _messenger = messenger();
require(msg.sender == address(_messenger), "Only the relayer can call this");
require(_messenger.xDomainMessageSender() == counterpart(), "Only a counterpart bridge can invoke");
}
/* ========== VIEWS ========== */
function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
bytes32[] memory existingAddresses = MixinSystemSettings.resolverAddressesRequired();
bytes32[] memory newAddresses = new bytes32[](8);
newAddresses[0] = CONTRACT_EXT_MESSENGER;
newAddresses[1] = CONTRACT_SYNTHETIX;
newAddresses[2] = CONTRACT_REWARDESCROW;
newAddresses[3] = CONTRACT_ISSUER;
newAddresses[4] = CONTRACT_FEEPOOL;
newAddresses[5] = CONTRACT_FLEXIBLESTORAGE;
newAddresses[6] = CONTRACT_EXCHANGERATES;
newAddresses[7] = CONTRACT_SYSTEM_STATUS;
addresses = combineArrays(existingAddresses, newAddresses);
}
function synthTransferSent() external view returns (uint) {
return _sumTransferAmounts(SYNTH_TRANSFER_SENT);
}
function synthTransferReceived() external view returns (uint) {
return _sumTransferAmounts(SYNTH_TRANSFER_RECV);
}
// ========== MODIFIERS ============
modifier requireInitiationActive() {
initiatingActive();
_;
}
modifier onlyCounterpart() {
onlyAllowFromCounterpart();
_;
}
// ========= RESTRICTED FUNCTIONS ==============
function suspendInitiation() external onlyOwner {
require(initiationActive, "Initiation suspended");
initiationActive = false;
emit InitiationSuspended();
}
function resumeInitiation() external onlyOwner {
require(!initiationActive, "Initiation not suspended");
initiationActive = true;
emit InitiationResumed();
}
function initiateSynthTransfer(
bytes32 currencyKey,
address destination,
uint amount
) external requireInitiationActive {
require(destination != address(0), "Cannot send to zero address");
require(getCrossChainSynthTransferEnabled(currencyKey) > 0, "Synth not enabled for cross chain transfer");
systemStatus().requireSynthActive(currencyKey);
_incrementSynthsTransferCounter(SYNTH_TRANSFER_SENT, currencyKey, amount);
bool rateInvalid = issuer().burnSynthsWithoutDebt(currencyKey, msg.sender, amount);
require(!rateInvalid, "Cannot initiate if synth rate is invalid");
// create message payload
bytes memory messageData =
abi.encodeWithSelector(this.finalizeSynthTransfer.selector, currencyKey, destination, amount);
// relay the message to Bridge on L1 via L2 Messenger
messenger().sendMessage(
counterpart(),
messageData,
uint32(getCrossDomainMessageGasLimit(CrossDomainMessageGasLimits.Withdrawal))
);
emit InitiateSynthTransfer(currencyKey, destination, amount);
}
function finalizeSynthTransfer(
bytes32 currencyKey,
address destination,
uint amount
) external onlyCounterpart {
_incrementSynthsTransferCounter(SYNTH_TRANSFER_RECV, currencyKey, amount);
issuer().issueSynthsWithoutDebt(currencyKey, destination, amount);
emit FinalizeSynthTransfer(currencyKey, destination, amount);
}
// ==== INTERNAL FUNCTIONS ====
function _incrementSynthsTransferCounter(
bytes32 group,
bytes32 currencyKey,
uint amount
) internal {
bytes32 key = keccak256(abi.encodePacked(SYNTH_TRANSFER_NAMESPACE, group, currencyKey));
uint currentSynths = flexibleStorage().getUIntValue(CONTRACT_NAME(), key);
flexibleStorage().setUIntValue(CONTRACT_NAME(), key, currentSynths.add(amount));
}
function _sumTransferAmounts(bytes32 group) internal view returns (uint sum) {
// get list of synths from issuer
bytes32[] memory currencyKeys = issuer().availableCurrencyKeys();
// get all synth rates
(uint[] memory rates, bool isInvalid) = exchangeRates().ratesAndInvalidForCurrencies(currencyKeys);
require(!isInvalid, "Rates are invalid");
// get all values
bytes32[] memory transferAmountKeys = new bytes32[](currencyKeys.length);
for (uint i = 0; i < currencyKeys.length; i++) {
transferAmountKeys[i] = keccak256(abi.encodePacked(SYNTH_TRANSFER_NAMESPACE, group, currencyKeys[i]));
}
uint[] memory transferAmounts = flexibleStorage().getUIntValues(CONTRACT_NAME(), transferAmountKeys);
for (uint i = 0; i < currencyKeys.length; i++) {
sum = sum.add(transferAmounts[i].multiplyDecimalRound(rates[i]));
}
}
// ========== EVENTS ==========
event InitiationSuspended();
event InitiationResumed();
event InitiateSynthTransfer(bytes32 indexed currencyKey, address indexed destination, uint256 amount);
event FinalizeSynthTransfer(bytes32 indexed currencyKey, address indexed destination, uint256 amount);
}
interface ISynthetixBridgeToOptimism {
function closeFeePeriod(uint snxBackedDebt, uint debtSharesSupply) external;
function migrateEscrow(uint256[][] calldata entryIDs) external;
function depositReward(uint amount) external;
function depositAndMigrateEscrow(uint256 depositAmount, uint256[][] calldata entryIDs) external;
}
// SPDX-License-Identifier: MIT
/**
* @title iOVM_L1TokenGateway
*/
interface iOVM_L1TokenGateway {
/**********
* Events *
**********/
event DepositInitiated(
address indexed _from,
address _to,
uint256 _amount
);
event WithdrawalFinalized(
address indexed _to,
uint256 _amount
);
/********************
* Public Functions *
********************/
function deposit(
uint _amount
)
external;
function depositTo(
address _to,
uint _amount
)
external;
/*************************
* Cross-chain Functions *
*************************/
function finalizeWithdrawal(
address _to,
uint _amount
)
external;
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see `ERC20Detailed`.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a `Transfer` event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through `transferFrom`. This is
* zero by default.
*
* This value changes when `approve` or `transferFrom` are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* > Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an `Approval` event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a `Transfer` event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to `approve`. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @dev Collection of functions related to the address type,
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* This test is non-exhaustive, and there may be false-negatives: during the
* execution of a contract's constructor, its address will be reported as
* not containing a contract.
*
* > It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*/
function isContract(address account) internal view returns (bool) {
// This method relies in extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
}
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(address(token).isContract(), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
interface ISynthetixBridgeToBase {
// invoked by the xDomain messenger on L2
function finalizeEscrowMigration(
address account,
uint256 escrowedAmount,
VestingEntries.VestingEntry[] calldata vestingEntries
) external;
// invoked by the xDomain messenger on L2
function finalizeRewardDeposit(address from, uint amount) external;
function finalizeFeePeriodClose(uint snxBackedDebt, uint debtSharesSupply) external;
}
// SPDX-License-Identifier: MIT
/**
* @title iOVM_L2DepositedToken
*/
interface iOVM_L2DepositedToken {
/**********
* Events *
**********/
event WithdrawalInitiated(
address indexed _from,
address _to,
uint256 _amount
);
event DepositFinalized(
address indexed _to,
uint256 _amount
);
/********************
* Public Functions *
********************/
function withdraw(
uint _amount
)
external;
function withdrawTo(
address _to,
uint _amount
)
external;
/*************************
* Cross-chain Functions *
*************************/
function finalizeDeposit(
address _to,
uint _amount
)
external;
}
// Inheritance
// Internal references
contract SynthetixBridgeToOptimism is BaseSynthetixBridge, ISynthetixBridgeToOptimism, iOVM_L1TokenGateway {
using SafeERC20 for IERC20;
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
bytes32 private constant CONTRACT_ISSUER = "Issuer";
bytes32 private constant CONTRACT_REWARDSDISTRIBUTION = "RewardsDistribution";
bytes32 private constant CONTRACT_OVM_SYNTHETIXBRIDGETOBASE = "ovm:SynthetixBridgeToBase";
bytes32 private constant CONTRACT_SYNTHETIXBRIDGEESCROW = "SynthetixBridgeEscrow";
uint8 private constant MAX_ENTRIES_MIGRATED_PER_MESSAGE = 26;
function CONTRACT_NAME() public pure returns (bytes32) {
return "SynthetixBridgeToOptimism";
}
// ========== CONSTRUCTOR ==========
constructor(address _owner, address _resolver) public BaseSynthetixBridge(_owner, _resolver) {}
// ========== INTERNALS ============
function synthetixERC20() internal view returns (IERC20) {
return IERC20(requireAndGetAddress(CONTRACT_SYNTHETIX));
}
function issuer() internal view returns (IIssuer) {
return IIssuer(requireAndGetAddress(CONTRACT_ISSUER));
}
function rewardsDistribution() internal view returns (address) {
return requireAndGetAddress(CONTRACT_REWARDSDISTRIBUTION);
}
function synthetixBridgeToBase() internal view returns (address) {
return requireAndGetAddress(CONTRACT_OVM_SYNTHETIXBRIDGETOBASE);
}
function synthetixBridgeEscrow() internal view returns (address) {
return requireAndGetAddress(CONTRACT_SYNTHETIXBRIDGEESCROW);
}
function hasZeroDebt() internal view {
require(issuer().debtBalanceOf(msg.sender, "sUSD") == 0, "Cannot deposit or migrate with debt");
}
function counterpart() internal view returns (address) {
return synthetixBridgeToBase();
}
/* ========== VIEWS ========== */
function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
bytes32[] memory existingAddresses = BaseSynthetixBridge.resolverAddressesRequired();
bytes32[] memory newAddresses = new bytes32[](4);
newAddresses[0] = CONTRACT_ISSUER;
newAddresses[1] = CONTRACT_REWARDSDISTRIBUTION;
newAddresses[2] = CONTRACT_OVM_SYNTHETIXBRIDGETOBASE;
newAddresses[3] = CONTRACT_SYNTHETIXBRIDGEESCROW;
addresses = combineArrays(existingAddresses, newAddresses);
}
// ========== MODIFIERS ============
modifier requireZeroDebt() {
hasZeroDebt();
_;
}
// ========== PUBLIC FUNCTIONS =========
function deposit(uint256 amount) external requireInitiationActive requireZeroDebt {
_initiateDeposit(msg.sender, amount);
}
function depositTo(address to, uint amount) external requireInitiationActive requireZeroDebt {
_initiateDeposit(to, amount);
}
function migrateEscrow(uint256[][] memory entryIDs) public requireInitiationActive requireZeroDebt {
_migrateEscrow(entryIDs);
}
// invoked by a generous user on L1
function depositReward(uint amount) external requireInitiationActive {
// move the SNX into the deposit escrow
synthetixERC20().transferFrom(msg.sender, synthetixBridgeEscrow(), amount);
_depositReward(msg.sender, amount);
}
// forward any accidental tokens sent here to the escrow
function forwardTokensToEscrow(address token) external {
IERC20 erc20 = IERC20(token);
erc20.safeTransfer(synthetixBridgeEscrow(), erc20.balanceOf(address(this)));
}
// ========= RESTRICTED FUNCTIONS ==============
function closeFeePeriod(uint snxBackedAmount, uint totalDebtShares) external requireInitiationActive {
require(msg.sender == address(feePool()), "Only the fee pool can call this");
ISynthetixBridgeToBase bridgeToBase;
bytes memory messageData =
abi.encodeWithSelector(bridgeToBase.finalizeFeePeriodClose.selector, snxBackedAmount, totalDebtShares);
// relay the message to this contract on L2 via L1 Messenger
messenger().sendMessage(
synthetixBridgeToBase(),
messageData,
uint32(getCrossDomainMessageGasLimit(CrossDomainMessageGasLimits.CloseFeePeriod))
);
emit FeePeriodClosed(snxBackedAmount, totalDebtShares);
}
// invoked by Messenger on L1 after L2 waiting period elapses
function finalizeWithdrawal(address to, uint256 amount) external onlyCounterpart {
// transfer amount back to user
synthetixERC20().transferFrom(synthetixBridgeEscrow(), to, amount);
// no escrow actions - escrow remains on L2
emit iOVM_L1TokenGateway.WithdrawalFinalized(to, amount);
}
// invoked by RewardsDistribution on L1 (takes SNX)
function notifyRewardAmount(uint256 amount) external {
require(msg.sender == address(rewardsDistribution()), "Caller is not RewardsDistribution contract");
// NOTE: transfer SNX to synthetixBridgeEscrow because RewardsDistribution transfers them initially to this contract.
synthetixERC20().transfer(synthetixBridgeEscrow(), amount);
// to be here means I've been given an amount of SNX to distribute onto L2
_depositReward(msg.sender, amount);
}
function depositAndMigrateEscrow(uint256 depositAmount, uint256[][] memory entryIDs)
public
requireInitiationActive
requireZeroDebt
{
if (entryIDs.length > 0) {
_migrateEscrow(entryIDs);
}
if (depositAmount > 0) {
_initiateDeposit(msg.sender, depositAmount);
}
}
// ========== PRIVATE/INTERNAL FUNCTIONS =========
function _depositReward(address _from, uint256 _amount) internal {
// create message payload for L2
ISynthetixBridgeToBase bridgeToBase;
bytes memory messageData = abi.encodeWithSelector(bridgeToBase.finalizeRewardDeposit.selector, _from, _amount);
// relay the message to this contract on L2 via L1 Messenger
messenger().sendMessage(
synthetixBridgeToBase(),
messageData,
uint32(getCrossDomainMessageGasLimit(CrossDomainMessageGasLimits.Reward))
);
emit RewardDepositInitiated(_from, _amount);
}
function _initiateDeposit(address _to, uint256 _depositAmount) private {
// Transfer SNX to L2
// First, move the SNX into the deposit escrow
synthetixERC20().transferFrom(msg.sender, synthetixBridgeEscrow(), _depositAmount);
// create message payload for L2
iOVM_L2DepositedToken bridgeToBase;
bytes memory messageData = abi.encodeWithSelector(bridgeToBase.finalizeDeposit.selector, _to, _depositAmount);
// relay the message to this contract on L2 via L1 Messenger
messenger().sendMessage(
synthetixBridgeToBase(),
messageData,
uint32(getCrossDomainMessageGasLimit(CrossDomainMessageGasLimits.Deposit))
);
emit iOVM_L1TokenGateway.DepositInitiated(msg.sender, _to, _depositAmount);
}
function _migrateEscrow(uint256[][] memory _entryIDs) private {
// loop through the entryID array
for (uint256 i = 0; i < _entryIDs.length; i++) {
// Cannot send more than MAX_ENTRIES_MIGRATED_PER_MESSAGE entries due to ovm gas restrictions
require(_entryIDs[i].length <= MAX_ENTRIES_MIGRATED_PER_MESSAGE, "Exceeds max entries per migration");
// Burn their reward escrow first
// Note: escrowSummary would lose the fidelity of the weekly escrows, so this may not be sufficient
uint256 escrowedAccountBalance;
VestingEntries.VestingEntry[] memory vestingEntries;
(escrowedAccountBalance, vestingEntries) = rewardEscrowV2().burnForMigration(msg.sender, _entryIDs[i]);
// if there is an escrow amount to be migrated
if (escrowedAccountBalance > 0) {
// NOTE: transfer SNX to synthetixBridgeEscrow because burnForMigration() transfers them to this contract.
synthetixERC20().transfer(synthetixBridgeEscrow(), escrowedAccountBalance);
// create message payload for L2
ISynthetixBridgeToBase bridgeToBase;
bytes memory messageData =
abi.encodeWithSelector(
bridgeToBase.finalizeEscrowMigration.selector,
msg.sender,
escrowedAccountBalance,
vestingEntries
);
// relay the message to this contract on L2 via L1 Messenger
messenger().sendMessage(
synthetixBridgeToBase(),
messageData,
uint32(getCrossDomainMessageGasLimit(CrossDomainMessageGasLimits.Escrow))
);
emit ExportedVestingEntries(msg.sender, escrowedAccountBalance, vestingEntries);
}
}
}
// ========== EVENTS ==========
event ExportedVestingEntries(
address indexed account,
uint256 escrowedAccountBalance,
VestingEntries.VestingEntry[] vestingEntries
);
event RewardDepositInitiated(address indexed account, uint256 amount);
event FeePeriodClosed(uint snxBackedDebt, uint totalDebtShares);
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_resolver","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"CacheUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"DepositInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"escrowedAccountBalance","type":"uint256"},{"components":[{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint256","name":"escrowAmount","type":"uint256"}],"indexed":false,"internalType":"struct VestingEntries.VestingEntry[]","name":"vestingEntries","type":"tuple[]"}],"name":"ExportedVestingEntries","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"snxBackedDebt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalDebtShares","type":"uint256"}],"name":"FeePeriodClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FinalizeSynthTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"InitiateSynthTransfer","type":"event"},{"anonymous":false,"inputs":[],"name":"InitiationResumed","type":"event"},{"anonymous":false,"inputs":[],"name":"InitiationSuspended","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardDepositInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"WithdrawalFinalized","type":"event"},{"constant":true,"inputs":[],"name":"CONTRACT_NAME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"snxBackedAmount","type":"uint256"},{"internalType":"uint256","name":"totalDebtShares","type":"uint256"}],"name":"closeFeePeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256[][]","name":"entryIDs","type":"uint256[][]"}],"name":"depositAndMigrateEscrow","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositReward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"finalizeSynthTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"finalizeWithdrawal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"forwardTokensToEscrow","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"currencyKey","type":"bytes32"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"initiateSynthTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initiationActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isResolverCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[][]","name":"entryIDs","type":"uint256[][]"}],"name":"migrateEscrow","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"rebuildCache","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"resolver","outputs":[{"internalType":"contract AddressResolver","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32[]","name":"addresses","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"resumeInitiation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"suspendInitiation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"synthTransferReceived","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"synthTransferSent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b506040516200394a3803806200394a83398101604081905262000034916200010d565b81818080836001600160a01b0381166200006b5760405162461bcd60e51b81526004016200006290620001c9565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91620000b8918490620001a3565b60405180910390a150600280546001600160a01b0319166001600160a01b039290921691909117905550506004805460ff191660011790555062000224915050565b805162000107816200020a565b92915050565b600080604083850312156200012157600080fd5b60006200012f8585620000fa565b92505060206200014285828601620000fa565b9150509250929050565b6200015781620001f6565b82525050565b6200015781620001e4565b600062000177601983620001db565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b60408101620001b382856200014c565b620001c260208301846200015d565b9392505050565b60208082528101620001078162000168565b90815260200190565b60006001600160a01b03821662000107565b6000620001078260006200010782620001e4565b6200021581620001e4565b81146200022157600080fd5b50565b61371680620002346000396000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c8063698a26b2116100de578063a18e230711610097578063b9958ab811610071578063b9958ab8146102cf578063bb91f6a3146102e2578063f4f7b41a146102ea578063ffaad6a5146102fd57610173565b8063a18e230714610296578063a6492fe2146102a9578063b6b55f25146102bc57610173565b8063698a26b21461024e578063741853601461025657806379ba50971461025e578063899ffef4146102665780638da5cb5b1461027b5780639a9e7f961461028357610173565b80633c6b16ab116101305780633c6b16ab146101e3578063462286d5146101f65780634873966f1461020957806353a47bb71461021c5780635aba32ae14610231578063614d08f81461024657610173565b806304f3bcec14610178578063100be6d4146101965780631627540c146101ab5780631e2720ff146101c05780632af64bd3146101d35780633872dda3146101db575b600080fd5b610180610310565b60405161018d9190613440565b60405180910390f35b61019e61031f565b60405161018d9190613384565b6101be6101b9366004612765565b610328565b005b6101be6101ce366004612934565b610386565b61019e61042c565b6101be610544565b6101be6101f1366004612934565b6105ac565b6101be610204366004612765565b610620565b6101be6102173660046128e7565b6106c3565b61022461094e565b60405161018d919061325a565b61023961095d565b60405161018d9190613392565b610239610974565b6101be610998565b6101be6109fb565b6101be610b4d565b61026e610be9565b60405161018d9190613373565b610224610ce7565b6101be6102913660046127e3565b610cf6565b6101be6102a4366004612970565b610d0f565b6101be6102b73660046128e7565b610d3f565b6101be6102ca366004612934565b610e2a565b6101be6102dd366004612a00565b610e44565b610239610f92565b6101be6102f83660046127a9565b610fa4565b6101be61030b3660046127a9565b611082565b6002546001600160a01b031681565b60045460ff1681565b61033061109c565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229061037b90839061325a565b60405180910390a150565b61038e6110c8565b6103966110ea565b6001600160a01b03166323b872dd336103ad611101565b846040518463ffffffff1660e01b81526004016103cc93929190613268565b602060405180830381600087803b1580156103e657600080fd5b505af11580156103fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061041e91908101906128c9565b506104293382611124565b50565b60006060610438610be9565b905060005b815181101561053a57600082828151811061045457fe5b602090810291909101810151600081815260039092526040918290205460025492516321f8a72160e01b81529193506001600160a01b039081169216906321f8a721906104a5908590600401613392565b60206040518083038186803b1580156104bd57600080fd5b505afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104f5919081019061278b565b6001600160a01b031614158061052057506000818152600360205260409020546001600160a01b0316155b156105315760009350505050610541565b5060010161043d565b5060019150505b90565b61054c61109c565b60045460ff166105775760405162461bcd60e51b815260040161056e9061348f565b60405180910390fd5b6004805460ff191690556040517f43e00f2c8f8651a29db34d34fb689573423f8aaae8f9d32e3e871b4c35c6254690600090a1565b6105b461123a565b6001600160a01b0316336001600160a01b0316146105e45760405162461bcd60e51b815260040161056e9061355f565b6105ec6110ea565b6001600160a01b031663a9059cbb610602611101565b836040518363ffffffff1660e01b81526004016103cc929190613358565b806106bf61062c611101565b6040516370a0823160e01b81526001600160a01b038416906370a082319061065890309060040161325a565b60206040518083038186803b15801561067057600080fd5b505afa158015610684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106a89190810190612952565b6001600160a01b038416919063ffffffff61125b16565b5050565b6106cb6110c8565b6001600160a01b0382166106f15760405162461bcd60e51b815260040161056e906134ef565b60006106fc846112b9565b116107195760405162461bcd60e51b815260040161056e9061352f565b6107216113a1565b6001600160a01b03166342a28e21846040518263ffffffff1660e01b815260040161074c9190613392565b60006040518083038186803b15801561076457600080fd5b505afa158015610778573d6000803e3d6000fd5b5050505061078e6314d95b9d60e21b84836113bb565b6000610798611510565b6001600160a01b031663c81ff8fa8533856040518463ffffffff1660e01b81526004016107c7939291906133ae565b602060405180830381600087803b1580156107e157600080fd5b505af11580156107f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061081991908101906128c9565b905080156108395760405162461bcd60e51b815260040161056e9061357f565b606063a6492fe260e01b858585604051602401610858939291906133c9565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050610894611524565b6001600160a01b0316633dbb202b6108aa61153f565b836108b56003611549565b6040518463ffffffff1660e01b81526004016108d393929190613329565b600060405180830381600087803b1580156108ed57600080fd5b505af1158015610901573d6000803e3d6000fd5b50505050836001600160a01b0316857f8437572793cb04c0a02524a185d39f9b72a4284bd2e69151b0ca0cf254b2cb0b8560405161093f9190613392565b60405180910390a35050505050565b6001546001600160a01b031681565b600061096f6314d95b9d60e21b611599565b905090565b7f53796e746865746978427269646765546f4f7074696d69736d0000000000000090565b6109a061109c565b60045460ff16156109c35760405162461bcd60e51b815260040161056e9061345f565b6004805460ff191660011790556040517f7c88488c18e2ff121a34a4a2a44990557a5b76ab1ceb6bd95ebe7d419c7575f490600090a1565b6060610a05610be9565b905060005b81518110156106bf576000828281518110610a2157fe5b602002602001015190506000600260009054906101000a90046001600160a01b03166001600160a01b031663dacb2d018384604051602001610a63919061324f565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610a8f929190613420565b60206040518083038186803b158015610aa757600080fd5b505afa158015610abb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610adf919081019061278b565b6000838152600360205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa6890610b3b90849084906133a0565b60405180910390a15050600101610a0a565b6001546001600160a01b03163314610b775760405162461bcd60e51b815260040161056e9061346f565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c92610bba926001600160a01b0391821692911690613300565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b606080610bf4611870565b60408051600480825260a0820190925291925060609190602082016080803883390190505090506524b9b9bab2b960d11b81600081518110610c3257fe5b602002602001018181525050722932bbb0b93239a234b9ba3934b13aba34b7b760691b81600181518110610c6257fe5b602002602001018181525050786f766d3a53796e746865746978427269646765546f4261736560381b81600281518110610c9857fe5b6020026020010181815250507453796e746865746978427269646765457363726f7760581b81600381518110610cca57fe5b602002602001018181525050610ce082826119d9565b9250505090565b6000546001600160a01b031681565b610cfe6110c8565b610d06611a95565b61042981611b35565b610d176110c8565b610d1f611a95565b805115610d2f57610d2f81611b35565b81156106bf576106bf3383611dd6565b610d47611f71565b610d59632932b1bb60e11b84836113bb565b610d61611510565b6001600160a01b031663890235d48484846040518463ffffffff1660e01b8152600401610d90939291906133c9565b602060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610de291908101906128c9565b50816001600160a01b0316837f81b100a611d2b249e23d093c64f09470928821e123a7cff2a033eb24c85b797983604051610e1d9190613392565b60405180910390a3505050565b610e326110c8565b610e3a611a95565b6104293382611dd6565b610e4c6110c8565b610e5461204d565b6001600160a01b0316336001600160a01b031614610e845760405162461bcd60e51b815260040161056e9061350f565b6040516000906060906325aae56360e01b90610ea690869086906024016133f7565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050610ee2611524565b6001600160a01b0316633dbb202b610ef8612062565b83610f036004611549565b6040518463ffffffff1660e01b8152600401610f2193929190613329565b600060405180830381600087803b158015610f3b57600080fd5b505af1158015610f4f573d6000803e3d6000fd5b505050507fcca0df3f2f18cd65d14c04abffc77c2d00aaca7ad00b0d2eb074adeea3fb54f48484604051610f849291906133f7565b60405180910390a150505050565b600061096f632932b1bb60e11b611599565b610fac611f71565b610fb46110ea565b6001600160a01b03166323b872dd610fca611101565b84846040518463ffffffff1660e01b8152600401610fea9392919061331b565b602060405180830381600087803b15801561100457600080fd5b505af1158015611018573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061103c91908101906128c9565b50816001600160a01b03167f9e5c4f9f4e46b8629d3dda85f43a69194f50254404a72dc62b9e932d9c94eda8826040516110769190613392565b60405180910390a25050565b61108a6110c8565b611092611a95565b6106bf8282611dd6565b6000546001600160a01b031633146110c65760405162461bcd60e51b815260040161056e906134ff565b565b60045460ff166110c65760405162461bcd60e51b815260040161056e906134bf565b600061096f680a6f2dce8d0cae8d2f60bb1b612085565b600061096f7453796e746865746978427269646765457363726f7760581b612085565b60405160009060609063a616cdfb60e01b906111469086908690602401613358565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050611182611524565b6001600160a01b0316633dbb202b611198612062565b836111a36002611549565b6040518463ffffffff1660e01b81526004016111c193929190613329565b600060405180830381600087803b1580156111db57600080fd5b505af11580156111ef573d6000803e3d6000fd5b50505050836001600160a01b03167f0ac6af0c6fd21e58850b0385f451cdcc08071424f47fd04652be4e51069f43cc8460405161122c9190613392565b60405180910390a250505050565b600061096f722932bbb0b93239a234b9ba3934b13aba34b7b760691b612085565b6040516112b490849063a9059cbb60e01b9061127d9086908690602401613358565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526120e2565b505050565b60006112c36121cd565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b7f63726f7373436861696e53796e74685472616e73666572456e61626c65640000856040516020016113169291906131c6565b604051602081830303815290604052805190602001206040518363ffffffff1660e01b81526004016113499291906133f7565b60206040518083038186803b15801561136157600080fd5b505afa158015611375573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113999190810190612952565b90505b919050565b600061096f6b53797374656d53746174757360a01b612085565b60006c29bcb73a342a3930b739b332b960991b84846040516020016113e2939291906131ec565b60405160208183030381529060405280519060200120905060006114046121cd565b6001600160a01b03166323257c2b61141a610974565b846040518363ffffffff1660e01b81526004016114389291906133f7565b60206040518083038186803b15801561145057600080fd5b505afa158015611464573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114889190810190612952565b90506114926121cd565b6001600160a01b0316631d5b277f6114a8610974565b846114b9858863ffffffff6121ea16565b6040518463ffffffff1660e01b81526004016114d793929190613405565b600060405180830381600087803b1580156114f157600080fd5b505af1158015611505573d6000803e3d6000fd5b505050505050505050565b600061096f6524b9b9bab2b960d11b612085565b600061096f6c32bc3a1d26b2b9b9b2b733b2b960991b612085565b600061096f612062565b60006115536121cd565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b61157c85612218565b6040518363ffffffff1660e01b81526004016113499291906133f7565b600060606115a5611510565b6001600160a01b03166372cb051f6040518163ffffffff1660e01b815260040160006040518083038186803b1580156115dd57600080fd5b505afa1580156115f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116199190810190612818565b905060606000611627612393565b6001600160a01b031663c8e5bbd5846040518263ffffffff1660e01b81526004016116529190613373565b60006040518083038186803b15801561166a57600080fd5b505afa15801561167e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116a69190810190612882565b9150915080156116c85760405162461bcd60e51b815260040161056e906134cf565b606083516040519080825280602002602001820160405280156116f5578160200160208202803883390190505b50905060005b8451811015611771576c29bcb73a342a3930b739b332b960991b8786838151811061172257fe5b602002602001015160405160200161173c939291906131ec565b6040516020818303038152906040528051906020012082828151811061175e57fe5b60209081029190910101526001016116fb565b50606061177c6121cd565b6001600160a01b031663b67fa7ed611792610974565b846040518363ffffffff1660e01b81526004016117b09291906133d7565b60006040518083038186803b1580156117c857600080fd5b505afa1580156117dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611804919081019061284d565b905060005b85518110156118655761185b61184e86838151811061182457fe5b602002602001015184848151811061183857fe5b60200260200101516123ae90919063ffffffff16565b889063ffffffff6121ea16565b9650600101611809565b505050505050919050565b60608061187b6123c3565b60408051600880825261012082019092529192506060919060208201610100803883390190505090506c32bc3a1d26b2b9b9b2b733b2b960991b816000815181106118c257fe5b602002602001018181525050680a6f2dce8d0cae8d2f60bb1b816001815181106118e857fe5b6020026020010181815250506d2932bbb0b93222b9b1b937bbab1960911b8160028151811061191357fe5b6020026020010181815250506524b9b9bab2b960d11b8160038151811061193657fe5b60200260200101818152505066119959541bdbdb60ca1b8160048151811061195a57fe5b6020026020010181815250506e466c657869626c6553746f7261676560881b8160058151811061198657fe5b6020026020010181815250506c45786368616e6765526174657360981b816006815181106119b057fe5b6020026020010181815250506b53797374656d53746174757360a01b81600781518110610cca57fe5b60608151835101604051908082528060200260200182016040528015611a09578160200160208202803883390190505b50905060005b8351811015611a4b57838181518110611a2457fe5b6020026020010151828281518110611a3857fe5b6020908102919091010152600101611a0f565b5060005b8251811015611a8e57828181518110611a6457fe5b6020026020010151828286510181518110611a7b57fe5b6020908102919091010152600101611a4f565b5092915050565b611a9d611510565b6001600160a01b031663d37c4d8b336040518263ffffffff1660e01b8152600401611ac891906132b0565b60206040518083038186803b158015611ae057600080fd5b505afa158015611af4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611b189190810190612952565b156110c65760405162461bcd60e51b815260040161056e906134df565b60005b81518110156106bf57601a60ff16828281518110611b5257fe5b6020026020010151511115611b795760405162461bcd60e51b815260040161056e906134af565b60006060611b85612414565b6001600160a01b03166380d46f5833868681518110611ba057fe5b60200260200101516040518363ffffffff1660e01b8152600401611bc5929190613290565b600060405180830381600087803b158015611bdf57600080fd5b505af1158015611bf3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c1b91908101906129b8565b90925090508115611dcc57611c2e6110ea565b6001600160a01b031663a9059cbb611c44611101565b846040518363ffffffff1660e01b8152600401611c62929190613358565b602060405180830381600087803b158015611c7c57600080fd5b505af1158015611c90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611cb491908101906128c9565b50604051600090606090637cbc127f60e11b90611cd9903390879087906024016132ca565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050611d15611524565b6001600160a01b0316633dbb202b611d2b612062565b83611d366001611549565b6040518463ffffffff1660e01b8152600401611d5493929190613329565b600060405180830381600087803b158015611d6e57600080fd5b505af1158015611d82573d6000803e3d6000fd5b50505050336001600160a01b03167f4dc5956ab6218a4dfa2cc5e5c50d98d039dde03aabfc504c54b601b6f56226968585604051611dc19291906135af565b60405180910390a250505b5050600101611b38565b611dde6110ea565b6001600160a01b03166323b872dd33611df5611101565b846040518463ffffffff1660e01b8152600401611e1493929190613268565b602060405180830381600087803b158015611e2e57600080fd5b505af1158015611e42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611e6691908101906128c9565b50604051600090606090638d6e9a5b60e01b90611e899086908690602401613358565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050611ec5611524565b6001600160a01b0316633dbb202b611edb612062565b83611ee66000611549565b6040518463ffffffff1660e01b8152600401611f0493929190613329565b600060405180830381600087803b158015611f1e57600080fd5b505af1158015611f32573d6000803e3d6000fd5b50505050336001600160a01b03167ff531653a5819e21265de50358610d55dbe6594c61605b209dfa4280d277938c1858560405161122c929190613358565b6000611f7b611524565b9050336001600160a01b03821614611fa55760405162461bcd60e51b815260040161056e9061353f565b611fad61153f565b6001600160a01b0316816001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b158015611fef57600080fd5b505afa158015612003573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612027919081019061278b565b6001600160a01b0316146104295760405162461bcd60e51b815260040161056e9061354f565b600061096f66119959541bdbdb60ca1b612085565b600061096f786f766d3a53796e746865746978427269646765546f4261736560381b5b60008181526003602090815260408083205490516001600160a01b0390911691821515916120b59186910161322f565b60405160208183030381529060405290611a8e5760405162461bcd60e51b815260040161056e919061344e565b6120f4826001600160a01b0316612430565b6121105760405162461bcd60e51b815260040161056e9061359f565b60006060836001600160a01b03168360405161212c9190613223565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150816121905760405162461bcd60e51b815260040161056e9061349f565b8051156121c757808060200190516121ab91908101906128c9565b6121c75760405162461bcd60e51b815260040161056e9061356f565b50505050565b600061096f6e466c657869626c6553746f7261676560881b612085565b60008282018381101561220f5760405162461bcd60e51b815260040161056e9061347f565b90505b92915050565b60008082600581111561222757fe5b141561225457507f63726f7373446f6d61696e4465706f7369744761734c696d697400000000000061139c565b600182600581111561226257fe5b141561228f57507f63726f7373446f6d61696e457363726f774761734c696d69740000000000000061139c565b600282600581111561229d57fe5b14156122ca57507f63726f7373446f6d61696e5265776172644761734c696d69740000000000000061139c565b60038260058111156122d857fe5b141561230557507f63726f7373446f6d61696e5769746864726177616c4761734c696d697400000061139c565b600582600581111561231357fe5b141561234057507f63726f7373446f6d61696e52656c61794761734c696d6974000000000000000061139c565b600482600581111561234e57fe5b141561237b57507f63726f7373446f6d61696e436c6f73654761734c696d6974000000000000000061139c565b60405162461bcd60e51b815260040161056e9061358f565b600061096f6c45786368616e6765526174657360981b612085565b600061220f8383670de0b6b3a7640000612436565b604080516001808252818301909252606091602080830190803883390190505090506e466c657869626c6553746f7261676560881b8160008151811061240557fe5b60200260200101818152505090565b600061096f6d2932bbb0b93222b9b1b937bbab1960911b612085565b3b151590565b600080600a830461244d868663ffffffff61247416565b8161245457fe5b0490506005600a82061061246657600a015b600a900490505b9392505050565b60008261248357506000612212565b8282028284828161249057fe5b041461220f5760405162461bcd60e51b815260040161056e9061351f565b8035612212816136a4565b8051612212816136a4565b600082601f8301126124d557600080fd5b81356124e86124e3826135f6565b6135cf565b81815260209384019390925082018360005b8381101561252657813586016125108882612612565b84525060209283019291909101906001016124fa565b5050505092915050565b600082601f83011261254157600080fd5b815161254f6124e3826135f6565b9150818183526020840193506020810190508385602084028201111561257457600080fd5b60005b83811015612526578161258a8882612708565b8452506020928301929190910190600101612577565b600082601f8301126125b157600080fd5b81516125bf6124e3826135f6565b915081818352602084019350602081019050838560408402820111156125e457600080fd5b60005b8381101561252657816125fa8882612713565b845250602090920191604091909101906001016125e7565b600082601f83011261262357600080fd5b81356126316124e3826135f6565b9150818183526020840193506020810190508385602084028201111561265657600080fd5b60005b83811015612526578161266c88826126fd565b8452506020928301929190910190600101612659565b600082601f83011261269357600080fd5b81516126a16124e3826135f6565b915081818352602084019350602081019050838560208402820111156126c657600080fd5b60005b8381101561252657816126dc8882612708565b84525060209283019291909101906001016126c9565b8051612212816136b8565b8035612212816136c1565b8051612212816136c1565b60006040828403121561272557600080fd5b61272f60406135cf565b9050600061273d848461275a565b825250602061274e84848301612708565b60208301525092915050565b8051612212816136ca565b60006020828403121561277757600080fd5b600061278384846124ae565b949350505050565b60006020828403121561279d57600080fd5b600061278384846124b9565b600080604083850312156127bc57600080fd5b60006127c885856124ae565b92505060206127d9858286016126fd565b9150509250929050565b6000602082840312156127f557600080fd5b813567ffffffffffffffff81111561280c57600080fd5b612783848285016124c4565b60006020828403121561282a57600080fd5b815167ffffffffffffffff81111561284157600080fd5b61278384828501612530565b60006020828403121561285f57600080fd5b815167ffffffffffffffff81111561287657600080fd5b61278384828501612682565b6000806040838503121561289557600080fd5b825167ffffffffffffffff8111156128ac57600080fd5b6128b885828601612682565b92505060206127d9858286016126f2565b6000602082840312156128db57600080fd5b600061278384846126f2565b6000806000606084860312156128fc57600080fd5b600061290886866126fd565b9350506020612919868287016124ae565b925050604061292a868287016126fd565b9150509250925092565b60006020828403121561294657600080fd5b600061278384846126fd565b60006020828403121561296457600080fd5b60006127838484612708565b6000806040838503121561298357600080fd5b600061298f85856126fd565b925050602083013567ffffffffffffffff8111156129ac57600080fd5b6127d9858286016124c4565b600080604083850312156129cb57600080fd5b60006129d78585612708565b925050602083015167ffffffffffffffff8111156129f457600080fd5b6127d9858286016125a0565b60008060408385031215612a1357600080fd5b60006127c885856126fd565b6000612a2b8383612b5d565b505060200190565b6000612a3f8383613190565b505060400190565b612a508161365c565b82525050565b612a508161362a565b6000612a6a8261361d565b612a748185613621565b9350612a7f83613617565b8060005b83811015612aad578151612a978882612a1f565b9750612aa283613617565b925050600101612a83565b509495945050505050565b6000612ac38261361d565b612acd8185613621565b9350612ad883613617565b8060005b83811015612aad578151612af08882612a33565b9750612afb83613617565b925050600101612adc565b6000612b118261361d565b612b1b8185613621565b9350612b2683613617565b8060005b83811015612aad578151612b3e8882612a1f565b9750612b4983613617565b925050600101612b2a565b612a5081613635565b612a5081610541565b612a50612b7282610541565b610541565b6000612b828261361d565b612b8c8185613621565b9350612b9c81856020860161366e565b612ba58161369a565b9093019392505050565b6000612bba8261361d565b612bc4818561139c565b9350612bd481856020860161366e565b9290920192915050565b612a5081613663565b6000612bf4601883613621565b7f496e6974696174696f6e206e6f742073757370656e6465640000000000000000815260200192915050565b6000612c2d603583613621565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527402063616e20616363657074206f776e65727368697605c1b602082015260400192915050565b6000612c84601b83613621565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000612cbd601483613621565b73125b9a5d1a585d1a5bdb881cdd5cdc195b99195960621b815260200192915050565b6000612ced602083613621565b7f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815260200192915050565b6000612d26602183613621565b7f45786365656473206d617820656e747269657320706572206d6967726174696f8152603760f91b602082015260400192915050565b6000612d6960118361139c565b70026b4b9b9b4b7339030b2323932b9b99d1607d1b815260110192915050565b6000612d96601683613621565b75125b9a5d1a585d1a5bdb8819195858dd1a5d985d195960521b815260200192915050565b6000612dc8601183613621565b7014985d195cc8185c99481a5b9d985b1a59607a1b815260200192915050565b6000612df5602383613621565b7f43616e6e6f74206465706f736974206f72206d6967726174652077697468206481526219589d60ea1b602082015260400192915050565b6000612e3a601b83613621565b7f43616e6e6f742073656e6420746f207a65726f20616464726573730000000000815260200192915050565b6000612e73602f83613621565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681526e37b936903a3434b99030b1ba34b7b760891b602082015260400192915050565b631cd554d160e21b9052565b6000612ed0601f83613621565b7f4f6e6c79207468652066656520706f6f6c2063616e2063616c6c207468697300815260200192915050565b6000612f09602183613621565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b6000612f4c602a83613621565b7f53796e7468206e6f7420656e61626c656420666f722063726f7373206368616981526937103a3930b739b332b960b11b602082015260400192915050565b6000612f98601e83613621565b7f4f6e6c79207468652072656c617965722063616e2063616c6c20746869730000815260200192915050565b6000612fd160198361139c565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b600061300a602483613621565b7f4f6e6c79206120636f756e74657270617274206272696467652063616e20696e815263766f6b6560e01b602082015260400192915050565b6000613050602a83613621565b7f43616c6c6572206973206e6f742052657761726473446973747269627574696f8152691b8818dbdb9d1c9858dd60b21b602082015260400192915050565b600061309c602a83613621565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b602082015260400192915050565b60006130e8602883613621565b7f43616e6e6f7420696e6974696174652069662073796e74682072617465206973815267081a5b9d985b1a5960c21b602082015260400192915050565b6000613132601683613621565b75556e6b6e6f776e20676173206c696d6974207479706560501b815260200192915050565b6000613164601f83613621565b7f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400815260200192915050565b805160408301906131a184826131bd565b5060208201516121c76020850182612b5d565b612a5081613646565b612a508161364f565b60006131d28285612b66565b6020820191506131e28284612b66565b5060200192915050565b60006131f88286612b66565b6020820191506132088285612b66565b6020820191506132188284612b66565b506020019392505050565b600061246d8284612baf565b600061323a82612d5c565b91506132468284612b66565b50602001919050565b600061323a82612fc4565b602081016122128284612a56565b606081016132768286612a47565b6132836020830185612a56565b6127836040830184612b5d565b6040810161329e8285612a47565b81810360208301526127838184612b06565b604081016132be8284612a47565b61221260208301612eb7565b606081016132d88286612a56565b6132e56020830185612b5d565b81810360408301526132f78184612ab8565b95945050505050565b6040810161330e8285612a56565b61246d6020830184612a56565b606081016132768286612a56565b606081016133378286612a56565b81810360208301526133498185612b77565b905061278360408301846131b4565b604081016133668285612a56565b61246d6020830184612b5d565b6020808252810161220f8184612a5f565b602081016122128284612b54565b602081016122128284612b5d565b6040810161330e8285612b5d565b606081016133bc8286612b5d565b6132836020830185612a47565b606081016132768286612b5d565b604081016133e58285612b5d565b81810360208301526127838184612a5f565b604081016133668285612b5d565b606081016134138286612b5d565b6132836020830185612b5d565b6040810161342e8285612b5d565b81810360208301526127838184612b77565b602081016122128284612bde565b6020808252810161220f8184612b77565b6020808252810161139981612be7565b6020808252810161139981612c20565b6020808252810161139981612c77565b6020808252810161139981612cb0565b6020808252810161139981612ce0565b6020808252810161139981612d19565b6020808252810161139981612d89565b6020808252810161139981612dbb565b6020808252810161139981612de8565b6020808252810161139981612e2d565b6020808252810161139981612e66565b6020808252810161139981612ec3565b6020808252810161139981612efc565b6020808252810161139981612f3f565b6020808252810161139981612f8b565b6020808252810161139981612ffd565b6020808252810161139981613043565b602080825281016113998161308f565b60208082528101611399816130db565b6020808252810161139981613125565b6020808252810161139981613157565b604081016135bd8285612b5d565b81810360208301526127838184612ab8565b60405181810167ffffffffffffffff811182821017156135ee57600080fd5b604052919050565b600067ffffffffffffffff82111561360d57600080fd5b5060209081020190565b60200190565b5190565b90815260200190565b60006113998261363a565b151590565b6001600160a01b031690565b63ffffffff1690565b67ffffffffffffffff1690565b6000611399825b60006113998261362a565b60005b83811015613689578181015183820152602001613671565b838111156121c75750506000910152565b601f01601f191690565b6136ad8161362a565b811461042957600080fd5b6136ad81613635565b6136ad81610541565b6136ad8161364f56fea365627a7a72315820fae196f19170575bc61868be3406147da6f7959d46ca1778e5c29d8d465bc0456c6578706572696d656e74616cf564736f6c63430005100040000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe0000000000000000000000004e3b31eb0e5cb73641ee1e65e7dcefe520ba3ef2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101735760003560e01c8063698a26b2116100de578063a18e230711610097578063b9958ab811610071578063b9958ab8146102cf578063bb91f6a3146102e2578063f4f7b41a146102ea578063ffaad6a5146102fd57610173565b8063a18e230714610296578063a6492fe2146102a9578063b6b55f25146102bc57610173565b8063698a26b21461024e578063741853601461025657806379ba50971461025e578063899ffef4146102665780638da5cb5b1461027b5780639a9e7f961461028357610173565b80633c6b16ab116101305780633c6b16ab146101e3578063462286d5146101f65780634873966f1461020957806353a47bb71461021c5780635aba32ae14610231578063614d08f81461024657610173565b806304f3bcec14610178578063100be6d4146101965780631627540c146101ab5780631e2720ff146101c05780632af64bd3146101d35780633872dda3146101db575b600080fd5b610180610310565b60405161018d9190613440565b60405180910390f35b61019e61031f565b60405161018d9190613384565b6101be6101b9366004612765565b610328565b005b6101be6101ce366004612934565b610386565b61019e61042c565b6101be610544565b6101be6101f1366004612934565b6105ac565b6101be610204366004612765565b610620565b6101be6102173660046128e7565b6106c3565b61022461094e565b60405161018d919061325a565b61023961095d565b60405161018d9190613392565b610239610974565b6101be610998565b6101be6109fb565b6101be610b4d565b61026e610be9565b60405161018d9190613373565b610224610ce7565b6101be6102913660046127e3565b610cf6565b6101be6102a4366004612970565b610d0f565b6101be6102b73660046128e7565b610d3f565b6101be6102ca366004612934565b610e2a565b6101be6102dd366004612a00565b610e44565b610239610f92565b6101be6102f83660046127a9565b610fa4565b6101be61030b3660046127a9565b611082565b6002546001600160a01b031681565b60045460ff1681565b61033061109c565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229061037b90839061325a565b60405180910390a150565b61038e6110c8565b6103966110ea565b6001600160a01b03166323b872dd336103ad611101565b846040518463ffffffff1660e01b81526004016103cc93929190613268565b602060405180830381600087803b1580156103e657600080fd5b505af11580156103fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061041e91908101906128c9565b506104293382611124565b50565b60006060610438610be9565b905060005b815181101561053a57600082828151811061045457fe5b602090810291909101810151600081815260039092526040918290205460025492516321f8a72160e01b81529193506001600160a01b039081169216906321f8a721906104a5908590600401613392565b60206040518083038186803b1580156104bd57600080fd5b505afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104f5919081019061278b565b6001600160a01b031614158061052057506000818152600360205260409020546001600160a01b0316155b156105315760009350505050610541565b5060010161043d565b5060019150505b90565b61054c61109c565b60045460ff166105775760405162461bcd60e51b815260040161056e9061348f565b60405180910390fd5b6004805460ff191690556040517f43e00f2c8f8651a29db34d34fb689573423f8aaae8f9d32e3e871b4c35c6254690600090a1565b6105b461123a565b6001600160a01b0316336001600160a01b0316146105e45760405162461bcd60e51b815260040161056e9061355f565b6105ec6110ea565b6001600160a01b031663a9059cbb610602611101565b836040518363ffffffff1660e01b81526004016103cc929190613358565b806106bf61062c611101565b6040516370a0823160e01b81526001600160a01b038416906370a082319061065890309060040161325a565b60206040518083038186803b15801561067057600080fd5b505afa158015610684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106a89190810190612952565b6001600160a01b038416919063ffffffff61125b16565b5050565b6106cb6110c8565b6001600160a01b0382166106f15760405162461bcd60e51b815260040161056e906134ef565b60006106fc846112b9565b116107195760405162461bcd60e51b815260040161056e9061352f565b6107216113a1565b6001600160a01b03166342a28e21846040518263ffffffff1660e01b815260040161074c9190613392565b60006040518083038186803b15801561076457600080fd5b505afa158015610778573d6000803e3d6000fd5b5050505061078e6314d95b9d60e21b84836113bb565b6000610798611510565b6001600160a01b031663c81ff8fa8533856040518463ffffffff1660e01b81526004016107c7939291906133ae565b602060405180830381600087803b1580156107e157600080fd5b505af11580156107f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061081991908101906128c9565b905080156108395760405162461bcd60e51b815260040161056e9061357f565b606063a6492fe260e01b858585604051602401610858939291906133c9565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050610894611524565b6001600160a01b0316633dbb202b6108aa61153f565b836108b56003611549565b6040518463ffffffff1660e01b81526004016108d393929190613329565b600060405180830381600087803b1580156108ed57600080fd5b505af1158015610901573d6000803e3d6000fd5b50505050836001600160a01b0316857f8437572793cb04c0a02524a185d39f9b72a4284bd2e69151b0ca0cf254b2cb0b8560405161093f9190613392565b60405180910390a35050505050565b6001546001600160a01b031681565b600061096f6314d95b9d60e21b611599565b905090565b7f53796e746865746978427269646765546f4f7074696d69736d0000000000000090565b6109a061109c565b60045460ff16156109c35760405162461bcd60e51b815260040161056e9061345f565b6004805460ff191660011790556040517f7c88488c18e2ff121a34a4a2a44990557a5b76ab1ceb6bd95ebe7d419c7575f490600090a1565b6060610a05610be9565b905060005b81518110156106bf576000828281518110610a2157fe5b602002602001015190506000600260009054906101000a90046001600160a01b03166001600160a01b031663dacb2d018384604051602001610a63919061324f565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610a8f929190613420565b60206040518083038186803b158015610aa757600080fd5b505afa158015610abb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610adf919081019061278b565b6000838152600360205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa6890610b3b90849084906133a0565b60405180910390a15050600101610a0a565b6001546001600160a01b03163314610b775760405162461bcd60e51b815260040161056e9061346f565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c92610bba926001600160a01b0391821692911690613300565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b606080610bf4611870565b60408051600480825260a0820190925291925060609190602082016080803883390190505090506524b9b9bab2b960d11b81600081518110610c3257fe5b602002602001018181525050722932bbb0b93239a234b9ba3934b13aba34b7b760691b81600181518110610c6257fe5b602002602001018181525050786f766d3a53796e746865746978427269646765546f4261736560381b81600281518110610c9857fe5b6020026020010181815250507453796e746865746978427269646765457363726f7760581b81600381518110610cca57fe5b602002602001018181525050610ce082826119d9565b9250505090565b6000546001600160a01b031681565b610cfe6110c8565b610d06611a95565b61042981611b35565b610d176110c8565b610d1f611a95565b805115610d2f57610d2f81611b35565b81156106bf576106bf3383611dd6565b610d47611f71565b610d59632932b1bb60e11b84836113bb565b610d61611510565b6001600160a01b031663890235d48484846040518463ffffffff1660e01b8152600401610d90939291906133c9565b602060405180830381600087803b158015610daa57600080fd5b505af1158015610dbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610de291908101906128c9565b50816001600160a01b0316837f81b100a611d2b249e23d093c64f09470928821e123a7cff2a033eb24c85b797983604051610e1d9190613392565b60405180910390a3505050565b610e326110c8565b610e3a611a95565b6104293382611dd6565b610e4c6110c8565b610e5461204d565b6001600160a01b0316336001600160a01b031614610e845760405162461bcd60e51b815260040161056e9061350f565b6040516000906060906325aae56360e01b90610ea690869086906024016133f7565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050610ee2611524565b6001600160a01b0316633dbb202b610ef8612062565b83610f036004611549565b6040518463ffffffff1660e01b8152600401610f2193929190613329565b600060405180830381600087803b158015610f3b57600080fd5b505af1158015610f4f573d6000803e3d6000fd5b505050507fcca0df3f2f18cd65d14c04abffc77c2d00aaca7ad00b0d2eb074adeea3fb54f48484604051610f849291906133f7565b60405180910390a150505050565b600061096f632932b1bb60e11b611599565b610fac611f71565b610fb46110ea565b6001600160a01b03166323b872dd610fca611101565b84846040518463ffffffff1660e01b8152600401610fea9392919061331b565b602060405180830381600087803b15801561100457600080fd5b505af1158015611018573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061103c91908101906128c9565b50816001600160a01b03167f9e5c4f9f4e46b8629d3dda85f43a69194f50254404a72dc62b9e932d9c94eda8826040516110769190613392565b60405180910390a25050565b61108a6110c8565b611092611a95565b6106bf8282611dd6565b6000546001600160a01b031633146110c65760405162461bcd60e51b815260040161056e906134ff565b565b60045460ff166110c65760405162461bcd60e51b815260040161056e906134bf565b600061096f680a6f2dce8d0cae8d2f60bb1b612085565b600061096f7453796e746865746978427269646765457363726f7760581b612085565b60405160009060609063a616cdfb60e01b906111469086908690602401613358565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050611182611524565b6001600160a01b0316633dbb202b611198612062565b836111a36002611549565b6040518463ffffffff1660e01b81526004016111c193929190613329565b600060405180830381600087803b1580156111db57600080fd5b505af11580156111ef573d6000803e3d6000fd5b50505050836001600160a01b03167f0ac6af0c6fd21e58850b0385f451cdcc08071424f47fd04652be4e51069f43cc8460405161122c9190613392565b60405180910390a250505050565b600061096f722932bbb0b93239a234b9ba3934b13aba34b7b760691b612085565b6040516112b490849063a9059cbb60e01b9061127d9086908690602401613358565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526120e2565b505050565b60006112c36121cd565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b7f63726f7373436861696e53796e74685472616e73666572456e61626c65640000856040516020016113169291906131c6565b604051602081830303815290604052805190602001206040518363ffffffff1660e01b81526004016113499291906133f7565b60206040518083038186803b15801561136157600080fd5b505afa158015611375573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113999190810190612952565b90505b919050565b600061096f6b53797374656d53746174757360a01b612085565b60006c29bcb73a342a3930b739b332b960991b84846040516020016113e2939291906131ec565b60405160208183030381529060405280519060200120905060006114046121cd565b6001600160a01b03166323257c2b61141a610974565b846040518363ffffffff1660e01b81526004016114389291906133f7565b60206040518083038186803b15801561145057600080fd5b505afa158015611464573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114889190810190612952565b90506114926121cd565b6001600160a01b0316631d5b277f6114a8610974565b846114b9858863ffffffff6121ea16565b6040518463ffffffff1660e01b81526004016114d793929190613405565b600060405180830381600087803b1580156114f157600080fd5b505af1158015611505573d6000803e3d6000fd5b505050505050505050565b600061096f6524b9b9bab2b960d11b612085565b600061096f6c32bc3a1d26b2b9b9b2b733b2b960991b612085565b600061096f612062565b60006115536121cd565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b61157c85612218565b6040518363ffffffff1660e01b81526004016113499291906133f7565b600060606115a5611510565b6001600160a01b03166372cb051f6040518163ffffffff1660e01b815260040160006040518083038186803b1580156115dd57600080fd5b505afa1580156115f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116199190810190612818565b905060606000611627612393565b6001600160a01b031663c8e5bbd5846040518263ffffffff1660e01b81526004016116529190613373565b60006040518083038186803b15801561166a57600080fd5b505afa15801561167e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116a69190810190612882565b9150915080156116c85760405162461bcd60e51b815260040161056e906134cf565b606083516040519080825280602002602001820160405280156116f5578160200160208202803883390190505b50905060005b8451811015611771576c29bcb73a342a3930b739b332b960991b8786838151811061172257fe5b602002602001015160405160200161173c939291906131ec565b6040516020818303038152906040528051906020012082828151811061175e57fe5b60209081029190910101526001016116fb565b50606061177c6121cd565b6001600160a01b031663b67fa7ed611792610974565b846040518363ffffffff1660e01b81526004016117b09291906133d7565b60006040518083038186803b1580156117c857600080fd5b505afa1580156117dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611804919081019061284d565b905060005b85518110156118655761185b61184e86838151811061182457fe5b602002602001015184848151811061183857fe5b60200260200101516123ae90919063ffffffff16565b889063ffffffff6121ea16565b9650600101611809565b505050505050919050565b60608061187b6123c3565b60408051600880825261012082019092529192506060919060208201610100803883390190505090506c32bc3a1d26b2b9b9b2b733b2b960991b816000815181106118c257fe5b602002602001018181525050680a6f2dce8d0cae8d2f60bb1b816001815181106118e857fe5b6020026020010181815250506d2932bbb0b93222b9b1b937bbab1960911b8160028151811061191357fe5b6020026020010181815250506524b9b9bab2b960d11b8160038151811061193657fe5b60200260200101818152505066119959541bdbdb60ca1b8160048151811061195a57fe5b6020026020010181815250506e466c657869626c6553746f7261676560881b8160058151811061198657fe5b6020026020010181815250506c45786368616e6765526174657360981b816006815181106119b057fe5b6020026020010181815250506b53797374656d53746174757360a01b81600781518110610cca57fe5b60608151835101604051908082528060200260200182016040528015611a09578160200160208202803883390190505b50905060005b8351811015611a4b57838181518110611a2457fe5b6020026020010151828281518110611a3857fe5b6020908102919091010152600101611a0f565b5060005b8251811015611a8e57828181518110611a6457fe5b6020026020010151828286510181518110611a7b57fe5b6020908102919091010152600101611a4f565b5092915050565b611a9d611510565b6001600160a01b031663d37c4d8b336040518263ffffffff1660e01b8152600401611ac891906132b0565b60206040518083038186803b158015611ae057600080fd5b505afa158015611af4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611b189190810190612952565b156110c65760405162461bcd60e51b815260040161056e906134df565b60005b81518110156106bf57601a60ff16828281518110611b5257fe5b6020026020010151511115611b795760405162461bcd60e51b815260040161056e906134af565b60006060611b85612414565b6001600160a01b03166380d46f5833868681518110611ba057fe5b60200260200101516040518363ffffffff1660e01b8152600401611bc5929190613290565b600060405180830381600087803b158015611bdf57600080fd5b505af1158015611bf3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611c1b91908101906129b8565b90925090508115611dcc57611c2e6110ea565b6001600160a01b031663a9059cbb611c44611101565b846040518363ffffffff1660e01b8152600401611c62929190613358565b602060405180830381600087803b158015611c7c57600080fd5b505af1158015611c90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611cb491908101906128c9565b50604051600090606090637cbc127f60e11b90611cd9903390879087906024016132ca565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050611d15611524565b6001600160a01b0316633dbb202b611d2b612062565b83611d366001611549565b6040518463ffffffff1660e01b8152600401611d5493929190613329565b600060405180830381600087803b158015611d6e57600080fd5b505af1158015611d82573d6000803e3d6000fd5b50505050336001600160a01b03167f4dc5956ab6218a4dfa2cc5e5c50d98d039dde03aabfc504c54b601b6f56226968585604051611dc19291906135af565b60405180910390a250505b5050600101611b38565b611dde6110ea565b6001600160a01b03166323b872dd33611df5611101565b846040518463ffffffff1660e01b8152600401611e1493929190613268565b602060405180830381600087803b158015611e2e57600080fd5b505af1158015611e42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611e6691908101906128c9565b50604051600090606090638d6e9a5b60e01b90611e899086908690602401613358565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050611ec5611524565b6001600160a01b0316633dbb202b611edb612062565b83611ee66000611549565b6040518463ffffffff1660e01b8152600401611f0493929190613329565b600060405180830381600087803b158015611f1e57600080fd5b505af1158015611f32573d6000803e3d6000fd5b50505050336001600160a01b03167ff531653a5819e21265de50358610d55dbe6594c61605b209dfa4280d277938c1858560405161122c929190613358565b6000611f7b611524565b9050336001600160a01b03821614611fa55760405162461bcd60e51b815260040161056e9061353f565b611fad61153f565b6001600160a01b0316816001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b158015611fef57600080fd5b505afa158015612003573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612027919081019061278b565b6001600160a01b0316146104295760405162461bcd60e51b815260040161056e9061354f565b600061096f66119959541bdbdb60ca1b612085565b600061096f786f766d3a53796e746865746978427269646765546f4261736560381b5b60008181526003602090815260408083205490516001600160a01b0390911691821515916120b59186910161322f565b60405160208183030381529060405290611a8e5760405162461bcd60e51b815260040161056e919061344e565b6120f4826001600160a01b0316612430565b6121105760405162461bcd60e51b815260040161056e9061359f565b60006060836001600160a01b03168360405161212c9190613223565b6000604051808303816000865af19150503d8060008114612169576040519150601f19603f3d011682016040523d82523d6000602084013e61216e565b606091505b5091509150816121905760405162461bcd60e51b815260040161056e9061349f565b8051156121c757808060200190516121ab91908101906128c9565b6121c75760405162461bcd60e51b815260040161056e9061356f565b50505050565b600061096f6e466c657869626c6553746f7261676560881b612085565b60008282018381101561220f5760405162461bcd60e51b815260040161056e9061347f565b90505b92915050565b60008082600581111561222757fe5b141561225457507f63726f7373446f6d61696e4465706f7369744761734c696d697400000000000061139c565b600182600581111561226257fe5b141561228f57507f63726f7373446f6d61696e457363726f774761734c696d69740000000000000061139c565b600282600581111561229d57fe5b14156122ca57507f63726f7373446f6d61696e5265776172644761734c696d69740000000000000061139c565b60038260058111156122d857fe5b141561230557507f63726f7373446f6d61696e5769746864726177616c4761734c696d697400000061139c565b600582600581111561231357fe5b141561234057507f63726f7373446f6d61696e52656c61794761734c696d6974000000000000000061139c565b600482600581111561234e57fe5b141561237b57507f63726f7373446f6d61696e436c6f73654761734c696d6974000000000000000061139c565b60405162461bcd60e51b815260040161056e9061358f565b600061096f6c45786368616e6765526174657360981b612085565b600061220f8383670de0b6b3a7640000612436565b604080516001808252818301909252606091602080830190803883390190505090506e466c657869626c6553746f7261676560881b8160008151811061240557fe5b60200260200101818152505090565b600061096f6d2932bbb0b93222b9b1b937bbab1960911b612085565b3b151590565b600080600a830461244d868663ffffffff61247416565b8161245457fe5b0490506005600a82061061246657600a015b600a900490505b9392505050565b60008261248357506000612212565b8282028284828161249057fe5b041461220f5760405162461bcd60e51b815260040161056e9061351f565b8035612212816136a4565b8051612212816136a4565b600082601f8301126124d557600080fd5b81356124e86124e3826135f6565b6135cf565b81815260209384019390925082018360005b8381101561252657813586016125108882612612565b84525060209283019291909101906001016124fa565b5050505092915050565b600082601f83011261254157600080fd5b815161254f6124e3826135f6565b9150818183526020840193506020810190508385602084028201111561257457600080fd5b60005b83811015612526578161258a8882612708565b8452506020928301929190910190600101612577565b600082601f8301126125b157600080fd5b81516125bf6124e3826135f6565b915081818352602084019350602081019050838560408402820111156125e457600080fd5b60005b8381101561252657816125fa8882612713565b845250602090920191604091909101906001016125e7565b600082601f83011261262357600080fd5b81356126316124e3826135f6565b9150818183526020840193506020810190508385602084028201111561265657600080fd5b60005b83811015612526578161266c88826126fd565b8452506020928301929190910190600101612659565b600082601f83011261269357600080fd5b81516126a16124e3826135f6565b915081818352602084019350602081019050838560208402820111156126c657600080fd5b60005b8381101561252657816126dc8882612708565b84525060209283019291909101906001016126c9565b8051612212816136b8565b8035612212816136c1565b8051612212816136c1565b60006040828403121561272557600080fd5b61272f60406135cf565b9050600061273d848461275a565b825250602061274e84848301612708565b60208301525092915050565b8051612212816136ca565b60006020828403121561277757600080fd5b600061278384846124ae565b949350505050565b60006020828403121561279d57600080fd5b600061278384846124b9565b600080604083850312156127bc57600080fd5b60006127c885856124ae565b92505060206127d9858286016126fd565b9150509250929050565b6000602082840312156127f557600080fd5b813567ffffffffffffffff81111561280c57600080fd5b612783848285016124c4565b60006020828403121561282a57600080fd5b815167ffffffffffffffff81111561284157600080fd5b61278384828501612530565b60006020828403121561285f57600080fd5b815167ffffffffffffffff81111561287657600080fd5b61278384828501612682565b6000806040838503121561289557600080fd5b825167ffffffffffffffff8111156128ac57600080fd5b6128b885828601612682565b92505060206127d9858286016126f2565b6000602082840312156128db57600080fd5b600061278384846126f2565b6000806000606084860312156128fc57600080fd5b600061290886866126fd565b9350506020612919868287016124ae565b925050604061292a868287016126fd565b9150509250925092565b60006020828403121561294657600080fd5b600061278384846126fd565b60006020828403121561296457600080fd5b60006127838484612708565b6000806040838503121561298357600080fd5b600061298f85856126fd565b925050602083013567ffffffffffffffff8111156129ac57600080fd5b6127d9858286016124c4565b600080604083850312156129cb57600080fd5b60006129d78585612708565b925050602083015167ffffffffffffffff8111156129f457600080fd5b6127d9858286016125a0565b60008060408385031215612a1357600080fd5b60006127c885856126fd565b6000612a2b8383612b5d565b505060200190565b6000612a3f8383613190565b505060400190565b612a508161365c565b82525050565b612a508161362a565b6000612a6a8261361d565b612a748185613621565b9350612a7f83613617565b8060005b83811015612aad578151612a978882612a1f565b9750612aa283613617565b925050600101612a83565b509495945050505050565b6000612ac38261361d565b612acd8185613621565b9350612ad883613617565b8060005b83811015612aad578151612af08882612a33565b9750612afb83613617565b925050600101612adc565b6000612b118261361d565b612b1b8185613621565b9350612b2683613617565b8060005b83811015612aad578151612b3e8882612a1f565b9750612b4983613617565b925050600101612b2a565b612a5081613635565b612a5081610541565b612a50612b7282610541565b610541565b6000612b828261361d565b612b8c8185613621565b9350612b9c81856020860161366e565b612ba58161369a565b9093019392505050565b6000612bba8261361d565b612bc4818561139c565b9350612bd481856020860161366e565b9290920192915050565b612a5081613663565b6000612bf4601883613621565b7f496e6974696174696f6e206e6f742073757370656e6465640000000000000000815260200192915050565b6000612c2d603583613621565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527402063616e20616363657074206f776e65727368697605c1b602082015260400192915050565b6000612c84601b83613621565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000612cbd601483613621565b73125b9a5d1a585d1a5bdb881cdd5cdc195b99195960621b815260200192915050565b6000612ced602083613621565b7f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815260200192915050565b6000612d26602183613621565b7f45786365656473206d617820656e747269657320706572206d6967726174696f8152603760f91b602082015260400192915050565b6000612d6960118361139c565b70026b4b9b9b4b7339030b2323932b9b99d1607d1b815260110192915050565b6000612d96601683613621565b75125b9a5d1a585d1a5bdb8819195858dd1a5d985d195960521b815260200192915050565b6000612dc8601183613621565b7014985d195cc8185c99481a5b9d985b1a59607a1b815260200192915050565b6000612df5602383613621565b7f43616e6e6f74206465706f736974206f72206d6967726174652077697468206481526219589d60ea1b602082015260400192915050565b6000612e3a601b83613621565b7f43616e6e6f742073656e6420746f207a65726f20616464726573730000000000815260200192915050565b6000612e73602f83613621565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681526e37b936903a3434b99030b1ba34b7b760891b602082015260400192915050565b631cd554d160e21b9052565b6000612ed0601f83613621565b7f4f6e6c79207468652066656520706f6f6c2063616e2063616c6c207468697300815260200192915050565b6000612f09602183613621565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b6000612f4c602a83613621565b7f53796e7468206e6f7420656e61626c656420666f722063726f7373206368616981526937103a3930b739b332b960b11b602082015260400192915050565b6000612f98601e83613621565b7f4f6e6c79207468652072656c617965722063616e2063616c6c20746869730000815260200192915050565b6000612fd160198361139c565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b600061300a602483613621565b7f4f6e6c79206120636f756e74657270617274206272696467652063616e20696e815263766f6b6560e01b602082015260400192915050565b6000613050602a83613621565b7f43616c6c6572206973206e6f742052657761726473446973747269627574696f8152691b8818dbdb9d1c9858dd60b21b602082015260400192915050565b600061309c602a83613621565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b602082015260400192915050565b60006130e8602883613621565b7f43616e6e6f7420696e6974696174652069662073796e74682072617465206973815267081a5b9d985b1a5960c21b602082015260400192915050565b6000613132601683613621565b75556e6b6e6f776e20676173206c696d6974207479706560501b815260200192915050565b6000613164601f83613621565b7f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400815260200192915050565b805160408301906131a184826131bd565b5060208201516121c76020850182612b5d565b612a5081613646565b612a508161364f565b60006131d28285612b66565b6020820191506131e28284612b66565b5060200192915050565b60006131f88286612b66565b6020820191506132088285612b66565b6020820191506132188284612b66565b506020019392505050565b600061246d8284612baf565b600061323a82612d5c565b91506132468284612b66565b50602001919050565b600061323a82612fc4565b602081016122128284612a56565b606081016132768286612a47565b6132836020830185612a56565b6127836040830184612b5d565b6040810161329e8285612a47565b81810360208301526127838184612b06565b604081016132be8284612a47565b61221260208301612eb7565b606081016132d88286612a56565b6132e56020830185612b5d565b81810360408301526132f78184612ab8565b95945050505050565b6040810161330e8285612a56565b61246d6020830184612a56565b606081016132768286612a56565b606081016133378286612a56565b81810360208301526133498185612b77565b905061278360408301846131b4565b604081016133668285612a56565b61246d6020830184612b5d565b6020808252810161220f8184612a5f565b602081016122128284612b54565b602081016122128284612b5d565b6040810161330e8285612b5d565b606081016133bc8286612b5d565b6132836020830185612a47565b606081016132768286612b5d565b604081016133e58285612b5d565b81810360208301526127838184612a5f565b604081016133668285612b5d565b606081016134138286612b5d565b6132836020830185612b5d565b6040810161342e8285612b5d565b81810360208301526127838184612b77565b602081016122128284612bde565b6020808252810161220f8184612b77565b6020808252810161139981612be7565b6020808252810161139981612c20565b6020808252810161139981612c77565b6020808252810161139981612cb0565b6020808252810161139981612ce0565b6020808252810161139981612d19565b6020808252810161139981612d89565b6020808252810161139981612dbb565b6020808252810161139981612de8565b6020808252810161139981612e2d565b6020808252810161139981612e66565b6020808252810161139981612ec3565b6020808252810161139981612efc565b6020808252810161139981612f3f565b6020808252810161139981612f8b565b6020808252810161139981612ffd565b6020808252810161139981613043565b602080825281016113998161308f565b60208082528101611399816130db565b6020808252810161139981613125565b6020808252810161139981613157565b604081016135bd8285612b5d565b81810360208301526127838184612ab8565b60405181810167ffffffffffffffff811182821017156135ee57600080fd5b604052919050565b600067ffffffffffffffff82111561360d57600080fd5b5060209081020190565b60200190565b5190565b90815260200190565b60006113998261363a565b151590565b6001600160a01b031690565b63ffffffff1690565b67ffffffffffffffff1690565b6000611399825b60006113998261362a565b60005b83811015613689578181015183820152602001613671565b838111156121c75750506000910152565b601f01601f191690565b6136ad8161362a565b811461042957600080fd5b6136ad81613635565b6136ad81610541565b6136ad8161364f56fea365627a7a72315820fae196f19170575bc61868be3406147da6f7959d46ca1778e5c29d8d465bc0456c6578706572696d656e74616cf564736f6c63430005100040
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe0000000000000000000000004e3b31eb0e5cb73641ee1e65e7dcefe520ba3ef2
-----Decoded View---------------
Arg [0] : _owner (address): 0xDe910777C787903F78C89e7a0bf7F4C435cBB1Fe
Arg [1] : _resolver (address): 0x4E3b31eB0E5CB73641EE1E65E7dCEFe520bA3ef2
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000de910777c787903f78c89e7a0bf7f4c435cbb1fe
Arg [1] : 0000000000000000000000004e3b31eb0e5cb73641ee1e65e7dcefe520ba3ef2
Libraries Used
SafeDecimalMath : 0x84d626b2bb4d0f064067e4bf80fce7055d8f3e7bSystemSettingsLib : 0x5dabae966208192e5c3028a7480392337014ed8eSignedSafeDecimalMath : 0x728a2b79cad691531cc1146ef802617ff50c7095
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.730594 | 130,178 | $95,107.27 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.