ETH Price: $3,259.54 (+4.64%)
Gas: 2 Gwei

Contract

0x007A66A2a13415DB3613C1a4dd1C942A285902d1
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Register Auction...159980562022-11-18 16:20:35616 days ago1668788435IN
Bond Protocol: Aggregator
0 ETH0.0022329126.64130284
Register Auction...159980552022-11-18 16:20:23616 days ago1668788423IN
Bond Protocol: Aggregator
0 ETH0.0026500226.26022095

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
159980362022-11-18 16:16:23616 days ago1668788183  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BondAggregator

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 100000 runs

Other Settings:
default evmVersion
File 1 of 7 : BondAggregator.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.15;

import {ERC20} from "solmate/tokens/ERC20.sol";
import {Auth, Authority} from "solmate/auth/Auth.sol";

import {IBondAggregator} from "./interfaces/IBondAggregator.sol";
import {IBondTeller} from "./interfaces/IBondTeller.sol";
import {IBondAuctioneer} from "./interfaces/IBondAuctioneer.sol";

import {FullMath} from "./lib/FullMath.sol";

/// @title Bond Aggregator
/// @notice Bond Aggregator 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 Aggregator contract keeps a unique set of market IDs across multiple
///      Tellers and Auctioneers. Additionally, it aggregates market data from
///      multiple Auctioneers in convenient view functions for front-end interfaces.
///      The Aggregator contract should be deployed first since Tellers, Auctioneers, and
///      Callbacks all require it in their constructors.
///
/// @author Oighty, Zeus, Potted Meat, indigo
contract BondAggregator is IBondAggregator, Auth {
    using FullMath for uint256;

    /* ========== ERRORS ========== */
    error Aggregator_OnlyAuctioneer();
    error Aggregator_AlreadyRegistered(address auctioneer_);
    error Aggregator_InvalidParams();

    /* ========== STATE VARIABLES ========== */

    /// @notice Counter for bond markets on approved auctioneers
    uint256 public marketCounter;

    /// @notice Approved auctioneers
    IBondAuctioneer[] public auctioneers;
    mapping(address => bool) internal _whitelist;

    /// @notice Auctioneer for Market ID
    mapping(uint256 => IBondAuctioneer) public marketsToAuctioneers;

    /// @notice Market IDs for payout token
    mapping(address => uint256[]) public marketsForPayout;

    /// @notice Market IDs for quote token
    mapping(address => uint256[]) public marketsForQuote;

    // A 'vesting' param longer than 50 years is considered a timestamp for fixed expiry.
    uint48 private constant MAX_FIXED_TERM = 52 weeks * 50;

    constructor(address guardian_, Authority authority_) Auth(guardian_, authority_) {}

    /// @inheritdoc IBondAggregator
    function registerAuctioneer(IBondAuctioneer auctioneer_) external requiresAuth {
        // Restricted to authorized addresses

        // Check that the auctioneer is not already registered
        if (_whitelist[address(auctioneer_)])
            revert Aggregator_AlreadyRegistered(address(auctioneer_));

        // Add the auctioneer to the whitelist
        auctioneers.push(auctioneer_);
        _whitelist[address(auctioneer_)] = true;
    }

    /// @inheritdoc IBondAggregator
    function registerMarket(ERC20 payoutToken_, ERC20 quoteToken_)
        external
        override
        returns (uint256 marketId)
    {
        if (!_whitelist[msg.sender]) revert Aggregator_OnlyAuctioneer();
        if (address(payoutToken_) == address(0) || address(quoteToken_) == address(0))
            revert Aggregator_InvalidParams();
        marketId = marketCounter;
        marketsToAuctioneers[marketId] = IBondAuctioneer(msg.sender);
        marketsForPayout[address(payoutToken_)].push(marketId);
        marketsForQuote[address(quoteToken_)].push(marketId);
        ++marketCounter;
    }

    /* ========== VIEW FUNCTIONS ========== */

    /// @inheritdoc IBondAggregator
    function getAuctioneer(uint256 id_) external view returns (IBondAuctioneer) {
        return marketsToAuctioneers[id_];
    }

    /// @inheritdoc IBondAggregator
    function marketPrice(uint256 id_) public view override returns (uint256) {
        IBondAuctioneer auctioneer = marketsToAuctioneers[id_];
        return auctioneer.marketPrice(id_);
    }

    /// @inheritdoc IBondAggregator
    function marketScale(uint256 id_) external view override returns (uint256) {
        IBondAuctioneer auctioneer = marketsToAuctioneers[id_];
        return auctioneer.marketScale(id_);
    }

    /// @inheritdoc IBondAggregator
    function payoutFor(
        uint256 amount_,
        uint256 id_,
        address referrer_
    ) public view override returns (uint256) {
        IBondAuctioneer auctioneer = marketsToAuctioneers[id_];
        return auctioneer.payoutFor(amount_, id_, referrer_);
    }

    /// @inheritdoc IBondAggregator
    function maxAmountAccepted(uint256 id_, address referrer_) external view returns (uint256) {
        IBondAuctioneer auctioneer = marketsToAuctioneers[id_];
        return auctioneer.maxAmountAccepted(id_, referrer_);
    }

    /// @inheritdoc IBondAggregator
    function isInstantSwap(uint256 id_) external view returns (bool) {
        IBondAuctioneer auctioneer = marketsToAuctioneers[id_];
        return auctioneer.isInstantSwap(id_);
    }

    /// @inheritdoc IBondAggregator
    function isLive(uint256 id_) public view override returns (bool) {
        IBondAuctioneer auctioneer = marketsToAuctioneers[id_];
        return auctioneer.isLive(id_);
    }

    /// @inheritdoc IBondAggregator
    function liveMarketsBetween(uint256 firstIndex_, uint256 lastIndex_)
        external
        view
        override
        returns (uint256[] memory)
    {
        uint256 count;
        for (uint256 i = firstIndex_; i < lastIndex_; ++i) {
            if (isLive(i)) ++count;
        }

        uint256[] memory ids = new uint256[](count);
        count = 0;
        for (uint256 i = firstIndex_; i < lastIndex_; ++i) {
            if (isLive(i)) {
                ids[count] = i;
                ++count;
            }
        }
        return ids;
    }

    /// @inheritdoc IBondAggregator
    function liveMarketsFor(address token_, bool isPayout_)
        public
        view
        override
        returns (uint256[] memory)
    {
        uint256[] memory mkts;

        mkts = isPayout_ ? marketsForPayout[token_] : marketsForQuote[token_];

        uint256 count;
        uint256 len = mkts.length;

        for (uint256 i; i < len; ++i) {
            if (isLive(mkts[i])) ++count;
        }

        uint256[] memory ids = new uint256[](count);
        count = 0;

        for (uint256 i; i < len; ++i) {
            if (isLive(mkts[i])) {
                ids[count] = mkts[i];
                ++count;
            }
        }

        return ids;
    }

    /// @inheritdoc IBondAggregator
    function marketsFor(address payout_, address quote_) public view returns (uint256[] memory) {
        uint256[] memory forPayout = liveMarketsFor(payout_, true);
        uint256 count;

        ERC20 quoteToken;
        IBondAuctioneer auctioneer;
        uint256 len = forPayout.length;
        for (uint256 i; i < len; ++i) {
            auctioneer = marketsToAuctioneers[forPayout[i]];
            (, , , quoteToken, , ) = auctioneer.getMarketInfoForPurchase(forPayout[i]);
            if (isLive(forPayout[i]) && address(quoteToken) == quote_) ++count;
        }

        uint256[] memory ids = new uint256[](count);
        count = 0;

        for (uint256 i; i < len; ++i) {
            auctioneer = marketsToAuctioneers[forPayout[i]];
            (, , , quoteToken, , ) = auctioneer.getMarketInfoForPurchase(forPayout[i]);
            if (isLive(forPayout[i]) && address(quoteToken) == quote_) {
                ids[count] = forPayout[i];
                ++count;
            }
        }

        return ids;
    }

    /// @inheritdoc IBondAggregator
    function findMarketFor(
        address payout_,
        address quote_,
        uint256 amountIn_,
        uint256 minAmountOut_,
        uint256 maxExpiry_
    ) external view returns (uint256) {
        uint256[] memory ids = marketsFor(payout_, quote_);
        uint256 len = ids.length;
        // uint256[] memory payouts = new uint256[](len);

        uint256 highestOut;
        uint256 id = type(uint256).max; // set to max so an empty set doesn't return 0, the first index
        uint48 vesting;
        uint256 maxPayout;
        IBondAuctioneer auctioneer;
        for (uint256 i; i < len; ++i) {
            auctioneer = marketsToAuctioneers[ids[i]];
            (, , , , vesting, maxPayout) = auctioneer.getMarketInfoForPurchase(ids[i]);

            uint256 expiry = (vesting <= MAX_FIXED_TERM) ? block.timestamp + vesting : vesting;

            if (expiry <= maxExpiry_) {
                if (minAmountOut_ <= maxPayout) {
                    try auctioneer.payoutFor(amountIn_, ids[i], address(0)) returns (
                        uint256 payout
                    ) {
                        if (payout > highestOut && payout >= minAmountOut_) {
                            highestOut = payout;
                            id = ids[i];
                        }
                    } catch {
                        // fail silently and try the next market
                    }
                }
            }
        }

        return id;
    }

    /// @inheritdoc IBondAggregator
    function liveMarketsBy(
        address owner_,
        uint256 firstIndex_,
        uint256 lastIndex_
    ) external view returns (uint256[] memory) {
        uint256 count;
        IBondAuctioneer auctioneer;
        for (uint256 i = firstIndex_; i < lastIndex_; ++i) {
            auctioneer = marketsToAuctioneers[i];
            if (auctioneer.isLive(i) && auctioneer.ownerOf(i) == owner_) {
                ++count;
            }
        }

        uint256[] memory ids = new uint256[](count);
        count = 0;
        for (uint256 j = firstIndex_; j < lastIndex_; ++j) {
            auctioneer = marketsToAuctioneers[j];
            if (auctioneer.isLive(j) && auctioneer.ownerOf(j) == owner_) {
                ids[count] = j;
                ++count;
            }
        }

        return ids;
    }

    /// @inheritdoc IBondAggregator
    function getTeller(uint256 id_) external view returns (IBondTeller) {
        IBondAuctioneer auctioneer = marketsToAuctioneers[id_];
        return auctioneer.getTeller();
    }

    /// @inheritdoc IBondAggregator
    function currentCapacity(uint256 id_) external view returns (uint256) {
        IBondAuctioneer auctioneer = marketsToAuctioneers[id_];
        return auctioneer.currentCapacity(id_);
    }
}

