Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
BinaryOptionMarketMastercopy
Compiler Version
v0.5.16+commit.9c3226ce
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.5.16;
// Inheritance
import "./BinaryOptionMarket.sol";
contract BinaryOptionMarketMastercopy is BinaryOptionMarket {
constructor() public MinimalProxyFactory() OwnedWithInit() {
// Freeze mastercopy on deployment so it can never be initialized with real arguments
initialized = true;
}
}pragma solidity ^0.5.16;
// Inheritance
import "synthetix-2.43.1/contracts/MinimalProxyFactory.sol";
import "./OwnedWithInit.sol";
import "./interfaces/IBinaryOptionMarket.sol";
import "./interfaces/IOracleInstance.sol";
// Libraries
import "synthetix-2.43.1/contracts/SafeDecimalMath.sol";
// Internal references
import "./BinaryOptionMarketManager.sol";
import "./BinaryOption.sol";
import "synthetix-2.43.1/contracts/interfaces/IExchangeRates.sol";
import "synthetix-2.43.1/contracts/interfaces/IERC20.sol";
import "synthetix-2.43.1/contracts/interfaces/IAddressResolver.sol";
contract BinaryOptionMarket is MinimalProxyFactory, OwnedWithInit, IBinaryOptionMarket {
/* ========== LIBRARIES ========== */
using SafeMath for uint;
using SafeDecimalMath for uint;
/* ========== TYPES ========== */
struct Options {
BinaryOption long;
BinaryOption short;
}
struct Times {
uint maturity;
uint expiry;
}
struct OracleDetails {
bytes32 key;
uint strikePrice;
uint finalPrice;
bool customMarket;
address iOracleInstanceAddress;
}
/* ========== STATE VARIABLES ========== */
Options public options;
Times public times;
OracleDetails public oracleDetails;
BinaryOptionMarketManager.Fees public fees;
IAddressResolver public resolver;
IOracleInstance public iOracleInstance;
bool public customMarket;
// `deposited` tracks the sum of all deposits minus the withheld fees.
// This must explicitly be kept, in case tokens are transferred to the contract directly.
uint public deposited;
uint public accumulatedFees;
uint public initialMint;
address public creator;
bool public resolved;
uint internal _feeMultiplier;
/* ---------- Address Resolver Configuration ---------- */
bytes32 internal constant CONTRACT_EXRATES = "ExchangeRates";
bytes32 internal constant CONTRACT_SYNTHSUSD = "SynthsUSD";
/* ========== CONSTRUCTOR ========== */
bool public initialized = false;
function initialize(
address _owner,
address _binaryOptionMastercopy,
IAddressResolver _resolver,
address _creator,
bytes32 _oracleKey,
uint _strikePrice,
uint[2] calldata _times, // [maturity, expiry]
uint _deposit, // sUSD deposit
uint[2] calldata _fees, // [poolFee, creatorFee]
bool _customMarket,
address _iOracleInstanceAddress
) external {
require(!initialized, "Binary Option Market already initialized");
initialized = true;
initOwner(_owner);
resolver = _resolver;
creator = _creator;
oracleDetails = OracleDetails(_oracleKey, _strikePrice, 0, _customMarket, _iOracleInstanceAddress);
customMarket = _customMarket;
iOracleInstance = IOracleInstance(_iOracleInstanceAddress);
times = Times(_times[0], _times[1]);
deposited = _deposit;
initialMint = _deposit;
(uint poolFee, uint creatorFee) = (_fees[0], _fees[1]);
fees = BinaryOptionMarketManager.Fees(poolFee, creatorFee);
_feeMultiplier = SafeDecimalMath.unit().sub(poolFee.add(creatorFee));
// Instantiate the options themselves
options.long = BinaryOption(_cloneAsMinimalProxy(_binaryOptionMastercopy, "Could not create a Binary Option"));
options.short = BinaryOption(_cloneAsMinimalProxy(_binaryOptionMastercopy, "Could not create a Binary Option"));
// abi.encodePacked("sLONG: ", _oracleKey)
// consider naming the option: sLongBTC>50@2021.12.31
options.long.initialize("Binary Option Long", "sLONG");
options.short.initialize("Binary Option Short", "sSHORT");
_mint(creator, initialMint);
// Note: the ERC20 base contract does not have a constructor, so we do not have to worry
// about initializing its state separately
}
/* ---------- External Contracts ---------- */
function _exchangeRates() internal view returns (IExchangeRates) {
return IExchangeRates(resolver.requireAndGetAddress(CONTRACT_EXRATES, "ExchangeRates contract not found"));
}
function _sUSD() internal view returns (IERC20) {
return IERC20(resolver.requireAndGetAddress(CONTRACT_SYNTHSUSD, "SynthsUSD contract not found"));
}
function _manager() internal view returns (BinaryOptionMarketManager) {
return BinaryOptionMarketManager(owner);
}
/* ---------- Phases ---------- */
function _matured() internal view returns (bool) {
return times.maturity < block.timestamp;
}
function _expired() internal view returns (bool) {
return resolved && (times.expiry < block.timestamp || deposited == 0);
}
function phase() external view returns (Phase) {
if (!_matured()) {
return Phase.Trading;
}
if (!_expired()) {
return Phase.Maturity;
}
return Phase.Expiry;
}
/* ---------- Market Resolution ---------- */
function _oraclePriceAndTimestamp() internal view returns (uint price, uint updatedAt) {
return _exchangeRates().rateAndUpdatedTime(oracleDetails.key);
}
function oraclePriceAndTimestamp() external view returns (uint price, uint updatedAt) {
return _oraclePriceAndTimestamp();
}
function _isFreshPriceUpdateTime(uint timestamp) internal view returns (bool) {
(uint maxOraclePriceAge, , ) = _manager().durations();
return (times.maturity.sub(maxOraclePriceAge)) <= timestamp;
}
function canResolve() public view returns (bool) {
if (customMarket) {
return !resolved && _matured() && iOracleInstance.resolvable();
} else {
(, uint updatedAt) = _oraclePriceAndTimestamp();
return !resolved && _matured() && _isFreshPriceUpdateTime(updatedAt);
}
}
function _result() internal view returns (Side) {
if (customMarket) {
return iOracleInstance.getOutcome() ? Side.Long : Side.Short;
} else {
uint price;
if (resolved) {
price = oracleDetails.finalPrice;
} else {
(price, ) = _oraclePriceAndTimestamp();
}
return oracleDetails.strikePrice <= price ? Side.Long : Side.Short;
}
}
function result() external view returns (Side) {
return _result();
}
/* ---------- Option Balances and Mints ---------- */
function _balancesOf(address account) internal view returns (uint long, uint short) {
return (options.long.balanceOf(account), options.short.balanceOf(account));
}
function balancesOf(address account) external view returns (uint long, uint short) {
return _balancesOf(account);
}
function totalSupplies() external view returns (uint long, uint short) {
return (options.long.totalSupply(), options.short.totalSupply());
}
/* ---------- Utilities ---------- */
function _incrementDeposited(uint value) internal returns (uint _deposited) {
_deposited = deposited.add(value);
deposited = _deposited;
_manager().incrementTotalDeposited(value);
}
function _decrementDeposited(uint value) internal returns (uint _deposited) {
_deposited = deposited.sub(value);
deposited = _deposited;
_manager().decrementTotalDeposited(value);
}
function _requireManagerNotPaused() internal view {
require(!_manager().paused(), "This action cannot be performed while the contract is paused");
}
function requireUnpaused() external view {
_requireManagerNotPaused();
}
/* ========== MUTATIVE FUNCTIONS ========== */
/* ---------- Minting ---------- */
function mint(uint value) external duringMinting {
if (value == 0) {
return;
}
uint valueAfterFees = value.multiplyDecimalRound(_feeMultiplier);
uint deductedFees = value.sub(valueAfterFees);
accumulatedFees = accumulatedFees.add(deductedFees);
_mint(msg.sender, valueAfterFees);
_incrementDeposited(value);
_manager().transferSusdTo(msg.sender, address(this), value);
}
function _mint(address minter, uint amount) internal {
options.long.mint(minter, amount);
options.short.mint(minter, amount);
emit Mint(Side.Long, minter, amount);
emit Mint(Side.Short, minter, amount);
}
/* ---------- Custom oracle configuration ---------- */
function setIOracleInstance(address _address) external onlyOwner {}
/* ---------- Market Resolution ---------- */
function resolve() external onlyOwner afterMaturity managerNotPaused {
require(canResolve(), "Can not resolve market");
(uint price, uint updatedAt) = _oraclePriceAndTimestamp();
if (!customMarket) {
oracleDetails.finalPrice = price;
}
resolved = true;
// Now remit any collected fees.
// Since the constructor enforces that creatorFee + poolFee < 1, the balance
// in the contract will be sufficient to cover these transfers.
IERC20 sUSD = _sUSD();
uint totalFeesRatio = fees.poolFee.add(fees.creatorFee);
uint poolFeesRatio = fees.poolFee.divideDecimalRound(totalFeesRatio);
uint poolFees = poolFeesRatio.multiplyDecimalRound(accumulatedFees);
uint creatorFees = accumulatedFees.sub(poolFees);
_decrementDeposited(creatorFees.add(poolFees));
sUSD.transfer(_manager().feeAddress(), poolFees);
sUSD.transfer(creator, creatorFees);
emit MarketResolved(_result(), price, updatedAt, deposited, poolFees, creatorFees);
}
/* ---------- Claiming and Exercising Options ---------- */
function exerciseOptions() external afterMaturity returns (uint) {
// The market must be resolved if it has not been.
// the first one to exercise pays the gas fees. Might be worth splitting it up.
if (!resolved) {
_manager().resolveMarket(address(this));
}
// If the account holds no options, revert.
(uint longBalance, uint shortBalance) = _balancesOf(msg.sender);
require(longBalance != 0 || shortBalance != 0, "Nothing to exercise");
// Each option only needs to be exercised if the account holds any of it.
if (longBalance != 0) {
options.long.exercise(msg.sender);
}
if (shortBalance != 0) {
options.short.exercise(msg.sender);
}
// Only pay out the side that won.
uint payout = (_result() == Side.Long) ? longBalance : shortBalance;
emit OptionsExercised(msg.sender, payout);
if (payout != 0) {
_decrementDeposited(payout);
_sUSD().transfer(msg.sender, payout);
}
return payout;
}
/* ---------- Market Expiry ---------- */
function _selfDestruct(address payable beneficiary) internal {
uint _deposited = deposited;
if (_deposited != 0) {
_decrementDeposited(_deposited);
}
// Transfer the balance rather than the deposit value in case there are any synths left over
// from direct transfers.
IERC20 sUSD = _sUSD();
uint balance = sUSD.balanceOf(address(this));
if (balance != 0) {
sUSD.transfer(beneficiary, balance);
}
// Destroy the option tokens before destroying the market itself.
options.long.expire(beneficiary);
options.short.expire(beneficiary);
selfdestruct(beneficiary);
}
function expire(address payable beneficiary) external onlyOwner {
require(_expired(), "Unexpired options remaining");
_selfDestruct(beneficiary);
}
/* ========== MODIFIERS ========== */
modifier duringMinting() {
require(!_matured(), "Minting inactive");
_;
}
modifier afterMaturity() {
require(_matured(), "Not yet mature");
_;
}
modifier managerNotPaused() {
_requireManagerNotPaused();
_;
}
/* ========== EVENTS ========== */
event Mint(Side side, address indexed account, uint value);
event MarketResolved(
Side result,
uint oraclePrice,
uint oracleTimestamp,
uint deposited,
uint poolFees,
uint creatorFees
);
event OptionsExercised(address indexed account, uint value);
}pragma solidity ^0.5.16;
// https://docs.synthetix.io/contracts/source/contracts/minimalproxyfactory
contract MinimalProxyFactory {
function _cloneAsMinimalProxy(address _base, string memory _revertMsg) internal returns (address clone) {
bytes memory createData = _generateMinimalProxyCreateData(_base);
assembly {
clone := create(
0, // no value
add(createData, 0x20), // data
55 // data is always 55 bytes (10 constructor + 45 code)
)
}
// If CREATE fails for some reason, address(0) is returned
require(clone != address(0), _revertMsg);
}
function _generateMinimalProxyCreateData(address _base) internal pure returns (bytes memory) {
return
abi.encodePacked(
//---- constructor -----
bytes10(0x3d602d80600a3d3981f3),
//---- proxy code -----
bytes10(0x363d3d373d3d3d363d73),
_base,
bytes15(0x5af43d82803e903d91602b57fd5bf3)
);
}
}pragma solidity ^0.5.16;
contract OwnedWithInit {
address public owner;
address public nominatedOwner;
constructor() public {}
function initOwner(address _owner) internal {
require(owner == address(0), "Init can only be called when owner is 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);
}pragma solidity >=0.4.24;
import "../interfaces/IBinaryOptionMarketManager.sol";
import "../interfaces/IBinaryOption.sol";
interface IBinaryOptionMarket {
/* ========== TYPES ========== */
enum Phase {Trading, Maturity, Expiry}
enum Side {Long, Short}
/* ========== VIEWS / VARIABLES ========== */
function options() external view returns (IBinaryOption long, IBinaryOption short);
function times()
external
view
returns (
uint maturity,
uint destructino
);
function oracleDetails()
external
view
returns (
bytes32 key,
uint strikePrice,
uint finalPrice
);
function fees()
external
view
returns (
uint poolFee,
uint creatorFee
);
function deposited() external view returns (uint);
function accumulatedFees() external view returns (uint);
function creator() external view returns (address);
function resolved() external view returns (bool);
function phase() external view returns (Phase);
function oraclePriceAndTimestamp() external view returns (uint price, uint updatedAt);
function canResolve() external view returns (bool);
function result() external view returns (Side);
function balancesOf(address account) external view returns (uint long, uint short);
function totalSupplies() external view returns (uint long, uint short);
/* ========== MUTATIVE FUNCTIONS ========== */
function mint(uint value) external;
function exerciseOptions() external returns (uint);
}pragma solidity >=0.4.24;
import "../interfaces/IBinaryOptionMarket.sol";
interface IOracleInstance {
/* ========== VIEWS / VARIABLES ========== */
function getOutcome() external view returns (bool);
function resolvable() external view returns (bool);
function targetName() external view returns (string memory);
function targetOutcome() external view returns (string memory);
function eventName() external view returns (string memory);
/* ========== MUTATIVE FUNCTIONS ========== */
}pragma solidity ^0.5.16;
// Libraries
import "openzeppelin-solidity-2.3.0/contracts/math/SafeMath.sol";
// 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;
}
}pragma solidity ^0.5.16;
// Inheritance
import "./interfaces/IBinaryOptionMarketManager.sol";
import "synthetix-2.43.1/contracts/Owned.sol";
import "synthetix-2.43.1/contracts/Pausable.sol";
// Libraries
import "synthetix-2.43.1/contracts/AddressSetLib.sol";
import "synthetix-2.43.1/contracts/SafeDecimalMath.sol";
// Internal references
import "./BinaryOptionMarketFactory.sol";
import "./BinaryOptionMarket.sol";
import "./BinaryOption.sol";
import "./interfaces/IBinaryOptionMarket.sol";
import "synthetix-2.43.1/contracts/interfaces/IExchangeRates.sol";
import "synthetix-2.43.1/contracts/interfaces/IERC20.sol";
import "synthetix-2.43.1/contracts/interfaces/IAddressResolver.sol";
contract BinaryOptionMarketManager is Owned, Pausable, IBinaryOptionMarketManager {
/* ========== LIBRARIES ========== */
using SafeMath for uint;
using AddressSetLib for AddressSetLib.AddressSet;
/* ========== TYPES ========== */
struct Fees {
uint poolFee;
uint creatorFee;
}
struct Durations {
uint maxOraclePriceAge;
uint expiryDuration;
uint maxTimeToMaturity;
}
/* ========== STATE VARIABLES ========== */
address public feeAddress;
Fees public fees;
Durations public durations;
uint public capitalRequirement;
bool public marketCreationEnabled = true;
bool public customMarketCreationEnabled = false;
uint public totalDeposited;
AddressSetLib.AddressSet internal _activeMarkets;
AddressSetLib.AddressSet internal _maturedMarkets;
BinaryOptionMarketManager internal _migratingManager;
IAddressResolver public resolver;
address public binaryOptionMarketFactory;
/* ---------- Address Resolver Configuration ---------- */
bytes32 internal constant CONTRACT_SYNTHSUSD = "SynthsUSD";
bytes32 internal constant CONTRACT_EXRATES = "ExchangeRates";
/* ========== CONSTRUCTOR ========== */
constructor(
address _owner,
IAddressResolver _resolver,
uint _maxOraclePriceAge,
uint _expiryDuration,
uint _maxTimeToMaturity,
uint _creatorCapitalRequirement,
uint _poolFee,
uint _creatorFee,
address _feeAddress
) public Owned(_owner) Pausable() {
resolver = _resolver;
// Temporarily change the owner so that the setters don't revert.
owner = msg.sender;
setFeeAddress(_feeAddress);
setExpiryDuration(_expiryDuration);
setMaxOraclePriceAge(_maxOraclePriceAge);
setMaxTimeToMaturity(_maxTimeToMaturity);
setCreatorCapitalRequirement(_creatorCapitalRequirement);
setPoolFee(_poolFee);
setCreatorFee(_creatorFee);
owner = _owner;
}
/* ========== SETTERS ========== */
function setBinaryOptionsMarketFactory(address _binaryOptionMarketFactory) external onlyOwner {
binaryOptionMarketFactory = _binaryOptionMarketFactory;
}
function setFeeAddress(address _feeAddress) public onlyOwner {
feeAddress = _feeAddress;
}
/* ========== VIEWS ========== */
/* ---------- Related Contracts ---------- */
function _sUSD() internal view returns (IERC20) {
return IERC20(resolver.requireAndGetAddress(CONTRACT_SYNTHSUSD, "Synth sUSD contract not found"));
}
function _exchangeRates() internal view returns (IExchangeRates) {
return IExchangeRates(resolver.requireAndGetAddress(CONTRACT_EXRATES, "ExchangeRates contract not found"));
}
/* ---------- Market Information ---------- */
function _isKnownMarket(address candidate) internal view returns (bool) {
return _activeMarkets.contains(candidate) || _maturedMarkets.contains(candidate);
}
function numActiveMarkets() external view returns (uint) {
return _activeMarkets.elements.length;
}
function activeMarkets(uint index, uint pageSize) external view returns (address[] memory) {
return _activeMarkets.getPage(index, pageSize);
}
function numMaturedMarkets() external view returns (uint) {
return _maturedMarkets.elements.length;
}
function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory) {
return _maturedMarkets.getPage(index, pageSize);
}
function _isValidKey(bytes32 oracleKey) internal view returns (bool) {
IExchangeRates exchangeRates = _exchangeRates();
// If it has a rate, then it's possibly a valid key
if (exchangeRates.rateForCurrency(oracleKey) != 0) {
// But not sUSD
if (oracleKey == "sUSD") {
return false;
}
// and not inverse rates
(uint entryPoint, , , , ) = exchangeRates.inversePricing(oracleKey);
if (entryPoint != 0) {
return false;
}
return true;
}
return false;
}
/* ========== MUTATIVE FUNCTIONS ========== */
/* ---------- Setters ---------- */
function setMaxOraclePriceAge(uint _maxOraclePriceAge) public onlyOwner {
durations.maxOraclePriceAge = _maxOraclePriceAge;
emit MaxOraclePriceAgeUpdated(_maxOraclePriceAge);
}
function setExpiryDuration(uint _expiryDuration) public onlyOwner {
durations.expiryDuration = _expiryDuration;
emit ExpiryDurationUpdated(_expiryDuration);
}
function setMaxTimeToMaturity(uint _maxTimeToMaturity) public onlyOwner {
durations.maxTimeToMaturity = _maxTimeToMaturity;
emit MaxTimeToMaturityUpdated(_maxTimeToMaturity);
}
function setPoolFee(uint _poolFee) public onlyOwner {
uint totalFee = _poolFee + fees.creatorFee;
require(totalFee < SafeDecimalMath.unit(), "Total fee must be less than 100%.");
require(0 < totalFee, "Total fee must be nonzero.");
fees.poolFee = _poolFee;
emit PoolFeeUpdated(_poolFee);
}
function setCreatorFee(uint _creatorFee) public onlyOwner {
uint totalFee = _creatorFee + fees.poolFee;
require(totalFee < SafeDecimalMath.unit(), "Total fee must be less than 100%.");
require(0 < totalFee, "Total fee must be nonzero.");
fees.creatorFee = _creatorFee;
emit CreatorFeeUpdated(_creatorFee);
}
function setCreatorCapitalRequirement(uint _creatorCapitalRequirement) public onlyOwner {
capitalRequirement = _creatorCapitalRequirement;
emit CreatorCapitalRequirementUpdated(_creatorCapitalRequirement);
}
/* ---------- Deposit Management ---------- */
function incrementTotalDeposited(uint delta) external onlyActiveMarkets notPaused {
totalDeposited = totalDeposited.add(delta);
}
function decrementTotalDeposited(uint delta) external onlyKnownMarkets notPaused {
// NOTE: As individual market debt is not tracked here, the underlying markets
// need to be careful never to subtract more debt than they added.
// This can't be enforced without additional state/communication overhead.
totalDeposited = totalDeposited.sub(delta);
}
/* ---------- Market Lifecycle ---------- */
function createMarket(
bytes32 oracleKey,
uint strikePrice,
uint maturity,
uint initialMint, // initial sUSD to mint options for,
bool customMarket,
address customOracle
)
external
notPaused
returns (
IBinaryOptionMarket // no support for returning BinaryOptionMarket polymorphically given the interface
)
{
require(marketCreationEnabled, "Market creation is disabled");
if (!customMarket) {
require(_isValidKey(oracleKey), "Invalid key");
} else {
if (!customMarketCreationEnabled) {
require(owner == msg.sender, "Only owner can create custom markets");
}
require(address(0) != customOracle, "Invalid custom oracle");
}
require(maturity <= block.timestamp + durations.maxTimeToMaturity, "Maturity too far in the future");
uint expiry = maturity.add(durations.expiryDuration);
require(block.timestamp < maturity, "Maturity has to be in the future");
// We also require maturity < expiry. But there is no need to check this.
// Fees being in range are checked in the setters.
// The market itself validates the capital and skew requirements.
require(capitalRequirement <= initialMint, "Insufficient capital");
BinaryOptionMarket market =
BinaryOptionMarketFactory(binaryOptionMarketFactory).createMarket(
msg.sender,
resolver,
oracleKey,
strikePrice,
[maturity, expiry],
initialMint,
[fees.poolFee, fees.creatorFee],
customMarket,
customOracle
);
_activeMarkets.add(address(market));
// The debt can't be incremented in the new market's constructor because until construction is complete,
// the manager doesn't know its address in order to grant it permission.
totalDeposited = totalDeposited.add(initialMint);
_sUSD().transferFrom(msg.sender, address(market), initialMint);
(BinaryOption long, BinaryOption short) = market.options();
emit MarketCreated(
address(market),
msg.sender,
oracleKey,
strikePrice,
maturity,
expiry,
address(long),
address(short),
customMarket,
customOracle
);
return market;
}
function transferSusdTo(
address sender,
address receiver,
uint amount
) external {
//only to be called by markets themselves
require(_isKnownMarket(address(msg.sender)), "Market unknown.");
_sUSD().transferFrom(sender, receiver, amount);
}
function resolveMarket(address market) external {
require(_activeMarkets.contains(market), "Not an active market");
BinaryOptionMarket(market).resolve();
_activeMarkets.remove(market);
_maturedMarkets.add(market);
}
function expireMarkets(address[] calldata markets) external notPaused onlyOwner {
for (uint i = 0; i < markets.length; i++) {
address market = markets[i];
require(_isKnownMarket(address(market)), "Market unknown.");
// The market itself handles decrementing the total deposits.
BinaryOptionMarket(market).expire(msg.sender);
// Note that we required that the market is known, which guarantees
// its index is defined and that the list of markets is not empty.
_maturedMarkets.remove(market);
emit MarketExpired(market);
}
}
function setMarketCreationEnabled(bool enabled) public onlyOwner {
if (enabled != marketCreationEnabled) {
marketCreationEnabled = enabled;
emit MarketCreationEnabledUpdated(enabled);
}
}
function setCustomMarketCreationEnabled(bool enabled) public onlyOwner {
customMarketCreationEnabled = enabled;
}
function setMigratingManager(BinaryOptionMarketManager manager) public onlyOwner {
_migratingManager = manager;
}
function migrateMarkets(
BinaryOptionMarketManager receivingManager,
bool active,
BinaryOptionMarket[] calldata marketsToMigrate
) external onlyOwner {
require(address(receivingManager) != address(this), "Can't migrate to self");
uint _numMarkets = marketsToMigrate.length;
if (_numMarkets == 0) {
return;
}
AddressSetLib.AddressSet storage markets = active ? _activeMarkets : _maturedMarkets;
uint runningDepositTotal;
for (uint i; i < _numMarkets; i++) {
BinaryOptionMarket market = marketsToMigrate[i];
require(_isKnownMarket(address(market)), "Market unknown.");
// Remove it from our list and deposit total.
markets.remove(address(market));
runningDepositTotal = runningDepositTotal.add(market.deposited());
// Prepare to transfer ownership to the new manager.
market.nominateNewOwner(address(receivingManager));
}
// Deduct the total deposits of the migrated markets.
totalDeposited = totalDeposited.sub(runningDepositTotal);
emit MarketsMigrated(receivingManager, marketsToMigrate);
// Now actually transfer the markets over to the new manager.
receivingManager.receiveMarkets(active, marketsToMigrate);
}
function receiveMarkets(bool active, BinaryOptionMarket[] calldata marketsToReceive) external {
require(msg.sender == address(_migratingManager), "Only permitted for migrating manager.");
uint _numMarkets = marketsToReceive.length;
if (_numMarkets == 0) {
return;
}
AddressSetLib.AddressSet storage markets = active ? _activeMarkets : _maturedMarkets;
uint runningDepositTotal;
for (uint i; i < _numMarkets; i++) {
BinaryOptionMarket market = marketsToReceive[i];
require(!_isKnownMarket(address(market)), "Market already known.");
market.acceptOwnership();
markets.add(address(market));
// Update the market with the new manager address,
runningDepositTotal = runningDepositTotal.add(market.deposited());
}
totalDeposited = totalDeposited.add(runningDepositTotal);
emit MarketsReceived(_migratingManager, marketsToReceive);
}
/* ========== MODIFIERS ========== */
modifier onlyActiveMarkets() {
require(_activeMarkets.contains(msg.sender), "Permitted only for active markets.");
_;
}
modifier onlyKnownMarkets() {
require(_isKnownMarket(msg.sender), "Permitted only for known markets.");
_;
}
/* ========== EVENTS ========== */
event MarketCreated(
address market,
address indexed creator,
bytes32 indexed oracleKey,
uint strikePrice,
uint maturityDate,
uint expiryDate,
address long,
address short,
bool customMarket,
address customOracle
);
event MarketExpired(address market);
event MarketsMigrated(BinaryOptionMarketManager receivingManager, BinaryOptionMarket[] markets);
event MarketsReceived(BinaryOptionMarketManager migratingManager, BinaryOptionMarket[] markets);
event MarketCreationEnabledUpdated(bool enabled);
event MaxOraclePriceAgeUpdated(uint duration);
event ExpiryDurationUpdated(uint duration);
event MaxTimeToMaturityUpdated(uint duration);
event CreatorCapitalRequirementUpdated(uint value);
event PoolFeeUpdated(uint fee);
event CreatorFeeUpdated(uint fee);
}pragma solidity ^0.5.16;
// Inheritance
import "synthetix-2.43.1/contracts/interfaces/IERC20.sol";
import "./interfaces/IBinaryOption.sol";
// Libraries
import "synthetix-2.43.1/contracts/SafeDecimalMath.sol";
// Internal references
import "./BinaryOptionMarket.sol";
contract BinaryOption is IERC20, IBinaryOption {
/* ========== LIBRARIES ========== */
using SafeMath for uint;
using SafeDecimalMath for uint;
/* ========== STATE VARIABLES ========== */
string public name;
string public symbol;
uint8 public constant decimals = 18;
BinaryOptionMarket public market;
mapping(address => uint) public balanceOf;
uint public totalSupply;
// The argument order is allowance[owner][spender]
mapping(address => mapping(address => uint)) public allowance;
// Enforce a 1 cent minimum amount
uint internal constant _MINIMUM_AMOUNT = 1e16;
/* ========== CONSTRUCTOR ========== */
bool public initialized = false;
function initialize(
string calldata _name,
string calldata _symbol
) external {
require(!initialized, "Binary Option Market already initialized");
initialized = true;
name = _name;
symbol = _symbol;
market = BinaryOptionMarket(msg.sender);
}
/* ========== MUTATIVE FUNCTIONS ========== */
function _requireMinimumAmount(uint amount) internal pure returns (uint) {
require(amount >= _MINIMUM_AMOUNT || amount == 0, "Balance < $0.01");
return amount;
}
function mint(address minter, uint amount) external onlyMarket {
_requireMinimumAmount(amount);
totalSupply = totalSupply.add(amount);
balanceOf[minter] = balanceOf[minter].add(amount); // Increment rather than assigning since a transfer may have occurred.
emit Transfer(address(0), minter, amount);
emit Issued(minter, amount);
}
// This must only be invoked after maturity.
function exercise(address claimant) external onlyMarket {
uint balance = balanceOf[claimant];
if (balance == 0) {
return;
}
balanceOf[claimant] = 0;
totalSupply = totalSupply.sub(balance);
emit Transfer(claimant, address(0), balance);
emit Burned(claimant, balance);
}
// This must only be invoked after the exercise window is complete.
// Note that any options which have not been exercised will linger.
function expire(address payable beneficiary) external onlyMarket {
selfdestruct(beneficiary);
}
/* ---------- ERC20 Functions ---------- */
function _transfer(
address _from,
address _to,
uint _value
) internal returns (bool success) {
market.requireUnpaused();
require(_to != address(0) && _to != address(this), "Invalid address");
uint fromBalance = balanceOf[_from];
require(_value <= fromBalance, "Insufficient balance");
balanceOf[_from] = fromBalance.sub(_value);
balanceOf[_to] = balanceOf[_to].add(_value);
emit Transfer(_from, _to, _value);
return true;
}
function transfer(address _to, uint _value) external returns (bool success) {
return _transfer(msg.sender, _to, _value);
}
function transferFrom(
address _from,
address _to,
uint _value
) external returns (bool success) {
uint fromAllowance = allowance[_from][msg.sender];
require(_value <= fromAllowance, "Insufficient allowance");
allowance[_from][msg.sender] = fromAllowance.sub(_value);
return _transfer(_from, _to, _value);
}
function approve(address _spender, uint _value) external returns (bool success) {
require(_spender != address(0));
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
/* ========== MODIFIERS ========== */
modifier onlyMarket() {
require(msg.sender == address(market), "Only market allowed");
_;
}
/* ========== EVENTS ========== */
event Issued(address indexed account, uint value);
event Burned(address indexed account, uint value);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}pragma solidity >=0.4.24;
// https://docs.synthetix.io/contracts/source/interfaces/iexchangerates
interface IExchangeRates {
// Structs
struct RateAndUpdatedTime {
uint216 rate;
uint40 time;
}
struct InversePricing {
uint entryPoint;
uint upperLimit;
uint lowerLimit;
bool frozenAtUpperLimit;
bool frozenAtLowerLimit;
}
// 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 canFreezeRate(bytes32 currencyKey) external view returns (bool);
function currentRoundForRate(bytes32 currencyKey) external view returns (uint);
function currenciesUsingAggregator(address aggregator) external view returns (bytes32[] memory);
function effectiveValue(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey
) external view returns (uint value);
function effectiveValueAndRates(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey
)
external
view
returns (
uint value,
uint sourceRate,
uint destinationRate
);
function effectiveValueAtRound(
bytes32 sourceCurrencyKey,
uint sourceAmount,
bytes32 destinationCurrencyKey,
uint roundIdForSrc,
uint roundIdForDest
) external view returns (uint value);
function getCurrentRoundId(bytes32 currencyKey) external view returns (uint);
function getLastRoundIdBeforeElapsedSecs(
bytes32 currencyKey,
uint startingRoundId,
uint startingTimestamp,
uint timediff
) external view returns (uint);
function inversePricing(bytes32 currencyKey)
external
view
returns (
uint entryPoint,
uint upperLimit,
uint lowerLimit,
bool frozenAtUpperLimit,
bool frozenAtLowerLimit
);
function lastRateUpdateTimes(bytes32 currencyKey) external view returns (uint256);
function oracle() external view returns (address);
function rateAndTimestampAtRound(bytes32 currencyKey, uint roundId) external view returns (uint rate, uint time);
function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time);
function rateAndInvalid(bytes32 currencyKey) external view returns (uint rate, bool isInvalid);
function rateForCurrency(bytes32 currencyKey) external view returns (uint);
function rateIsFlagged(bytes32 currencyKey) external view returns (bool);
function rateIsFrozen(bytes32 currencyKey) external view returns (bool);
function rateIsInvalid(bytes32 currencyKey) external view returns (bool);
function rateIsStale(bytes32 currencyKey) external view returns (bool);
function rateStalePeriod() external view returns (uint);
function ratesAndUpdatedTimeForCurrencyLastNRounds(bytes32 currencyKey, uint numRounds)
external
view
returns (uint[] memory rates, uint[] memory times);
function ratesAndInvalidForCurrencies(bytes32[] calldata currencyKeys)
external
view
returns (uint[] memory rates, bool anyRateInvalid);
function ratesForCurrencies(bytes32[] calldata currencyKeys) external view returns (uint[] memory);
// Mutative functions
function freezeRate(bytes32 currencyKey) external;
}pragma solidity >=0.4.24;
// https://docs.synthetix.io/contracts/source/interfaces/ierc20
interface IERC20 {
// ERC20 Optional Views
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
// Views
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
// Mutative functions
function transfer(address to, uint value) external returns (bool);
function approve(address spender, uint value) external returns (bool);
function transferFrom(
address from,
address to,
uint value
) external returns (bool);
// Events
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}pragma solidity >=0.4.24;
// 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);
}pragma solidity >=0.4.24;
import "../interfaces/IBinaryOptionMarket.sol";
interface IBinaryOptionMarketManager {
/* ========== VIEWS / VARIABLES ========== */
function fees() external view returns (uint poolFee, uint creatorFee);
function durations()
external
view
returns (
uint maxOraclePriceAge,
uint expiryDuration,
uint maxTimeToMaturity
);
function capitalRequirement() external view returns (uint);
function marketCreationEnabled() external view returns (bool);
function totalDeposited() external view returns (uint);
function numActiveMarkets() external view returns (uint);
function activeMarkets(uint index, uint pageSize) external view returns (address[] memory);
function numMaturedMarkets() external view returns (uint);
function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory);
/* ========== MUTATIVE FUNCTIONS ========== */
function createMarket(
bytes32 oracleKey,
uint strikePrice,
uint maturity,
uint initialMint, // initial sUSD to mint options for,
bool customMarket,
address customOracle
) external returns (IBinaryOptionMarket);
function resolveMarket(address market) external;
function expireMarkets(address[] calldata market) external;
function transferSusdTo(
address sender,
address receiver,
uint amount
) external;
}pragma solidity >=0.4.24;
import "../interfaces/IBinaryOptionMarket.sol";
import "synthetix-2.43.1/contracts/interfaces/IERC20.sol";
interface IBinaryOption {
/* ========== VIEWS / VARIABLES ========== */
function market() external view returns (IBinaryOptionMarket);
function balanceOf(address account) external view returns (uint);
function totalSupply() external view returns (uint);
}pragma solidity ^0.5.0;
/**
* @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;
}
}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);
}pragma solidity ^0.5.16;
// Inheritance
import "./Owned.sol";
// https://docs.synthetix.io/contracts/source/contracts/pausable
contract Pausable is Owned {
uint public lastPauseTime;
bool public paused;
constructor() internal {
// This contract is abstract, and thus cannot be instantiated directly
require(owner != address(0), "Owner must be set");
// Paused will be false, and lastPauseTime will be 0 upon initialisation
}
/**
* @notice Change the paused state of the contract
* @dev Only the contract owner may call this.
*/
function setPaused(bool _paused) external onlyOwner {
// Ensure we're actually changing the state before we do anything
if (_paused == paused) {
return;
}
// Set our paused state.
paused = _paused;
// If applicable, set the last pause time.
if (paused) {
lastPauseTime = now;
}
// Let everyone know that our pause state has changed.
emit PauseChanged(paused);
}
event PauseChanged(bool isPaused);
modifier notPaused {
require(!paused, "This action cannot be performed while the contract is paused");
_;
}
}pragma solidity ^0.5.16;
// https://docs.synthetix.io/contracts/source/libraries/addresssetlib/
library AddressSetLib {
struct AddressSet {
address[] elements;
mapping(address => uint) indices;
}
function contains(AddressSet storage set, address candidate) internal view returns (bool) {
if (set.elements.length == 0) {
return false;
}
uint index = set.indices[candidate];
return index != 0 || set.elements[0] == candidate;
}
function getPage(
AddressSet storage set,
uint index,
uint pageSize
) internal view returns (address[] memory) {
// NOTE: This implementation should be converted to slice operators if the compiler is updated to v0.6.0+
uint endIndex = index + pageSize; // The check below that endIndex <= index handles overflow.
// If the page extends past the end of the list, truncate it.
if (endIndex > set.elements.length) {
endIndex = set.elements.length;
}
if (endIndex <= index) {
return new address[](0);
}
uint n = endIndex - index; // We already checked for negative overflow.
address[] memory page = new address[](n);
for (uint i; i < n; i++) {
page[i] = set.elements[i + index];
}
return page;
}
function add(AddressSet storage set, address element) internal {
// Adding to a set is an idempotent operation.
if (!contains(set, element)) {
set.indices[element] = set.elements.length;
set.elements.push(element);
}
}
function remove(AddressSet storage set, address element) internal {
require(contains(set, element), "Element not in set.");
// Replace the removed element with the last element of the list.
uint index = set.indices[element];
uint lastIndex = set.elements.length - 1; // We required that element is in the list, so it is not empty.
if (index != lastIndex) {
// No need to shift the last element if it is the one we want to delete.
address shiftedElement = set.elements[lastIndex];
set.elements[index] = shiftedElement;
set.indices[shiftedElement] = index;
}
set.elements.pop();
delete set.indices[element];
}
}pragma solidity ^0.5.16;
// Inheritance
import "synthetix-2.43.1/contracts/MinimalProxyFactory.sol";
import "synthetix-2.43.1/contracts/Owned.sol";
// Internal references
import "./BinaryOptionMarket.sol";
import "synthetix-2.43.1/contracts/interfaces/IAddressResolver.sol";
contract BinaryOptionMarketFactory is MinimalProxyFactory, Owned {
/* ========== STATE VARIABLES ========== */
address public binaryOptionMarketManager;
address public binaryOptionMarketMastercopy;
address public binaryOptionMastercopy;
/* ========== CONSTRUCTOR ========== */
constructor(address _owner) public MinimalProxyFactory() Owned(_owner) {}
/* ========== MUTATIVE FUNCTIONS ========== */
function createMarket(
address creator,
IAddressResolver _resolver,
bytes32 oracleKey,
uint strikePrice,
uint[2] calldata times, // [maturity, expiry]
uint initialMint,
uint[2] calldata fees, // [poolFee, creatorFee]
bool customMarket,
address customOracle
) external returns (BinaryOptionMarket) {
require(binaryOptionMarketManager == msg.sender, "Only permitted by the manager.");
BinaryOptionMarket bom =
BinaryOptionMarket(
_cloneAsMinimalProxy(binaryOptionMarketMastercopy, "Could not create a Binary Option Market")
);
bom.initialize(
binaryOptionMarketManager,
binaryOptionMastercopy,
_resolver,
creator,
oracleKey,
strikePrice,
times,
initialMint,
fees,
customMarket,
customOracle
);
return bom;
}
/* ========== SETTERS ========== */
function setBinaryOptionMarketManager(address _binaryOptionMarketManager) external onlyOwner {
binaryOptionMarketManager = _binaryOptionMarketManager;
emit BinaryOptionMarketManagerChanged(_binaryOptionMarketManager);
}
function setBinaryOptionMarketMastercopy(address _binaryOptionMarketMastercopy) external onlyOwner {
binaryOptionMarketMastercopy = _binaryOptionMarketMastercopy;
emit BinaryOptionMarketMastercopyChanged(_binaryOptionMarketMastercopy);
}
function setBinaryOptionMastercopy(address _binaryOptionMastercopy) external onlyOwner {
binaryOptionMastercopy = _binaryOptionMastercopy;
emit BinaryOptionMastercopyChanged(_binaryOptionMastercopy);
}
event BinaryOptionMarketManagerChanged(address _binaryOptionMarketManager);
event BinaryOptionMarketMastercopyChanged(address _binaryOptionMarketMastercopy);
event BinaryOptionMastercopyChanged(address _binaryOptionMastercopy);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"libraries": {
"synthetix-2.43.1/contracts/SafeDecimalMath.sol": {
"SafeDecimalMath": "0x84d626b2bb4d0f064067e4bf80fce7055d8f3e7b"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum IBinaryOptionMarket.Side","name":"result","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"oraclePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oracleTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deposited","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"poolFees","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"creatorFees","type":"uint256"}],"name":"MarketResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum IBinaryOptionMarket.Side","name":"side","type":"uint8"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"OptionsExercised","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":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"accumulatedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balancesOf","outputs":[{"internalType":"uint256","name":"long","type":"uint256"},{"internalType":"uint256","name":"short","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canResolve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"creator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"customMarket","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"deposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"exerciseOptions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"expire","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fees","outputs":[{"internalType":"uint256","name":"poolFee","type":"uint256"},{"internalType":"uint256","name":"creatorFee","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"iOracleInstance","outputs":[{"internalType":"contract IOracleInstance","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"initialMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_binaryOptionMastercopy","type":"address"},{"internalType":"contract IAddressResolver","name":"_resolver","type":"address"},{"internalType":"address","name":"_creator","type":"address"},{"internalType":"bytes32","name":"_oracleKey","type":"bytes32"},{"internalType":"uint256","name":"_strikePrice","type":"uint256"},{"internalType":"uint256[2]","name":"_times","type":"uint256[2]"},{"internalType":"uint256","name":"_deposit","type":"uint256"},{"internalType":"uint256[2]","name":"_fees","type":"uint256[2]"},{"internalType":"bool","name":"_customMarket","type":"bool"},{"internalType":"address","name":"_iOracleInstanceAddress","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"mint","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":true,"inputs":[],"name":"options","outputs":[{"internalType":"contract BinaryOption","name":"long","type":"address"},{"internalType":"contract BinaryOption","name":"short","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oracleDetails","outputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"uint256","name":"strikePrice","type":"uint256"},{"internalType":"uint256","name":"finalPrice","type":"uint256"},{"internalType":"bool","name":"customMarket","type":"bool"},{"internalType":"address","name":"iOracleInstanceAddress","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oraclePriceAndTimestamp","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"}],"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":"phase","outputs":[{"internalType":"enum IBinaryOptionMarket.Phase","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"requireUnpaused","outputs":[],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"resolve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"resolved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"resolver","outputs":[{"internalType":"contract IAddressResolver","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"result","outputs":[{"internalType":"enum IBinaryOptionMarket.Side","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setIOracleInstance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"times","outputs":[{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupplies","outputs":[{"internalType":"uint256","name":"long","type":"uint256"},{"internalType":"uint256","name":"short","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]Contract Creation Code
60806040526013805460ff1916905534801561001a57600080fd5b506013805460ff19166001179055612445806100376000396000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80639af1d35a11610104578063c1113c5a116100a2578063c8db233e11610071578063c8db233e14610474578063d068cdc51461049a578063d16e15e9146104a2578063eef49ee3146104aa576101da565b8063c1113c5a146103cd578063c54fd649146103f3578063c7a5bdc814610464578063c7e8bcca1461046c576101da565b8063a0712d68116100de578063a0712d6814610388578063a14f5823146103a5578063ac3791e3146103ad578063b1c9fe6e146103b5576101da565b80639af1d35a146103705780639e3b34bf146103785780639fc5ce2a14610380576101da565b806353a47bb71161017c57806379ba50971161014b57806379ba50971461031a57806385149258146103225780638da5cb5b1461032a57806398508ecd14610332576101da565b806353a47bb71461028d578063587f5ed7146102955780636392a51f146102af57806365372147146102ee576101da565b8063158ef93e116101b8578063158ef93e146102395780631627540c146102555780632810e1d61461027d5780633f6fa65514610285576101da565b806302d05d3f146101df57806304f3bcec146102035780631069143a1461020b575b600080fd5b6101e76104b2565b604080516001600160a01b039092168252519081900360200190f35b6101e76104c1565b6102136104d0565b604080516001600160a01b03938416815291909216602082015281519081900390910190f35b6102416104e6565b604080519115158252519081900360200190f35b61027b6004803603602081101561026b57600080fd5b50356001600160a01b03166104ef565b005b61027b61054b565b6102416108b1565b6101e76108c1565b61029d6108d0565b60408051918252519081900360200190f35b6102d5600480360360208110156102c557600080fd5b50356001600160a01b03166108d6565b6040805192835260208301919091528051918290030190f35b6102f66108eb565b6040518082600181111561030657fe5b60ff16815260200191505060405180910390f35b61027b6108fb565b61029d6109b7565b6101e7610cce565b61033a610cdd565b60408051958652602086019490945284840192909252151560608401526001600160a01b03166080830152519081900360a00190f35b6102d5610cff565b6102d5610d08565b61029d610d11565b61027b6004803603602081101561039e57600080fd5b5035610d17565b61027b610e43565b610241610e4d565b6103bd610f4c565b6040518082600281111561030657fe5b61027b600480360360208110156103e357600080fd5b50356001600160a01b0316610f7c565b61027b60048036036101a081101561040a57600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013582169160808201359160a08101359160c0820191610100810135916101208201916101608101351515916101809091013516610f84565b6102d5611380565b610241611393565b61027b6004803603602081101561048a57600080fd5b50356001600160a01b03166113a3565b6102d561140d565b6101e7611507565b61029d611516565b6011546001600160a01b031681565b600c546001600160a01b031681565b6002546003546001600160a01b03918216911682565b60135460ff1681565b6104f761151c565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b61055361151c565b61055b611565565b61059d576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420796574206d617475726560901b604482015290519081900360640190fd5b6105a561156d565b6105ad610e4d565b6105f7576040805162461bcd60e51b815260206004820152601660248201527510d85b881b9bdd081c995cdbdb1d99481b585c9ad95d60521b604482015290519081900360640190fd5b600080610602611615565b600d549193509150600160a01b900460ff1661061e5760088290555b6011805460ff60a01b1916600160a01b179055600061063b6116a3565b600b54600a549192506000916106569163ffffffff61175f16565b600a5490915060009061066f908363ffffffff6117c216565b90506000610688600f54836117d790919063ffffffff16565b905060006106a182600f546117ec90919063ffffffff16565b90506106bb6106b6828463ffffffff61175f16565b611849565b50846001600160a01b031663a9059cbb6106d36118d0565b6001600160a01b031663412753586040518163ffffffff1660e01b815260040160206040518083038186803b15801561070b57600080fd5b505afa15801561071f573d6000803e3d6000fd5b505050506040513d602081101561073557600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482018690525160448083019260209291908290030181600087803b15801561078557600080fd5b505af1158015610799573d6000803e3d6000fd5b505050506040513d60208110156107af57600080fd5b50506011546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519187169163a9059cbb916044808201926020929091908290030181600087803b15801561080757600080fd5b505af115801561081b573d6000803e3d6000fd5b505050506040513d602081101561083157600080fd5b507f5528b7e06f48a519cf814c4e5293ee2737c3f5c28d93e30cca112ac649fdd235905061085d6118df565b8888600e5486866040518087600181111561087457fe5b60ff1681526020810196909652506040808601949094526060850192909252608084015260a0830152519081900360c0019150a150505050505050565b601154600160a01b900460ff1681565b6001546001600160a01b031681565b600f5481565b6000806108e2836119c6565b91509150915091565b60006108f56118df565b90505b90565b6001546001600160a01b031633146109445760405162461bcd60e51b81526004018080602001828103825260358152602001806123016035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006109c1611565565b610a03576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420796574206d617475726560901b604482015290519081900360640190fd5b601154600160a01b900460ff16610a8c57610a1c6118d0565b6001600160a01b0316637859f410306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b158015610a7357600080fd5b505af1158015610a87573d6000803e3d6000fd5b505050505b600080610a98336119c6565b91509150816000141580610aab57508015155b610af2576040805162461bcd60e51b81526020600482015260136024820152724e6f7468696e6720746f20657865726369736560681b604482015290519081900360640190fd5b8115610b5d5760025460408051630d8acc1560e11b815233600482015290516001600160a01b0390921691631b15982a9160248082019260009290919082900301818387803b158015610b4457600080fd5b505af1158015610b58573d6000803e3d6000fd5b505050505b8015610bc85760035460408051630d8acc1560e11b815233600482015290516001600160a01b0390921691631b15982a9160248082019260009290919082900301818387803b158015610baf57600080fd5b505af1158015610bc3573d6000803e3d6000fd5b505050505b600080610bd36118df565b6001811115610bde57fe5b14610be95781610beb565b825b60408051828152905191925033917fd82b6f69d7477fb41cd83d936de94990cee2fa1a309feeee90101fc0513b6a439181900360200190a28015610cc757610c3281611849565b50610c3b6116a3565b6001600160a01b031663a9059cbb33836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610c9a57600080fd5b505af1158015610cae573d6000803e3d6000fd5b505050506040513d6020811015610cc457600080fd5b50505b9250505090565b6000546001600160a01b031681565b60065460075460085460095460ff81169061010090046001600160a01b031685565b600a54600b5482565b60045460055482565b60105481565b610d1f611565565b15610d64576040805162461bcd60e51b815260206004820152601060248201526f4d696e74696e6720696e61637469766560801b604482015290519081900360640190fd5b80610d6e57610e40565b6000610d85601254836117d790919063ffffffff16565b90506000610d99838363ffffffff6117ec16565b600f54909150610daf908263ffffffff61175f16565b600f55610dbc3383611ac4565b610dc583611c52565b50610dce6118d0565b60408051635c847f5960e11b81523360048201523060248201526044810186905290516001600160a01b03929092169163b908feb29160648082019260009290919082900301818387803b158015610e2557600080fd5b505af1158015610e39573d6000803e3d6000fd5b5050505050505b50565b610e4b61156d565b565b600d54600090600160a01b900460ff1615610f0857601154600160a01b900460ff16158015610e7f5750610e7f611565565b8015610f015750600d60009054906101000a90046001600160a01b03166001600160a01b031663a9720eea6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ed457600080fd5b505afa158015610ee8573d6000803e3d6000fd5b505050506040513d6020811015610efe57600080fd5b50515b90506108f8565b6000610f12611615565b601154909250600160a01b900460ff161590508015610f345750610f34611565565b8015610f445750610f4481611cbc565b9150506108f8565b6000610f56611565565b610f62575060006108f8565b610f6a611d4c565b610f76575060016108f8565b50600290565b610e4061151c565b60135460ff1615610fc65760405162461bcd60e51b81526004018080602001828103825260288152602001806123366028913960400191505060405180910390fd5b6013805460ff19166001179055610fdc8b611d76565b600c80546001600160a01b03199081166001600160a01b038c8116919091179092556011805482168b84161790556040805160a0810182528a815260208082018b9052600082840181905287151560608401819052958716608090930183905260068d905560078c90556008556009805460ff19168617610100600160a81b0319166101008402179055600d805460ff60a01b1916600160a01b909602959095179093161790925581518083018352873580825288830135918301829052600455600555600e8690556010869055815180830190925284358083528582013592909101829052600a819055600b829055906111566110da838361175f565b7384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b15801561111e57600080fd5b505af4158015611132573d6000803e3d6000fd5b505050506040513d602081101561114857600080fd5b50519063ffffffff6117ec16565b60128190555061119b8c6040518060400160405280602081526020017f436f756c64206e6f742063726561746520612042696e617279204f7074696f6e815250611e19565b600280546001600160a01b0319166001600160a01b03929092169190911790556040805180820190915260208082527f436f756c64206e6f742063726561746520612042696e617279204f7074696f6e908201526111fa908d90611e19565b600380546001600160a01b0319166001600160a01b039283161790556002546040805163266c45bb60e11b815260048101829052601260448201527142696e617279204f7074696f6e204c6f6e6760701b6064820152608060248201526005608482015264734c4f4e4760d81b60a482015290519190921691634cd88b769160c480830192600092919082900301818387803b15801561129957600080fd5b505af11580156112ad573d6000803e3d6000fd5b50506003546040805163266c45bb60e11b8152600481018290526013604482015272109a5b985c9e4813dc1d1a5bdb8814da1bdc9d606a1b60648201526080602482015260066084820152651cd4d213d49560d21b60a482015290516001600160a01b039092169350634cd88b76925060c48082019260009290919082900301818387803b15801561133e57600080fd5b505af1158015611352573d6000803e3d6000fd5b505060115460105461137193506001600160a01b039091169150611ac4565b50505050505050505050505050565b60008061138b611615565b915091509091565b600d54600160a01b900460ff1681565b6113ab61151c565b6113b3611d4c565b611404576040805162461bcd60e51b815260206004820152601b60248201527f556e65787069726564206f7074696f6e732072656d61696e696e670000000000604482015290519081900360640190fd5b610e4081611ece565b600080600260000160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561146157600080fd5b505afa158015611475573d6000803e3d6000fd5b505050506040513d602081101561148b57600080fd5b5051600354604080516318160ddd60e01b815290516001600160a01b03909216916318160ddd91600480820192602092909190829003018186803b1580156114d257600080fd5b505afa1580156114e6573d6000803e3d6000fd5b505050506040513d60208110156114fc57600080fd5b505190925090509091565b600d546001600160a01b031681565b600e5481565b6000546001600160a01b03163314610e4b5760405162461bcd60e51b815260040180806020018281038252602f815260200180612385602f913960400191505060405180910390fd5b600454421190565b6115756118d0565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115ad57600080fd5b505afa1580156115c1573d6000803e3d6000fd5b505050506040513d60208110156115d757600080fd5b505115610e4b5760405162461bcd60e51b815260040180806020018281038252603c8152602001806123d5603c913960400191505060405180910390fd5b6000806116206120d1565b6001600160a01b0316634308a94f6006600001546040518263ffffffff1660e01b815260040180828152602001915050604080518083038186803b15801561166757600080fd5b505afa15801561167b573d6000803e3d6000fd5b505050506040513d604081101561169157600080fd5b50805160209091015190925090509091565b600c546040805163dacb2d0160e01b81526814de5b9d1a1cd554d160ba1b600482015260248101829052601c60448201527f53796e74687355534420636f6e7472616374206e6f7420666f756e6400000000606482015290516000926001600160a01b03169163dacb2d01916084808301926020929190829003018186803b15801561172e57600080fd5b505afa158015611742573d6000803e3d6000fd5b505050506040513d602081101561175857600080fd5b5051905090565b6000828201838110156117b9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b60006117b98383670de0b6b3a764000061215e565b60006117b98383670de0b6b3a76400006121a2565b600082821115611843576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600e5460009061185f908363ffffffff6117ec16565b600e819055905061186e6118d0565b6001600160a01b0316636b3a0984836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156118b357600080fd5b505af11580156118c7573d6000803e3d6000fd5b50505050919050565b6000546001600160a01b031690565b600d54600090600160a01b900460ff161561198157600d60009054906101000a90046001600160a01b03166001600160a01b0316637e7e4b476040518163ffffffff1660e01b815260040160206040518083038186803b15801561194257600080fd5b505afa158015611956573d6000803e3d6000fd5b505050506040513d602081101561196c57600080fd5b5051611979576001610f01565b5060006108f8565b601154600090600160a01b900460ff161561199f57506008546119ab565b6119a7611615565b5090505b6007548110156119bc576001610f44565b60009150506108f8565b600254604080516370a0823160e01b81526001600160a01b0384811660048301529151600093849316916370a08231916024808301926020929190829003018186803b158015611a1557600080fd5b505afa158015611a29573d6000803e3d6000fd5b505050506040513d6020811015611a3f57600080fd5b5051600354604080516370a0823160e01b81526001600160a01b038781166004830152915191909216916370a08231916024808301926020929190829003018186803b158015611a8e57600080fd5b505afa158015611aa2573d6000803e3d6000fd5b505050506040513d6020811015611ab857600080fd5b50519092509050915091565b600254604080516340c10f1960e01b81526001600160a01b03858116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015611b1957600080fd5b505af1158015611b2d573d6000803e3d6000fd5b5050600354604080516340c10f1960e01b81526001600160a01b0387811660048301526024820187905291519190921693506340c10f199250604480830192600092919082900301818387803b158015611b8657600080fd5b505af1158015611b9a573d6000803e3d6000fd5b50505050816001600160a01b03167f377111a2ead9c89151d782f261f5cfbfff7958bed8335f97dd6356765ad5c15560008360405180836001811115611bdc57fe5b60ff1681526020018281526020019250505060405180910390a2816001600160a01b03167f377111a2ead9c89151d782f261f5cfbfff7958bed8335f97dd6356765ad5c15560018360405180836001811115611c3457fe5b60ff1681526020018281526020019250505060405180910390a25050565b600e54600090611c68908363ffffffff61175f16565b600e8190559050611c776118d0565b6001600160a01b031663aeab5849836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156118b357600080fd5b600080611cc76118d0565b6001600160a01b0316634a41d89d6040518163ffffffff1660e01b815260040160606040518083038186803b158015611cff57600080fd5b505afa158015611d13573d6000803e3d6000fd5b505050506040513d6060811015611d2957600080fd5b50516004549091508390611d43908363ffffffff6117ec16565b11159392505050565b601154600090600160a01b900460ff1680156108f557506005544211806108f5575050600e541590565b6000546001600160a01b031615611dbe5760405162461bcd60e51b815260040180806020018281038252602781526020018061235e6027913960400191505060405180910390fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60006060611e26846121cd565b90506037602082016000f09150826001600160a01b038316611ec65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611e8b578181015183820152602001611e73565b50505050905090810190601f168015611eb85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505092915050565b600e548015611ee257611ee081611849565b505b6000611eec6116a3565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015611f3857600080fd5b505afa158015611f4c573d6000803e3d6000fd5b505050506040513d6020811015611f6257600080fd5b505190508015611ff957816001600160a01b031663a9059cbb85836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611fcc57600080fd5b505af1158015611fe0573d6000803e3d6000fd5b505050506040513d6020811015611ff657600080fd5b50505b6002546040805163646d919f60e11b81526001600160a01b0387811660048301529151919092169163c8db233e91602480830192600092919082900301818387803b15801561204757600080fd5b505af115801561205b573d6000803e3d6000fd5b50506003546040805163646d919f60e11b81526001600160a01b038981166004830152915191909216935063c8db233e9250602480830192600092919082900301818387803b1580156120ad57600080fd5b505af11580156120c1573d6000803e3d6000fd5b50505050836001600160a01b0316ff5b600c546040805163dacb2d0160e01b81526c45786368616e6765526174657360981b6004820152602481018290526020604482018190527f45786368616e6765526174657320636f6e7472616374206e6f7420666f756e64606483015291516000936001600160a01b03169263dacb2d019260848082019391829003018186803b15801561172e57600080fd5b6000806121848461217887600a870263ffffffff61223d16565b9063ffffffff61229616565b90506005600a825b061061219657600a015b600a9004949350505050565b600080600a83046121b9868663ffffffff61223d16565b816121c057fe5b0490506005600a8261218c565b60408051693d602d80600a3d3981f360b01b602082015269363d3d373d3d3d363d7360b01b602a82015260609290921b6bffffffffffffffffffffffff191660348301526e5af43d82803e903d91602b57fd5bf360881b6048830152805180830360370181526057909201905290565b60008261224c575060006117bc565b8282028284828161225957fe5b04146117b95760405162461bcd60e51b81526004018080602001828103825260218152602001806123b46021913960400191505060405180910390fd5b60008082116122ec576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816122f757fe5b0494935050505056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e65727368697042696e617279204f7074696f6e204d61726b657420616c726561647920696e697469616c697a6564496e69742063616e206f6e6c792062652063616c6c6564207768656e206f776e657220697320304f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564a265627a7a72315820690e8333c3109638ff224b32e910238fe903947094e95177450ce59045fb2d4d64736f6c63430005100032
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101da5760003560e01c80639af1d35a11610104578063c1113c5a116100a2578063c8db233e11610071578063c8db233e14610474578063d068cdc51461049a578063d16e15e9146104a2578063eef49ee3146104aa576101da565b8063c1113c5a146103cd578063c54fd649146103f3578063c7a5bdc814610464578063c7e8bcca1461046c576101da565b8063a0712d68116100de578063a0712d6814610388578063a14f5823146103a5578063ac3791e3146103ad578063b1c9fe6e146103b5576101da565b80639af1d35a146103705780639e3b34bf146103785780639fc5ce2a14610380576101da565b806353a47bb71161017c57806379ba50971161014b57806379ba50971461031a57806385149258146103225780638da5cb5b1461032a57806398508ecd14610332576101da565b806353a47bb71461028d578063587f5ed7146102955780636392a51f146102af57806365372147146102ee576101da565b8063158ef93e116101b8578063158ef93e146102395780631627540c146102555780632810e1d61461027d5780633f6fa65514610285576101da565b806302d05d3f146101df57806304f3bcec146102035780631069143a1461020b575b600080fd5b6101e76104b2565b604080516001600160a01b039092168252519081900360200190f35b6101e76104c1565b6102136104d0565b604080516001600160a01b03938416815291909216602082015281519081900390910190f35b6102416104e6565b604080519115158252519081900360200190f35b61027b6004803603602081101561026b57600080fd5b50356001600160a01b03166104ef565b005b61027b61054b565b6102416108b1565b6101e76108c1565b61029d6108d0565b60408051918252519081900360200190f35b6102d5600480360360208110156102c557600080fd5b50356001600160a01b03166108d6565b6040805192835260208301919091528051918290030190f35b6102f66108eb565b6040518082600181111561030657fe5b60ff16815260200191505060405180910390f35b61027b6108fb565b61029d6109b7565b6101e7610cce565b61033a610cdd565b60408051958652602086019490945284840192909252151560608401526001600160a01b03166080830152519081900360a00190f35b6102d5610cff565b6102d5610d08565b61029d610d11565b61027b6004803603602081101561039e57600080fd5b5035610d17565b61027b610e43565b610241610e4d565b6103bd610f4c565b6040518082600281111561030657fe5b61027b600480360360208110156103e357600080fd5b50356001600160a01b0316610f7c565b61027b60048036036101a081101561040a57600080fd5b506001600160a01b03813581169160208101358216916040820135811691606081013582169160808201359160a08101359160c0820191610100810135916101208201916101608101351515916101809091013516610f84565b6102d5611380565b610241611393565b61027b6004803603602081101561048a57600080fd5b50356001600160a01b03166113a3565b6102d561140d565b6101e7611507565b61029d611516565b6011546001600160a01b031681565b600c546001600160a01b031681565b6002546003546001600160a01b03918216911682565b60135460ff1681565b6104f761151c565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b61055361151c565b61055b611565565b61059d576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420796574206d617475726560901b604482015290519081900360640190fd5b6105a561156d565b6105ad610e4d565b6105f7576040805162461bcd60e51b815260206004820152601660248201527510d85b881b9bdd081c995cdbdb1d99481b585c9ad95d60521b604482015290519081900360640190fd5b600080610602611615565b600d549193509150600160a01b900460ff1661061e5760088290555b6011805460ff60a01b1916600160a01b179055600061063b6116a3565b600b54600a549192506000916106569163ffffffff61175f16565b600a5490915060009061066f908363ffffffff6117c216565b90506000610688600f54836117d790919063ffffffff16565b905060006106a182600f546117ec90919063ffffffff16565b90506106bb6106b6828463ffffffff61175f16565b611849565b50846001600160a01b031663a9059cbb6106d36118d0565b6001600160a01b031663412753586040518163ffffffff1660e01b815260040160206040518083038186803b15801561070b57600080fd5b505afa15801561071f573d6000803e3d6000fd5b505050506040513d602081101561073557600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b039092166004830152602482018690525160448083019260209291908290030181600087803b15801561078557600080fd5b505af1158015610799573d6000803e3d6000fd5b505050506040513d60208110156107af57600080fd5b50506011546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519187169163a9059cbb916044808201926020929091908290030181600087803b15801561080757600080fd5b505af115801561081b573d6000803e3d6000fd5b505050506040513d602081101561083157600080fd5b507f5528b7e06f48a519cf814c4e5293ee2737c3f5c28d93e30cca112ac649fdd235905061085d6118df565b8888600e5486866040518087600181111561087457fe5b60ff1681526020810196909652506040808601949094526060850192909252608084015260a0830152519081900360c0019150a150505050505050565b601154600160a01b900460ff1681565b6001546001600160a01b031681565b600f5481565b6000806108e2836119c6565b91509150915091565b60006108f56118df565b90505b90565b6001546001600160a01b031633146109445760405162461bcd60e51b81526004018080602001828103825260358152602001806123016035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b60006109c1611565565b610a03576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420796574206d617475726560901b604482015290519081900360640190fd5b601154600160a01b900460ff16610a8c57610a1c6118d0565b6001600160a01b0316637859f410306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b158015610a7357600080fd5b505af1158015610a87573d6000803e3d6000fd5b505050505b600080610a98336119c6565b91509150816000141580610aab57508015155b610af2576040805162461bcd60e51b81526020600482015260136024820152724e6f7468696e6720746f20657865726369736560681b604482015290519081900360640190fd5b8115610b5d5760025460408051630d8acc1560e11b815233600482015290516001600160a01b0390921691631b15982a9160248082019260009290919082900301818387803b158015610b4457600080fd5b505af1158015610b58573d6000803e3d6000fd5b505050505b8015610bc85760035460408051630d8acc1560e11b815233600482015290516001600160a01b0390921691631b15982a9160248082019260009290919082900301818387803b158015610baf57600080fd5b505af1158015610bc3573d6000803e3d6000fd5b505050505b600080610bd36118df565b6001811115610bde57fe5b14610be95781610beb565b825b60408051828152905191925033917fd82b6f69d7477fb41cd83d936de94990cee2fa1a309feeee90101fc0513b6a439181900360200190a28015610cc757610c3281611849565b50610c3b6116a3565b6001600160a01b031663a9059cbb33836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610c9a57600080fd5b505af1158015610cae573d6000803e3d6000fd5b505050506040513d6020811015610cc457600080fd5b50505b9250505090565b6000546001600160a01b031681565b60065460075460085460095460ff81169061010090046001600160a01b031685565b600a54600b5482565b60045460055482565b60105481565b610d1f611565565b15610d64576040805162461bcd60e51b815260206004820152601060248201526f4d696e74696e6720696e61637469766560801b604482015290519081900360640190fd5b80610d6e57610e40565b6000610d85601254836117d790919063ffffffff16565b90506000610d99838363ffffffff6117ec16565b600f54909150610daf908263ffffffff61175f16565b600f55610dbc3383611ac4565b610dc583611c52565b50610dce6118d0565b60408051635c847f5960e11b81523360048201523060248201526044810186905290516001600160a01b03929092169163b908feb29160648082019260009290919082900301818387803b158015610e2557600080fd5b505af1158015610e39573d6000803e3d6000fd5b5050505050505b50565b610e4b61156d565b565b600d54600090600160a01b900460ff1615610f0857601154600160a01b900460ff16158015610e7f5750610e7f611565565b8015610f015750600d60009054906101000a90046001600160a01b03166001600160a01b031663a9720eea6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ed457600080fd5b505afa158015610ee8573d6000803e3d6000fd5b505050506040513d6020811015610efe57600080fd5b50515b90506108f8565b6000610f12611615565b601154909250600160a01b900460ff161590508015610f345750610f34611565565b8015610f445750610f4481611cbc565b9150506108f8565b6000610f56611565565b610f62575060006108f8565b610f6a611d4c565b610f76575060016108f8565b50600290565b610e4061151c565b60135460ff1615610fc65760405162461bcd60e51b81526004018080602001828103825260288152602001806123366028913960400191505060405180910390fd5b6013805460ff19166001179055610fdc8b611d76565b600c80546001600160a01b03199081166001600160a01b038c8116919091179092556011805482168b84161790556040805160a0810182528a815260208082018b9052600082840181905287151560608401819052958716608090930183905260068d905560078c90556008556009805460ff19168617610100600160a81b0319166101008402179055600d805460ff60a01b1916600160a01b909602959095179093161790925581518083018352873580825288830135918301829052600455600555600e8690556010869055815180830190925284358083528582013592909101829052600a819055600b829055906111566110da838361175f565b7384d626b2bb4d0f064067e4bf80fce7055d8f3e7b63907af6c06040518163ffffffff1660e01b815260040160206040518083038186803b15801561111e57600080fd5b505af4158015611132573d6000803e3d6000fd5b505050506040513d602081101561114857600080fd5b50519063ffffffff6117ec16565b60128190555061119b8c6040518060400160405280602081526020017f436f756c64206e6f742063726561746520612042696e617279204f7074696f6e815250611e19565b600280546001600160a01b0319166001600160a01b03929092169190911790556040805180820190915260208082527f436f756c64206e6f742063726561746520612042696e617279204f7074696f6e908201526111fa908d90611e19565b600380546001600160a01b0319166001600160a01b039283161790556002546040805163266c45bb60e11b815260048101829052601260448201527142696e617279204f7074696f6e204c6f6e6760701b6064820152608060248201526005608482015264734c4f4e4760d81b60a482015290519190921691634cd88b769160c480830192600092919082900301818387803b15801561129957600080fd5b505af11580156112ad573d6000803e3d6000fd5b50506003546040805163266c45bb60e11b8152600481018290526013604482015272109a5b985c9e4813dc1d1a5bdb8814da1bdc9d606a1b60648201526080602482015260066084820152651cd4d213d49560d21b60a482015290516001600160a01b039092169350634cd88b76925060c48082019260009290919082900301818387803b15801561133e57600080fd5b505af1158015611352573d6000803e3d6000fd5b505060115460105461137193506001600160a01b039091169150611ac4565b50505050505050505050505050565b60008061138b611615565b915091509091565b600d54600160a01b900460ff1681565b6113ab61151c565b6113b3611d4c565b611404576040805162461bcd60e51b815260206004820152601b60248201527f556e65787069726564206f7074696f6e732072656d61696e696e670000000000604482015290519081900360640190fd5b610e4081611ece565b600080600260000160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561146157600080fd5b505afa158015611475573d6000803e3d6000fd5b505050506040513d602081101561148b57600080fd5b5051600354604080516318160ddd60e01b815290516001600160a01b03909216916318160ddd91600480820192602092909190829003018186803b1580156114d257600080fd5b505afa1580156114e6573d6000803e3d6000fd5b505050506040513d60208110156114fc57600080fd5b505190925090509091565b600d546001600160a01b031681565b600e5481565b6000546001600160a01b03163314610e4b5760405162461bcd60e51b815260040180806020018281038252602f815260200180612385602f913960400191505060405180910390fd5b600454421190565b6115756118d0565b6001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115ad57600080fd5b505afa1580156115c1573d6000803e3d6000fd5b505050506040513d60208110156115d757600080fd5b505115610e4b5760405162461bcd60e51b815260040180806020018281038252603c8152602001806123d5603c913960400191505060405180910390fd5b6000806116206120d1565b6001600160a01b0316634308a94f6006600001546040518263ffffffff1660e01b815260040180828152602001915050604080518083038186803b15801561166757600080fd5b505afa15801561167b573d6000803e3d6000fd5b505050506040513d604081101561169157600080fd5b50805160209091015190925090509091565b600c546040805163dacb2d0160e01b81526814de5b9d1a1cd554d160ba1b600482015260248101829052601c60448201527f53796e74687355534420636f6e7472616374206e6f7420666f756e6400000000606482015290516000926001600160a01b03169163dacb2d01916084808301926020929190829003018186803b15801561172e57600080fd5b505afa158015611742573d6000803e3d6000fd5b505050506040513d602081101561175857600080fd5b5051905090565b6000828201838110156117b9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b60006117b98383670de0b6b3a764000061215e565b60006117b98383670de0b6b3a76400006121a2565b600082821115611843576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600e5460009061185f908363ffffffff6117ec16565b600e819055905061186e6118d0565b6001600160a01b0316636b3a0984836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156118b357600080fd5b505af11580156118c7573d6000803e3d6000fd5b50505050919050565b6000546001600160a01b031690565b600d54600090600160a01b900460ff161561198157600d60009054906101000a90046001600160a01b03166001600160a01b0316637e7e4b476040518163ffffffff1660e01b815260040160206040518083038186803b15801561194257600080fd5b505afa158015611956573d6000803e3d6000fd5b505050506040513d602081101561196c57600080fd5b5051611979576001610f01565b5060006108f8565b601154600090600160a01b900460ff161561199f57506008546119ab565b6119a7611615565b5090505b6007548110156119bc576001610f44565b60009150506108f8565b600254604080516370a0823160e01b81526001600160a01b0384811660048301529151600093849316916370a08231916024808301926020929190829003018186803b158015611a1557600080fd5b505afa158015611a29573d6000803e3d6000fd5b505050506040513d6020811015611a3f57600080fd5b5051600354604080516370a0823160e01b81526001600160a01b038781166004830152915191909216916370a08231916024808301926020929190829003018186803b158015611a8e57600080fd5b505afa158015611aa2573d6000803e3d6000fd5b505050506040513d6020811015611ab857600080fd5b50519092509050915091565b600254604080516340c10f1960e01b81526001600160a01b03858116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015611b1957600080fd5b505af1158015611b2d573d6000803e3d6000fd5b5050600354604080516340c10f1960e01b81526001600160a01b0387811660048301526024820187905291519190921693506340c10f199250604480830192600092919082900301818387803b158015611b8657600080fd5b505af1158015611b9a573d6000803e3d6000fd5b50505050816001600160a01b03167f377111a2ead9c89151d782f261f5cfbfff7958bed8335f97dd6356765ad5c15560008360405180836001811115611bdc57fe5b60ff1681526020018281526020019250505060405180910390a2816001600160a01b03167f377111a2ead9c89151d782f261f5cfbfff7958bed8335f97dd6356765ad5c15560018360405180836001811115611c3457fe5b60ff1681526020018281526020019250505060405180910390a25050565b600e54600090611c68908363ffffffff61175f16565b600e8190559050611c776118d0565b6001600160a01b031663aeab5849836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156118b357600080fd5b600080611cc76118d0565b6001600160a01b0316634a41d89d6040518163ffffffff1660e01b815260040160606040518083038186803b158015611cff57600080fd5b505afa158015611d13573d6000803e3d6000fd5b505050506040513d6060811015611d2957600080fd5b50516004549091508390611d43908363ffffffff6117ec16565b11159392505050565b601154600090600160a01b900460ff1680156108f557506005544211806108f5575050600e541590565b6000546001600160a01b031615611dbe5760405162461bcd60e51b815260040180806020018281038252602781526020018061235e6027913960400191505060405180910390fd5b600080546001600160a01b0319166001600160a01b038316908117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60006060611e26846121cd565b90506037602082016000f09150826001600160a01b038316611ec65760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611e8b578181015183820152602001611e73565b50505050905090810190601f168015611eb85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505092915050565b600e548015611ee257611ee081611849565b505b6000611eec6116a3565b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015611f3857600080fd5b505afa158015611f4c573d6000803e3d6000fd5b505050506040513d6020811015611f6257600080fd5b505190508015611ff957816001600160a01b031663a9059cbb85836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611fcc57600080fd5b505af1158015611fe0573d6000803e3d6000fd5b505050506040513d6020811015611ff657600080fd5b50505b6002546040805163646d919f60e11b81526001600160a01b0387811660048301529151919092169163c8db233e91602480830192600092919082900301818387803b15801561204757600080fd5b505af115801561205b573d6000803e3d6000fd5b50506003546040805163646d919f60e11b81526001600160a01b038981166004830152915191909216935063c8db233e9250602480830192600092919082900301818387803b1580156120ad57600080fd5b505af11580156120c1573d6000803e3d6000fd5b50505050836001600160a01b0316ff5b600c546040805163dacb2d0160e01b81526c45786368616e6765526174657360981b6004820152602481018290526020604482018190527f45786368616e6765526174657320636f6e7472616374206e6f7420666f756e64606483015291516000936001600160a01b03169263dacb2d019260848082019391829003018186803b15801561172e57600080fd5b6000806121848461217887600a870263ffffffff61223d16565b9063ffffffff61229616565b90506005600a825b061061219657600a015b600a9004949350505050565b600080600a83046121b9868663ffffffff61223d16565b816121c057fe5b0490506005600a8261218c565b60408051693d602d80600a3d3981f360b01b602082015269363d3d373d3d3d363d7360b01b602a82015260609290921b6bffffffffffffffffffffffff191660348301526e5af43d82803e903d91602b57fd5bf360881b6048830152805180830360370181526057909201905290565b60008261224c575060006117bc565b8282028284828161225957fe5b04146117b95760405162461bcd60e51b81526004018080602001828103825260218152602001806123b46021913960400191505060405180910390fd5b60008082116122ec576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b60008284816122f757fe5b0494935050505056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e65727368697042696e617279204f7074696f6e204d61726b657420616c726561647920696e697469616c697a6564496e69742063616e206f6e6c792062652063616c6c6564207768656e206f776e657220697320304f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564a265627a7a72315820690e8333c3109638ff224b32e910238fe903947094e95177450ce59045fb2d4d64736f6c63430005100032
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.