Overview
ETH Balance
ETH Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Nominate New Own... | 19544445 | 1255 days ago | IN | 0 ETH | 0.000037282527 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | ||||
|---|---|---|---|---|---|---|---|
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH | |||||
| 146843001 | 10 mins ago | 0 ETH |
Cross-Chain Transactions
Contract Source Code (Solidity)
/**
*Submitted for verification at optimistic.etherscan.io on 2022-08-17
*/
/*
____ __ __ __ _
/ __/__ __ ___ / /_ / / ___ / /_ (_)__ __
_\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ /
/___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\
/___/
* Synthetix: CircuitBreaker.sol
*
* Latest source (may be newer): https://github.com/Synthetixio/synthetix/blob/master/contracts/CircuitBreaker.sol
* Docs: https://docs.synthetix.io/contracts/CircuitBreaker
*
* Contract Dependencies:
* - IAddressResolver
* - ICircuitBreaker
* - MixinResolver
* - MixinSystemSettings
* - Owned
* Libraries:
* - SafeDecimalMath
* - SafeMath
*
* 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 allNetworksDebtInfo()
external
view
returns (
uint256 debt,
uint256 sharesSupply,
bool isStale
);
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 addSynths(ISynth[] calldata synthsToAdd) external;
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 setCurrentPeriodId(uint128 periodId) external;
function liquidateAccount(address account, bool isSelfLiquidation)
external
returns (uint totalRedeemed, uint amountToLiquidate);
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_ESCROW_DURATION = "liquidationEscrowDuration";
bytes32 internal constant SETTING_LIQUIDATION_PENALTY = "liquidationPenalty";
bytes32 internal constant SETTING_SNX_LIQUIDATION_PENALTY = "snxLiquidationPenalty";
bytes32 internal constant SETTING_SELF_LIQUIDATION_PENALTY = "selfLiquidationPenalty";
bytes32 internal constant SETTING_FLAG_REWARD = "flagReward";
bytes32 internal constant SETTING_LIQUIDATE_REWARD = "liquidateReward";
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 getLiquidationEscrowDuration() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_ESCROW_DURATION);
}
function getLiquidationPenalty() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATION_PENALTY);
}
function getSnxLiquidationPenalty() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_SNX_LIQUIDATION_PENALTY);
}
function getSelfLiquidationPenalty() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_SELF_LIQUIDATION_PENALTY);
}
function getFlagReward() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_FLAG_REWARD);
}
function getLiquidateReward() internal view returns (uint) {
return flexibleStorage().getUIntValue(SETTING_CONTRACT_NAME, SETTING_LIQUIDATE_REWARD);
}
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))
);
}
}
// https://docs.synthetix.io/contracts/source/interfaces/ICircuitBreaker
interface ICircuitBreaker {
// Views
function isInvalid(address oracleAddress, uint value) external view returns (bool);
function priceDeviationThresholdFactor() external view returns (uint);
function isDeviationAboveThreshold(uint base, uint comparison) external view returns (bool);
function lastValue(address oracleAddress) external view returns (uint);
function circuitBroken(address oracleAddress) external view returns (bool);
// Mutative functions
function resetLastValue(address[] calldata oracleAddresses, uint[] calldata values) external;
function probeCircuitBreaker(address oracleAddress, uint value) external returns (bool circuitBroken);
}
/**
* @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));
}
}
// 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;
}
// 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);
function rateWithSafetyChecks(bytes32 currencyKey)
external
returns (
uint rate,
bool broken,
bool invalid
);
}
// Inheritance
// Internal references
// https://docs.synthetix.io/contracts/source/contracts/proxy
contract Proxy is Owned {
Proxyable public target;
constructor(address _owner) public Owned(_owner) {}
function setTarget(Proxyable _target) external onlyOwner {
target = _target;
emit TargetUpdated(_target);
}
function _emit(
bytes calldata callData,
uint numTopics,
bytes32 topic1,
bytes32 topic2,
bytes32 topic3,
bytes32 topic4
) external onlyTarget {
uint size = callData.length;
bytes memory _callData = callData;
assembly {
/* The first 32 bytes of callData contain its length (as specified by the abi).
* Length is assumed to be a uint256 and therefore maximum of 32 bytes
* in length. It is also leftpadded to be a multiple of 32 bytes.
* This means moving call_data across 32 bytes guarantees we correctly access
* the data itself. */
switch numTopics
case 0 {
log0(add(_callData, 32), size)
}
case 1 {
log1(add(_callData, 32), size, topic1)
}
case 2 {
log2(add(_callData, 32), size, topic1, topic2)
}
case 3 {
log3(add(_callData, 32), size, topic1, topic2, topic3)
}
case 4 {
log4(add(_callData, 32), size, topic1, topic2, topic3, topic4)
}
}
}
// solhint-disable no-complex-fallback
function() external payable {
// Mutable call setting Proxyable.messageSender as this is using call not delegatecall
target.setMessageSender(msg.sender);
assembly {
let free_ptr := mload(0x40)
calldatacopy(free_ptr, 0, calldatasize)
/* We must explicitly forward ether to the underlying contract as well. */
let result := call(gas, sload(target_slot), callvalue, free_ptr, calldatasize, 0, 0)
returndatacopy(free_ptr, 0, returndatasize)
if iszero(result) {
revert(free_ptr, returndatasize)
}
return(free_ptr, returndatasize)
}
}
modifier onlyTarget {
require(Proxyable(msg.sender) == target, "Must be proxy target");
_;
}
event TargetUpdated(Proxyable newTarget);
}
// Inheritance
// Internal references
// https://docs.synthetix.io/contracts/source/contracts/proxyable
contract Proxyable is Owned {
// This contract should be treated like an abstract contract
/* The proxy this contract exists behind. */
Proxy public proxy;
/* The caller of the proxy, passed through to this contract.
* Note that every function using this member must apply the onlyProxy or
* optionalProxy modifiers, otherwise their invocations can use stale values. */
address public messageSender;
constructor(address payable _proxy) internal {
// This contract is abstract, and thus cannot be instantiated directly
require(owner != address(0), "Owner must be set");
proxy = Proxy(_proxy);
emit ProxyUpdated(_proxy);
}
function setProxy(address payable _proxy) external onlyOwner {
proxy = Proxy(_proxy);
emit ProxyUpdated(_proxy);
}
function setMessageSender(address sender) external onlyProxy {
messageSender = sender;
}
modifier onlyProxy {
_onlyProxy();
_;
}
function _onlyProxy() private view {
require(Proxy(msg.sender) == proxy, "Only the proxy can call");
}
modifier optionalProxy {
_optionalProxy();
_;
}
function _optionalProxy() private {
if (Proxy(msg.sender) != proxy && messageSender != msg.sender) {
messageSender = msg.sender;
}
}
modifier optionalProxy_onlyOwner {
_optionalProxy_onlyOwner();
_;
}
// solhint-disable-next-line func-name-mixedcase
function _optionalProxy_onlyOwner() private {
if (Proxy(msg.sender) != proxy && messageSender != msg.sender) {
messageSender = msg.sender;
}
require(messageSender == owner, "Owner only function");
}
event ProxyUpdated(address proxyAddress);
}
interface AggregatorInterface {
function latestAnswer() external view returns (int256);
function latestTimestamp() external view returns (uint256);
function latestRound() external view returns (uint256);
function getAnswer(uint256 roundId) external view returns (int256);
function getTimestamp(uint256 roundId) external view returns (uint256);
event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp);
event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
}
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
// getRoundData and latestRoundData should both raise "No data present"
// if they do not have data to report, instead of returning unset values
// which could be misinterpreted as actual reported values.
function getRoundData(uint80 _roundId)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
/**
* @title The V2 & V3 Aggregator Interface
* @notice Solidity V0.5 does not allow interfaces to inherit from other
* interfaces so this contract is a combination of v0.5 AggregatorInterface.sol
* and v0.5 AggregatorV3Interface.sol.
*/
interface AggregatorV2V3Interface {
//
// V2 Interface:
//
function latestAnswer() external view returns (int256);
function latestTimestamp() external view returns (uint256);
function latestRound() external view returns (uint256);
function getAnswer(uint256 roundId) external view returns (int256);
function getTimestamp(uint256 roundId) external view returns (uint256);
event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp);
event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
//
// V3 Interface:
//
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
// getRoundData and latestRoundData should both raise "No data present"
// if they do not have data to report, instead of returning unset values
// which could be misinterpreted as actual reported values.
function getRoundData(uint80 _roundId)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
// Inheritance
// Libraries
// Internal references
// Chainlink
/**
* Compares current exchange rate to previous, and suspends a synth if the
* difference is outside of deviation bounds.
* Stores last "good" rate for each synth on each invocation.
* Inteded use is to use in combination with ExchangeRates on mutative exchange-like
* methods.
* Suspend functionality is public, resume functionality is controlled by owner.
*
* https://docs.synthetix.io/contracts/source/contracts/CircuitBreaker
*/
contract CircuitBreaker is Owned, MixinSystemSettings, ICircuitBreaker {
using SafeMath for uint;
using SafeDecimalMath for uint;
bytes32 public constant CONTRACT_NAME = "CircuitBreaker";
// is internal to have lastValue getter in interface in solidity v0.5
// TODO: after upgrading solidity, switch to just public lastValue instead
// of maintaining this internal one
mapping(address => uint) internal _lastValue;
mapping(address => bool) internal _circuitBroken;
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
bytes32 private constant CONTRACT_ISSUER = "Issuer";
bytes32 private constant CONTRACT_EXRATES = "ExchangeRates";
constructor(address _owner, address _resolver) public Owned(_owner) MixinSystemSettings(_resolver) {}
/* ========== VIEWS ========== */
function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
bytes32[] memory existingAddresses = MixinSystemSettings.resolverAddressesRequired();
bytes32[] memory newAddresses = new bytes32[](3);
newAddresses[0] = CONTRACT_SYSTEMSTATUS;
newAddresses[1] = CONTRACT_ISSUER;
newAddresses[2] = CONTRACT_EXRATES;
addresses = combineArrays(existingAddresses, newAddresses);
}
// Returns whether or not a rate would be come invalid
// ignores systemStatus check
function isInvalid(address oracleAddress, uint value) external view returns (bool) {
return _circuitBroken[oracleAddress] || _isRateOutOfBounds(oracleAddress, value) || value == 0;
}
function isDeviationAboveThreshold(uint base, uint comparison) external view returns (bool) {
return _isDeviationAboveThreshold(base, comparison);
}
function priceDeviationThresholdFactor() external view returns (uint) {
return getPriceDeviationThresholdFactor();
}
function lastValue(address oracleAddress) external view returns (uint) {
return _lastValue[oracleAddress];
}
function circuitBroken(address oracleAddress) external view returns (bool) {
return _circuitBroken[oracleAddress];
}
/* ========== Internal views ========== */
function systemStatus() internal view returns (ISystemStatus) {
return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS));
}
/* ========== Mutating ========== */
/**
* Checks rate deviation from previous and its "invalid" oracle state (stale rate, of flagged by oracle).
* If its valid, set the `circuitBoken` flag and return false. Continue storing price updates as normal.
* Also, checks that system is not suspended currently, if it is - doesn't perform any checks, and
* returns last rate and the current broken state, to prevent synths suspensions during maintenance.
*/
function probeCircuitBreaker(address oracleAddress, uint value) external onlyProbers returns (bool circuitBroken) {
require(oracleAddress != address(0), "Oracle address is 0");
// these conditional statements are ordered for short circuit (heh) efficiency to reduce gas usage
// in the usual case of no circuit broken.
if (
// cases where the new price should be triggering a circuit break
(value == 0 || _isRateOutOfBounds(oracleAddress, value)) &&
// other necessary states in order to break
!_circuitBroken[oracleAddress] &&
!systemStatus().systemSuspended()
) {
_circuitBroken[oracleAddress] = true;
emit CircuitBroken(oracleAddress, _lastValue[oracleAddress], value);
}
_lastValue[oracleAddress] = value;
return _circuitBroken[oracleAddress];
}
/**
* SIP-139
* resets the stored value for _lastValue for multiple currencies to the latest rate
* can be used to enable synths after a broken circuit happenned
* doesn't check deviations here, so believes that owner knows better
* emits LastRateOverridden
*/
function resetLastValue(address[] calldata oracleAddresses, uint[] calldata values) external onlyOwner {
for (uint i = 0; i < oracleAddresses.length; i++) {
require(oracleAddresses[i] != address(0), "Oracle address is 0");
emit LastValueOverridden(oracleAddresses[i], _lastValue[oracleAddresses[i]], values[i]);
_lastValue[oracleAddresses[i]] = values[i];
_circuitBroken[oracleAddresses[i]] = false;
}
}
/* ========== INTERNAL FUNCTIONS ========== */
function _isDeviationAboveThreshold(uint base, uint comparison) internal view returns (bool) {
if (base == 0 || comparison == 0) {
return true;
}
uint factor;
if (comparison > base) {
factor = comparison.divideDecimal(base);
} else {
factor = base.divideDecimal(comparison);
}
return factor >= getPriceDeviationThresholdFactor();
}
/**
* Rate is invalid if it is outside of deviation bounds relative to previous non-zero rate
*/
function _isRateOutOfBounds(address oracleAddress, uint current) internal view returns (bool) {
uint last = _lastValue[oracleAddress];
// `last == 0` indicates unset/unpopulated oracle. If we dont have any data on the previous oracle price,
// we should skip the deviation check and allow it to be populated.
if (last > 0) {
return _isDeviationAboveThreshold(last, current);
}
return false;
}
// ========== MODIFIERS =======
modifier onlyProbers() {
require(
msg.sender == requireAndGetAddress(CONTRACT_ISSUER) || msg.sender == requireAndGetAddress(CONTRACT_EXRATES),
"Only internal contracts can call this function"
);
_;
}
// ========== EVENTS ==========
// @notice signals that a the "last value" was overridden by one of the admin methods
// with a value that didn't come directly from the ExchangeRates.getRates methods
event LastValueOverridden(address indexed oracleAddress, uint256 previousValue, uint256 newValue);
// @notice signals that the circuit was broken
event CircuitBroken(address indexed oracleAddress, uint256 previousValue, uint256 newValue);
}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":"oracleAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"CircuitBroken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oracleAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"LastValueOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"constant":true,"inputs":[],"name":"CONTRACT_NAME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"oracleAddress","type":"address"}],"name":"circuitBroken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"base","type":"uint256"},{"internalType":"uint256","name":"comparison","type":"uint256"}],"name":"isDeviationAboveThreshold","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"oracleAddress","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"isInvalid","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":true,"inputs":[{"internalType":"address","name":"oracleAddress","type":"address"}],"name":"lastValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"priceDeviationThresholdFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"oracleAddress","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"probeCircuitBreaker","outputs":[{"internalType":"bool","name":"circuitBroken","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"rebuildCache","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"oracleAddresses","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"resetLastValue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"resolver","outputs":[{"internalType":"contract AddressResolver","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32[]","name":"addresses","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506040516113cc3803806113cc8339818101604052604081101561003357600080fd5b5080516020909101518080836001600160a01b03811661009a576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150600280546001600160a01b039092166001600160a01b03199092169190911790555050506112a6806101266000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806374185360116100975780638da5cb5b116100665780638da5cb5b1461027a578063ba03e93f14610282578063cfefbc7f146102a8578063ec5f638e1461036a57610100565b806374185360146101ef57806378cb51cb146101f757806379ba50971461021a578063899ffef41461022257610100565b8063372a395a116100d3578063372a395a14610199578063413caeb5146101b357806353a47bb7146101df578063614d08f8146101e757610100565b806304f3bcec146101055780631627540c1461012957806318b844ad146101515780632af64bd314610191575b600080fd5b61010d610390565b604080516001600160a01b039092168252519081900360200190f35b61014f6004803603602081101561013f57600080fd5b50356001600160a01b031661039f565b005b61017d6004803603604081101561016757600080fd5b506001600160a01b0381351690602001356103fb565b604080519115158252519081900360200190f35b61017d610439565b6101a1610544565b60408051918252519081900360200190f35b61017d600480360360408110156101c957600080fd5b506001600160a01b038135169060200135610553565b61010d610782565b6101a1610791565b61014f6107a6565b61017d6004803603604081101561020d57600080fd5b508035906020013561096e565b61014f61097a565b61022a610a36565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561026657818101518382015260200161024e565b505050509050019250505060405180910390f35b61010d610aee565b6101a16004803603602081101561029857600080fd5b50356001600160a01b0316610afd565b61014f600480360360408110156102be57600080fd5b8101906020810181356401000000008111156102d957600080fd5b8201836020820111156102eb57600080fd5b8035906020019184602083028401116401000000008311171561030d57600080fd5b91939092909160208101903564010000000081111561032b57600080fd5b82018360208201111561033d57600080fd5b8035906020019184602083028401116401000000008311171561035f57600080fd5b509092509050610b18565b61017d6004803603602081101561038057600080fd5b50356001600160a01b0316610cf6565b6002546001600160a01b031681565b6103a7610d14565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b6001600160a01b03821660009081526005602052604081205460ff168061042757506104278383610d5f565b80610430575081155b90505b92915050565b60006060610445610a36565b905060005b815181101561053a57600082828151811061046157fe5b6020908102919091018101516000818152600383526040908190205460025482516321f8a72160e01b81526004810185905292519395506001600160a01b03918216949116926321f8a721926024808201939291829003018186803b1580156104c957600080fd5b505afa1580156104dd573d6000803e3d6000fd5b505050506040513d60208110156104f357600080fd5b50516001600160a01b031614158061052057506000818152600360205260409020546001600160a01b0316155b156105315760009350505050610541565b5060010161044a565b5060019150505b90565b600061054e610d9a565b905090565b60006105676524b9b9bab2b960d11b610e51565b6001600160a01b0316336001600160a01b031614806105af575061059a6c45786368616e6765526174657360981b610e51565b6001600160a01b0316336001600160a01b0316145b6105ea5760405162461bcd60e51b815260040180806020018281038252602e815260200180611244602e913960400191505060405180910390fd5b6001600160a01b03831661063b576040805162461bcd60e51b815260206004820152601360248201527204f7261636c652061646472657373206973203606c1b604482015290519081900360640190fd5b81158061064d575061064d8383610d5f565b801561067257506001600160a01b03831660009081526005602052604090205460ff16155b80156106e75750610681610f35565b6001600160a01b031663c0eee4436040518163ffffffff1660e01b815260040160206040518083038186803b1580156106b957600080fd5b505afa1580156106cd573d6000803e3d6000fd5b505050506040513d60208110156106e357600080fd5b5051155b15610754576001600160a01b0383166000818152600560209081526040808320805460ff19166001179055600482529182902054825190815290810185905281517f67bad4b353dfb692ff5355991cbbb32b44e8b68fe393f9116791efc111beefe7929181900390910190a25b506001600160a01b039190911660009081526004602090815260408083209390935560059052205460ff1690565b6001546001600160a01b031681565b6d21b4b931bab4ba213932b0b5b2b960911b81565b60606107b0610a36565b905060005b815181101561096a5760008282815181106107cc57fe5b602090810291909101810151600254604080517f5265736f6c766572206d697373696e67207461726765743a2000000000000000818601526039808201859052825180830390910181526059820180845263dacb2d0160e01b9052605d8201858152607d83019384528151609d84015281519597506000966001600160a01b039095169563dacb2d01958995939492939260bd0191908501908083838c5b8381101561088257818101518382015260200161086a565b50505050905090810190601f1680156108af5780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b1580156108cd57600080fd5b505afa1580156108e1573d6000803e3d6000fd5b505050506040513d60208110156108f757600080fd5b505160008381526003602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518681529182015281519293507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68929081900390910190a150506001016107b5565b5050565b60006104308383610f4f565b6001546001600160a01b031633146109c35760405162461bcd60e51b81526004018080602001828103825260358152602001806111bf6035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b606080610a41610fae565b60408051600380825260808201909252919250606091906020820183803883390190505090506b53797374656d53746174757360a01b81600081518110610a8457fe5b6020026020010181815250506524b9b9bab2b960d11b81600181518110610aa757fe5b6020026020010181815250506c45786368616e6765526174657360981b81600281518110610ad157fe5b602002602001018181525050610ae78282610fff565b9250505090565b6000546001600160a01b031681565b6001600160a01b031660009081526004602052604090205490565b610b20610d14565b60005b83811015610cef576000858583818110610b3957fe5b905060200201356001600160a01b03166001600160a01b03161415610b9b576040805162461bcd60e51b815260206004820152601360248201527204f7261636c652061646472657373206973203606c1b604482015290519081900360640190fd5b848482818110610ba757fe5b905060200201356001600160a01b03166001600160a01b03167f915f74751eb02d50f865435828021de99701d7eca4ccd06a308d5dc01ab70ace60046000888886818110610bf157fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002054858585818110610c2e57fe5b604080519485526020918202939093013590840152508051918290030190a2828282818110610c5957fe5b9050602002013560046000878785818110610c7057fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002081905550600060056000878785818110610cb657fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff1916911515919091179055600101610b23565b5050505050565b6001600160a01b031660009081526005602052604090205460ff1690565b6000546001600160a01b03163314610d5d5760405162461bcd60e51b815260040180806020018281038252602f8152602001806111f4602f913960400191505060405180910390fd5b565b6001600160a01b0382166000908152600460205260408120548015610d9057610d888184610f4f565b915050610433565b5060009392505050565b6000610da46110b4565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b7f7072696365446576696174696f6e5468726573686f6c64466163746f720000006040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015610e2057600080fd5b505afa158015610e34573d6000803e3d6000fd5b505050506040513d6020811015610e4a57600080fd5b5051905090565b600081815260036020908152604080832054815170026b4b9b9b4b7339030b2323932b9b99d1607d1b9381019390935260318084018690528251808503909101815260519093019091526001600160a01b03169081610f2e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610ef3578181015183820152602001610edb565b50505050905090810190601f168015610f205780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5092915050565b600061054e6b53797374656d53746174757360a01b610e51565b6000821580610f5c575081155b15610f6957506001610433565b600083831115610f8a57610f83838563ffffffff6110d116565b9050610f9d565b610f9a848463ffffffff6110d116565b90505b610fa5610d9a565b11159392505050565b604080516001808252818301909252606091602080830190803883390190505090506e466c657869626c6553746f7261676560881b81600081518110610ff057fe5b60200260200101818152505090565b6060815183510160405190808252806020026020018201604052801561102f578160200160208202803883390190505b50905060005b83518110156110715783818151811061104a57fe5b602002602001015182828151811061105e57fe5b6020908102919091010152600101611035565b5060005b8251811015610f2e5782818151811061108a57fe5b60200260200101518282865101815181106110a157fe5b6020908102919091010152600101611075565b600061054e6e466c657869626c6553746f7261676560881b610e51565b6000610430826110ef85670de0b6b3a764000063ffffffff6110fb16565b9063ffffffff61115416565b60008261110a57506000610433565b8282028284828161111757fe5b04146104305760405162461bcd60e51b81526004018080602001828103825260218152602001806112236021913960400191505060405180910390fd5b60008082116111aa576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816111b557fe5b0494935050505056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e6572736869704f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f6e6c7920696e7465726e616c20636f6e7472616374732063616e2063616c6c20746869732066756e6374696f6ea265627a7a723158201a3a0aff9c339f00b0b926ad3067bd81d9155a470f7dbb7ef6250e8991bebf3e64736f6c63430005100032000000000000000000000000819addc3dd780704ae85ea12c18252f7020c24d00000000000000000000000001cb059b7e74fd21665968c908806143e744d5f30
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101005760003560e01c806374185360116100975780638da5cb5b116100665780638da5cb5b1461027a578063ba03e93f14610282578063cfefbc7f146102a8578063ec5f638e1461036a57610100565b806374185360146101ef57806378cb51cb146101f757806379ba50971461021a578063899ffef41461022257610100565b8063372a395a116100d3578063372a395a14610199578063413caeb5146101b357806353a47bb7146101df578063614d08f8146101e757610100565b806304f3bcec146101055780631627540c1461012957806318b844ad146101515780632af64bd314610191575b600080fd5b61010d610390565b604080516001600160a01b039092168252519081900360200190f35b61014f6004803603602081101561013f57600080fd5b50356001600160a01b031661039f565b005b61017d6004803603604081101561016757600080fd5b506001600160a01b0381351690602001356103fb565b604080519115158252519081900360200190f35b61017d610439565b6101a1610544565b60408051918252519081900360200190f35b61017d600480360360408110156101c957600080fd5b506001600160a01b038135169060200135610553565b61010d610782565b6101a1610791565b61014f6107a6565b61017d6004803603604081101561020d57600080fd5b508035906020013561096e565b61014f61097a565b61022a610a36565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561026657818101518382015260200161024e565b505050509050019250505060405180910390f35b61010d610aee565b6101a16004803603602081101561029857600080fd5b50356001600160a01b0316610afd565b61014f600480360360408110156102be57600080fd5b8101906020810181356401000000008111156102d957600080fd5b8201836020820111156102eb57600080fd5b8035906020019184602083028401116401000000008311171561030d57600080fd5b91939092909160208101903564010000000081111561032b57600080fd5b82018360208201111561033d57600080fd5b8035906020019184602083028401116401000000008311171561035f57600080fd5b509092509050610b18565b61017d6004803603602081101561038057600080fd5b50356001600160a01b0316610cf6565b6002546001600160a01b031681565b6103a7610d14565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b6001600160a01b03821660009081526005602052604081205460ff168061042757506104278383610d5f565b80610430575081155b90505b92915050565b60006060610445610a36565b905060005b815181101561053a57600082828151811061046157fe5b6020908102919091018101516000818152600383526040908190205460025482516321f8a72160e01b81526004810185905292519395506001600160a01b03918216949116926321f8a721926024808201939291829003018186803b1580156104c957600080fd5b505afa1580156104dd573d6000803e3d6000fd5b505050506040513d60208110156104f357600080fd5b50516001600160a01b031614158061052057506000818152600360205260409020546001600160a01b0316155b156105315760009350505050610541565b5060010161044a565b5060019150505b90565b600061054e610d9a565b905090565b60006105676524b9b9bab2b960d11b610e51565b6001600160a01b0316336001600160a01b031614806105af575061059a6c45786368616e6765526174657360981b610e51565b6001600160a01b0316336001600160a01b0316145b6105ea5760405162461bcd60e51b815260040180806020018281038252602e815260200180611244602e913960400191505060405180910390fd5b6001600160a01b03831661063b576040805162461bcd60e51b815260206004820152601360248201527204f7261636c652061646472657373206973203606c1b604482015290519081900360640190fd5b81158061064d575061064d8383610d5f565b801561067257506001600160a01b03831660009081526005602052604090205460ff16155b80156106e75750610681610f35565b6001600160a01b031663c0eee4436040518163ffffffff1660e01b815260040160206040518083038186803b1580156106b957600080fd5b505afa1580156106cd573d6000803e3d6000fd5b505050506040513d60208110156106e357600080fd5b5051155b15610754576001600160a01b0383166000818152600560209081526040808320805460ff19166001179055600482529182902054825190815290810185905281517f67bad4b353dfb692ff5355991cbbb32b44e8b68fe393f9116791efc111beefe7929181900390910190a25b506001600160a01b039190911660009081526004602090815260408083209390935560059052205460ff1690565b6001546001600160a01b031681565b6d21b4b931bab4ba213932b0b5b2b960911b81565b60606107b0610a36565b905060005b815181101561096a5760008282815181106107cc57fe5b602090810291909101810151600254604080517f5265736f6c766572206d697373696e67207461726765743a2000000000000000818601526039808201859052825180830390910181526059820180845263dacb2d0160e01b9052605d8201858152607d83019384528151609d84015281519597506000966001600160a01b039095169563dacb2d01958995939492939260bd0191908501908083838c5b8381101561088257818101518382015260200161086a565b50505050905090810190601f1680156108af5780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b1580156108cd57600080fd5b505afa1580156108e1573d6000803e3d6000fd5b505050506040513d60208110156108f757600080fd5b505160008381526003602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518681529182015281519293507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68929081900390910190a150506001016107b5565b5050565b60006104308383610f4f565b6001546001600160a01b031633146109c35760405162461bcd60e51b81526004018080602001828103825260358152602001806111bf6035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b606080610a41610fae565b60408051600380825260808201909252919250606091906020820183803883390190505090506b53797374656d53746174757360a01b81600081518110610a8457fe5b6020026020010181815250506524b9b9bab2b960d11b81600181518110610aa757fe5b6020026020010181815250506c45786368616e6765526174657360981b81600281518110610ad157fe5b602002602001018181525050610ae78282610fff565b9250505090565b6000546001600160a01b031681565b6001600160a01b031660009081526004602052604090205490565b610b20610d14565b60005b83811015610cef576000858583818110610b3957fe5b905060200201356001600160a01b03166001600160a01b03161415610b9b576040805162461bcd60e51b815260206004820152601360248201527204f7261636c652061646472657373206973203606c1b604482015290519081900360640190fd5b848482818110610ba757fe5b905060200201356001600160a01b03166001600160a01b03167f915f74751eb02d50f865435828021de99701d7eca4ccd06a308d5dc01ab70ace60046000888886818110610bf157fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002054858585818110610c2e57fe5b604080519485526020918202939093013590840152508051918290030190a2828282818110610c5957fe5b9050602002013560046000878785818110610c7057fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002081905550600060056000878785818110610cb657fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff1916911515919091179055600101610b23565b5050505050565b6001600160a01b031660009081526005602052604090205460ff1690565b6000546001600160a01b03163314610d5d5760405162461bcd60e51b815260040180806020018281038252602f8152602001806111f4602f913960400191505060405180910390fd5b565b6001600160a01b0382166000908152600460205260408120548015610d9057610d888184610f4f565b915050610433565b5060009392505050565b6000610da46110b4565b6001600160a01b03166323257c2b6d53797374656d53657474696e677360901b7f7072696365446576696174696f6e5468726573686f6c64466163746f720000006040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015610e2057600080fd5b505afa158015610e34573d6000803e3d6000fd5b505050506040513d6020811015610e4a57600080fd5b5051905090565b600081815260036020908152604080832054815170026b4b9b9b4b7339030b2323932b9b99d1607d1b9381019390935260318084018690528251808503909101815260519093019091526001600160a01b03169081610f2e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610ef3578181015183820152602001610edb565b50505050905090810190601f168015610f205780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5092915050565b600061054e6b53797374656d53746174757360a01b610e51565b6000821580610f5c575081155b15610f6957506001610433565b600083831115610f8a57610f83838563ffffffff6110d116565b9050610f9d565b610f9a848463ffffffff6110d116565b90505b610fa5610d9a565b11159392505050565b604080516001808252818301909252606091602080830190803883390190505090506e466c657869626c6553746f7261676560881b81600081518110610ff057fe5b60200260200101818152505090565b6060815183510160405190808252806020026020018201604052801561102f578160200160208202803883390190505b50905060005b83518110156110715783818151811061104a57fe5b602002602001015182828151811061105e57fe5b6020908102919091010152600101611035565b5060005b8251811015610f2e5782818151811061108a57fe5b60200260200101518282865101815181106110a157fe5b6020908102919091010152600101611075565b600061054e6e466c657869626c6553746f7261676560881b610e51565b6000610430826110ef85670de0b6b3a764000063ffffffff6110fb16565b9063ffffffff61115416565b60008261110a57506000610433565b8282028284828161111757fe5b04146104305760405162461bcd60e51b81526004018080602001828103825260218152602001806112236021913960400191505060405180910390fd5b60008082116111aa576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816111b557fe5b0494935050505056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e6572736869704f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f6e6c7920696e7465726e616c20636f6e7472616374732063616e2063616c6c20746869732066756e6374696f6ea265627a7a723158201a3a0aff9c339f00b0b926ad3067bd81d9155a470f7dbb7ef6250e8991bebf3e64736f6c63430005100032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000819addc3dd780704ae85ea12c18252f7020c24d00000000000000000000000001cb059b7e74fd21665968c908806143e744d5f30
-----Decoded View---------------
Arg [0] : _owner (address): 0x819aDDc3Dd780704aE85eA12c18252f7020C24D0
Arg [1] : _resolver (address): 0x1Cb059b7e74fD21665968C908806143E744D5F30
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000819addc3dd780704ae85ea12c18252f7020c24d0
Arg [1] : 0000000000000000000000001cb059b7e74fd21665968c908806143e744d5f30
Library Used
SafeDecimalMath : 0x0142f40c25ce1f1177ed131101fa19217396cb88SystemSettingsLib : 0xb17d51df8e3a134e8304f682be38e5204e4672e4SignedSafeDecimalMath : 0x253914cf059f4c3e277c28060c404acfc38fb6e2
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.