File 2 of 7 : Auth.sol
// 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);
}

File 3 of 7 : ERC20.sol
// 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);
    }
}

File 4 of 7 : IBondAggregator.sol
// 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);
}

File 5 of 7 : IBondAuctioneer.sol
// 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);
}

File 6 of 7 : IBondTeller.sol
// 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;
}

File 7 of 7 : FullMath.sol
// 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++;
            }
        }
    }
}

Settings
{
  "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": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"guardian_","type":"address"},{"internalType":"contract Authority","name":"authority_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"auctioneer_","type":"address"}],"name":"Aggregator_AlreadyRegistered","type":"error"},{"inputs":[],"name":"Aggregator_InvalidParams","type":"error"},{"inputs":[],"name":"Aggregator_OnlyAuctioneer","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":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctioneers","outputs":[{"internalType":"contract IBondAuctioneer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"currentCapacity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"payout_","type":"address"},{"internalType":"address","name":"quote_","type":"address"},{"internalType":"uint256","name":"amountIn_","type":"uint256"},{"internalType":"uint256","name":"minAmountOut_","type":"uint256"},{"internalType":"uint256","name":"maxExpiry_","type":"uint256"}],"name":"findMarketFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"getAuctioneer","outputs":[{"internalType":"contract IBondAuctioneer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"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":"firstIndex_","type":"uint256"},{"internalType":"uint256","name":"lastIndex_","type":"uint256"}],"name":"liveMarketsBetween","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"uint256","name":"firstIndex_","type":"uint256"},{"internalType":"uint256","name":"lastIndex_","type":"uint256"}],"name":"liveMarketsBy","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"bool","name":"isPayout_","type":"bool"}],"name":"liveMarketsFor","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"address","name":"payout_","type":"address"},{"internalType":"address","name":"quote_","type":"address"}],"name":"marketsFor","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketsForPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketsForQuote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketsToAuctioneers","outputs":[{"internalType":"contract IBondAuctioneer","name":"","type":"address"}],"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":[],"name":"owner","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":"contract IBondAuctioneer","name":"auctioneer_","type":"address"}],"name":"registerAuctioneer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"payoutToken_","type":"address"},{"internalType":"contract ERC20","name":"quoteToken_","type":"address"}],"name":"registerMarket","outputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506040516200216a3803806200216a8339810160408190526200003491620000e8565b600080546001600160a01b03199081166001600160a01b0385811691821784556001805490931690851617909155604051849284929133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7691a36040516001600160a01b0382169033907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a35050505062000127565b6001600160a01b0381168114620000e557600080fd5b50565b60008060408385031215620000fc57600080fd5b82516200010981620000cf565b60208401519092506200011c81620000cf565b809150509250929050565b61203380620001376000396000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c80638da5cb5b116100ee578063bf48582b11610097578063c3b7b13611610071578063c3b7b136146103c1578063c7bf8ca0146103d4578063ea5e0c60146103e7578063f9e709df1461041d57600080fd5b8063bf48582b1461037b578063bf7e214f1461038e578063c0680e20146103ae57600080fd5b8063b4359143116100c8578063b435914314610342578063bb6e75de14610355578063bbfe3a321461036857600080fd5b80638da5cb5b146102fc578063946824cd1461031c5780639a0fae9b1461032f57600080fd5b80634938a3fe1161015057806378b5a87a1161012a57806378b5a87a146102c35780637a9e5e4b146102d65780638b098db3146102e957600080fd5b80634938a3fe14610235578063520479421461025557806366b382ee146102b057600080fd5b8063247608071161018157806324760807146101f657806327507458146101ff5780633adec5a71461022257600080fd5b806306b40ea3146101a857806313af4035146101ce5780631c063a6c146101e3575b600080fd5b6101bb6101b6366004611c24565b610430565b6040519081526020015b60405180910390f35b6101e16101dc366004611c50565b610461565b005b6101bb6101f1366004611c6d565b61056a565b6101bb60025481565b61021261020d366004611c6d565b610613565b60405190151581526020016101c5565b6101bb610230366004611c6d565b6106b5565b610248610243366004611c86565b61071a565b6040516101c59190611cbb565b61028b610263366004611c6d565b60009081526005602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c5565b6101e16102be366004611c50565b610a96565b61028b6102d1366004611c6d565b610c4c565b6101e16102e4366004611c50565b610cea565b6102126102f7366004611c6d565b610e47565b60005461028b9073ffffffffffffffffffffffffffffffffffffffff1681565b6101bb61032a366004611c6d565b610eac565b6101bb61033d366004611cff565b610f11565b6101bb610350366004611d50565b6111ba565b610248610363366004611d89565b611317565b610248610376366004611d50565b6113f6565b6101bb610389366004611dab565b61177c565b60015461028b9073ffffffffffffffffffffffffffffffffffffffff1681565b6101bb6103bc366004611c24565b611835565b61028b6103cf366004611c6d565b611851565b6101bb6103e2366004611de4565b611888565b61028b6103f5366004611c6d565b60056020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61024861042b366004611e17565b611939565b6006602052816000526040600020818154811061044c57600080fd5b90600052602060002001600091509150505481565b61048f336000357fffffffff0000000000000000000000000000000000000000000000000000000016611aee565b6104fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b6000818152600560205260408082205490517f1c063a6c0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff909116908190631c063a6c906024015b602060405180830381865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190611e45565b9392505050565b6000818152600560205260408082205490517f275074580000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff9091169081906327507458906024015b602060405180830381865afa158015610691573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190611e5e565b6000818152600560205260408082205490517f3adec5a70000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff909116908190633adec5a7906024016105cb565b6060600080845b848110156108a057600081815260056020526040908190205490517f275074580000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff90911692508290632750745890602401602060405180830381865afa1580156107a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107cc9190611e5e565b801561087f57506040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff8089169190841690636352211e90602401602060405180830381865afa158015610843573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108679190611e7b565b73ffffffffffffffffffffffffffffffffffffffff16145b156108905761088d83611ec7565b92505b61089981611ec7565b9050610721565b5060008267ffffffffffffffff8111156108bc576108bc611eff565b6040519080825280602002602001820160405280156108e5578160200160208202803683370190505b50600093509050855b85811015610a8b57600081815260056020526040908190205490517f275074580000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff90911693508390632750745890602401602060405180830381865afa158015610975573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109999190611e5e565b8015610a4c57506040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff808a169190851690636352211e90602401602060405180830381865afa158015610a10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a349190611e7b565b73ffffffffffffffffffffffffffffffffffffffff16145b15610a7b5780828581518110610a6457610a64611f2e565b6020908102919091010152610a7884611ec7565b93505b610a8481611ec7565b90506108ee565b509695505050505050565b610ac4336000357fffffffff0000000000000000000000000000000000000000000000000000000016611aee565b610b2a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016104f1565b73ffffffffffffffffffffffffffffffffffffffff811660009081526004602052604090205460ff1615610ba2576040517fcba9dee200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016104f1565b6003805460018181019092557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b01805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff00000000000000000000000000000000000000009093168317905560009182526004602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055565b60008181526005602090815260408083205481517f9787d107000000000000000000000000000000000000000000000000000000008152915173ffffffffffffffffffffffffffffffffffffffff909116928392639787d10792600480830193928290030181865afa158015610cc6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190611e7b565b60005473ffffffffffffffffffffffffffffffffffffffff16331480610dcd57506001546040517fb70096130000000000000000000000000000000000000000000000000000000081523360048201523060248201526000357fffffffff0000000000000000000000000000000000000000000000000000000016604482015273ffffffffffffffffffffffffffffffffffffffff9091169063b700961390606401602060405180830381865afa158015610da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcd9190611e5e565b610dd657600080fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350565b6000818152600560205260408082205490517f8b098db30000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff909116908190638b098db390602401610674565b6000818152600560205260408082205490517f946824cd0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff90911690819063946824cd906024016105cb565b600080610f1e87876113f6565b805190915060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818080805b868110156111a85760056000898381518110610f6957610f69611f2e565b6020026020010151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508173ffffffffffffffffffffffffffffffffffffffff1663acc5570c898381518110610fd057610fd0611f2e565b60200260200101516040518263ffffffff1660e01b8152600401610ff691815260200190565b60c060405180830381865afa158015611013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110379190611f5d565b9098509650600093505050635dba240065ffffffffffff871611159050611066578465ffffffffffff16611078565b61107865ffffffffffff861642611fe5565b90508a811161119757838c11611197578273ffffffffffffffffffffffffffffffffffffffff1663bf48582b8e8b85815181106110b7576110b7611f2e565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526004810192909252602482015260006044820152606401602060405180830381865afa92505050801561115c575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261115991810190611e45565b60015b1561119757878111801561117057508c8110155b156111955780975089838151811061118a5761118a611f2e565b602002602001015196505b505b506111a181611ec7565b9050610f4b565b50929c9b505050505050505050505050565b3360009081526004602052604081205460ff16611203576040517f8feeaaa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316158061123a575073ffffffffffffffffffffffffffffffffffffffff8216155b15611271576040517f018c362a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060028054600081815260056020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905573ffffffffffffffffffffffffffffffffffffffff8781168452600683528184208054600181810183559186528486200186905590871684526007835290832080549182018155835290822001829055825491929161130d90611ec7565b9091555092915050565b60606000835b8381101561134f5761132e81610613565b1561133f5761133c82611ec7565b91505b61134881611ec7565b905061131d565b5060008167ffffffffffffffff81111561136b5761136b611eff565b604051908082528060200260200182016040528015611394578160200160208202803683370190505b50600092509050845b848110156113ed576113ae81610613565b156113dd57808284815181106113c6576113c6611f2e565b60209081029190910101526113da83611ec7565b92505b6113e681611ec7565b905061139d565b50949350505050565b60606000611405846001611939565b90506000806000808451905060005b81811015611585576005600087838151811061143257611432611f2e565b6020026020010151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692508273ffffffffffffffffffffffffffffffffffffffff1663acc5570c87838151811061149957611499611f2e565b60200260200101516040518263ffffffff1660e01b81526004016114bf91815260200190565b60c060405180830381865afa1580156114dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115009190611f5d565b5050895190975061152d9350899250849150811061152057611520611f2e565b6020026020010151610613565b801561156457508773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b156115755761157285611ec7565b94505b61157e81611ec7565b9050611414565b5060008467ffffffffffffffff8111156115a1576115a1611eff565b6040519080825280602002602001820160405280156115ca578160200160208202803683370190505b5090506000945060005b8281101561176f57600560008883815181106115f2576115f2611f2e565b6020026020010151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508373ffffffffffffffffffffffffffffffffffffffff1663acc5570c88838151811061165957611659611f2e565b60200260200101516040518263ffffffff1660e01b815260040161167f91815260200190565b60c060405180830381865afa15801561169c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116c09190611f5d565b50508a519098506116e093508a9250849150811061152057611520611f2e565b801561171757508873ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b1561175f5786818151811061172e5761172e611f2e565b602002602001015182878151811061174857611748611f2e565b602090810291909101015261175c86611ec7565b95505b61176881611ec7565b90506115d4565b5098975050505050505050565b6000828152600560205260408082205490517fbf48582b000000000000000000000000000000000000000000000000000000008152600481018690526024810185905273ffffffffffffffffffffffffffffffffffffffff848116604483015290911690819063bf48582b90606401602060405180830381865afa158015611808573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182c9190611e45565b95945050505050565b6007602052816000526040600020818154811061044c57600080fd5b6003818154811061186157600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b6000828152600560205260408082205490517fc7bf8ca00000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff848116602483015290911690819063c7bf8ca090604401602060405180830381865afa15801561190d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119319190611e45565b949350505050565b6060808261196b5773ffffffffffffffffffffffffffffffffffffffff84166000908152600760205260409020611991565b73ffffffffffffffffffffffffffffffffffffffff841660009081526006602052604090205b8054806020026020016040519081016040528092919081815260200182805480156119db57602002820191906000526020600020905b8154815260200190600101908083116119c7575b505050505090506000808251905060005b81811015611a2a57611a0984828151811061152057611520611f2e565b15611a1a57611a1783611ec7565b92505b611a2381611ec7565b90506119ec565b5060008267ffffffffffffffff811115611a4657611a46611eff565b604051908082528060200260200182016040528015611a6f578160200160208202803683370190505b5090506000925060005b82811015610a8b57611a9685828151811061152057611520611f2e565b15611ade57848181518110611aad57611aad611f2e565b6020026020010151828581518110611ac757611ac7611f2e565b6020908102919091010152611adb84611ec7565b93505b611ae781611ec7565b9050611a79565b60015460009073ffffffffffffffffffffffffffffffffffffffff168015801590611bd257506040517fb700961300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527fffffffff000000000000000000000000000000000000000000000000000000008516604483015282169063b700961390606401602060405180830381865afa158015611bae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd29190611e5e565b80611931575060005473ffffffffffffffffffffffffffffffffffffffff85811691161491505092915050565b73ffffffffffffffffffffffffffffffffffffffff81168114611c2157600080fd5b50565b60008060408385031215611c3757600080fd5b8235611c4281611bff565b946020939093013593505050565b600060208284031215611c6257600080fd5b813561060c81611bff565b600060208284031215611c7f57600080fd5b5035919050565b600080600060608486031215611c9b57600080fd5b8335611ca681611bff565b95602085013595506040909401359392505050565b6020808252825182820181905260009190848201906040850190845b81811015611cf357835183529284019291840191600101611cd7565b50909695505050505050565b600080600080600060a08688031215611d1757600080fd5b8535611d2281611bff565b94506020860135611d3281611bff565b94979496505050506040830135926060810135926080909101359150565b60008060408385031215611d6357600080fd5b8235611d6e81611bff565b91506020830135611d7e81611bff565b809150509250929050565b60008060408385031215611d9c57600080fd5b50508035926020909101359150565b600080600060608486031215611dc057600080fd5b83359250602084013591506040840135611dd981611bff565b809150509250925092565b60008060408385031215611df757600080fd5b823591506020830135611d7e81611bff565b8015158114611c2157600080fd5b60008060408385031215611e2a57600080fd5b8235611e3581611bff565b91506020830135611d7e81611e09565b600060208284031215611e5757600080fd5b5051919050565b600060208284031215611e7057600080fd5b815161060c81611e09565b600060208284031215611e8d57600080fd5b815161060c81611bff565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611ef857611ef8611e98565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060008060008060c08789031215611f7657600080fd5b8651611f8181611bff565b6020880151909650611f9281611bff565b6040880151909550611fa381611bff565b6060880151909450611fb481611bff565b608088015190935065ffffffffffff81168114611fd057600080fd5b8092505060a087015190509295509295509295565b60008219821115611ff857611ff8611e98565b50019056fea2646970667358221220ba286c6d6ce9c50ea976df0013cb65eb875fdf24af038e02dcb81b114cf03fd864736f6c634300080f0033000000000000000000000000007bd11fca0daaeadd455b51826f9a015f2f0969000000000000000000000000007a0f48a4e3d74ab4234adf9ea9eb32f87b4b14

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101a35760003560e01c80638da5cb5b116100ee578063bf48582b11610097578063c3b7b13611610071578063c3b7b136146103c1578063c7bf8ca0146103d4578063ea5e0c60146103e7578063f9e709df1461041d57600080fd5b8063bf48582b1461037b578063bf7e214f1461038e578063c0680e20146103ae57600080fd5b8063b4359143116100c8578063b435914314610342578063bb6e75de14610355578063bbfe3a321461036857600080fd5b80638da5cb5b146102fc578063946824cd1461031c5780639a0fae9b1461032f57600080fd5b80634938a3fe1161015057806378b5a87a1161012a57806378b5a87a146102c35780637a9e5e4b146102d65780638b098db3146102e957600080fd5b80634938a3fe14610235578063520479421461025557806366b382ee146102b057600080fd5b8063247608071161018157806324760807146101f657806327507458146101ff5780633adec5a71461022257600080fd5b806306b40ea3146101a857806313af4035146101ce5780631c063a6c146101e3575b600080fd5b6101bb6101b6366004611c24565b610430565b6040519081526020015b60405180910390f35b6101e16101dc366004611c50565b610461565b005b6101bb6101f1366004611c6d565b61056a565b6101bb60025481565b61021261020d366004611c6d565b610613565b60405190151581526020016101c5565b6101bb610230366004611c6d565b6106b5565b610248610243366004611c86565b61071a565b6040516101c59190611cbb565b61028b610263366004611c6d565b60009081526005602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c5565b6101e16102be366004611c50565b610a96565b61028b6102d1366004611c6d565b610c4c565b6101e16102e4366004611c50565b610cea565b6102126102f7366004611c6d565b610e47565b60005461028b9073ffffffffffffffffffffffffffffffffffffffff1681565b6101bb61032a366004611c6d565b610eac565b6101bb61033d366004611cff565b610f11565b6101bb610350366004611d50565b6111ba565b610248610363366004611d89565b611317565b610248610376366004611d50565b6113f6565b6101bb610389366004611dab565b61177c565b60015461028b9073ffffffffffffffffffffffffffffffffffffffff1681565b6101bb6103bc366004611c24565b611835565b61028b6103cf366004611c6d565b611851565b6101bb6103e2366004611de4565b611888565b61028b6103f5366004611c6d565b60056020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61024861042b366004611e17565b611939565b6006602052816000526040600020818154811061044c57600080fd5b90600052602060002001600091509150505481565b61048f336000357fffffffff0000000000000000000000000000000000000000000000000000000016611aee565b6104fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b6000818152600560205260408082205490517f1c063a6c0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff909116908190631c063a6c906024015b602060405180830381865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190611e45565b9392505050565b6000818152600560205260408082205490517f275074580000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff9091169081906327507458906024015b602060405180830381865afa158015610691573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190611e5e565b6000818152600560205260408082205490517f3adec5a70000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff909116908190633adec5a7906024016105cb565b6060600080845b848110156108a057600081815260056020526040908190205490517f275074580000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff90911692508290632750745890602401602060405180830381865afa1580156107a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107cc9190611e5e565b801561087f57506040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff8089169190841690636352211e90602401602060405180830381865afa158015610843573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108679190611e7b565b73ffffffffffffffffffffffffffffffffffffffff16145b156108905761088d83611ec7565b92505b61089981611ec7565b9050610721565b5060008267ffffffffffffffff8111156108bc576108bc611eff565b6040519080825280602002602001820160405280156108e5578160200160208202803683370190505b50600093509050855b85811015610a8b57600081815260056020526040908190205490517f275074580000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff90911693508390632750745890602401602060405180830381865afa158015610975573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109999190611e5e565b8015610a4c57506040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff808a169190851690636352211e90602401602060405180830381865afa158015610a10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a349190611e7b565b73ffffffffffffffffffffffffffffffffffffffff16145b15610a7b5780828581518110610a6457610a64611f2e565b6020908102919091010152610a7884611ec7565b93505b610a8481611ec7565b90506108ee565b509695505050505050565b610ac4336000357fffffffff0000000000000000000000000000000000000000000000000000000016611aee565b610b2a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016104f1565b73ffffffffffffffffffffffffffffffffffffffff811660009081526004602052604090205460ff1615610ba2576040517fcba9dee200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016104f1565b6003805460018181019092557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b01805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff00000000000000000000000000000000000000009093168317905560009182526004602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169091179055565b60008181526005602090815260408083205481517f9787d107000000000000000000000000000000000000000000000000000000008152915173ffffffffffffffffffffffffffffffffffffffff909116928392639787d10792600480830193928290030181865afa158015610cc6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190611e7b565b60005473ffffffffffffffffffffffffffffffffffffffff16331480610dcd57506001546040517fb70096130000000000000000000000000000000000000000000000000000000081523360048201523060248201526000357fffffffff0000000000000000000000000000000000000000000000000000000016604482015273ffffffffffffffffffffffffffffffffffffffff9091169063b700961390606401602060405180830381865afa158015610da9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcd9190611e5e565b610dd657600080fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350565b6000818152600560205260408082205490517f8b098db30000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff909116908190638b098db390602401610674565b6000818152600560205260408082205490517f946824cd0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff90911690819063946824cd906024016105cb565b600080610f1e87876113f6565b805190915060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818080805b868110156111a85760056000898381518110610f6957610f69611f2e565b6020026020010151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691508173ffffffffffffffffffffffffffffffffffffffff1663acc5570c898381518110610fd057610fd0611f2e565b60200260200101516040518263ffffffff1660e01b8152600401610ff691815260200190565b60c060405180830381865afa158015611013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110379190611f5d565b9098509650600093505050635dba240065ffffffffffff871611159050611066578465ffffffffffff16611078565b61107865ffffffffffff861642611fe5565b90508a811161119757838c11611197578273ffffffffffffffffffffffffffffffffffffffff1663bf48582b8e8b85815181106110b7576110b7611f2e565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526004810192909252602482015260006044820152606401602060405180830381865afa92505050801561115c575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261115991810190611e45565b60015b1561119757878111801561117057508c8110155b156111955780975089838151811061118a5761118a611f2e565b602002602001015196505b505b506111a181611ec7565b9050610f4b565b50929c9b505050505050505050505050565b3360009081526004602052604081205460ff16611203576040517f8feeaaa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316158061123a575073ffffffffffffffffffffffffffffffffffffffff8216155b15611271576040517f018c362a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060028054600081815260056020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905573ffffffffffffffffffffffffffffffffffffffff8781168452600683528184208054600181810183559186528486200186905590871684526007835290832080549182018155835290822001829055825491929161130d90611ec7565b9091555092915050565b60606000835b8381101561134f5761132e81610613565b1561133f5761133c82611ec7565b91505b61134881611ec7565b905061131d565b5060008167ffffffffffffffff81111561136b5761136b611eff565b604051908082528060200260200182016040528015611394578160200160208202803683370190505b50600092509050845b848110156113ed576113ae81610613565b156113dd57808284815181106113c6576113c6611f2e565b60209081029190910101526113da83611ec7565b92505b6113e681611ec7565b905061139d565b50949350505050565b60606000611405846001611939565b90506000806000808451905060005b81811015611585576005600087838151811061143257611432611f2e565b6020026020010151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692508273ffffffffffffffffffffffffffffffffffffffff1663acc5570c87838151811061149957611499611f2e565b60200260200101516040518263ffffffff1660e01b81526004016114bf91815260200190565b60c060405180830381865afa1580156114dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115009190611f5d565b5050895190975061152d9350899250849150811061152057611520611f2e565b6020026020010151610613565b801561156457508773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b156115755761157285611ec7565b94505b61157e81611ec7565b9050611414565b5060008467ffffffffffffffff8111156115a1576115a1611eff565b6040519080825280602002602001820160405280156115ca578160200160208202803683370190505b5090506000945060005b8281101561176f57600560008883815181106115f2576115f2611f2e565b6020026020010151815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1693508373ffffffffffffffffffffffffffffffffffffffff1663acc5570c88838151811061165957611659611f2e565b60200260200101516040518263ffffffff1660e01b815260040161167f91815260200190565b60c060405180830381865afa15801561169c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116c09190611f5d565b50508a519098506116e093508a9250849150811061152057611520611f2e565b801561171757508873ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b1561175f5786818151811061172e5761172e611f2e565b602002602001015182878151811061174857611748611f2e565b602090810291909101015261175c86611ec7565b95505b61176881611ec7565b90506115d4565b5098975050505050505050565b6000828152600560205260408082205490517fbf48582b000000000000000000000000000000000000000000000000000000008152600481018690526024810185905273ffffffffffffffffffffffffffffffffffffffff848116604483015290911690819063bf48582b90606401602060405180830381865afa158015611808573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182c9190611e45565b95945050505050565b6007602052816000526040600020818154811061044c57600080fd5b6003818154811061186157600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b6000828152600560205260408082205490517fc7bf8ca00000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff848116602483015290911690819063c7bf8ca090604401602060405180830381865afa15801561190d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119319190611e45565b949350505050565b6060808261196b5773ffffffffffffffffffffffffffffffffffffffff84166000908152600760205260409020611991565b73ffffffffffffffffffffffffffffffffffffffff841660009081526006602052604090205b8054806020026020016040519081016040528092919081815260200182805480156119db57602002820191906000526020600020905b8154815260200190600101908083116119c7575b505050505090506000808251905060005b81811015611a2a57611a0984828151811061152057611520611f2e565b15611a1a57611a1783611ec7565b92505b611a2381611ec7565b90506119ec565b5060008267ffffffffffffffff811115611a4657611a46611eff565b604051908082528060200260200182016040528015611a6f578160200160208202803683370190505b5090506000925060005b82811015610a8b57611a9685828151811061152057611520611f2e565b15611ade57848181518110611aad57611aad611f2e565b6020026020010151828581518110611ac757611ac7611f2e565b6020908102919091010152611adb84611ec7565b93505b611ae781611ec7565b9050611a79565b60015460009073ffffffffffffffffffffffffffffffffffffffff168015801590611bd257506040517fb700961300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527fffffffff000000000000000000000000000000000000000000000000000000008516604483015282169063b700961390606401602060405180830381865afa158015611bae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd29190611e5e565b80611931575060005473ffffffffffffffffffffffffffffffffffffffff85811691161491505092915050565b73ffffffffffffffffffffffffffffffffffffffff81168114611c2157600080fd5b50565b60008060408385031215611c3757600080fd5b8235611c4281611bff565b946020939093013593505050565b600060208284031215611c6257600080fd5b813561060c81611bff565b600060208284031215611c7f57600080fd5b5035919050565b600080600060608486031215611c9b57600080fd5b8335611ca681611bff565b95602085013595506040909401359392505050565b6020808252825182820181905260009190848201906040850190845b81811015611cf357835183529284019291840191600101611cd7565b50909695505050505050565b600080600080600060a08688031215611d1757600080fd5b8535611d2281611bff565b94506020860135611d3281611bff565b94979496505050506040830135926060810135926080909101359150565b60008060408385031215611d6357600080fd5b8235611d6e81611bff565b91506020830135611d7e81611bff565b809150509250929050565b60008060408385031215611d9c57600080fd5b50508035926020909101359150565b600080600060608486031215611dc057600080fd5b83359250602084013591506040840135611dd981611bff565b809150509250925092565b60008060408385031215611df757600080fd5b823591506020830135611d7e81611bff565b8015158114611c2157600080fd5b60008060408385031215611e2a57600080fd5b8235611e3581611bff565b91506020830135611d7e81611e09565b600060208284031215611e5757600080fd5b5051919050565b600060208284031215611e7057600080fd5b815161060c81611e09565b600060208284031215611e8d57600080fd5b815161060c81611bff565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611ef857611ef8611e98565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060008060008060c08789031215611f7657600080fd5b8651611f8181611bff565b6020880151909650611f9281611bff565b6040880151909550611fa381611bff565b6060880151909450611fb481611bff565b608088015190935065ffffffffffff81168114611fd057600080fd5b8092505060a087015190509295509295509295565b60008219821115611ff857611ff8611e98565b50019056fea2646970667358221220ba286c6d6ce9c50ea976df0013cb65eb875fdf24af038e02dcb81b114cf03fd864736f6c634300080f0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000007bd11fca0daaeadd455b51826f9a015f2f0969000000000000000000000000007a0f48a4e3d74ab4234adf9ea9eb32f87b4b14

-----Decoded View---------------
Arg [0] : guardian_ (address): 0x007BD11FCa0dAaeaDD455b51826F9a015f2f0969
Arg [1] : authority_ (address): 0x007A0F48A4e3d74Ab4234adf9eA9EB32f87b4b14

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000007bd11fca0daaeadd455b51826f9a015f2f0969
Arg [1] : 000000000000000000000000007a0f48a4e3d74ab4234adf9ea9eb32f87b4b14


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.