Source Code
Overview
ETH Balance
0 ETH
Token Holdings
More Info
ContractCreator
Multi Chain
Multichain Addresses
12 addresses found via
Latest 25 from a total of 131 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Set Callback Aut... | 9688599 | 12 days 4 hrs ago | IN | 0 ETH | 0.0001702 | ||||
Create Market | 9404296 | 62 days 13 hrs ago | IN | 0 ETH | 0.00074063 | ||||
Create Market | 9294533 | 82 days 7 hrs ago | IN | 0 ETH | 0.00186789 | ||||
Close Market | 9219800 | 95 days 14 hrs ago | IN | 0 ETH | 0 | ||||
Create Market | 9216369 | 96 days 4 hrs ago | IN | 0 ETH | 0.00000001 | ||||
Create Market | 9209496 | 97 days 11 hrs ago | IN | 0 ETH | 0 | ||||
Create Market | 9143215 | 109 days 10 hrs ago | IN | 0 ETH | 0 | ||||
Create Market | 9134810 | 110 days 23 hrs ago | IN | 0 ETH | 0 | ||||
Close Market | 9134396 | 111 days 49 mins ago | IN | 0 ETH | 0 | ||||
Create Market | 9133875 | 111 days 3 hrs ago | IN | 0 ETH | 0 | ||||
Create Market | 9031529 | 128 days 13 hrs ago | IN | 0 ETH | 0.00006442 | ||||
Create Market | 8906878 | 150 days 5 hrs ago | IN | 0 ETH | 0.01244484 | ||||
Create Market | 8867404 | 157 days 5 hrs ago | IN | 0 ETH | 0.00234928 | ||||
Create Market | 8862083 | 158 days 4 hrs ago | IN | 0 ETH | 0.04448608 | ||||
Create Market | 8824798 | 165 days 1 hr ago | IN | 0 ETH | 0.01337223 | ||||
Create Market | 8815259 | 166 days 18 hrs ago | IN | 0 ETH | 0.02556646 | ||||
Create Market | 8815171 | 166 days 18 hrs ago | IN | 0 ETH | 0.03221429 | ||||
Create Market | 8815141 | 166 days 18 hrs ago | IN | 0 ETH | 0.02358016 | ||||
Create Market | 8815067 | 166 days 19 hrs ago | IN | 0 ETH | 0.00622593 | ||||
Close Market | 8815016 | 166 days 19 hrs ago | IN | 0 ETH | 0.00029965 | ||||
Create Market | 8812878 | 167 days 4 hrs ago | IN | 0 ETH | 0.07366356 | ||||
Create Market | 8812680 | 167 days 5 hrs ago | IN | 0 ETH | 0.11866359 | ||||
Create Market | 8812324 | 167 days 6 hrs ago | IN | 0 ETH | 0.10653875 | ||||
Create Market | 8812273 | 167 days 6 hrs ago | IN | 0 ETH | 0.06579947 | ||||
Create Market | 8812259 | 167 days 7 hrs ago | IN | 0 ETH | 0.06945898 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Txn Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
9717942 | 7 days 3 hrs ago | 0 ETH | ||||
9717942 | 7 days 3 hrs ago | 0 ETH | ||||
9688599 | 12 days 4 hrs ago | 0 ETH | ||||
9404296 | 62 days 13 hrs ago | 0 ETH | ||||
9404296 | 62 days 13 hrs ago | 0 ETH | ||||
9404296 | 62 days 13 hrs ago | 0 ETH | ||||
9334209 | 75 days 4 hrs ago | 0 ETH | ||||
9334209 | 75 days 4 hrs ago | 0 ETH | ||||
9334209 | 75 days 4 hrs ago | 0 ETH | ||||
9294596 | 82 days 7 hrs ago | 0 ETH | ||||
9294596 | 82 days 7 hrs ago | 0 ETH | ||||
9294596 | 82 days 7 hrs ago | 0 ETH | ||||
9294592 | 82 days 7 hrs ago | 0 ETH | ||||
9294592 | 82 days 7 hrs ago | 0 ETH | ||||
9294592 | 82 days 7 hrs ago | 0 ETH | ||||
9294585 | 82 days 7 hrs ago | 0 ETH | ||||
9294585 | 82 days 7 hrs ago | 0 ETH | ||||
9294585 | 82 days 7 hrs ago | 0 ETH | ||||
9294579 | 82 days 7 hrs ago | 0 ETH | ||||
9294579 | 82 days 7 hrs ago | 0 ETH | ||||
9294579 | 82 days 7 hrs ago | 0 ETH | ||||
9294571 | 82 days 7 hrs ago | 0 ETH | ||||
9294571 | 82 days 7 hrs ago | 0 ETH | ||||
9294571 | 82 days 7 hrs ago | 0 ETH | ||||
9294533 | 82 days 7 hrs ago | 0 ETH |
Loading...
Loading
Contract Name:
BondFixedTermSDA
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 100000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity 0.8.15; import {BondBaseSDA, IBondAggregator, Authority} from "./bases/BondBaseSDA.sol"; import {IBondTeller} from "./interfaces/IBondTeller.sol"; /// @title Bond Fixed-Term Sequential Dutch Auctioneer /// @notice Bond Fixed-Term Sequential Dutch Auctioneer Contract /// @dev Bond Protocol is a permissionless system to create Olympus-style bond markets /// for any token pair. The markets do not require maintenance and will manage /// bond prices based on activity. Bond issuers create BondMarkets that pay out /// a Payout Token in exchange for deposited Quote Tokens. Users can purchase /// future-dated Payout Tokens with Quote Tokens at the current market price and /// receive Bond Tokens to represent their position while their bond vests. /// Once the Bond Tokens vest, they can redeem it for the Quote Tokens. /// /// @dev The Fixed-Term Auctioneer is an implementation of the /// Bond Base Auctioneer contract specific to creating bond markets where /// purchases vest in a fixed amount of time after purchased (rounded to the day). /// /// @author Oighty, Zeus, Potted Meat, indigo contract BondFixedTermSDA is BondBaseSDA { /* ========== CONSTRUCTOR ========== */ constructor( IBondTeller teller_, IBondAggregator aggregator_, address guardian_, Authority authority_ ) BondBaseSDA(teller_, aggregator_, guardian_, authority_) {} /* ========== MARKET FUNCTIONS ========== */ /// @inheritdoc BondBaseSDA function createMarket(bytes calldata params_) external override returns (uint256) { // Decode params into the struct type expected by this auctioneer MarketParams memory params = abi.decode(params_, (MarketParams)); // Check that the vesting parameter is valid for a fixed-term market if (params.vesting != 0 && (params.vesting < 1 days || params.vesting > MAX_FIXED_TERM)) revert Auctioneer_InvalidParams(); // Create market and return market ID return _createMarket(params); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Auth.sol) /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) abstract contract Auth { event OwnerUpdated(address indexed user, address indexed newOwner); event AuthorityUpdated(address indexed user, Authority indexed newAuthority); address public owner; Authority public authority; constructor(address _owner, Authority _authority) { owner = _owner; authority = _authority; emit OwnerUpdated(msg.sender, _owner); emit AuthorityUpdated(msg.sender, _authority); } modifier requiresAuth() { require(isAuthorized(msg.sender, msg.sig), "UNAUTHORIZED"); _; } function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) { Authority auth = authority; // Memoizing authority saves us a warm SLOAD, around 100 gas. // Checking if the caller is the owner only after calling the authority saves gas in most cases, but be // aware that this makes protected functions uncallable even to the owner if the authority is out of order. return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) || user == owner; } function setAuthority(Authority newAuthority) public virtual { // We check if the caller is the owner first because we want to ensure they can // always swap out the authority even if it's reverting or using up a lot of gas. require(msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig)); authority = newAuthority; emit AuthorityUpdated(msg.sender, newAuthority); } function setOwner(address newOwner) public virtual requiresAuth { owner = newOwner; emit OwnerUpdated(msg.sender, newOwner); } } /// @notice A generic interface for a contract which provides authorization data to an Auth instance. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Auth.sol) /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) interface Authority { function canCall( address user, address target, bytes4 functionSig ) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*/////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*/////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*/////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*/////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*/////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*/////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*/////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) ) ); address recoveredAddress = ecrecover(digest, v, r, s); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*/////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Gas optimized reentrancy protection for smart contracts. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol) abstract contract ReentrancyGuard { uint256 private locked = 1; modifier nonReentrant() { require(locked == 1, "REENTRANCY"); locked = 2; _; locked = 1; } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity 0.8.15; import {ERC20} from "solmate/tokens/ERC20.sol"; import {ReentrancyGuard} from "solmate/utils/ReentrancyGuard.sol"; import {Auth, Authority} from "solmate/auth/Auth.sol"; import {IBondSDA, IBondAuctioneer} from "../interfaces/IBondSDA.sol"; import {IBondTeller} from "../interfaces/IBondTeller.sol"; import {IBondCallback} from "../interfaces/IBondCallback.sol"; import {IBondAggregator} from "../interfaces/IBondAggregator.sol"; import {TransferHelper} from "../lib/TransferHelper.sol"; import {FullMath} from "../lib/FullMath.sol"; /// @title Bond Sequential Dutch Auctioneer (SDA) /// @notice Bond Sequential Dutch Auctioneer Base Contract /// @dev Bond Protocol is a system to create Olympus-style bond markets /// for any token pair. The markets do not require maintenance and will manage /// bond prices based on activity. Bond issuers create BondMarkets that pay out /// a Payout Token in exchange for deposited Quote Tokens. Users can purchase /// future-dated Payout Tokens with Quote Tokens at the current market price and /// receive Bond Tokens to represent their position while their bond vests. /// Once the Bond Tokens vest, they can redeem it for the Quote Tokens. /// /// @dev The Auctioneer contract allows users to create and manage bond markets. /// All bond pricing logic and market data is stored in the Auctioneer. /// A Auctioneer is dependent on a Teller to serve external users and /// an Aggregator to register new markets. This implementation of the Auctioneer /// uses a Sequential Dutch Auction pricing system to buy a target amount of quote /// tokens or sell a target amount of payout tokens over the duration of a market. /// /// @author Oighty, Zeus, Potted Meat, indigo abstract contract BondBaseSDA is IBondSDA, Auth { using TransferHelper for ERC20; using FullMath for uint256; /* ========== ERRORS ========== */ error Auctioneer_OnlyMarketOwner(); error Auctioneer_InitialPriceLessThanMin(); error Auctioneer_MarketConcluded(uint256 conclusion_); error Auctioneer_MaxPayoutExceeded(); error Auctioneer_AmountLessThanMinimum(); error Auctioneer_NotEnoughCapacity(); error Auctioneer_InvalidCallback(); error Auctioneer_BadExpiry(); error Auctioneer_InvalidParams(); error Auctioneer_NotAuthorized(); error Auctioneer_NewMarketsNotAllowed(); /* ========== EVENTS ========== */ event MarketCreated( uint256 indexed id, address indexed payoutToken, address indexed quoteToken, uint48 vesting, uint256 initialPrice ); event MarketClosed(uint256 indexed id); event Tuned(uint256 indexed id, uint256 oldControlVariable, uint256 newControlVariable); event DefaultsUpdated( uint32 defaultTuneInterval, uint32 defaultTuneAdjustment, uint32 minDebtDecayInterval, uint32 minDepositInterval, uint32 minMarketDuration, uint32 minDebtBuffer ); /* ========== STATE VARIABLES ========== */ /// @notice Main information pertaining to bond market mapping(uint256 => BondMarket) public markets; /// @notice Information used to control how a bond market changes mapping(uint256 => BondTerms) public terms; /// @notice Data needed for tuning bond market mapping(uint256 => BondMetadata) public metadata; /// @notice Control variable changes mapping(uint256 => Adjustment) public adjustments; /// @notice New address to designate as market owner. They must accept ownership to transfer permissions. mapping(uint256 => address) public newOwners; /// @notice Whether or not the auctioneer allows new markets to be created /// @dev Changing to false will sunset the auctioneer after all active markets end bool public allowNewMarkets; /// @notice Whether or not the market creator is authorized to use a callback address mapping(address => bool) public callbackAuthorized; /// Sane defaults for tuning. Can be adjusted for a specific market via setters. uint32 public defaultTuneInterval; uint32 public defaultTuneAdjustment; /// Minimum values for decay, deposit interval, market duration and debt buffer. uint32 public minDebtDecayInterval; uint32 public minDepositInterval; uint32 public minMarketDuration; uint32 public minDebtBuffer; // A 'vesting' param longer than 50 years is considered a timestamp for fixed expiry. uint48 internal constant MAX_FIXED_TERM = 52 weeks * 50; uint48 internal constant FEE_DECIMALS = 1e5; // one percent equals 1000. // BondAggregator contract with utility functions IBondAggregator internal immutable _aggregator; // BondTeller contract that handles interactions with users and issues tokens IBondTeller internal immutable _teller; constructor( IBondTeller teller_, IBondAggregator aggregator_, address guardian_, Authority authority_ ) Auth(guardian_, authority_) { _aggregator = aggregator_; _teller = teller_; defaultTuneInterval = 24 hours; defaultTuneAdjustment = 1 hours; minDebtDecayInterval = 3 days; minDepositInterval = 1 hours; minMarketDuration = 1 days; minDebtBuffer = 10000; // 10% allowNewMarkets = true; } /* ========== MARKET FUNCTIONS ========== */ /// @inheritdoc IBondAuctioneer function createMarket(bytes calldata params_) external virtual returns (uint256); /// @notice core market creation logic, see IBondSDA.MarketParams documentation function _createMarket(MarketParams memory params_) internal returns (uint256) { { // Check that the auctioneer is allowing new markets to be created if (!allowNewMarkets) revert Auctioneer_NewMarketsNotAllowed(); // Ensure params are in bounds uint8 payoutTokenDecimals = params_.payoutToken.decimals(); uint8 quoteTokenDecimals = params_.quoteToken.decimals(); if (payoutTokenDecimals < 6 || payoutTokenDecimals > 18) revert Auctioneer_InvalidParams(); if (quoteTokenDecimals < 6 || quoteTokenDecimals > 18) revert Auctioneer_InvalidParams(); if (params_.scaleAdjustment < -24 || params_.scaleAdjustment > 24) revert Auctioneer_InvalidParams(); // Restrict the use of a callback address unless allowed if (!callbackAuthorized[msg.sender] && params_.callbackAddr != address(0)) revert Auctioneer_NotAuthorized(); } // Unit to scale calculation for this market by to ensure reasonable values // for price, debt, and control variable without under/overflows. // See IBondSDA for more details. // // scaleAdjustment should be equal to (payoutDecimals - quoteDecimals) - ((payoutPriceDecimals - quotePriceDecimals) / 2) uint256 scale; unchecked { scale = 10**uint8(36 + params_.scaleAdjustment); } if (params_.formattedInitialPrice < params_.formattedMinimumPrice) revert Auctioneer_InitialPriceLessThanMin(); // Register new market on aggregator and get marketId uint256 marketId = _aggregator.registerMarket(params_.payoutToken, params_.quoteToken); uint32 secondsToConclusion; uint32 debtDecayInterval; { // Conclusion must be later than the current block timestamp or will revert secondsToConclusion = uint32(params_.conclusion - block.timestamp); if ( secondsToConclusion < minMarketDuration || params_.depositInterval < minDepositInterval || params_.depositInterval > secondsToConclusion ) revert Auctioneer_InvalidParams(); // The debt decay interval is how long it takes for price to drop to 0 from the last decay timestamp. // In reality, a 50% drop is likely a guaranteed bond sale. Therefore, debt decay interval needs to be // long enough to allow a bond to adjust if oversold. It also needs to be some multiple of deposit interval // because you don't want to go from 100 to 0 during the time frame you expected to sell a single bond. // A multiple of 5 is a sane default observed from running OP v1 bond markets. uint32 userDebtDecay = params_.depositInterval * 5; debtDecayInterval = minDebtDecayInterval > userDebtDecay ? minDebtDecayInterval : userDebtDecay; uint256 tuneIntervalCapacity = params_.capacity.mulDiv( uint256( params_.depositInterval > defaultTuneInterval ? params_.depositInterval : defaultTuneInterval ), uint256(secondsToConclusion) ); metadata[marketId] = BondMetadata({ lastTune: uint48(block.timestamp), lastDecay: uint48(block.timestamp), length: secondsToConclusion, depositInterval: params_.depositInterval, tuneInterval: params_.depositInterval > defaultTuneInterval ? params_.depositInterval : defaultTuneInterval, tuneAdjustmentDelay: defaultTuneAdjustment, debtDecayInterval: debtDecayInterval, tuneIntervalCapacity: tuneIntervalCapacity, tuneBelowCapacity: params_.capacity - tuneIntervalCapacity, lastTuneDebt: ( params_.capacityInQuote ? params_.capacity.mulDiv(scale, params_.formattedInitialPrice) : params_.capacity ).mulDiv(uint256(debtDecayInterval), uint256(secondsToConclusion)) }); } // Initial target debt is equal to capacity scaled by the ratio of the debt decay interval and the length of the market. // This is the amount of debt that should be decayed over the decay interval if no purchases are made. // Note price should be passed in a specific format: // price = (payoutPriceCoefficient / quotePriceCoefficient) // * 10**(36 + scaleAdjustment + quoteDecimals - payoutDecimals + payoutPriceDecimals - quotePriceDecimals) // See IBondSDA for more details and variable definitions. uint256 targetDebt; uint256 maxPayout; { uint256 capacity = params_.capacityInQuote ? params_.capacity.mulDiv(scale, params_.formattedInitialPrice) : params_.capacity; targetDebt = capacity.mulDiv(uint256(debtDecayInterval), uint256(secondsToConclusion)); // Max payout is the amount of capacity that should be utilized in a deposit // interval. for example, if capacity is 1,000 TOKEN, there are 10 days to conclusion, // and the preferred deposit interval is 1 day, max payout would be 100 TOKEN. // Additionally, max payout is the maximum amount that a user can receive from a single // purchase at that moment in time. maxPayout = capacity.mulDiv( uint256(params_.depositInterval), uint256(secondsToConclusion) ); } markets[marketId] = BondMarket({ owner: msg.sender, payoutToken: params_.payoutToken, quoteToken: params_.quoteToken, callbackAddr: params_.callbackAddr, capacityInQuote: params_.capacityInQuote, capacity: params_.capacity, totalDebt: targetDebt, minPrice: params_.formattedMinimumPrice, maxPayout: maxPayout, purchased: 0, sold: 0, scale: scale }); // Max debt serves as a circuit breaker for the market. let's say the quote token is a stablecoin, // and that stablecoin depegs. without max debt, the market would continue to buy until it runs // out of capacity. this is configurable with a 3 decimal buffer (1000 = 1% above initial price). // Note that its likely advisable to keep this buffer wide. // Note that the buffer is above 100%. i.e. 10% buffer = initial debt * 1.1 // 1e5 = 100,000. 10,000 / 100,000 = 10%. // See IBondSDA.MarketParams for more information on determining a reasonable debt buffer. uint256 minDebtBuffer_ = maxPayout.mulDiv(FEE_DECIMALS, targetDebt) > minDebtBuffer ? maxPayout.mulDiv(FEE_DECIMALS, targetDebt) : minDebtBuffer; uint256 maxDebt = targetDebt + targetDebt.mulDiv( uint256(params_.debtBuffer > minDebtBuffer_ ? params_.debtBuffer : minDebtBuffer_), 1e5 ); // The control variable is set as the ratio of price to the initial targetDebt, scaled to prevent under/overflows. // It determines the price of the market as the debt decays and is tuned by the market based on user activity. // See _tune() for more information. // // price = control variable * debt / scale // therefore, control variable = price * scale / debt uint256 controlVariable = params_.formattedInitialPrice.mulDiv(scale, targetDebt); terms[marketId] = BondTerms({ controlVariable: controlVariable, maxDebt: maxDebt, vesting: params_.vesting, conclusion: params_.conclusion }); emit MarketCreated( marketId, address(params_.payoutToken), address(params_.quoteToken), params_.vesting, params_.formattedInitialPrice ); return marketId; } /// @inheritdoc IBondAuctioneer function setIntervals(uint256 id_, uint32[3] calldata intervals_) external override { // Check that the market is live if (!isLive(id_)) revert Auctioneer_InvalidParams(); // Check that the intervals are non-zero if (intervals_[0] == 0 || intervals_[1] == 0 || intervals_[2] == 0) revert Auctioneer_InvalidParams(); // Check that tuneInterval >= tuneAdjustmentDelay if (intervals_[0] < intervals_[1]) revert Auctioneer_InvalidParams(); BondMetadata storage meta = metadata[id_]; // Check that tuneInterval >= depositInterval if (intervals_[0] < meta.depositInterval) revert Auctioneer_InvalidParams(); // Check that debtDecayInterval >= minDebtDecayInterval if (intervals_[2] < minDebtDecayInterval) revert Auctioneer_InvalidParams(); // Check that sender is market owner BondMarket memory market = markets[id_]; if (msg.sender != market.owner) revert Auctioneer_OnlyMarketOwner(); // Update intervals meta.tuneInterval = intervals_[0]; meta.tuneIntervalCapacity = market.capacity.mulDiv( uint256(intervals_[0]), uint256(terms[id_].conclusion) - block.timestamp ); // don't have a stored value for market duration, this will update tuneIntervalCapacity based on time remaining meta.tuneBelowCapacity = market.capacity > meta.tuneIntervalCapacity ? market.capacity - meta.tuneIntervalCapacity : 0; meta.tuneAdjustmentDelay = intervals_[1]; meta.debtDecayInterval = intervals_[2]; } /// @inheritdoc IBondAuctioneer function pushOwnership(uint256 id_, address newOwner_) external override { if (msg.sender != markets[id_].owner) revert Auctioneer_OnlyMarketOwner(); newOwners[id_] = newOwner_; } /// @inheritdoc IBondAuctioneer function pullOwnership(uint256 id_) external override { if (msg.sender != newOwners[id_]) revert Auctioneer_NotAuthorized(); markets[id_].owner = newOwners[id_]; } /// @inheritdoc IBondAuctioneer function setDefaults(uint32[6] memory defaults_) external override requiresAuth { // Restricted to authorized addresses // Validate inputs // Check that defaultTuneInterval >= defaultTuneAdjustment if (defaults_[0] < defaults_[1]) revert Auctioneer_InvalidParams(); // Check that defaultTuneInterval >= minDepositInterval if (defaults_[0] < defaults_[3]) revert Auctioneer_InvalidParams(); // Check that minDepositInterval <= minMarketDuration if (defaults_[3] > defaults_[4]) revert Auctioneer_InvalidParams(); // Check that minDebtDecayInterval >= 5 * minDepositInterval if (defaults_[2] < defaults_[3] * 5) revert Auctioneer_InvalidParams(); // Update defaults defaultTuneInterval = defaults_[0]; defaultTuneAdjustment = defaults_[1]; minDebtDecayInterval = defaults_[2]; minDepositInterval = defaults_[3]; minMarketDuration = defaults_[4]; minDebtBuffer = defaults_[5]; emit DefaultsUpdated( defaultTuneInterval, defaultTuneAdjustment, minDebtDecayInterval, minDepositInterval, minMarketDuration, minDebtBuffer ); } /// @inheritdoc IBondAuctioneer function setAllowNewMarkets(bool status_) external override requiresAuth { // Restricted to authorized addresses allowNewMarkets = status_; } /// @inheritdoc IBondAuctioneer function setCallbackAuthStatus(address creator_, bool status_) external override requiresAuth { // Restricted to authorized addresses callbackAuthorized[creator_] = status_; } /// @inheritdoc IBondAuctioneer function closeMarket(uint256 id_) external override { if (msg.sender != markets[id_].owner) revert Auctioneer_OnlyMarketOwner(); _close(id_); } /* ========== TELLER FUNCTIONS ========== */ /// @inheritdoc IBondAuctioneer function purchaseBond( uint256 id_, uint256 amount_, uint256 minAmountOut_ ) external override returns (uint256 payout) { if (msg.sender != address(_teller)) revert Auctioneer_NotAuthorized(); BondMarket storage market = markets[id_]; BondTerms memory term = terms[id_]; // If market uses a callback, check that owner is still callback authorized if (market.callbackAddr != address(0) && !callbackAuthorized[market.owner]) revert Auctioneer_NotAuthorized(); // Markets end at a defined timestamp uint48 currentTime = uint48(block.timestamp); if (currentTime >= term.conclusion) revert Auctioneer_MarketConcluded(term.conclusion); uint256 price; (price, payout) = _decayAndGetPrice(id_, amount_, uint48(block.timestamp)); // Debt and the control variable decay over time // Payout must be greater than user inputted minimum if (payout < minAmountOut_) revert Auctioneer_AmountLessThanMinimum(); // Markets have a max payout amount, capping size because deposits // do not experience slippage. max payout is recalculated upon tuning if (payout > market.maxPayout) revert Auctioneer_MaxPayoutExceeded(); // Update Capacity and Debt values // Capacity is either the number of payout tokens that the market can sell // (if capacity in quote is false), // // or the number of quote tokens that the market can buy // (if capacity in quote is true) // If amount/payout is greater than capacity remaining, revert if (market.capacityInQuote ? amount_ > market.capacity : payout > market.capacity) revert Auctioneer_NotEnoughCapacity(); // Capacity is decreased by the deposited or paid amount market.capacity -= market.capacityInQuote ? amount_ : payout; // Markets keep track of how many quote tokens have been // purchased, and how many payout tokens have been sold market.purchased += amount_; market.sold += payout; // Circuit breaker. If max debt is breached, the market is closed if (term.maxDebt < market.totalDebt) { _close(id_); } else { // If market will continue, the control variable is tuned to to expend remaining capacity over remaining market duration _tune(id_, currentTime, price); } } /* ========== INTERNAL DEPO FUNCTIONS ========== */ /// @notice Close a market /// @dev Closing a market sets capacity to 0 and immediately stops bonding function _close(uint256 id_) internal { terms[id_].conclusion = uint48(block.timestamp); markets[id_].capacity = 0; emit MarketClosed(id_); } /// @notice Decay debt, and adjust control variable if there is an active change /// @param id_ ID of market /// @param amount_ Amount of quote tokens being purchased /// @param time_ Current timestamp (saves gas when passed in) /// @return marketPrice_ Current market price of bond, accounting for decay /// @return payout_ Amount of payout tokens received at current price function _decayAndGetPrice( uint256 id_, uint256 amount_, uint48 time_ ) internal returns (uint256 marketPrice_, uint256 payout_) { BondMarket memory market = markets[id_]; // Debt is a time-decayed sum of tokens spent in a market // Debt is added when deposits occur and removed over time // | // | debt falls with // | / \ inactivity / \ // | / \ /\ / \ // | \ / \ / \ // | \ /\/ // | \ / and rises // | with deposits // | // |------------------------------------| t // Decay debt by the amount of time since the last decay uint256 decayedDebt = currentDebt(id_); markets[id_].totalDebt = decayedDebt; // Control variable decay // The bond control variable is continually tuned. When it is lowered (which // lowers the market price), the change is carried out smoothly over time. if (adjustments[id_].active) { Adjustment storage adjustment = adjustments[id_]; (uint256 adjustBy, uint48 secondsSince, bool stillActive) = _controlDecay(id_); terms[id_].controlVariable -= adjustBy; if (stillActive) { adjustment.change -= adjustBy; adjustment.timeToAdjusted -= secondsSince; adjustment.lastAdjustment = time_; } else { adjustment.active = false; } } // Price is not allowed to be lower than the minimum price marketPrice_ = _currentMarketPrice(id_); uint256 minPrice = market.minPrice; if (marketPrice_ < minPrice) marketPrice_ = minPrice; // Payout for the deposit = amount / price // // where: // payout = payout tokens out // amount = quote tokens in // price = quote tokens : payout token (i.e. 200 QUOTE : BASE), adjusted for scaling payout_ = amount_.mulDiv(market.scale, marketPrice_); // Cache storage variables to memory uint256 debtDecayInterval = uint256(metadata[id_].debtDecayInterval); uint256 lastTuneDebt = metadata[id_].lastTuneDebt; uint256 lastDecay = uint256(metadata[id_].lastDecay); // Set last decay timestamp based on size of purchase to linearize decay uint256 lastDecayIncrement = debtDecayInterval.mulDivUp(payout_, lastTuneDebt); metadata[id_].lastDecay += uint48(lastDecayIncrement); // Update total debt following the purchase // Goal is to have the same decayed debt post-purchase as pre-purchase so that price is the same as before purchase and then add new debt to increase price // 1. Adjust total debt so that decayed debt is equal to the current debt after updating the last decay timestamp. // This is the currentDebt function solved for totalDebt and adding lastDecayIncrement (the number of seconds lastDecay moves forward in time) // to the number of seconds used to calculate the previous currentDebt. // 2. Add the payout to the total debt to increase the price. uint256 decayOffset = time_ > lastDecay ? ( debtDecayInterval > (time_ - lastDecay) ? debtDecayInterval - (time_ - lastDecay) : 0 ) : debtDecayInterval + (lastDecay - time_); markets[id_].totalDebt = decayedDebt.mulDiv(debtDecayInterval, decayOffset + lastDecayIncrement) + payout_ + 1; // add 1 to satisfy price inequality } /// @notice Auto-adjust control variable to hit capacity/spend target /// @param id_ ID of market /// @param time_ Timestamp (saves gas when passed in) /// @param price_ Current price of the market function _tune( uint256 id_, uint48 time_, uint256 price_ ) internal { BondMetadata memory meta = metadata[id_]; BondMarket memory market = markets[id_]; // Market tunes in 2 situations: // 1. If capacity has exceeded target since last tune adjustment and the market is oversold // 2. If a tune interval has passed since last tune adjustment and the market is undersold // // Markets are created with a target capacity with the expectation that capacity will // be utilized evenly over the duration of the market. // The intuition with tuning is: // - When the market is ahead of target capacity, we should tune based on capacity. // - When the market is behind target capacity, we should tune based on time. // Compute seconds remaining until market will conclude uint256 timeRemaining = uint256(terms[id_].conclusion - time_); // Standardize capacity into an payout token amount uint256 capacity = market.capacityInQuote ? market.capacity.mulDiv(market.scale, price_) : market.capacity; // Calculate initial capacity based on remaining capacity and amount sold/purchased up to this point uint256 initialCapacity = capacity + (market.capacityInQuote ? market.purchased.mulDiv(market.scale, price_) : market.sold); // Calculate timeNeutralCapacity as the capacity expected to be sold up to this point and the current capacity // Higher than initial capacity means the market is undersold, lower than initial capacity means the market is oversold uint256 timeNeutralCapacity = initialCapacity.mulDiv( uint256(meta.length) - timeRemaining, uint256(meta.length) ) + capacity; if ( (market.capacity < meta.tuneBelowCapacity && timeNeutralCapacity < initialCapacity) || (time_ >= meta.lastTune + meta.tuneInterval && timeNeutralCapacity > initialCapacity) ) { // Calculate the correct payout to complete on time assuming each bond // will be max size in the desired deposit interval for the remaining time // // i.e. market has 10 days remaining. deposit interval is 1 day. capacity // is 10,000 TOKEN. max payout would be 1,000 TOKEN (10,000 * 1 / 10). markets[id_].maxPayout = capacity.mulDiv(uint256(meta.depositInterval), timeRemaining); // Calculate ideal target debt to satisty capacity in the remaining time // The target debt is based on whether the market is under or oversold at this point in time // This target debt will ensure price is reactive while ensuring the magnitude of being over/undersold // doesn't cause larger fluctuations towards the end of the market. // // Calculate target debt from the timeNeutralCapacity and the ratio of debt decay interval and the length of the market uint256 targetDebt = timeNeutralCapacity.mulDiv( uint256(meta.debtDecayInterval), uint256(meta.length) ); // Derive a new control variable from the target debt uint256 controlVariable = terms[id_].controlVariable; uint256 newControlVariable = price_.mulDivUp(market.scale, targetDebt); emit Tuned(id_, controlVariable, newControlVariable); if (newControlVariable < controlVariable) { // If decrease, control variable change will be carried out over the tune interval // this is because price will be lowered uint256 change = controlVariable - newControlVariable; adjustments[id_] = Adjustment(change, time_, meta.tuneAdjustmentDelay, true); } else { // Tune up immediately terms[id_].controlVariable = newControlVariable; // Set current adjustment to inactive (e.g. if we are re-tuning early) adjustments[id_].active = false; } metadata[id_].lastTune = time_; metadata[id_].tuneBelowCapacity = market.capacity > meta.tuneIntervalCapacity ? market.capacity - meta.tuneIntervalCapacity : 0; metadata[id_].lastTuneDebt = targetDebt; } } /* ========== INTERNAL VIEW FUNCTIONS ========== */ /// @notice Calculate current market price of payout token in quote tokens /// @dev See marketPrice() in IBondSDA for explanation of price computation /// @dev Uses info from storage because data has been updated before call (vs marketPrice()) /// @param id_ Market ID /// @return Price for market in payout token decimals function _currentMarketPrice(uint256 id_) internal view returns (uint256) { BondMarket memory market = markets[id_]; return terms[id_].controlVariable.mulDivUp(market.totalDebt, market.scale); } /// @notice Amount to decay control variable by /// @param id_ ID of market /// @return decay change in control variable /// @return secondsSince seconds since last change in control variable /// @return active whether or not change remains active function _controlDecay(uint256 id_) internal view returns ( uint256 decay, uint48 secondsSince, bool active ) { Adjustment memory info = adjustments[id_]; if (!info.active) return (0, 0, false); secondsSince = uint48(block.timestamp) - info.lastAdjustment; active = secondsSince < info.timeToAdjusted; decay = active ? info.change.mulDiv(uint256(secondsSince), uint256(info.timeToAdjusted)) : info.change; } /* ========== EXTERNAL VIEW FUNCTIONS ========== */ /// @inheritdoc IBondAuctioneer function getMarketInfoForPurchase(uint256 id_) external view returns ( address owner, address callbackAddr, ERC20 payoutToken, ERC20 quoteToken, uint48 vesting, uint256 maxPayout ) { BondMarket memory market = markets[id_]; return ( market.owner, market.callbackAddr, market.payoutToken, market.quoteToken, terms[id_].vesting, market.maxPayout ); } /// @inheritdoc IBondSDA function marketPrice(uint256 id_) public view override returns (uint256) { uint256 price = currentControlVariable(id_).mulDivUp(currentDebt(id_), markets[id_].scale); return (price > markets[id_].minPrice) ? price : markets[id_].minPrice; } /// @inheritdoc IBondAuctioneer function marketScale(uint256 id_) external view override returns (uint256) { return markets[id_].scale; } /// @inheritdoc IBondAuctioneer function payoutFor( uint256 amount_, uint256 id_, address referrer_ ) public view override returns (uint256) { // Calculate the payout for the given amount of tokens uint256 fee = amount_.mulDiv(_teller.getFee(referrer_), 1e5); uint256 payout = (amount_ - fee).mulDiv(markets[id_].scale, marketPrice(id_)); // Check that the payout is less than or equal to the maximum payout, // Revert if not, otherwise return the payout if (payout > markets[id_].maxPayout) { revert Auctioneer_MaxPayoutExceeded(); } else { return payout; } } /// @inheritdoc IBondAuctioneer function maxAmountAccepted(uint256 id_, address referrer_) external view returns (uint256) { // Calculate maximum amount of quote tokens that correspond to max bond size // Maximum of the maxPayout and the remaining capacity converted to quote tokens BondMarket memory market = markets[id_]; uint256 price = marketPrice(id_); uint256 quoteCapacity = market.capacityInQuote ? market.capacity : market.capacity.mulDiv(price, market.scale); uint256 maxQuote = market.maxPayout.mulDiv(price, market.scale); uint256 amountAccepted = quoteCapacity < maxQuote ? quoteCapacity : maxQuote; // Take into account teller fees and return // Estimate fee based on amountAccepted. Fee taken will be slightly larger than // this given it will be taken off the larger amount, but this avoids rounding // errors with trying to calculate the exact amount. // Therefore, the maxAmountAccepted is slightly conservative. uint256 estimatedFee = amountAccepted.mulDiv(_teller.getFee(referrer_), 1e5); return amountAccepted + estimatedFee; } /// @inheritdoc IBondSDA function currentDebt(uint256 id_) public view override returns (uint256) { BondMetadata memory meta = metadata[id_]; uint256 lastDecay = uint256(meta.lastDecay); uint256 currentTime = block.timestamp; // Determine if decay should increase or decrease debt based on last decay time // If last decay time is in the future, then debt should be increased // If last decay time is in the past, then debt should be decreased if (lastDecay > currentTime) { uint256 secondsUntil; unchecked { secondsUntil = lastDecay - currentTime; } return markets[id_].totalDebt.mulDiv( uint256(meta.debtDecayInterval) + secondsUntil, uint256(meta.debtDecayInterval) ); } else { uint256 secondsSince; unchecked { secondsSince = currentTime - lastDecay; } return secondsSince > meta.debtDecayInterval ? 0 : markets[id_].totalDebt.mulDiv( uint256(meta.debtDecayInterval) - secondsSince, uint256(meta.debtDecayInterval) ); } } /// @inheritdoc IBondSDA function currentControlVariable(uint256 id_) public view override returns (uint256) { (uint256 decay, , ) = _controlDecay(id_); return terms[id_].controlVariable - decay; } /// @inheritdoc IBondAuctioneer function isInstantSwap(uint256 id_) public view returns (bool) { uint256 vesting = terms[id_].vesting; return (vesting <= MAX_FIXED_TERM) ? vesting == 0 : vesting <= block.timestamp; } /// @inheritdoc IBondAuctioneer function isLive(uint256 id_) public view override returns (bool) { return (markets[id_].capacity != 0 && terms[id_].conclusion > block.timestamp); } /// @inheritdoc IBondAuctioneer function ownerOf(uint256 id_) external view override returns (address) { return markets[id_].owner; } /// @inheritdoc IBondAuctioneer function getTeller() external view override returns (IBondTeller) { return _teller; } /// @inheritdoc IBondAuctioneer function getAggregator() external view override returns (IBondAggregator) { return _aggregator; } /// @inheritdoc IBondAuctioneer function currentCapacity(uint256 id_) external view override returns (uint256) { return markets[id_].capacity; } }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity >=0.8.0; import {ERC20} from "solmate/tokens/ERC20.sol"; import {IBondAuctioneer} from "../interfaces/IBondAuctioneer.sol"; import {IBondTeller} from "../interfaces/IBondTeller.sol"; interface IBondAggregator { /// @notice Register a auctioneer with the aggregator /// @notice Only Guardian /// @param auctioneer_ Address of the Auctioneer to register /// @dev A auctioneer must be registered with an aggregator to create markets function registerAuctioneer(IBondAuctioneer auctioneer_) external; /// @notice Register a new market with the aggregator /// @notice Only registered depositories /// @param payoutToken_ Token to be paid out by the market /// @param quoteToken_ Token to be accepted by the market /// @param marketId ID of the market being created function registerMarket(ERC20 payoutToken_, ERC20 quoteToken_) external returns (uint256 marketId); /// @notice Get the auctioneer for the provided market ID /// @param id_ ID of Market function getAuctioneer(uint256 id_) external view returns (IBondAuctioneer); /// @notice Calculate current market price of payout token in quote tokens /// @dev Accounts for debt and control variable decay since last deposit (vs _marketPrice()) /// @param id_ ID of market /// @return Price for market (see the specific auctioneer for units) // // if price is below minimum price, minimum price is returned // this is enforced on deposits by manipulating total debt (see _decay()) function marketPrice(uint256 id_) external view returns (uint256); /// @notice Scale value to use when converting between quote token and payout token amounts with marketPrice() /// @param id_ ID of market /// @return Scaling factor for market in configured decimals function marketScale(uint256 id_) external view returns (uint256); /// @notice Payout due for amount of quote tokens /// @dev Accounts for debt and control variable decay so it is up to date /// @param amount_ Amount of quote tokens to spend /// @param id_ ID of market /// @param referrer_ Address of referrer, used to get fees to calculate accurate payout amount. /// Inputting the zero address will take into account just the protocol fee. /// @return amount of payout tokens to be paid function payoutFor( uint256 amount_, uint256 id_, address referrer_ ) external view returns (uint256); /// @notice Returns maximum amount of quote token accepted by the market /// @param id_ ID of market /// @param referrer_ Address of referrer, used to get fees to calculate accurate payout amount. /// Inputting the zero address will take into account just the protocol fee. function maxAmountAccepted(uint256 id_, address referrer_) external view returns (uint256); /// @notice Does market send payout immediately /// @param id_ Market ID to search for function isInstantSwap(uint256 id_) external view returns (bool); /// @notice Is a given market accepting deposits /// @param id_ ID of market function isLive(uint256 id_) external view returns (bool); /// @notice Returns array of active market IDs within a range /// @dev Should be used if length exceeds max to query entire array function liveMarketsBetween(uint256 firstIndex_, uint256 lastIndex_) external view returns (uint256[] memory); /// @notice Returns an array of all active market IDs for a given quote token /// @param token_ Address of token to query by /// @param isPayout_ If true, search by payout token, else search for quote token function liveMarketsFor(address token_, bool isPayout_) external view returns (uint256[] memory); /// @notice Returns an array of all active market IDs for a given owner /// @param owner_ Address of owner to query by /// @param firstIndex_ Market ID to start at /// @param lastIndex_ Market ID to end at (non-inclusive) function liveMarketsBy( address owner_, uint256 firstIndex_, uint256 lastIndex_ ) external view returns (uint256[] memory); /// @notice Returns an array of all active market IDs for a given payout and quote token /// @param payout_ Address of payout token /// @param quote_ Address of quote token function marketsFor(address payout_, address quote_) external view returns (uint256[] memory); /// @notice Returns the market ID with the highest current payoutToken payout for depositing quoteToken /// @param payout_ Address of payout token /// @param quote_ Address of quote token /// @param amountIn_ Amount of quote tokens to deposit /// @param minAmountOut_ Minimum amount of payout tokens to receive as payout /// @param maxExpiry_ Latest acceptable vesting timestamp for bond /// Inputting the zero address will take into account just the protocol fee. function findMarketFor( address payout_, address quote_, uint256 amountIn_, uint256 minAmountOut_, uint256 maxExpiry_ ) external view returns (uint256 id); /// @notice Returns the Teller that services the market ID function getTeller(uint256 id_) external view returns (IBondTeller); /// @notice Returns current capacity of a market function currentCapacity(uint256 id_) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity >=0.8.0; import {ERC20} from "solmate/tokens/ERC20.sol"; import {IBondTeller} from "../interfaces/IBondTeller.sol"; import {IBondAggregator} from "../interfaces/IBondAggregator.sol"; interface IBondAuctioneer { /// @notice Creates a new bond market /// @param params_ Configuration data needed for market creation, encoded in a bytes array /// @dev See specific auctioneer implementations for details on encoding the parameters. /// @return id ID of new bond market function createMarket(bytes memory params_) external returns (uint256); /// @notice Disable existing bond market /// @notice Must be market owner /// @param id_ ID of market to close function closeMarket(uint256 id_) external; /// @notice Exchange quote tokens for a bond in a specified market /// @notice Must be teller /// @param id_ ID of the Market the bond is being purchased from /// @param amount_ Amount to deposit in exchange for bond (after fee has been deducted) /// @param minAmountOut_ Minimum acceptable amount of bond to receive. Prevents frontrunning /// @return payout Amount of payout token to be received from the bond function purchaseBond( uint256 id_, uint256 amount_, uint256 minAmountOut_ ) external returns (uint256 payout); /// @notice Set market intervals to different values than the defaults /// @notice Must be market owner /// @dev Changing the intervals could cause markets to behave in unexpected way /// tuneInterval should be greater than tuneAdjustmentDelay /// @param id_ Market ID /// @param intervals_ Array of intervals (3) /// 1. Tune interval - Frequency of tuning /// 2. Tune adjustment delay - Time to implement downward tuning adjustments /// 3. Debt decay interval - Interval over which debt should decay completely function setIntervals(uint256 id_, uint32[3] calldata intervals_) external; /// @notice Designate a new owner of a market /// @notice Must be market owner /// @dev Doesn't change permissions until newOwner calls pullOwnership /// @param id_ Market ID /// @param newOwner_ New address to give ownership to function pushOwnership(uint256 id_, address newOwner_) external; /// @notice Accept ownership of a market /// @notice Must be market newOwner /// @dev The existing owner must call pushOwnership prior to the newOwner calling this function /// @param id_ Market ID function pullOwnership(uint256 id_) external; /// @notice Set the auctioneer defaults /// @notice Must be policy /// @param defaults_ Array of default values /// 1. Tune interval - amount of time between tuning adjustments /// 2. Tune adjustment delay - amount of time to apply downward tuning adjustments /// 3. Minimum debt decay interval - minimum amount of time to let debt decay to zero /// 4. Minimum deposit interval - minimum amount of time to wait between deposits /// 5. Minimum market duration - minimum amount of time a market can be created for /// 6. Minimum debt buffer - the minimum amount of debt over the initial debt to trigger a market shutdown /// @dev The defaults set here are important to avoid edge cases in market behavior, e.g. a very short market reacts doesn't tune well /// @dev Only applies to new markets that are created after the change function setDefaults(uint32[6] memory defaults_) external; /// @notice Change the status of the auctioneer to allow creation of new markets /// @dev Setting to false and allowing active markets to end will sunset the auctioneer /// @param status_ Allow market creation (true) : Disallow market creation (false) function setAllowNewMarkets(bool status_) external; /// @notice Change whether a market creator is allowed to use a callback address in their markets or not /// @notice Must be guardian /// @dev Callback is believed to be safe, but a whitelist is implemented to prevent abuse /// @param creator_ Address of market creator /// @param status_ Allow callback (true) : Disallow callback (false) function setCallbackAuthStatus(address creator_, bool status_) external; /* ========== VIEW FUNCTIONS ========== */ /// @notice Provides information for the Teller to execute purchases on a Market /// @param id_ Market ID /// @return owner Address of the market owner (tokens transferred from this address if no callback) /// @return callbackAddr Address of the callback contract to get tokens for payouts /// @return payoutToken Payout Token (token paid out) for the Market /// @return quoteToken Quote Token (token received) for the Market /// @return vesting Timestamp or duration for vesting, implementation-dependent /// @return maxPayout Maximum amount of payout tokens you can purchase in one transaction function getMarketInfoForPurchase(uint256 id_) external view returns ( address owner, address callbackAddr, ERC20 payoutToken, ERC20 quoteToken, uint48 vesting, uint256 maxPayout ); /// @notice Calculate current market price of payout token in quote tokens /// @param id_ ID of market /// @return Price for market in configured decimals // // if price is below minimum price, minimum price is returned function marketPrice(uint256 id_) external view returns (uint256); /// @notice Scale value to use when converting between quote token and payout token amounts with marketPrice() /// @param id_ ID of market /// @return Scaling factor for market in configured decimals function marketScale(uint256 id_) external view returns (uint256); /// @notice Payout due for amount of quote tokens /// @dev Accounts for debt and control variable decay so it is up to date /// @param amount_ Amount of quote tokens to spend /// @param id_ ID of market /// @param referrer_ Address of referrer, used to get fees to calculate accurate payout amount. /// Inputting the zero address will take into account just the protocol fee. /// @return amount of payout tokens to be paid function payoutFor( uint256 amount_, uint256 id_, address referrer_ ) external view returns (uint256); /// @notice Returns maximum amount of quote token accepted by the market /// @param id_ ID of market /// @param referrer_ Address of referrer, used to get fees to calculate accurate payout amount. /// Inputting the zero address will take into account just the protocol fee. function maxAmountAccepted(uint256 id_, address referrer_) external view returns (uint256); /// @notice Does market send payout immediately /// @param id_ Market ID to search for function isInstantSwap(uint256 id_) external view returns (bool); /// @notice Is a given market accepting deposits /// @param id_ ID of market function isLive(uint256 id_) external view returns (bool); /// @notice Returns the address of the market owner /// @param id_ ID of market function ownerOf(uint256 id_) external view returns (address); /// @notice Returns the Teller that services the Auctioneer function getTeller() external view returns (IBondTeller); /// @notice Returns the Aggregator that services the Auctioneer function getAggregator() external view returns (IBondAggregator); /// @notice Returns current capacity of a market function currentCapacity(uint256 id_) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity >=0.8.0; import {ERC20} from "solmate/tokens/ERC20.sol"; interface IBondCallback { /// @notice Send payout tokens to Teller while allowing market owners to perform custom logic on received or paid out tokens /// @notice Market ID on Teller must be whitelisted /// @param id_ ID of the market /// @param inputAmount_ Amount of quote tokens bonded to the market /// @param outputAmount_ Amount of payout tokens to be paid out to the market /// @dev Must transfer the output amount of payout tokens back to the Teller /// @dev Should check that the quote tokens have been transferred to the contract in the _callback function function callback( uint256 id_, uint256 inputAmount_, uint256 outputAmount_ ) external; /// @notice Returns the number of quote tokens received and payout tokens paid out for a market /// @param id_ ID of the market /// @return in_ Amount of quote tokens bonded to the market /// @return out_ Amount of payout tokens paid out to the market function amountsForMarket(uint256 id_) external view returns (uint256 in_, uint256 out_); /// @notice Whitelist a teller and market ID combination /// @notice Must be callback owner /// @param teller_ Address of the Teller contract which serves the market /// @param id_ ID of the market function whitelist(address teller_, uint256 id_) external; /// @notice Remove a market ID on a teller from the whitelist /// @dev Shutdown function in case there's an issue with the teller /// @param teller_ Address of the Teller contract which serves the market /// @param id_ ID of the market to remove from whitelist function blacklist(address teller_, uint256 id_) external; /// @notice Withdraw tokens from the callback and update balances /// @notice Only callback owner /// @param to_ Address of the recipient /// @param token_ Address of the token to withdraw /// @param amount_ Amount of tokens to withdraw function withdraw( address to_, ERC20 token_, uint256 amount_ ) external; /// @notice Deposit tokens to the callback and update balances /// @notice Only callback owner /// @param token_ Address of the token to deposit /// @param amount_ Amount of tokens to deposit function deposit(ERC20 token_, uint256 amount_) external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity >=0.8.0; import {ERC20} from "solmate/tokens/ERC20.sol"; import {IBondAuctioneer} from "../interfaces/IBondAuctioneer.sol"; interface IBondSDA is IBondAuctioneer { /// @notice Main information pertaining to bond market struct BondMarket { address owner; // market owner. sends payout tokens, receives quote tokens (defaults to creator) ERC20 payoutToken; // token to pay depositors with ERC20 quoteToken; // token to accept as payment address callbackAddr; // address to call for any operations on bond purchase. Must inherit to IBondCallback. bool capacityInQuote; // capacity limit is in payment token (true) or in payout (false, default) uint256 capacity; // capacity remaining uint256 totalDebt; // total payout token debt from market uint256 minPrice; // minimum price (hard floor for the market) uint256 maxPayout; // max payout tokens out in one order uint256 sold; // payout tokens out uint256 purchased; // quote tokens in uint256 scale; // scaling factor for the market (see MarketParams struct) } /// @notice Information used to control how a bond market changes struct BondTerms { uint256 controlVariable; // scaling variable for price uint256 maxDebt; // max payout token debt accrued uint48 vesting; // length of time from deposit to expiry if fixed-term, vesting timestamp if fixed-expiry uint48 conclusion; // timestamp when market no longer offered } /// @notice Data needed for tuning bond market /// @dev Durations are stored in uint32 (not int32) and timestamps are stored in uint48, so is not subject to Y2K38 overflow struct BondMetadata { uint48 lastTune; // last timestamp when control variable was tuned uint48 lastDecay; // last timestamp when market was created and debt was decayed uint32 length; // time from creation to conclusion. uint32 depositInterval; // target frequency of deposits uint32 tuneInterval; // frequency of tuning uint32 tuneAdjustmentDelay; // time to implement downward tuning adjustments uint32 debtDecayInterval; // interval over which debt should decay completely uint256 tuneIntervalCapacity; // capacity expected to be used during a tuning interval uint256 tuneBelowCapacity; // capacity that the next tuning will occur at uint256 lastTuneDebt; // target debt calculated at last tuning } /// @notice Control variable adjustment data struct Adjustment { uint256 change; uint48 lastAdjustment; uint48 timeToAdjusted; // how long until adjustment happens bool active; } /// @notice Parameters to create a new bond market /// @dev Note price should be passed in a specific format: /// formatted price = (payoutPriceCoefficient / quotePriceCoefficient) /// * 10**(36 + scaleAdjustment + quoteDecimals - payoutDecimals + payoutPriceDecimals - quotePriceDecimals) /// where: /// payoutDecimals - Number of decimals defined for the payoutToken in its ERC20 contract /// quoteDecimals - Number of decimals defined for the quoteToken in its ERC20 contract /// payoutPriceCoefficient - The coefficient of the payoutToken price in scientific notation (also known as the significant digits) /// payoutPriceDecimals - The significand of the payoutToken price in scientific notation (also known as the base ten exponent) /// quotePriceCoefficient - The coefficient of the quoteToken price in scientific notation (also known as the significant digits) /// quotePriceDecimals - The significand of the quoteToken price in scientific notation (also known as the base ten exponent) /// scaleAdjustment - see below /// * In the above definitions, the "prices" need to have the same unit of account (i.e. both in OHM, $, ETH, etc.) /// If price is not provided in this format, the market will not behave as intended. /// @param params_ Encoded bytes array, with the following elements /// @dev 0. Payout Token (token paid out) /// @dev 1. Quote Token (token to be received) /// @dev 2. Callback contract address, should conform to IBondCallback. If 0x00, tokens will be transferred from market.owner /// @dev 3. Is Capacity in Quote Token? /// @dev 4. Capacity (amount in quoteDecimals or amount in payoutDecimals) /// @dev 5. Formatted initial price (see note above) /// @dev 6. Formatted minimum price (see note above) /// @dev 7. Debt buffer. Percent with 3 decimals. Percentage over the initial debt to allow the market to accumulate at anyone time. /// @dev Works as a circuit breaker for the market in case external conditions incentivize massive buying (e.g. stablecoin depeg). /// @dev Minimum is the greater of 10% or initial max payout as a percentage of capacity. /// @dev If the value is too small, the market will not be able function normally and close prematurely. /// @dev If the value is too large, the market will not circuit break when intended. The value must be > 10% but can exceed 100% if desired. /// @dev A good heuristic to calculate a debtBuffer with is to determine the amount of capacity that you think is reasonable to be expended /// @dev in a short duration as a percent, e.g. 25%. Then a reasonable debtBuffer would be: 0.25 * 1e3 * decayInterval / marketDuration /// @dev where decayInterval = max(3 days, 5 * depositInterval) and marketDuration = conclusion - creation time. /// @dev 8. Is fixed term ? Vesting length (seconds) : Vesting expiry (timestamp). /// @dev A 'vesting' param longer than 50 years is considered a timestamp for fixed expiry. /// @dev 9. Conclusion (timestamp) /// @dev 10. Deposit interval (seconds) /// @dev 11. Market scaling factor adjustment, ranges from -24 to +24 within the configured market bounds. /// @dev Should be calculated as: (payoutDecimals - quoteDecimals) - ((payoutPriceDecimals - quotePriceDecimals) / 2) /// @dev Providing a scaling factor adjustment that doesn't follow this formula could lead to under or overflow errors in the market. /// @return ID of new bond market struct MarketParams { ERC20 payoutToken; ERC20 quoteToken; address callbackAddr; bool capacityInQuote; uint256 capacity; uint256 formattedInitialPrice; uint256 formattedMinimumPrice; uint32 debtBuffer; uint48 vesting; uint48 conclusion; uint32 depositInterval; int8 scaleAdjustment; } /* ========== VIEW FUNCTIONS ========== */ /// @notice Calculate current market price of payout token in quote tokens /// @dev Accounts for debt and control variable decay since last deposit (vs _marketPrice()) /// @param id_ ID of market /// @return Price for market in configured decimals (see MarketParams) // // price is derived from the equation // // p = c * d // // where // p = price // c = control variable // d = debt // // d -= ( d * (dt / l) ) // // where // dt = change in time // l = length of program // // if price is below minimum price, minimum price is returned // this is enforced on deposits by manipulating total debt (see _decay()) function marketPrice(uint256 id_) external view override returns (uint256); /// @notice Calculate debt factoring in decay /// @dev Accounts for debt decay since last deposit /// @param id_ ID of market /// @return Current debt for market in payout token decimals function currentDebt(uint256 id_) external view returns (uint256); /// @notice Up to date control variable /// @dev Accounts for control variable adjustment /// @param id_ ID of market /// @return Control variable for market in payout token decimals function currentControlVariable(uint256 id_) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity >=0.8.0; import {ERC20} from "solmate/tokens/ERC20.sol"; interface IBondTeller { /// @notice Exchange quote tokens for a bond in a specified market /// @param recipient_ Address of recipient of bond. Allows deposits for other addresses /// @param referrer_ Address of referrer who will receive referral fee. For frontends to fill. /// Direct calls can use the zero address for no referrer fee. /// @param id_ ID of the Market the bond is being purchased from /// @param amount_ Amount to deposit in exchange for bond /// @param minAmountOut_ Minimum acceptable amount of bond to receive. Prevents frontrunning /// @return Amount of payout token to be received from the bond /// @return Timestamp at which the bond token can be redeemed for the underlying token function purchase( address recipient_, address referrer_, uint256 id_, uint256 amount_, uint256 minAmountOut_ ) external returns (uint256, uint48); /// @notice Get current fee charged by the teller based on the combined protocol and referrer fee /// @param referrer_ Address of the referrer /// @return Fee in basis points (3 decimal places) function getFee(address referrer_) external view returns (uint48); /// @notice Set protocol fee /// @notice Must be guardian /// @param fee_ Protocol fee in basis points (3 decimal places) function setProtocolFee(uint48 fee_) external; /// @notice Set the discount for creating bond tokens from the base protocol fee /// @dev The discount is subtracted from the protocol fee to determine the fee /// when using create() to mint bond tokens without using an Auctioneer /// @param discount_ Create Fee Discount in basis points (3 decimal places) function setCreateFeeDiscount(uint48 discount_) external; /// @notice Set your fee as a referrer to the protocol /// @notice Fee is set for sending address /// @param fee_ Referrer fee in basis points (3 decimal places) function setReferrerFee(uint48 fee_) external; /// @notice Claim fees accrued by sender in the input tokens and sends them to the provided address /// @param tokens_ Array of tokens to claim fees for /// @param to_ Address to send fees to function claimFees(ERC20[] memory tokens_, address to_) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = (type(uint256).max - denominator + 1) & denominator; // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the precoditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivUp( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { result = mulDiv(a, b, denominator); unchecked { if (mulmod(a, b, denominator) > 0) { require(result < type(uint256).max); result++; } } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "solmate/tokens/ERC20.sol"; /// @notice Safe ERC20 and ETH transfer library that safely handles missing return values. /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/libraries/TransferHelper.sol) /// @author Taken from Solmate. library TransferHelper { function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { (bool success, bytes memory data) = address(token).call( abi.encodeWithSelector(ERC20.transferFrom.selector, from, to, amount) ); require( success && (data.length == 0 || abi.decode(data, (bool))) && address(token).code.length > 0, "TRANSFER_FROM_FAILED" ); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { (bool success, bytes memory data) = address(token).call( abi.encodeWithSelector(ERC20.transfer.selector, to, amount) ); require( success && (data.length == 0 || abi.decode(data, (bool))) && address(token).code.length > 0, "TRANSFER_FAILED" ); } // function safeApprove( // ERC20 token, // address to, // uint256 amount // ) internal { // (bool success, bytes memory data) = address(token).call( // abi.encodeWithSelector(ERC20.approve.selector, to, amount) // ); // require(success && (data.length == 0 || abi.decode(data, (bool))), "APPROVE_FAILED"); // } // function safeTransferETH(address to, uint256 amount) internal { // (bool success, ) = to.call{value: amount}(new bytes(0)); // require(success, "ETH_TRANSFER_FAILED"); // } }
{ "remappings": [ "clones-with-immutable-args/=lib/clones-with-immutable-args/src/", "clones/=lib/clones-with-immutable-args/src/", "ds-test/=lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "hardhat/=node_modules/hardhat/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "solidity-code-metrics/=node_modules/solidity-code-metrics/", "solmate/=lib/solmate/src/", "weird-erc20/=lib/solmate/lib/weird-erc20/src/" ], "optimizer": { "enabled": true, "runs": 100000 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
[{"inputs":[{"internalType":"contract IBondTeller","name":"teller_","type":"address"},{"internalType":"contract IBondAggregator","name":"aggregator_","type":"address"},{"internalType":"address","name":"guardian_","type":"address"},{"internalType":"contract Authority","name":"authority_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Auctioneer_AmountLessThanMinimum","type":"error"},{"inputs":[],"name":"Auctioneer_BadExpiry","type":"error"},{"inputs":[],"name":"Auctioneer_InitialPriceLessThanMin","type":"error"},{"inputs":[],"name":"Auctioneer_InvalidCallback","type":"error"},{"inputs":[],"name":"Auctioneer_InvalidParams","type":"error"},{"inputs":[{"internalType":"uint256","name":"conclusion_","type":"uint256"}],"name":"Auctioneer_MarketConcluded","type":"error"},{"inputs":[],"name":"Auctioneer_MaxPayoutExceeded","type":"error"},{"inputs":[],"name":"Auctioneer_NewMarketsNotAllowed","type":"error"},{"inputs":[],"name":"Auctioneer_NotAuthorized","type":"error"},{"inputs":[],"name":"Auctioneer_NotEnoughCapacity","type":"error"},{"inputs":[],"name":"Auctioneer_OnlyMarketOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"defaultTuneInterval","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"defaultTuneAdjustment","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"minDebtDecayInterval","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"minDepositInterval","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"minMarketDuration","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"minDebtBuffer","type":"uint32"}],"name":"DefaultsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"MarketClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"payoutToken","type":"address"},{"indexed":true,"internalType":"address","name":"quoteToken","type":"address"},{"indexed":false,"internalType":"uint48","name":"vesting","type":"uint48"},{"indexed":false,"internalType":"uint256","name":"initialPrice","type":"uint256"}],"name":"MarketCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldControlVariable","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newControlVariable","type":"uint256"}],"name":"Tuned","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"adjustments","outputs":[{"internalType":"uint256","name":"change","type":"uint256"},{"internalType":"uint48","name":"lastAdjustment","type":"uint48"},{"internalType":"uint48","name":"timeToAdjusted","type":"uint48"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowNewMarkets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"callbackAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"closeMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"params_","type":"bytes"}],"name":"createMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"currentCapacity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"currentControlVariable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"currentDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultTuneAdjustment","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultTuneInterval","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAggregator","outputs":[{"internalType":"contract IBondAggregator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"getMarketInfoForPurchase","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"callbackAddr","type":"address"},{"internalType":"contract ERC20","name":"payoutToken","type":"address"},{"internalType":"contract ERC20","name":"quoteToken","type":"address"},{"internalType":"uint48","name":"vesting","type":"uint48"},{"internalType":"uint256","name":"maxPayout","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTeller","outputs":[{"internalType":"contract IBondTeller","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"isInstantSwap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"isLive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"marketPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"marketScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"markets","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"contract ERC20","name":"payoutToken","type":"address"},{"internalType":"contract ERC20","name":"quoteToken","type":"address"},{"internalType":"address","name":"callbackAddr","type":"address"},{"internalType":"bool","name":"capacityInQuote","type":"bool"},{"internalType":"uint256","name":"capacity","type":"uint256"},{"internalType":"uint256","name":"totalDebt","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"uint256","name":"maxPayout","type":"uint256"},{"internalType":"uint256","name":"sold","type":"uint256"},{"internalType":"uint256","name":"purchased","type":"uint256"},{"internalType":"uint256","name":"scale","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"address","name":"referrer_","type":"address"}],"name":"maxAmountAccepted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"metadata","outputs":[{"internalType":"uint48","name":"lastTune","type":"uint48"},{"internalType":"uint48","name":"lastDecay","type":"uint48"},{"internalType":"uint32","name":"length","type":"uint32"},{"internalType":"uint32","name":"depositInterval","type":"uint32"},{"internalType":"uint32","name":"tuneInterval","type":"uint32"},{"internalType":"uint32","name":"tuneAdjustmentDelay","type":"uint32"},{"internalType":"uint32","name":"debtDecayInterval","type":"uint32"},{"internalType":"uint256","name":"tuneIntervalCapacity","type":"uint256"},{"internalType":"uint256","name":"tuneBelowCapacity","type":"uint256"},{"internalType":"uint256","name":"lastTuneDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDebtBuffer","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDebtDecayInterval","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDepositInterval","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minMarketDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"newOwners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"address","name":"referrer_","type":"address"}],"name":"payoutFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"pullOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"minAmountOut_","type":"uint256"}],"name":"purchaseBond","outputs":[{"internalType":"uint256","name":"payout","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"address","name":"newOwner_","type":"address"}],"name":"pushOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"status_","type":"bool"}],"name":"setAllowNewMarkets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creator_","type":"address"},{"internalType":"bool","name":"status_","type":"bool"}],"name":"setCallbackAuthStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[6]","name":"defaults_","type":"uint32[6]"}],"name":"setDefaults","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"uint32[3]","name":"intervals_","type":"uint32[3]"}],"name":"setIntervals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"terms","outputs":[{"internalType":"uint256","name":"controlVariable","type":"uint256"},{"internalType":"uint256","name":"maxDebt","type":"uint256"},{"internalType":"uint48","name":"vesting","type":"uint48"},{"internalType":"uint48","name":"conclusion","type":"uint48"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b50604051620047e3380380620047e383398101604081905262000034916200013d565b600080546001600160a01b03199081166001600160a01b0385811691821784556001805490931690851617909155604051869286928692869284928492909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a36040516001600160a01b0382169033907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a3505050506001600160a01b039081166080521660a0525050600980546001600160c01b0319167527100001518000000e100003f48000000e100001518017905550506007805460ff19166001179055620001a5565b6001600160a01b03811681146200013a57600080fd5b50565b600080600080608085870312156200015457600080fd5b8451620001618162000124565b6020860151909450620001748162000124565b6040860151909350620001878162000124565b60608601519092506200019a8162000124565b939692955090935050565b60805160a0516145fc620001e76000396000818161051001528181611d7e0152818161201001526120c301526000818161034801526129a401526145fc6000f3fe608060405234801561001057600080fd5b50600436106102ad5760003560e01c8063acc5570c1161017b578063bf7e214f116100d8578063d9ccdc931161008c578063e3684e3911610071578063e3684e39146109af578063e922067314610aed578063ea0aca3314610b0957600080fd5b8063d9ccdc931461098c578063e007fa971461099c57600080fd5b8063c7bf8ca0116100bd578063c7bf8ca014610935578063d204068714610948578063d2bee3231461096857600080fd5b8063bf7e214f146108a2578063c0aa0e8a146108c257600080fd5b8063bc3b2b121161012f578063bcf6cde811610114578063bcf6cde814610869578063bd1f3a5e1461087c578063bf48582b1461088f57600080fd5b8063bc3b2b12146107d2578063bcb296671461085657600080fd5b8063afa9d3b011610160578063afa9d3b0146106a1578063b1283e77146106ae578063bbbdd95a146107bf57600080fd5b8063acc5570c14610534578063ae4180951461068e57600080fd5b80635f77274e116102295780638973082c116101dd5780638da5cb5b116101c25780638da5cb5b146104cb578063946824cd146104eb5780639787d1071461050e57600080fd5b80638973082c1461047b5780638b098db3146104b857600080fd5b80636729a41e1161020e5780636729a41e1461041f578063699e17d9146104555780637a9e5e4b1461046857600080fd5b80635f77274e146103d65780636352211e146103e957600080fd5b806327507458116102805780633adec5a7116102655780633adec5a71461038d57806353c7f8e0146103a05780635dc4d16b146103b357600080fd5b806327507458146103235780633ad59dbc1461034657600080fd5b80630a9d85eb146102b257806310b05317146102d857806313af4035146102ed5780631c063a6c14610300575b600080fd5b6102c56102c036600461402b565b610b21565b6040519081526020015b60405180910390f35b6102eb6102e636600461402b565b610b53565b005b6102eb6102fb366004614076565b610c0e565b6102c561030e36600461402b565b60009081526002602052604090206004015490565b61033661033136600461402b565b610d17565b60405190151581526020016102cf565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102cf565b6102c561039b36600461402b565b610d60565b6102c56103ae366004614093565b610dc3565b6103366103c1366004614076565b60086020526000908152604090205460ff1681565b6102eb6103e436600461411e565b610e6b565b6103686103f736600461402b565b60009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b61036861042d36600461402b565b60066020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6102eb61046336600461413b565b610f30565b6102eb610476366004614076565b6113d7565b6009546104a39074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102cf565b6103366104c636600461402b565b611534565b6000546103689073ffffffffffffffffffffffffffffffffffffffff1681565b6102c56104f936600461402b565b6000908152600260205260409020600a015490565b7f0000000000000000000000000000000000000000000000000000000000000000610368565b61063861054236600461402b565b6000818152600260208181526040808420815161018081018352815473ffffffffffffffffffffffffffffffffffffffff90811680835260018401548216838701819052848801548316848701819052600380870154948516606087018190527401000000000000000000000000000000000000000090950460ff1615156080870152600487015460a0870152600587015460c0870152600687015460e08701526007870154610100870190815260088801546101208801526009880154610140880152600a90970154610160909601959095529989529290955292909520909301549251919590949265ffffffffffff169190565b6040805173ffffffffffffffffffffffffffffffffffffffff97881681529587166020870152938616938501939093529316606083015265ffffffffffff909216608082015260a081019190915260c0016102cf565b6102eb61069c36600461402b565b61156a565b6007546103369060ff1681565b6107456106bc36600461402b565b600260208190526000918252604090912080546001820154928201546003830154600484015460058501546006860154600787015460088801546009890154600a9099015473ffffffffffffffffffffffffffffffffffffffff9889169a891699978916988716977401000000000000000000000000000000000000000090970460ff1696908c565b6040805173ffffffffffffffffffffffffffffffffffffffff9d8e1681529b8d1660208d0152998c16998b0199909952999096166060890152931515608088015260a087019290925260c086015260e0850152610100840152610120830152610140820192909252610160810191909152610180016102cf565b6102eb6107cd36600461416e565b6115d3565b6108256107e036600461402b565b6005602052600090815260409020805460019091015465ffffffffffff8082169166010000000000008104909116906c01000000000000000000000000900460ff1684565b6040516102cf949392919093845265ffffffffffff9283166020850152911660408301521515606082015260800190565b6102c561086436600461402b565b6116bd565b6102eb6108773660046141a7565b611851565b6102eb61088a366004614239565b611901565b6102c561089d3660046142be565b611d30565b6001546103689073ffffffffffffffffffffffffffffffffffffffff1681565b6109076108d036600461402b565b60036020526000908152604090208054600182015460029092015490919065ffffffffffff80821691660100000000000090041684565b60408051948552602085019390935265ffffffffffff918216928401929092521660608201526080016102cf565b6102c56109433660046141a7565b611e89565b6009546104a3906c01000000000000000000000000900463ffffffff1681565b6009546104a390700100000000000000000000000000000000900463ffffffff1681565b6009546104a39063ffffffff1681565b6102c56109aa3660046142f7565b6120a9565b610a876109bd36600461402b565b600460205260009081526040902080546001820154600283015460039093015465ffffffffffff80841694660100000000000085049091169363ffffffff6c0100000000000000000000000082048116947001000000000000000000000000000000008304821694740100000000000000000000000000000000000000008404831694780100000000000000000000000000000000000000000000000085048416947c0100000000000000000000000000000000000000000000000000000000900490931692908a565b6040805165ffffffffffff9b8c1681529a90991660208b015263ffffffff978816988a01989098529486166060890152928516608088015290841660a08701529290921660c085015260e0840191909152610100830152610120820152610140016102cf565b6009546104a39068010000000000000000900463ffffffff1681565b6009546104a390640100000000900463ffffffff1681565b600080610b2d83612402565b5050600084815260036020526040902054909150610b4c908290614352565b9392505050565b60008181526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314610bb0576040517f2c47703200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600090815260066020908152604080832054600290925290912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b610c3c336000357fffffffff00000000000000000000000000000000000000000000000000000000166124dd565b610ca7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60008181526002602052604081206004015415801590610d5a575060008281526003602052604090206002015442660100000000000090910465ffffffffffff16115b92915050565b600080610d91610d6f846116bd565b6000858152600260205260409020600a0154610d8a86610b21565b91906125ee565b6000848152600260205260409020600601549091508111610d5a57600083815260026020526040902060060154610b4c565b600080610dd28385018561439a565b905080610100015165ffffffffffff16600014158015610e2357506201518081610100015165ffffffffffff161080610e235750635dba240065ffffffffffff1681610100015165ffffffffffff16115b15610e5a576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e638161264c565b949350505050565b610e99336000357fffffffff00000000000000000000000000000000000000000000000000000000166124dd565b610eff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c9e565b600780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610f3982610d17565b610f6f576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f7c6020820182614471565b63ffffffff161580610fa15750610f996040820160208301614471565b63ffffffff16155b80610fbf5750610fb76060820160408301614471565b63ffffffff16155b15610ff6576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110066040820160208301614471565b63ffffffff166110196020830183614471565b63ffffffff161015611057576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526004602090815260409091208054909170010000000000000000000000000000000090910463ffffffff169061109490840184614471565b63ffffffff1610156110d2576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60095468010000000000000000900463ffffffff166110f76060840160408501614471565b63ffffffff161015611135576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260026020818152604092839020835161018081018552815473ffffffffffffffffffffffffffffffffffffffff908116808352600184015482169483019490945293820154841694810194909452600381015492831660608501527401000000000000000000000000000000000000000090920460ff1615156080840152600482015460a0840152600582015460c0840152600682015460e0840152600782015461010084015260088201546101208401526009820154610140840152600a90910154610160830152331461123b576040517f4e1c8b5d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112486020840184614471565b825463ffffffff9190911674010000000000000000000000000000000000000000027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff9091161782556112e66112a16020850185614471565b60008681526003602052604090206002015463ffffffff91909116906112da9042906601000000000000900465ffffffffffff16614352565b60a08401519190613335565b6001830181905560a0820151116112fe576000611312565b81600101548160a001516113129190614352565b60028301556113276040840160208501614471565b825463ffffffff919091167801000000000000000000000000000000000000000000000000027fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff9091161782556113846060840160408501614471565b825463ffffffff919091167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617909155505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806114ba57506001546040517fb70096130000000000000000000000000000000000000000000000000000000081523360048201523060248201526000357fffffffff0000000000000000000000000000000000000000000000000000000016604482015273ffffffffffffffffffffffffffffffffffffffff9091169063b700961390606401602060405180830381865afa158015611496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ba919061448c565b6114c357600080fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350565b60008181526003602052604081206002015465ffffffffffff16635dba24008111156115635742811115610b4c565b1592915050565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1633146115c7576040517f4e1c8b5d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115d081613401565b50565b611601336000357fffffffff00000000000000000000000000000000000000000000000000000000166124dd565b611667576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c9e565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6000818152600460209081526040808320815161014081018352815465ffffffffffff8082168352660100000000000082041694820185905263ffffffff6c0100000000000000000000000082048116948301949094527001000000000000000000000000000000008104841660608301527401000000000000000000000000000000000000000081048416608083015278010000000000000000000000000000000000000000000000008104841660a08301527c0100000000000000000000000000000000000000000000000000000000900490921660c0830152600181015460e08301526002810154610100830152600301546101208201529042808211156118125760c083015181830390611808906117e090839063ffffffff166144a9565b60c0860151600089815260026020526040902060050154919063ffffffff9081169061333516565b9695505050505050565b60c08301518282039063ffffffff16811161184557611840818560c0015163ffffffff166117e09190614352565b611808565b60009695505050505050565b60008281526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1633146118ae576040517f4e1c8b5d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60009182526006602052604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b61192f336000357fffffffff00000000000000000000000000000000000000000000000000000000166124dd565b611995576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c9e565b6020810151815163ffffffff918216911610156119de576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060810151815163ffffffff91821691161015611a27576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151606082015163ffffffff91821691161115611a73576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060810151611a839060056144c1565b63ffffffff16816002602002015163ffffffff161015611acf576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060006020020151600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90921691909117905580600160200201516009805463ffffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117905580600260200201516009805463ffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff90921691909117905580600360200201516009805463ffffffff9092166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff90921691909117905580600460200201516009805463ffffffff909216700100000000000000000000000000000000027fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff90921691909117905580600560209081029190910151600980547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff81167401000000000000000000000000000000000000000063ffffffff9485168102918217938490556040805193861692861692909217835264010000000084048516958301959095526801000000000000000083048416908201526c010000000000000000000000008204831660608201527001000000000000000000000000000000008204831660808201529290041660a08201527fbbc02fa2138d26ec5ecb379612618d1b291bf5140167f3028178080953459c5a9060c00160405180910390a150565b6040517fb88c914800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000918291611dfe917f00000000000000000000000000000000000000000000000000000000000000009091169063b88c914890602401602060405180830381865afa158015611dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611deb91906144ed565b869065ffffffffffff16620186a0613335565b6000858152600260205260408120600a015491925090611e3290611e2187610d60565b611e2b858a614352565b9190613335565b600086815260026020526040902060070154909150811115611e80576040517f5c430eae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9150610b4c9050565b6000828152600260208181526040808420815161018081018352815473ffffffffffffffffffffffffffffffffffffffff9081168252600183015481169482019490945293810154831691840191909152600381015491821660608401527401000000000000000000000000000000000000000090910460ff1615156080830152600481015460a0830152600581015460c0830152600681015460e0830152600781015461010083015260088101546101208301526009810154610140830152600a015461016082015281611f5d85610d60565b905060008260800151611f855761016083015160a0840151611f80918490613335565b611f8b565b8260a001515b90506000611fae838561016001518661010001516133359092919063ffffffff16565b90506000818310611fbf5781611fc1565b825b6040517fb88c914800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8981166004830152919250600091612090917f00000000000000000000000000000000000000000000000000000000000000009091169063b88c914890602401602060405180830381865afa158015612059573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207d91906144ed565b839065ffffffffffff16620186a0613335565b905061209c81836144a9565b9998505050505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461211a576040517f2c47703200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526002602081815260408084206003808452948290208251608081018452815481526001820154948101949094529093015465ffffffffffff80821692840192909252660100000000000090041660608201529181015490919073ffffffffffffffffffffffffffffffffffffffff16158015906121c35750815473ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205460ff16155b156121fa576040517f2c47703200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000429050816060015165ffffffffffff168165ffffffffffff161061225c5760608201516040517f07fc4a7000000000000000000000000000000000000000000000000000000000815265ffffffffffff9091166004820152602401610c9e565b6000612269888842613485565b95509050858510156122a7576040517f74ec9d5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600701548511156122e5576040517f5c430eae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600384015474010000000000000000000000000000000000000000900460ff16612315578360040154851161231d565b836004015487115b15612354576040517ff3383dc900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600384015474010000000000000000000000000000000000000000900460ff1661237e5784612380565b865b8460040160008282546123939190614352565b92505081905550868460090160008282546123ae91906144a9565b92505081905550848460080160008282546123c991906144a9565b90915550506005840154602084015110156123ec576123e788613401565b6123f7565b6123f7888383613854565b505050509392505050565b600081815260056020908152604080832081516080810183528154815260019091015465ffffffffffff8082169483019490945266010000000000008104909316918101919091526c0100000000000000000000000090910460ff1615156060820181905282918291612480576000806000935093509350506124d6565b602081015161248f904261450a565b9250806040015165ffffffffffff168365ffffffffffff16109150816124b65780516124d2565b604081015181516124d29165ffffffffffff8087169116613335565b9350505b9193909250565b60015460009073ffffffffffffffffffffffffffffffffffffffff1680158015906125c157506040517fb700961300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527fffffffff000000000000000000000000000000000000000000000000000000008516604483015282169063b700961390606401602060405180830381865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c1919061448c565b80610e63575060005473ffffffffffffffffffffffffffffffffffffffff85811691161491505092915050565b60006125fb848484613335565b90506000828061260d5761260d614531565b8486091115610b4c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811061264257600080fd5b6001019392505050565b60075460009060ff1661268b576040517f64be3ffa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000826000015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127009190614560565b90506000836020015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612753573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127779190614560565b905060068260ff16108061278e575060128260ff16115b156127c5576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60068160ff1610806127da575060128160ff16115b15612811576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe884610160015160000b128061284f5750601884610160015160000b135b15612886576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526008602052604090205460ff161580156128bf5750604084015173ffffffffffffffffffffffffffffffffffffffff1615155b156128f6576040517f2c47703200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600082610160015160240160ff16600a0a90508260c001518360a00151101561294d576040517f4496547d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825160208401516040517fb435914300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316600482015290821660248201526000917f0000000000000000000000000000000000000000000000000000000000000000169063b4359143906044016020604051808303816000875af11580156129ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a119190614583565b90506000804286610120015165ffffffffffff16612a2f9190614352565b60095490925063ffffffff70010000000000000000000000000000000090910481169083161080612a80575060095461014087015163ffffffff6c0100000000000000000000000090920482169116105b80612a9b57508163ffffffff1686610140015163ffffffff16115b15612ad2576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008661014001516005612ae691906144c1565b60095490915063ffffffff808316680100000000000000009092041611612b0d5780612b23565b60095468010000000000000000900463ffffffff165b600954610140890151919350600091612b7b9163ffffffff908116911611612b535760095463ffffffff16612b5a565b8861014001515b63ffffffff168563ffffffff168a608001516133359092919063ffffffff16565b60408051610140808201835265ffffffffffff4216808352602083015263ffffffff808916938301939093528b01805183166060830152600954905193945090926080840192918216911611612bd95760095463ffffffff16612be0565b8961014001515b63ffffffff9081168252600954640100000000900481166020830152851660408201526060810183905260808a810151910190612c1e908490614352565b8152602001612c5c8563ffffffff168763ffffffff168c60600151612c47578c60800151611e2b565b60a08d015160808e0151611e2b918d90613335565b90526000868152600460209081526040808320845181549386015192860151606080880151608089015160a08a015160c08b015165ffffffffffff9687167fffffffffffffffffffffffffffffffffffffffff000000000000000000000000909a169990991766010000000000009690981695909502969096177fffffffffffffffffffffffff0000000000000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff948516027fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff161770010000000000000000000000000000000091841691909102177fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000958316959095027fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff1694909417780100000000000000000000000000000000000000000000000092821692909202919091177bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c0100000000000000000000000000000000000000000000000000000000919094160292909217825560e08401516001830155610100840151600283015561012090930151600390910155908901519092508291508190612e59578860800151612e6e565b60a089015160808a0151612e6e918990613335565b9050612e878163ffffffff808716908881169061333516565b9250612eaf89610140015163ffffffff168663ffffffff16836133359092919063ffffffff16565b9150506040518061018001604052803373ffffffffffffffffffffffffffffffffffffffff168152602001896000015173ffffffffffffffffffffffffffffffffffffffff168152602001896020015173ffffffffffffffffffffffffffffffffffffffff168152602001896040015173ffffffffffffffffffffffffffffffffffffffff168152602001896060015115158152602001896080015181526020018381526020018960c0015181526020018281526020016000815260200160008152602001878152506002600087815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160030160146101000a81548160ff02191690831515021790555060a0820151816004015560c0820151816005015560e0820151816006015561010082015181600701556101208201518160080155610140820151816009015561016082015181600a01559050506000600960149054906101000a900463ffffffff1663ffffffff1661314f620186a065ffffffffffff1685856133359092919063ffffffff16565b1161317a5760095474010000000000000000000000000000000000000000900463ffffffff16613188565b61318882620186a085613335565b905060006131bd828b60e0015163ffffffff16116131a657826131b2565b8a60e0015163ffffffff165b8590620186a0613335565b6131c790856144a9565b60a08b01519091506000906131dd908a87613335565b905060405180608001604052808281526020018381526020018c610100015165ffffffffffff1681526020018c610120015165ffffffffffff16815250600360008a8152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548165ffffffffffff021916908365ffffffffffff16021790555060608201518160020160066101000a81548165ffffffffffff021916908365ffffffffffff1602179055509050508a6020015173ffffffffffffffffffffffffffffffffffffffff168b6000015173ffffffffffffffffffffffffffffffffffffffff16897f8235b14cd272b4e791960fe1118559bb7fed86934fcffeeae9b1175103b0756d8e61010001518f60a0015160405161331e92919065ffffffffffff929092168252602082015260400190565b60405180910390a450959998505050505050505050565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8587098587029250828110838203039150508060000361338c576000841161338157600080fd5b508290049050610b4c565b80841161339857600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000818152600360209081526040808320600290810180547fffffffffffffffffffffffffffffffffffffffff000000000000ffffffffffff1666010000000000004265ffffffffffff16021790559091528082206004018290555182917f9dc30b8eda31a6a144e092e5de600955523a6a925cc15cc1d1b9b4872cfa615591a250565b6000838152600260208181526040808420815161018081018352815473ffffffffffffffffffffffffffffffffffffffff9081168252600183015481169482019490945293810154831691840191909152600381015491821660608401527401000000000000000000000000000000000000000090910460ff1615156080830152600481015460a0830152600581015460c0830152600681015460e0830152600781015461010083015260088101546101208301526009810154610140830152600a015461016082015281908161355b876116bd565b600088815260026020908152604080832060059081018590559091529020600101549091506c01000000000000000000000000900460ff16156136a35760008781526005602052604081209080806135b28b612402565b60008e8152600360205260408120805494975092955090935085926135d8908490614352565b9091555050801561367357828460000160008282546135f79190614352565b90915550506001840180548391906006906136259084906601000000000000900465ffffffffffff1661450a565b92506101000a81548165ffffffffffff021916908365ffffffffffff160217905550888460010160006101000a81548165ffffffffffff021916908365ffffffffffff16021790555061369e565b6001840180547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff1690555b505050505b6136ac87613f48565b60e0830151909450808510156136c0578094505b6101608301516136d290889087613335565b600089815260046020526040812080546003909101549296507c0100000000000000000000000000000000000000000000000000000000810463ffffffff9081169392660100000000000090920465ffffffffffff16919061373a9085908a9086906125ee16565b60008d81526004602052604090208054919250829160069061376f9084906601000000000000900465ffffffffffff1661459c565b92506101000a81548165ffffffffffff021916908365ffffffffffff1602179055506000828b65ffffffffffff16116137c3576137b465ffffffffffff8c1684614352565b6137be90866144a9565b6137fe565b6137d58365ffffffffffff8d16614352565b85116137e25760006137fe565b6137f48365ffffffffffff8d16614352565b6137fe9086614352565b9050886138178661380f85856144a9565b8a9190613335565b61382191906144a9565b61382c9060016144a9565b60009d8e5260026020526040909d206005019c909c5550969a95995094975050505050505050565b600060046000858152602001908152602001600020604051806101400160405290816000820160009054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016000820160069054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160189054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160018201548152602001600282015481526020016003820154815250509050600060026000868152602001908152602001600020604051806101800160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820160149054906101000a900460ff16151515158152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152505090506000846003600088815260200190815260200160002060020160069054906101000a900465ffffffffffff16613bbd919061450a565b65ffffffffffff16905060008260800151613bdc578260a00151613bf1565b61016083015160a0840151613bf19187613335565b905060008360800151613c0957836101200151613c1f565b610160840151610140850151613c1f9188613335565b613c2990836144a9565b9050600082613c6285886040015163ffffffff16613c479190614352565b886040015163ffffffff16856133359092919063ffffffff16565b613c6c91906144a9565b90508561010001518560a00151108015613c8557508181105b80613cc0575060808601518651613ca29163ffffffff169061459c565b65ffffffffffff168865ffffffffffff1610158015613cc057508181115b15613f3d57613ce4866060015163ffffffff1685856133359092919063ffffffff16565b60008a8152600260205260408082206007019290925560c0880151918801519091613d1d91849163ffffffff9081169181169061333516565b60008b81526003602052604081205461016089015192935091613d42908b90856125ee565b60408051848152602081018390529192508d917f78f9c01d72705dba80d6ce051d36a1f987bf2a3800fee938c111a2ae741e57d1910160405180910390a281811015613e70576000613d948284614352565b905060405180608001604052808281526020018d65ffffffffffff1681526020018b60a0015163ffffffff1665ffffffffffff16815260200160011515815250600560008f81526020019081526020016000206000820151816000015560208201518160010160006101000a81548165ffffffffffff021916908365ffffffffffff16021790555060408201518160010160066101000a81548165ffffffffffff021916908365ffffffffffff160217905550606082015181600101600c6101000a81548160ff02191690831515021790555090505050613eb5565b60008c81526003602090815260408083208490556005909152902060010180547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff1690555b60008c815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000001665ffffffffffff8d1617905560e089015160a089015111613f09576000613f1d565b8860e001518860a00151613f1d9190614352565b60008d815260046020526040902060028101919091556003019290925550505b505050505050505050565b6000818152600260208181526040808420815161018081018352815473ffffffffffffffffffffffffffffffffffffffff908116825260018301548116828601529482015485168184015260038083015495861660608301527401000000000000000000000000000000000000000090950460ff1615156080820152600482015460a0820152600582015460c08201819052600683015460e0830152600783015461010083015260088301546101208301526009830154610140830152600a90920154610160820181905287875294909352908420549192610b4c9291906125ee565b60006020828403121561403d57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146115d057600080fd5b803561407181614044565b919050565b60006020828403121561408857600080fd5b8135610b4c81614044565b600080602083850312156140a657600080fd5b823567ffffffffffffffff808211156140be57600080fd5b818501915085601f8301126140d257600080fd5b8135818111156140e157600080fd5b8660208285010111156140f357600080fd5b60209290920196919550909350505050565b80151581146115d057600080fd5b803561407181614105565b60006020828403121561413057600080fd5b8135610b4c81614105565b6000806080838503121561414e57600080fd5b823591508360808401111561416257600080fd5b50926020919091019150565b6000806040838503121561418157600080fd5b823561418c81614044565b9150602083013561419c81614105565b809150509250929050565b600080604083850312156141ba57600080fd5b82359150602083013561419c81614044565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610180810167ffffffffffffffff8111828210171561421f5761421f6141cc565b60405290565b803563ffffffff8116811461407157600080fd5b600060c0828403121561424b57600080fd5b82601f83011261425a57600080fd5b60405160c0810181811067ffffffffffffffff8211171561427d5761427d6141cc565b6040528060c084018581111561429257600080fd5b845b818110156142b3576142a581614225565b835260209283019201614294565b509195945050505050565b6000806000606084860312156142d357600080fd5b833592506020840135915060408401356142ec81614044565b809150509250925092565b60008060006060848603121561430c57600080fd5b505081359360208301359350604090920135919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561436457614364614323565b500390565b65ffffffffffff811681146115d057600080fd5b803561407181614369565b8035600081900b811461407157600080fd5b600061018082840312156143ad57600080fd5b6143b56141fb565b6143be83614066565b81526143cc60208401614066565b60208201526143dd60408401614066565b60408201526143ee60608401614113565b60608201526080830135608082015260a083013560a082015260c083013560c082015261441d60e08401614225565b60e082015261010061443081850161437d565b9082015261012061444284820161437d565b90820152610140614454848201614225565b90820152610160614466848201614388565b908201529392505050565b60006020828403121561448357600080fd5b610b4c82614225565b60006020828403121561449e57600080fd5b8151610b4c81614105565b600082198211156144bc576144bc614323565b500190565b600063ffffffff808316818516818304811182151516156144e4576144e4614323565b02949350505050565b6000602082840312156144ff57600080fd5b8151610b4c81614369565b600065ffffffffffff8381169083168181101561452957614529614323565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006020828403121561457257600080fd5b815160ff81168114610b4c57600080fd5b60006020828403121561459557600080fd5b5051919050565b600065ffffffffffff8083168185168083038211156145bd576145bd614323565b0194935050505056fea264697066735822122002658b0afe08675b067feef823a44a070e3a2df151f9592a79df19d495fbfe7864736f6c634300080f0033000000000000000000000000007f7735baf391e207e3aa380bb53c4bd9a5fed6000000000000000000000000007a66a2a13415db3613c1a4dd1c942a285902d1000000000000000000000000007bd11fca0daaeadd455b51826f9a015f2f0969000000000000000000000000007a0f48a4e3d74ab4234adf9ea9eb32f87b4b14
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102ad5760003560e01c8063acc5570c1161017b578063bf7e214f116100d8578063d9ccdc931161008c578063e3684e3911610071578063e3684e39146109af578063e922067314610aed578063ea0aca3314610b0957600080fd5b8063d9ccdc931461098c578063e007fa971461099c57600080fd5b8063c7bf8ca0116100bd578063c7bf8ca014610935578063d204068714610948578063d2bee3231461096857600080fd5b8063bf7e214f146108a2578063c0aa0e8a146108c257600080fd5b8063bc3b2b121161012f578063bcf6cde811610114578063bcf6cde814610869578063bd1f3a5e1461087c578063bf48582b1461088f57600080fd5b8063bc3b2b12146107d2578063bcb296671461085657600080fd5b8063afa9d3b011610160578063afa9d3b0146106a1578063b1283e77146106ae578063bbbdd95a146107bf57600080fd5b8063acc5570c14610534578063ae4180951461068e57600080fd5b80635f77274e116102295780638973082c116101dd5780638da5cb5b116101c25780638da5cb5b146104cb578063946824cd146104eb5780639787d1071461050e57600080fd5b80638973082c1461047b5780638b098db3146104b857600080fd5b80636729a41e1161020e5780636729a41e1461041f578063699e17d9146104555780637a9e5e4b1461046857600080fd5b80635f77274e146103d65780636352211e146103e957600080fd5b806327507458116102805780633adec5a7116102655780633adec5a71461038d57806353c7f8e0146103a05780635dc4d16b146103b357600080fd5b806327507458146103235780633ad59dbc1461034657600080fd5b80630a9d85eb146102b257806310b05317146102d857806313af4035146102ed5780631c063a6c14610300575b600080fd5b6102c56102c036600461402b565b610b21565b6040519081526020015b60405180910390f35b6102eb6102e636600461402b565b610b53565b005b6102eb6102fb366004614076565b610c0e565b6102c561030e36600461402b565b60009081526002602052604090206004015490565b61033661033136600461402b565b610d17565b60405190151581526020016102cf565b7f000000000000000000000000007a66a2a13415db3613c1a4dd1c942a285902d15b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102cf565b6102c561039b36600461402b565b610d60565b6102c56103ae366004614093565b610dc3565b6103366103c1366004614076565b60086020526000908152604090205460ff1681565b6102eb6103e436600461411e565b610e6b565b6103686103f736600461402b565b60009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b61036861042d36600461402b565b60066020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6102eb61046336600461413b565b610f30565b6102eb610476366004614076565b6113d7565b6009546104a39074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102cf565b6103366104c636600461402b565b611534565b6000546103689073ffffffffffffffffffffffffffffffffffffffff1681565b6102c56104f936600461402b565b6000908152600260205260409020600a015490565b7f000000000000000000000000007f7735baf391e207e3aa380bb53c4bd9a5fed6610368565b61063861054236600461402b565b6000818152600260208181526040808420815161018081018352815473ffffffffffffffffffffffffffffffffffffffff90811680835260018401548216838701819052848801548316848701819052600380870154948516606087018190527401000000000000000000000000000000000000000090950460ff1615156080870152600487015460a0870152600587015460c0870152600687015460e08701526007870154610100870190815260088801546101208801526009880154610140880152600a90970154610160909601959095529989529290955292909520909301549251919590949265ffffffffffff169190565b6040805173ffffffffffffffffffffffffffffffffffffffff97881681529587166020870152938616938501939093529316606083015265ffffffffffff909216608082015260a081019190915260c0016102cf565b6102eb61069c36600461402b565b61156a565b6007546103369060ff1681565b6107456106bc36600461402b565b600260208190526000918252604090912080546001820154928201546003830154600484015460058501546006860154600787015460088801546009890154600a9099015473ffffffffffffffffffffffffffffffffffffffff9889169a891699978916988716977401000000000000000000000000000000000000000090970460ff1696908c565b6040805173ffffffffffffffffffffffffffffffffffffffff9d8e1681529b8d1660208d0152998c16998b0199909952999096166060890152931515608088015260a087019290925260c086015260e0850152610100840152610120830152610140820192909252610160810191909152610180016102cf565b6102eb6107cd36600461416e565b6115d3565b6108256107e036600461402b565b6005602052600090815260409020805460019091015465ffffffffffff8082169166010000000000008104909116906c01000000000000000000000000900460ff1684565b6040516102cf949392919093845265ffffffffffff9283166020850152911660408301521515606082015260800190565b6102c561086436600461402b565b6116bd565b6102eb6108773660046141a7565b611851565b6102eb61088a366004614239565b611901565b6102c561089d3660046142be565b611d30565b6001546103689073ffffffffffffffffffffffffffffffffffffffff1681565b6109076108d036600461402b565b60036020526000908152604090208054600182015460029092015490919065ffffffffffff80821691660100000000000090041684565b60408051948552602085019390935265ffffffffffff918216928401929092521660608201526080016102cf565b6102c56109433660046141a7565b611e89565b6009546104a3906c01000000000000000000000000900463ffffffff1681565b6009546104a390700100000000000000000000000000000000900463ffffffff1681565b6009546104a39063ffffffff1681565b6102c56109aa3660046142f7565b6120a9565b610a876109bd36600461402b565b600460205260009081526040902080546001820154600283015460039093015465ffffffffffff80841694660100000000000085049091169363ffffffff6c0100000000000000000000000082048116947001000000000000000000000000000000008304821694740100000000000000000000000000000000000000008404831694780100000000000000000000000000000000000000000000000085048416947c0100000000000000000000000000000000000000000000000000000000900490931692908a565b6040805165ffffffffffff9b8c1681529a90991660208b015263ffffffff978816988a01989098529486166060890152928516608088015290841660a08701529290921660c085015260e0840191909152610100830152610120820152610140016102cf565b6009546104a39068010000000000000000900463ffffffff1681565b6009546104a390640100000000900463ffffffff1681565b600080610b2d83612402565b5050600084815260036020526040902054909150610b4c908290614352565b9392505050565b60008181526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314610bb0576040517f2c47703200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600090815260066020908152604080832054600290925290912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b610c3c336000357fffffffff00000000000000000000000000000000000000000000000000000000166124dd565b610ca7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60008181526002602052604081206004015415801590610d5a575060008281526003602052604090206002015442660100000000000090910465ffffffffffff16115b92915050565b600080610d91610d6f846116bd565b6000858152600260205260409020600a0154610d8a86610b21565b91906125ee565b6000848152600260205260409020600601549091508111610d5a57600083815260026020526040902060060154610b4c565b600080610dd28385018561439a565b905080610100015165ffffffffffff16600014158015610e2357506201518081610100015165ffffffffffff161080610e235750635dba240065ffffffffffff1681610100015165ffffffffffff16115b15610e5a576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e638161264c565b949350505050565b610e99336000357fffffffff00000000000000000000000000000000000000000000000000000000166124dd565b610eff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c9e565b600780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610f3982610d17565b610f6f576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f7c6020820182614471565b63ffffffff161580610fa15750610f996040820160208301614471565b63ffffffff16155b80610fbf5750610fb76060820160408301614471565b63ffffffff16155b15610ff6576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110066040820160208301614471565b63ffffffff166110196020830183614471565b63ffffffff161015611057576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526004602090815260409091208054909170010000000000000000000000000000000090910463ffffffff169061109490840184614471565b63ffffffff1610156110d2576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60095468010000000000000000900463ffffffff166110f76060840160408501614471565b63ffffffff161015611135576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260026020818152604092839020835161018081018552815473ffffffffffffffffffffffffffffffffffffffff908116808352600184015482169483019490945293820154841694810194909452600381015492831660608501527401000000000000000000000000000000000000000090920460ff1615156080840152600482015460a0840152600582015460c0840152600682015460e0840152600782015461010084015260088201546101208401526009820154610140840152600a90910154610160830152331461123b576040517f4e1c8b5d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112486020840184614471565b825463ffffffff9190911674010000000000000000000000000000000000000000027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff9091161782556112e66112a16020850185614471565b60008681526003602052604090206002015463ffffffff91909116906112da9042906601000000000000900465ffffffffffff16614352565b60a08401519190613335565b6001830181905560a0820151116112fe576000611312565b81600101548160a001516113129190614352565b60028301556113276040840160208501614471565b825463ffffffff919091167801000000000000000000000000000000000000000000000000027fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff9091161782556113846060840160408501614471565b825463ffffffff919091167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911617909155505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314806114ba57506001546040517fb70096130000000000000000000000000000000000000000000000000000000081523360048201523060248201526000357fffffffff0000000000000000000000000000000000000000000000000000000016604482015273ffffffffffffffffffffffffffffffffffffffff9091169063b700961390606401602060405180830381865afa158015611496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ba919061448c565b6114c357600080fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350565b60008181526003602052604081206002015465ffffffffffff16635dba24008111156115635742811115610b4c565b1592915050565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1633146115c7576040517f4e1c8b5d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115d081613401565b50565b611601336000357fffffffff00000000000000000000000000000000000000000000000000000000166124dd565b611667576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c9e565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6000818152600460209081526040808320815161014081018352815465ffffffffffff8082168352660100000000000082041694820185905263ffffffff6c0100000000000000000000000082048116948301949094527001000000000000000000000000000000008104841660608301527401000000000000000000000000000000000000000081048416608083015278010000000000000000000000000000000000000000000000008104841660a08301527c0100000000000000000000000000000000000000000000000000000000900490921660c0830152600181015460e08301526002810154610100830152600301546101208201529042808211156118125760c083015181830390611808906117e090839063ffffffff166144a9565b60c0860151600089815260026020526040902060050154919063ffffffff9081169061333516565b9695505050505050565b60c08301518282039063ffffffff16811161184557611840818560c0015163ffffffff166117e09190614352565b611808565b60009695505050505050565b60008281526002602052604090205473ffffffffffffffffffffffffffffffffffffffff1633146118ae576040517f4e1c8b5d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60009182526006602052604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b61192f336000357fffffffff00000000000000000000000000000000000000000000000000000000166124dd565b611995576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610c9e565b6020810151815163ffffffff918216911610156119de576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060810151815163ffffffff91821691161015611a27576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151606082015163ffffffff91821691161115611a73576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060810151611a839060056144c1565b63ffffffff16816002602002015163ffffffff161015611acf576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060006020020151600980547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90921691909117905580600160200201516009805463ffffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117905580600260200201516009805463ffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff90921691909117905580600360200201516009805463ffffffff9092166c01000000000000000000000000027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff90921691909117905580600460200201516009805463ffffffff909216700100000000000000000000000000000000027fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff90921691909117905580600560209081029190910151600980547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff81167401000000000000000000000000000000000000000063ffffffff9485168102918217938490556040805193861692861692909217835264010000000084048516958301959095526801000000000000000083048416908201526c010000000000000000000000008204831660608201527001000000000000000000000000000000008204831660808201529290041660a08201527fbbc02fa2138d26ec5ecb379612618d1b291bf5140167f3028178080953459c5a9060c00160405180910390a150565b6040517fb88c914800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000918291611dfe917f000000000000000000000000007f7735baf391e207e3aa380bb53c4bd9a5fed69091169063b88c914890602401602060405180830381865afa158015611dc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611deb91906144ed565b869065ffffffffffff16620186a0613335565b6000858152600260205260408120600a015491925090611e3290611e2187610d60565b611e2b858a614352565b9190613335565b600086815260026020526040902060070154909150811115611e80576040517f5c430eae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9150610b4c9050565b6000828152600260208181526040808420815161018081018352815473ffffffffffffffffffffffffffffffffffffffff9081168252600183015481169482019490945293810154831691840191909152600381015491821660608401527401000000000000000000000000000000000000000090910460ff1615156080830152600481015460a0830152600581015460c0830152600681015460e0830152600781015461010083015260088101546101208301526009810154610140830152600a015461016082015281611f5d85610d60565b905060008260800151611f855761016083015160a0840151611f80918490613335565b611f8b565b8260a001515b90506000611fae838561016001518661010001516133359092919063ffffffff16565b90506000818310611fbf5781611fc1565b825b6040517fb88c914800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8981166004830152919250600091612090917f000000000000000000000000007f7735baf391e207e3aa380bb53c4bd9a5fed69091169063b88c914890602401602060405180830381865afa158015612059573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207d91906144ed565b839065ffffffffffff16620186a0613335565b905061209c81836144a9565b9998505050505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000007f7735baf391e207e3aa380bb53c4bd9a5fed6161461211a576040517f2c47703200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526002602081815260408084206003808452948290208251608081018452815481526001820154948101949094529093015465ffffffffffff80821692840192909252660100000000000090041660608201529181015490919073ffffffffffffffffffffffffffffffffffffffff16158015906121c35750815473ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205460ff16155b156121fa576040517f2c47703200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000429050816060015165ffffffffffff168165ffffffffffff161061225c5760608201516040517f07fc4a7000000000000000000000000000000000000000000000000000000000815265ffffffffffff9091166004820152602401610c9e565b6000612269888842613485565b95509050858510156122a7576040517f74ec9d5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600701548511156122e5576040517f5c430eae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600384015474010000000000000000000000000000000000000000900460ff16612315578360040154851161231d565b836004015487115b15612354576040517ff3383dc900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600384015474010000000000000000000000000000000000000000900460ff1661237e5784612380565b865b8460040160008282546123939190614352565b92505081905550868460090160008282546123ae91906144a9565b92505081905550848460080160008282546123c991906144a9565b90915550506005840154602084015110156123ec576123e788613401565b6123f7565b6123f7888383613854565b505050509392505050565b600081815260056020908152604080832081516080810183528154815260019091015465ffffffffffff8082169483019490945266010000000000008104909316918101919091526c0100000000000000000000000090910460ff1615156060820181905282918291612480576000806000935093509350506124d6565b602081015161248f904261450a565b9250806040015165ffffffffffff168365ffffffffffff16109150816124b65780516124d2565b604081015181516124d29165ffffffffffff8087169116613335565b9350505b9193909250565b60015460009073ffffffffffffffffffffffffffffffffffffffff1680158015906125c157506040517fb700961300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527fffffffff000000000000000000000000000000000000000000000000000000008516604483015282169063b700961390606401602060405180830381865afa15801561259d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c1919061448c565b80610e63575060005473ffffffffffffffffffffffffffffffffffffffff85811691161491505092915050565b60006125fb848484613335565b90506000828061260d5761260d614531565b8486091115610b4c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811061264257600080fd5b6001019392505050565b60075460009060ff1661268b576040517f64be3ffa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000826000015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127009190614560565b90506000836020015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612753573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127779190614560565b905060068260ff16108061278e575060128260ff16115b156127c5576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60068160ff1610806127da575060128160ff16115b15612811576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe884610160015160000b128061284f5750601884610160015160000b135b15612886576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526008602052604090205460ff161580156128bf5750604084015173ffffffffffffffffffffffffffffffffffffffff1615155b156128f6576040517f2c47703200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600082610160015160240160ff16600a0a90508260c001518360a00151101561294d576040517f4496547d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825160208401516040517fb435914300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316600482015290821660248201526000917f000000000000000000000000007a66a2a13415db3613c1a4dd1c942a285902d1169063b4359143906044016020604051808303816000875af11580156129ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a119190614583565b90506000804286610120015165ffffffffffff16612a2f9190614352565b60095490925063ffffffff70010000000000000000000000000000000090910481169083161080612a80575060095461014087015163ffffffff6c0100000000000000000000000090920482169116105b80612a9b57508163ffffffff1686610140015163ffffffff16115b15612ad2576040517f3b596f5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008661014001516005612ae691906144c1565b60095490915063ffffffff808316680100000000000000009092041611612b0d5780612b23565b60095468010000000000000000900463ffffffff165b600954610140890151919350600091612b7b9163ffffffff908116911611612b535760095463ffffffff16612b5a565b8861014001515b63ffffffff168563ffffffff168a608001516133359092919063ffffffff16565b60408051610140808201835265ffffffffffff4216808352602083015263ffffffff808916938301939093528b01805183166060830152600954905193945090926080840192918216911611612bd95760095463ffffffff16612be0565b8961014001515b63ffffffff9081168252600954640100000000900481166020830152851660408201526060810183905260808a810151910190612c1e908490614352565b8152602001612c5c8563ffffffff168763ffffffff168c60600151612c47578c60800151611e2b565b60a08d015160808e0151611e2b918d90613335565b90526000868152600460209081526040808320845181549386015192860151606080880151608089015160a08a015160c08b015165ffffffffffff9687167fffffffffffffffffffffffffffffffffffffffff000000000000000000000000909a169990991766010000000000009690981695909502969096177fffffffffffffffffffffffff0000000000000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff948516027fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff161770010000000000000000000000000000000091841691909102177fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000958316959095027fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff1694909417780100000000000000000000000000000000000000000000000092821692909202919091177bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c0100000000000000000000000000000000000000000000000000000000919094160292909217825560e08401516001830155610100840151600283015561012090930151600390910155908901519092508291508190612e59578860800151612e6e565b60a089015160808a0151612e6e918990613335565b9050612e878163ffffffff808716908881169061333516565b9250612eaf89610140015163ffffffff168663ffffffff16836133359092919063ffffffff16565b9150506040518061018001604052803373ffffffffffffffffffffffffffffffffffffffff168152602001896000015173ffffffffffffffffffffffffffffffffffffffff168152602001896020015173ffffffffffffffffffffffffffffffffffffffff168152602001896040015173ffffffffffffffffffffffffffffffffffffffff168152602001896060015115158152602001896080015181526020018381526020018960c0015181526020018281526020016000815260200160008152602001878152506002600087815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160030160146101000a81548160ff02191690831515021790555060a0820151816004015560c0820151816005015560e0820151816006015561010082015181600701556101208201518160080155610140820151816009015561016082015181600a01559050506000600960149054906101000a900463ffffffff1663ffffffff1661314f620186a065ffffffffffff1685856133359092919063ffffffff16565b1161317a5760095474010000000000000000000000000000000000000000900463ffffffff16613188565b61318882620186a085613335565b905060006131bd828b60e0015163ffffffff16116131a657826131b2565b8a60e0015163ffffffff165b8590620186a0613335565b6131c790856144a9565b60a08b01519091506000906131dd908a87613335565b905060405180608001604052808281526020018381526020018c610100015165ffffffffffff1681526020018c610120015165ffffffffffff16815250600360008a8152602001908152602001600020600082015181600001556020820151816001015560408201518160020160006101000a81548165ffffffffffff021916908365ffffffffffff16021790555060608201518160020160066101000a81548165ffffffffffff021916908365ffffffffffff1602179055509050508a6020015173ffffffffffffffffffffffffffffffffffffffff168b6000015173ffffffffffffffffffffffffffffffffffffffff16897f8235b14cd272b4e791960fe1118559bb7fed86934fcffeeae9b1175103b0756d8e61010001518f60a0015160405161331e92919065ffffffffffff929092168252602082015260400190565b60405180910390a450959998505050505050505050565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8587098587029250828110838203039150508060000361338c576000841161338157600080fd5b508290049050610b4c565b80841161339857600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6000818152600360209081526040808320600290810180547fffffffffffffffffffffffffffffffffffffffff000000000000ffffffffffff1666010000000000004265ffffffffffff16021790559091528082206004018290555182917f9dc30b8eda31a6a144e092e5de600955523a6a925cc15cc1d1b9b4872cfa615591a250565b6000838152600260208181526040808420815161018081018352815473ffffffffffffffffffffffffffffffffffffffff9081168252600183015481169482019490945293810154831691840191909152600381015491821660608401527401000000000000000000000000000000000000000090910460ff1615156080830152600481015460a0830152600581015460c0830152600681015460e0830152600781015461010083015260088101546101208301526009810154610140830152600a015461016082015281908161355b876116bd565b600088815260026020908152604080832060059081018590559091529020600101549091506c01000000000000000000000000900460ff16156136a35760008781526005602052604081209080806135b28b612402565b60008e8152600360205260408120805494975092955090935085926135d8908490614352565b9091555050801561367357828460000160008282546135f79190614352565b90915550506001840180548391906006906136259084906601000000000000900465ffffffffffff1661450a565b92506101000a81548165ffffffffffff021916908365ffffffffffff160217905550888460010160006101000a81548165ffffffffffff021916908365ffffffffffff16021790555061369e565b6001840180547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff1690555b505050505b6136ac87613f48565b60e0830151909450808510156136c0578094505b6101608301516136d290889087613335565b600089815260046020526040812080546003909101549296507c0100000000000000000000000000000000000000000000000000000000810463ffffffff9081169392660100000000000090920465ffffffffffff16919061373a9085908a9086906125ee16565b60008d81526004602052604090208054919250829160069061376f9084906601000000000000900465ffffffffffff1661459c565b92506101000a81548165ffffffffffff021916908365ffffffffffff1602179055506000828b65ffffffffffff16116137c3576137b465ffffffffffff8c1684614352565b6137be90866144a9565b6137fe565b6137d58365ffffffffffff8d16614352565b85116137e25760006137fe565b6137f48365ffffffffffff8d16614352565b6137fe9086614352565b9050886138178661380f85856144a9565b8a9190613335565b61382191906144a9565b61382c9060016144a9565b60009d8e5260026020526040909d206005019c909c5550969a95995094975050505050505050565b600060046000858152602001908152602001600020604051806101400160405290816000820160009054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016000820160069054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160189054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160018201548152602001600282015481526020016003820154815250509050600060026000868152602001908152602001600020604051806101800160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820160149054906101000a900460ff16151515158152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152505090506000846003600088815260200190815260200160002060020160069054906101000a900465ffffffffffff16613bbd919061450a565b65ffffffffffff16905060008260800151613bdc578260a00151613bf1565b61016083015160a0840151613bf19187613335565b905060008360800151613c0957836101200151613c1f565b610160840151610140850151613c1f9188613335565b613c2990836144a9565b9050600082613c6285886040015163ffffffff16613c479190614352565b886040015163ffffffff16856133359092919063ffffffff16565b613c6c91906144a9565b90508561010001518560a00151108015613c8557508181105b80613cc0575060808601518651613ca29163ffffffff169061459c565b65ffffffffffff168865ffffffffffff1610158015613cc057508181115b15613f3d57613ce4866060015163ffffffff1685856133359092919063ffffffff16565b60008a8152600260205260408082206007019290925560c0880151918801519091613d1d91849163ffffffff9081169181169061333516565b60008b81526003602052604081205461016089015192935091613d42908b90856125ee565b60408051848152602081018390529192508d917f78f9c01d72705dba80d6ce051d36a1f987bf2a3800fee938c111a2ae741e57d1910160405180910390a281811015613e70576000613d948284614352565b905060405180608001604052808281526020018d65ffffffffffff1681526020018b60a0015163ffffffff1665ffffffffffff16815260200160011515815250600560008f81526020019081526020016000206000820151816000015560208201518160010160006101000a81548165ffffffffffff021916908365ffffffffffff16021790555060408201518160010160066101000a81548165ffffffffffff021916908365ffffffffffff160217905550606082015181600101600c6101000a81548160ff02191690831515021790555090505050613eb5565b60008c81526003602090815260408083208490556005909152902060010180547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff1690555b60008c815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000001665ffffffffffff8d1617905560e089015160a089015111613f09576000613f1d565b8860e001518860a00151613f1d9190614352565b60008d815260046020526040902060028101919091556003019290925550505b505050505050505050565b6000818152600260208181526040808420815161018081018352815473ffffffffffffffffffffffffffffffffffffffff908116825260018301548116828601529482015485168184015260038083015495861660608301527401000000000000000000000000000000000000000090950460ff1615156080820152600482015460a0820152600582015460c08201819052600683015460e0830152600783015461010083015260088301546101208301526009830154610140830152600a90920154610160820181905287875294909352908420549192610b4c9291906125ee565b60006020828403121561403d57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146115d057600080fd5b803561407181614044565b919050565b60006020828403121561408857600080fd5b8135610b4c81614044565b600080602083850312156140a657600080fd5b823567ffffffffffffffff808211156140be57600080fd5b818501915085601f8301126140d257600080fd5b8135818111156140e157600080fd5b8660208285010111156140f357600080fd5b60209290920196919550909350505050565b80151581146115d057600080fd5b803561407181614105565b60006020828403121561413057600080fd5b8135610b4c81614105565b6000806080838503121561414e57600080fd5b823591508360808401111561416257600080fd5b50926020919091019150565b6000806040838503121561418157600080fd5b823561418c81614044565b9150602083013561419c81614105565b809150509250929050565b600080604083850312156141ba57600080fd5b82359150602083013561419c81614044565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610180810167ffffffffffffffff8111828210171561421f5761421f6141cc565b60405290565b803563ffffffff8116811461407157600080fd5b600060c0828403121561424b57600080fd5b82601f83011261425a57600080fd5b60405160c0810181811067ffffffffffffffff8211171561427d5761427d6141cc565b6040528060c084018581111561429257600080fd5b845b818110156142b3576142a581614225565b835260209283019201614294565b509195945050505050565b6000806000606084860312156142d357600080fd5b833592506020840135915060408401356142ec81614044565b809150509250925092565b60008060006060848603121561430c57600080fd5b505081359360208301359350604090920135919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561436457614364614323565b500390565b65ffffffffffff811681146115d057600080fd5b803561407181614369565b8035600081900b811461407157600080fd5b600061018082840312156143ad57600080fd5b6143b56141fb565b6143be83614066565b81526143cc60208401614066565b60208201526143dd60408401614066565b60408201526143ee60608401614113565b60608201526080830135608082015260a083013560a082015260c083013560c082015261441d60e08401614225565b60e082015261010061443081850161437d565b9082015261012061444284820161437d565b90820152610140614454848201614225565b90820152610160614466848201614388565b908201529392505050565b60006020828403121561448357600080fd5b610b4c82614225565b60006020828403121561449e57600080fd5b8151610b4c81614105565b600082198211156144bc576144bc614323565b500190565b600063ffffffff808316818516818304811182151516156144e4576144e4614323565b02949350505050565b6000602082840312156144ff57600080fd5b8151610b4c81614369565b600065ffffffffffff8381169083168181101561452957614529614323565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006020828403121561457257600080fd5b815160ff81168114610b4c57600080fd5b60006020828403121561459557600080fd5b5051919050565b600065ffffffffffff8083168185168083038211156145bd576145bd614323565b0194935050505056fea264697066735822122002658b0afe08675b067feef823a44a070e3a2df151f9592a79df19d495fbfe7864736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000007f7735baf391e207e3aa380bb53c4bd9a5fed6000000000000000000000000007a66a2a13415db3613c1a4dd1c942a285902d1000000000000000000000000007bd11fca0daaeadd455b51826f9a015f2f0969000000000000000000000000007a0f48a4e3d74ab4234adf9ea9eb32f87b4b14
-----Decoded View---------------
Arg [0] : teller_ (address): 0x007F7735baF391e207E3aA380bb53c4Bd9a5Fed6
Arg [1] : aggregator_ (address): 0x007A66A2a13415DB3613C1a4dd1C942A285902d1
Arg [2] : guardian_ (address): 0x007BD11FCa0dAaeaDD455b51826F9a015f2f0969
Arg [3] : authority_ (address): 0x007A0F48A4e3d74Ab4234adf9eA9EB32f87b4b14
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000007f7735baf391e207e3aa380bb53c4bd9a5fed6
Arg [1] : 000000000000000000000000007a66a2a13415db3613c1a4dd1c942a285902d1
Arg [2] : 000000000000000000000000007bd11fca0daaeadd455b51826f9a015f2f0969
Arg [3] : 000000000000000000000000007a0f48a4e3d74ab4234adf9ea9eb32f87b4b14
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.