Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
NounsAuctionHouse
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0 /// @title The CNNouns DAO auction house /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ // LICENSE // NounsAuctionHouse.sol is a modified version of Zora's AuctionHouse.sol: // https://github.com/ourzora/auction-house/blob/54a12ec1a6cf562e49f0a4917990474b11350a2d/contracts/AuctionHouse.sol // // AuctionHouse.sol source code Copyright Zora licensed under the GPL-3.0 license. // With modifications by Nounders DAO. // With modifications by CNNouns DAO. pragma solidity ^0.8.6; import { PausableUpgradeable } from '@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol'; import { ReentrancyGuardUpgradeable } from '@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol'; import { OwnableUpgradeable } from '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import { ABDKMathQuad } from 'abdk-libraries-solidity/ABDKMathQuad.sol'; import { INounsAuctionHouse } from './interfaces/INounsAuctionHouse.sol'; import { INounsToken } from './interfaces/INounsToken.sol'; import { IWETH } from './interfaces/IWETH.sol'; contract NounsAuctionHouse is INounsAuctionHouse, PausableUpgradeable, ReentrancyGuardUpgradeable, OwnableUpgradeable { // The Nouns ERC721 token contract INounsToken public nouns; // The address of the WETH contract address public weth; // The minimum amount of time left in an auction after a new bid is created uint256 public timeBuffer; // The minimum price accepted in an auction uint256 public reservePrice; // The minimum percentage difference between the last bid amount and the current bid uint8 public minBidIncrementPercentage; // The base duration of a single auction uint256 public baseDuration; // The origin date for calculating duration uint256 public origin; // The active auction INounsAuctionHouse.Auction public auction; /** * @notice Initialize the auction house and base contracts, * populate configuration values, and pause the contract. * @dev This function can only be called once. */ function initialize( INounsToken _nouns, address _weth, uint256 _timeBuffer, uint256 _reservePrice, uint8 _minBidIncrementPercentage, uint256 _baseDuration ) external initializer { __Pausable_init(); __ReentrancyGuard_init(); __Ownable_init(); _pause(); nouns = _nouns; weth = _weth; timeBuffer = _timeBuffer; reservePrice = _reservePrice; minBidIncrementPercentage = _minBidIncrementPercentage; baseDuration = _baseDuration; origin = block.timestamp; } /** * @notice Settle the current auction, mint a new Noun, and put it up for auction. */ function settleCurrentAndCreateNewAuction() external override nonReentrant whenNotPaused { _settleAuction(); _createAuction(); } /** * @notice Settle the current auction. * @dev This function can only be called when the contract is paused. */ function settleAuction() external override whenPaused nonReentrant { _settleAuction(); } /** * @notice Create a bid for a Noun, with a given amount. * @dev This contract only accepts payment in ETH. */ function createBid(uint256 nounId) external payable override nonReentrant { INounsAuctionHouse.Auction memory _auction = auction; require(_auction.nounId == nounId, 'Noun not up for auction'); require(block.timestamp < _auction.endTime, 'Auction expired'); require(msg.value >= reservePrice, 'Must send at least reservePrice'); require( msg.value >= _auction.amount + ((_auction.amount * minBidIncrementPercentage) / 100), 'Must send more than last bid by minBidIncrementPercentage amount' ); address payable lastBidder = _auction.bidder; // Refund the last bidder, if applicable if (lastBidder != address(0)) { _safeTransferETHWithFallback(lastBidder, _auction.amount); } auction.amount = msg.value; auction.bidder = payable(msg.sender); // Extend the auction if the bid was received within `timeBuffer` of the auction end time bool extended = _auction.endTime - block.timestamp < timeBuffer; if (extended) { auction.endTime = _auction.endTime = block.timestamp + timeBuffer; } emit AuctionBid(_auction.nounId, msg.sender, msg.value, extended); if (extended) { emit AuctionExtended(_auction.nounId, _auction.endTime); } } /** * @notice Pause the Nouns auction house. * @dev This function can only be called by the owner when the * contract is unpaused. While no new auctions can be started when paused, * anyone can settle an ongoing auction. */ function pause() external override onlyOwner { _pause(); } /** * @notice Unpause the Nouns auction house. * @dev This function can only be called by the owner when the * contract is paused. If required, this function will start a new auction. */ function unpause() external override onlyOwner { _unpause(); if (auction.startTime == 0 || auction.settled) { _createAuction(); } } /** * @notice Set the auction time buffer. * @dev Only callable by the owner. */ function setTimeBuffer(uint256 _timeBuffer) external override onlyOwner { timeBuffer = _timeBuffer; emit AuctionTimeBufferUpdated(_timeBuffer); } /** * @notice Set the auction reserve price. * @dev Only callable by the owner. */ function setReservePrice(uint256 _reservePrice) external override onlyOwner { reservePrice = _reservePrice; emit AuctionReservePriceUpdated(_reservePrice); } /** * @notice Set the auction minimum bid increment percentage. * @dev Only callable by the owner. */ function setMinBidIncrementPercentage(uint8 _minBidIncrementPercentage) external override onlyOwner { minBidIncrementPercentage = _minBidIncrementPercentage; emit AuctionMinBidIncrementPercentageUpdated(_minBidIncrementPercentage); } /** * @notice Calculate a next auction duration. */ function _calcDuration(uint256 _timestamp) internal view returns (uint256) { // It implements a geometric sequence that doubles in 4 years with // an upper limit of 1.4 years uint256 interval = _timestamp - origin; if (interval >= 1135296000) { return 44236800; } else if (interval < 0) { interval = 0; } bytes16 x = ABDKMathQuad.fromUInt(interval); x = ABDKMathQuad.div(x, ABDKMathQuad.fromUInt(1460 * 86400)); x = ABDKMathQuad.pow_2(x); x = ABDKMathQuad.mul(x, ABDKMathQuad.fromUInt(baseDuration)); return ABDKMathQuad.toUInt(x); } /** * @notice Create an auction. * @dev Store the auction details in the `auction` state variable and emit an AuctionCreated event. * If the mint reverts, the minter was updated without pausing this contract first. To remedy this, * catch the revert and pause this contract. */ function _createAuction() internal { try nouns.mint() returns (uint256 nounId) { uint256 startTime = block.timestamp; uint256 endTime = startTime + _calcDuration(startTime); auction = Auction({ nounId: nounId, amount: 0, startTime: startTime, endTime: endTime, bidder: payable(0), settled: false }); emit AuctionCreated(nounId, startTime, endTime); } catch Error(string memory) { _pause(); } } /** * @notice Settle an auction, finalizing the bid and paying out to the owner. * @dev If there are no bids, the Noun is burned. */ function _settleAuction() internal { INounsAuctionHouse.Auction memory _auction = auction; require(_auction.startTime != 0, "Auction hasn't begun"); require(!_auction.settled, 'Auction has already been settled'); require(block.timestamp >= _auction.endTime, "Auction hasn't completed"); auction.settled = true; if (_auction.bidder == address(0)) { nouns.burn(_auction.nounId); } else { nouns.transferFrom(address(this), _auction.bidder, _auction.nounId); } if (_auction.amount > 0) { _safeTransferETHWithFallback(owner(), _auction.amount); } emit AuctionSettled(_auction.nounId, _auction.bidder, _auction.amount); } /** * @notice Transfer ETH. If the ETH transfer fails, wrap the ETH and try send it as WETH. */ function _safeTransferETHWithFallback(address to, uint256 amount) internal { if (!_safeTransferETH(to, amount)) { IWETH(weth).deposit{ value: amount }(); IERC20(weth).transfer(to, amount); } } /** * @notice Transfer ETH and return the success status. * @dev This function only forwards 30,000 gas to the callee. */ function _safeTransferETH(address to, uint256 value) internal returns (bool) { (bool success, ) = to.call{ value: value, gas: 30_000 }(new bytes(0)); return success; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal initializer { __Context_init_unchained(); __Pausable_init_unchained(); } function __Pausable_init_unchained() internal initializer { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal initializer { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal initializer { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal initializer { __Context_init_unchained(); __Ownable_init_unchained(); } function __Ownable_init_unchained() internal initializer { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: BSD-4-Clause /* * ABDK Math Quad Smart Contract Library. Copyright © 2019 by ABDK Consulting. * Author: Mikhail Vladimirov <[email protected]> */ pragma solidity ^0.8.0; /** * Smart contract library of mathematical functions operating with IEEE 754 * quadruple-precision binary floating-point numbers (quadruple precision * numbers). As long as quadruple precision numbers are 16-bytes long, they are * represented by bytes16 type. */ library ABDKMathQuad { /* * 0. */ bytes16 private constant POSITIVE_ZERO = 0x00000000000000000000000000000000; /* * -0. */ bytes16 private constant NEGATIVE_ZERO = 0x80000000000000000000000000000000; /* * +Infinity. */ bytes16 private constant POSITIVE_INFINITY = 0x7FFF0000000000000000000000000000; /* * -Infinity. */ bytes16 private constant NEGATIVE_INFINITY = 0xFFFF0000000000000000000000000000; /* * Canonical NaN value. */ bytes16 private constant NaN = 0x7FFF8000000000000000000000000000; /** * Convert signed 256-bit integer number into quadruple precision number. * * @param x signed 256-bit integer number * @return quadruple precision number */ function fromInt (int256 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16 (0); else { // We rely on overflow behavior here uint256 result = uint256 (x > 0 ? x : -x); uint256 msb = mostSignificantBit (result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16383 + msb << 112; if (x < 0) result |= 0x80000000000000000000000000000000; return bytes16 (uint128 (result)); } } } /** * Convert quadruple precision number into signed 256-bit integer number * rounding towards zero. Revert on overflow. * * @param x quadruple precision number * @return signed 256-bit integer number */ function toInt (bytes16 x) internal pure returns (int256) { unchecked { uint256 exponent = uint128 (x) >> 112 & 0x7FFF; require (exponent <= 16638); // Overflow if (exponent < 16383) return 0; // Underflow uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 0x10000000000000000000000000000; if (exponent < 16495) result >>= 16495 - exponent; else if (exponent > 16495) result <<= exponent - 16495; if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative require (result <= 0x8000000000000000000000000000000000000000000000000000000000000000); return -int256 (result); // We rely on overflow behavior here } else { require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int256 (result); } } } /** * Convert unsigned 256-bit integer number into quadruple precision number. * * @param x unsigned 256-bit integer number * @return quadruple precision number */ function fromUInt (uint256 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16 (0); else { uint256 result = x; uint256 msb = mostSignificantBit (result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16383 + msb << 112; return bytes16 (uint128 (result)); } } } /** * Convert quadruple precision number into unsigned 256-bit integer number * rounding towards zero. Revert on underflow. Note, that negative floating * point numbers in range (-1.0 .. 0.0) may be converted to unsigned integer * without error, because they are rounded to zero. * * @param x quadruple precision number * @return unsigned 256-bit integer number */ function toUInt (bytes16 x) internal pure returns (uint256) { unchecked { uint256 exponent = uint128 (x) >> 112 & 0x7FFF; if (exponent < 16383) return 0; // Underflow require (uint128 (x) < 0x80000000000000000000000000000000); // Negative require (exponent <= 16638); // Overflow uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 0x10000000000000000000000000000; if (exponent < 16495) result >>= 16495 - exponent; else if (exponent > 16495) result <<= exponent - 16495; return result; } } /** * Convert signed 128.128 bit fixed point number into quadruple precision * number. * * @param x signed 128.128 bit fixed point number * @return quadruple precision number */ function from128x128 (int256 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16 (0); else { // We rely on overflow behavior here uint256 result = uint256 (x > 0 ? x : -x); uint256 msb = mostSignificantBit (result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16255 + msb << 112; if (x < 0) result |= 0x80000000000000000000000000000000; return bytes16 (uint128 (result)); } } } /** * Convert quadruple precision number into signed 128.128 bit fixed point * number. Revert on overflow. * * @param x quadruple precision number * @return signed 128.128 bit fixed point number */ function to128x128 (bytes16 x) internal pure returns (int256) { unchecked { uint256 exponent = uint128 (x) >> 112 & 0x7FFF; require (exponent <= 16510); // Overflow if (exponent < 16255) return 0; // Underflow uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 0x10000000000000000000000000000; if (exponent < 16367) result >>= 16367 - exponent; else if (exponent > 16367) result <<= exponent - 16367; if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative require (result <= 0x8000000000000000000000000000000000000000000000000000000000000000); return -int256 (result); // We rely on overflow behavior here } else { require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int256 (result); } } } /** * Convert signed 64.64 bit fixed point number into quadruple precision * number. * * @param x signed 64.64 bit fixed point number * @return quadruple precision number */ function from64x64 (int128 x) internal pure returns (bytes16) { unchecked { if (x == 0) return bytes16 (0); else { // We rely on overflow behavior here uint256 result = uint128 (x > 0 ? x : -x); uint256 msb = mostSignificantBit (result); if (msb < 112) result <<= 112 - msb; else if (msb > 112) result >>= msb - 112; result = result & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 16319 + msb << 112; if (x < 0) result |= 0x80000000000000000000000000000000; return bytes16 (uint128 (result)); } } } /** * Convert quadruple precision number into signed 64.64 bit fixed point * number. Revert on overflow. * * @param x quadruple precision number * @return signed 64.64 bit fixed point number */ function to64x64 (bytes16 x) internal pure returns (int128) { unchecked { uint256 exponent = uint128 (x) >> 112 & 0x7FFF; require (exponent <= 16446); // Overflow if (exponent < 16319) return 0; // Underflow uint256 result = uint256 (uint128 (x)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF | 0x10000000000000000000000000000; if (exponent < 16431) result >>= 16431 - exponent; else if (exponent > 16431) result <<= exponent - 16431; if (uint128 (x) >= 0x80000000000000000000000000000000) { // Negative require (result <= 0x80000000000000000000000000000000); return -int128 (int256 (result)); // We rely on overflow behavior here } else { require (result <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int128 (int256 (result)); } } } /** * Convert octuple precision number into quadruple precision number. * * @param x octuple precision number * @return quadruple precision number */ function fromOctuple (bytes32 x) internal pure returns (bytes16) { unchecked { bool negative = x & 0x8000000000000000000000000000000000000000000000000000000000000000 > 0; uint256 exponent = uint256 (x) >> 236 & 0x7FFFF; uint256 significand = uint256 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (exponent == 0x7FFFF) { if (significand > 0) return NaN; else return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY; } if (exponent > 278526) return negative ? NEGATIVE_INFINITY : POSITIVE_INFINITY; else if (exponent < 245649) return negative ? NEGATIVE_ZERO : POSITIVE_ZERO; else if (exponent < 245761) { significand = (significand | 0x100000000000000000000000000000000000000000000000000000000000) >> 245885 - exponent; exponent = 0; } else { significand >>= 124; exponent -= 245760; } uint128 result = uint128 (significand | exponent << 112); if (negative) result |= 0x80000000000000000000000000000000; return bytes16 (result); } } /** * Convert quadruple precision number into octuple precision number. * * @param x quadruple precision number * @return octuple precision number */ function toOctuple (bytes16 x) internal pure returns (bytes32) { unchecked { uint256 exponent = uint128 (x) >> 112 & 0x7FFF; uint256 result = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (exponent == 0x7FFF) exponent = 0x7FFFF; // Infinity or NaN else if (exponent == 0) { if (result > 0) { uint256 msb = mostSignificantBit (result); result = result << 236 - msb & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; exponent = 245649 + msb; } } else { result <<= 124; exponent += 245760; } result |= exponent << 236; if (uint128 (x) >= 0x80000000000000000000000000000000) result |= 0x8000000000000000000000000000000000000000000000000000000000000000; return bytes32 (result); } } /** * Convert double precision number into quadruple precision number. * * @param x double precision number * @return quadruple precision number */ function fromDouble (bytes8 x) internal pure returns (bytes16) { unchecked { uint256 exponent = uint64 (x) >> 52 & 0x7FF; uint256 result = uint64 (x) & 0xFFFFFFFFFFFFF; if (exponent == 0x7FF) exponent = 0x7FFF; // Infinity or NaN else if (exponent == 0) { if (result > 0) { uint256 msb = mostSignificantBit (result); result = result << 112 - msb & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; exponent = 15309 + msb; } } else { result <<= 60; exponent += 15360; } result |= exponent << 112; if (x & 0x8000000000000000 > 0) result |= 0x80000000000000000000000000000000; return bytes16 (uint128 (result)); } } /** * Convert quadruple precision number into double precision number. * * @param x quadruple precision number * @return double precision number */ function toDouble (bytes16 x) internal pure returns (bytes8) { unchecked { bool negative = uint128 (x) >= 0x80000000000000000000000000000000; uint256 exponent = uint128 (x) >> 112 & 0x7FFF; uint256 significand = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (exponent == 0x7FFF) { if (significand > 0) return 0x7FF8000000000000; // NaN else return negative ? bytes8 (0xFFF0000000000000) : // -Infinity bytes8 (0x7FF0000000000000); // Infinity } if (exponent > 17406) return negative ? bytes8 (0xFFF0000000000000) : // -Infinity bytes8 (0x7FF0000000000000); // Infinity else if (exponent < 15309) return negative ? bytes8 (0x8000000000000000) : // -0 bytes8 (0x0000000000000000); // 0 else if (exponent < 15361) { significand = (significand | 0x10000000000000000000000000000) >> 15421 - exponent; exponent = 0; } else { significand >>= 60; exponent -= 15360; } uint64 result = uint64 (significand | exponent << 52); if (negative) result |= 0x8000000000000000; return bytes8 (result); } } /** * Test whether given quadruple precision number is NaN. * * @param x quadruple precision number * @return true if x is NaN, false otherwise */ function isNaN (bytes16 x) internal pure returns (bool) { unchecked { return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF > 0x7FFF0000000000000000000000000000; } } /** * Test whether given quadruple precision number is positive or negative * infinity. * * @param x quadruple precision number * @return true if x is positive or negative infinity, false otherwise */ function isInfinity (bytes16 x) internal pure returns (bool) { unchecked { return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x7FFF0000000000000000000000000000; } } /** * Calculate sign of x, i.e. -1 if x is negative, 0 if x if zero, and 1 if x * is positive. Note that sign (-0) is zero. Revert if x is NaN. * * @param x quadruple precision number * @return sign of x */ function sign (bytes16 x) internal pure returns (int8) { unchecked { uint128 absoluteX = uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; require (absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN if (absoluteX == 0) return 0; else if (uint128 (x) >= 0x80000000000000000000000000000000) return -1; else return 1; } } /** * Calculate sign (x - y). Revert if either argument is NaN, or both * arguments are infinities of the same sign. * * @param x quadruple precision number * @param y quadruple precision number * @return sign (x - y) */ function cmp (bytes16 x, bytes16 y) internal pure returns (int8) { unchecked { uint128 absoluteX = uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; require (absoluteX <= 0x7FFF0000000000000000000000000000); // Not NaN uint128 absoluteY = uint128 (y) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; require (absoluteY <= 0x7FFF0000000000000000000000000000); // Not NaN // Not infinities of the same sign require (x != y || absoluteX < 0x7FFF0000000000000000000000000000); if (x == y) return 0; else { bool negativeX = uint128 (x) >= 0x80000000000000000000000000000000; bool negativeY = uint128 (y) >= 0x80000000000000000000000000000000; if (negativeX) { if (negativeY) return absoluteX > absoluteY ? -1 : int8 (1); else return -1; } else { if (negativeY) return 1; else return absoluteX > absoluteY ? int8 (1) : -1; } } } } /** * Test whether x equals y. NaN, infinity, and -infinity are not equal to * anything. * * @param x quadruple precision number * @param y quadruple precision number * @return true if x equals to y, false otherwise */ function eq (bytes16 x, bytes16 y) internal pure returns (bool) { unchecked { if (x == y) { return uint128 (x) & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF < 0x7FFF0000000000000000000000000000; } else return false; } } /** * Calculate x + y. Special values behave in the following way: * * NaN + x = NaN for any x. * Infinity + x = Infinity for any finite x. * -Infinity + x = -Infinity for any finite x. * Infinity + Infinity = Infinity. * -Infinity + -Infinity = -Infinity. * Infinity + -Infinity = -Infinity + Infinity = NaN. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function add (bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; uint256 yExponent = uint128 (y) >> 112 & 0x7FFF; if (xExponent == 0x7FFF) { if (yExponent == 0x7FFF) { if (x == y) return x; else return NaN; } else return x; } else if (yExponent == 0x7FFF) return y; else { bool xSign = uint128 (x) >= 0x80000000000000000000000000000000; uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; bool ySign = uint128 (y) >= 0x80000000000000000000000000000000; uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (yExponent == 0) yExponent = 1; else ySignifier |= 0x10000000000000000000000000000; if (xSignifier == 0) return y == NEGATIVE_ZERO ? POSITIVE_ZERO : y; else if (ySignifier == 0) return x == NEGATIVE_ZERO ? POSITIVE_ZERO : x; else { int256 delta = int256 (xExponent) - int256 (yExponent); if (xSign == ySign) { if (delta > 112) return x; else if (delta > 0) ySignifier >>= uint256 (delta); else if (delta < -112) return y; else if (delta < 0) { xSignifier >>= uint256 (-delta); xExponent = yExponent; } xSignifier += ySignifier; if (xSignifier >= 0x20000000000000000000000000000) { xSignifier >>= 1; xExponent += 1; } if (xExponent == 0x7FFF) return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY; else { if (xSignifier < 0x10000000000000000000000000000) xExponent = 0; else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; return bytes16 (uint128 ( (xSign ? 0x80000000000000000000000000000000 : 0) | (xExponent << 112) | xSignifier)); } } else { if (delta > 0) { xSignifier <<= 1; xExponent -= 1; } else if (delta < 0) { ySignifier <<= 1; xExponent = yExponent - 1; } if (delta > 112) ySignifier = 1; else if (delta > 1) ySignifier = (ySignifier - 1 >> uint256 (delta - 1)) + 1; else if (delta < -112) xSignifier = 1; else if (delta < -1) xSignifier = (xSignifier - 1 >> uint256 (-delta - 1)) + 1; if (xSignifier >= ySignifier) xSignifier -= ySignifier; else { xSignifier = ySignifier - xSignifier; xSign = ySign; } if (xSignifier == 0) return POSITIVE_ZERO; uint256 msb = mostSignificantBit (xSignifier); if (msb == 113) { xSignifier = xSignifier >> 1 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent += 1; } else if (msb < 112) { uint256 shift = 112 - msb; if (xExponent > shift) { xSignifier = xSignifier << shift & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent -= shift; } else { xSignifier <<= xExponent - 1; xExponent = 0; } } else xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0x7FFF) return xSign ? NEGATIVE_INFINITY : POSITIVE_INFINITY; else return bytes16 (uint128 ( (xSign ? 0x80000000000000000000000000000000 : 0) | (xExponent << 112) | xSignifier)); } } } } } /** * Calculate x - y. Special values behave in the following way: * * NaN - x = NaN for any x. * Infinity - x = Infinity for any finite x. * -Infinity - x = -Infinity for any finite x. * Infinity - -Infinity = Infinity. * -Infinity - Infinity = -Infinity. * Infinity - Infinity = -Infinity - -Infinity = NaN. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function sub (bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { return add (x, y ^ 0x80000000000000000000000000000000); } } /** * Calculate x * y. Special values behave in the following way: * * NaN * x = NaN for any x. * Infinity * x = Infinity for any finite positive x. * Infinity * x = -Infinity for any finite negative x. * -Infinity * x = -Infinity for any finite positive x. * -Infinity * x = Infinity for any finite negative x. * Infinity * 0 = NaN. * -Infinity * 0 = NaN. * Infinity * Infinity = Infinity. * Infinity * -Infinity = -Infinity. * -Infinity * Infinity = -Infinity. * -Infinity * -Infinity = Infinity. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function mul (bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; uint256 yExponent = uint128 (y) >> 112 & 0x7FFF; if (xExponent == 0x7FFF) { if (yExponent == 0x7FFF) { if (x == y) return x ^ y & 0x80000000000000000000000000000000; else if (x ^ y == 0x80000000000000000000000000000000) return x | y; else return NaN; } else { if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; else return x ^ y & 0x80000000000000000000000000000000; } } else if (yExponent == 0x7FFF) { if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; else return y ^ x & 0x80000000000000000000000000000000; } else { uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (yExponent == 0) yExponent = 1; else ySignifier |= 0x10000000000000000000000000000; xSignifier *= ySignifier; if (xSignifier == 0) return (x ^ y) & 0x80000000000000000000000000000000 > 0 ? NEGATIVE_ZERO : POSITIVE_ZERO; xExponent += yExponent; uint256 msb = xSignifier >= 0x200000000000000000000000000000000000000000000000000000000 ? 225 : xSignifier >= 0x100000000000000000000000000000000000000000000000000000000 ? 224 : mostSignificantBit (xSignifier); if (xExponent + msb < 16496) { // Underflow xExponent = 0; xSignifier = 0; } else if (xExponent + msb < 16608) { // Subnormal if (xExponent < 16496) xSignifier >>= 16496 - xExponent; else if (xExponent > 16496) xSignifier <<= xExponent - 16496; xExponent = 0; } else if (xExponent + msb > 49373) { xExponent = 0x7FFF; xSignifier = 0; } else { if (msb > 112) xSignifier >>= msb - 112; else if (msb < 112) xSignifier <<= 112 - msb; xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent = xExponent + msb - 16607; } return bytes16 (uint128 (uint128 ((x ^ y) & 0x80000000000000000000000000000000) | xExponent << 112 | xSignifier)); } } } /** * Calculate x / y. Special values behave in the following way: * * NaN / x = NaN for any x. * x / NaN = NaN for any x. * Infinity / x = Infinity for any finite non-negative x. * Infinity / x = -Infinity for any finite negative x including -0. * -Infinity / x = -Infinity for any finite non-negative x. * -Infinity / x = Infinity for any finite negative x including -0. * x / Infinity = 0 for any finite non-negative x. * x / -Infinity = -0 for any finite non-negative x. * x / Infinity = -0 for any finite non-negative x including -0. * x / -Infinity = 0 for any finite non-negative x including -0. * * Infinity / Infinity = NaN. * Infinity / -Infinity = -NaN. * -Infinity / Infinity = -NaN. * -Infinity / -Infinity = NaN. * * Division by zero behaves in the following way: * * x / 0 = Infinity for any finite positive x. * x / -0 = -Infinity for any finite positive x. * x / 0 = -Infinity for any finite negative x. * x / -0 = Infinity for any finite negative x. * 0 / 0 = NaN. * 0 / -0 = NaN. * -0 / 0 = NaN. * -0 / -0 = NaN. * * @param x quadruple precision number * @param y quadruple precision number * @return quadruple precision number */ function div (bytes16 x, bytes16 y) internal pure returns (bytes16) { unchecked { uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; uint256 yExponent = uint128 (y) >> 112 & 0x7FFF; if (xExponent == 0x7FFF) { if (yExponent == 0x7FFF) return NaN; else return x ^ y & 0x80000000000000000000000000000000; } else if (yExponent == 0x7FFF) { if (y & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFF != 0) return NaN; else return POSITIVE_ZERO | (x ^ y) & 0x80000000000000000000000000000000; } else if (y & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) { if (x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) return NaN; else return POSITIVE_INFINITY | (x ^ y) & 0x80000000000000000000000000000000; } else { uint256 ySignifier = uint128 (y) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (yExponent == 0) yExponent = 1; else ySignifier |= 0x10000000000000000000000000000; uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) { if (xSignifier != 0) { uint shift = 226 - mostSignificantBit (xSignifier); xSignifier <<= shift; xExponent = 1; yExponent += shift - 114; } } else { xSignifier = (xSignifier | 0x10000000000000000000000000000) << 114; } xSignifier = xSignifier / ySignifier; if (xSignifier == 0) return (x ^ y) & 0x80000000000000000000000000000000 > 0 ? NEGATIVE_ZERO : POSITIVE_ZERO; assert (xSignifier >= 0x1000000000000000000000000000); uint256 msb = xSignifier >= 0x80000000000000000000000000000 ? mostSignificantBit (xSignifier) : xSignifier >= 0x40000000000000000000000000000 ? 114 : xSignifier >= 0x20000000000000000000000000000 ? 113 : 112; if (xExponent + msb > yExponent + 16497) { // Overflow xExponent = 0x7FFF; xSignifier = 0; } else if (xExponent + msb + 16380 < yExponent) { // Underflow xExponent = 0; xSignifier = 0; } else if (xExponent + msb + 16268 < yExponent) { // Subnormal if (xExponent + 16380 > yExponent) xSignifier <<= xExponent + 16380 - yExponent; else if (xExponent + 16380 < yExponent) xSignifier >>= yExponent - xExponent - 16380; xExponent = 0; } else { // Normal if (msb > 112) xSignifier >>= msb - 112; xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; xExponent = xExponent + msb + 16269 - yExponent; } return bytes16 (uint128 (uint128 ((x ^ y) & 0x80000000000000000000000000000000) | xExponent << 112 | xSignifier)); } } } /** * Calculate -x. * * @param x quadruple precision number * @return quadruple precision number */ function neg (bytes16 x) internal pure returns (bytes16) { unchecked { return x ^ 0x80000000000000000000000000000000; } } /** * Calculate |x|. * * @param x quadruple precision number * @return quadruple precision number */ function abs (bytes16 x) internal pure returns (bytes16) { unchecked { return x & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; } } /** * Calculate square root of x. Return NaN on negative x excluding -0. * * @param x quadruple precision number * @return quadruple precision number */ function sqrt (bytes16 x) internal pure returns (bytes16) { unchecked { if (uint128 (x) > 0x80000000000000000000000000000000) return NaN; else { uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; if (xExponent == 0x7FFF) return x; else { uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; if (xSignifier == 0) return POSITIVE_ZERO; bool oddExponent = xExponent & 0x1 == 0; xExponent = xExponent + 16383 >> 1; if (oddExponent) { if (xSignifier >= 0x10000000000000000000000000000) xSignifier <<= 113; else { uint256 msb = mostSignificantBit (xSignifier); uint256 shift = (226 - msb) & 0xFE; xSignifier <<= shift; xExponent -= shift - 112 >> 1; } } else { if (xSignifier >= 0x10000000000000000000000000000) xSignifier <<= 112; else { uint256 msb = mostSignificantBit (xSignifier); uint256 shift = (225 - msb) & 0xFE; xSignifier <<= shift; xExponent -= shift - 112 >> 1; } } uint256 r = 0x10000000000000000000000000000; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; r = (r + xSignifier / r) >> 1; // Seven iterations should be enough uint256 r1 = xSignifier / r; if (r1 < r) r = r1; return bytes16 (uint128 (xExponent << 112 | r & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)); } } } } /** * Calculate binary logarithm of x. Return NaN on negative x excluding -0. * * @param x quadruple precision number * @return quadruple precision number */ function log_2 (bytes16 x) internal pure returns (bytes16) { unchecked { if (uint128 (x) > 0x80000000000000000000000000000000) return NaN; else if (x == 0x3FFF0000000000000000000000000000) return POSITIVE_ZERO; else { uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; if (xExponent == 0x7FFF) return x; else { uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; if (xSignifier == 0) return NEGATIVE_INFINITY; bool resultNegative; uint256 resultExponent = 16495; uint256 resultSignifier; if (xExponent >= 0x3FFF) { resultNegative = false; resultSignifier = xExponent - 0x3FFF; xSignifier <<= 15; } else { resultNegative = true; if (xSignifier >= 0x10000000000000000000000000000) { resultSignifier = 0x3FFE - xExponent; xSignifier <<= 15; } else { uint256 msb = mostSignificantBit (xSignifier); resultSignifier = 16493 - msb; xSignifier <<= 127 - msb; } } if (xSignifier == 0x80000000000000000000000000000000) { if (resultNegative) resultSignifier += 1; uint256 shift = 112 - mostSignificantBit (resultSignifier); resultSignifier <<= shift; resultExponent -= shift; } else { uint256 bb = resultNegative ? 1 : 0; while (resultSignifier < 0x10000000000000000000000000000) { resultSignifier <<= 1; resultExponent -= 1; xSignifier *= xSignifier; uint256 b = xSignifier >> 255; resultSignifier += b ^ bb; xSignifier >>= 127 + b; } } return bytes16 (uint128 ((resultNegative ? 0x80000000000000000000000000000000 : 0) | resultExponent << 112 | resultSignifier & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF)); } } } } /** * Calculate natural logarithm of x. Return NaN on negative x excluding -0. * * @param x quadruple precision number * @return quadruple precision number */ function ln (bytes16 x) internal pure returns (bytes16) { unchecked { return mul (log_2 (x), 0x3FFE62E42FEFA39EF35793C7673007E5); } } /** * Calculate 2^x. * * @param x quadruple precision number * @return quadruple precision number */ function pow_2 (bytes16 x) internal pure returns (bytes16) { unchecked { bool xNegative = uint128 (x) > 0x80000000000000000000000000000000; uint256 xExponent = uint128 (x) >> 112 & 0x7FFF; uint256 xSignifier = uint128 (x) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xExponent == 0x7FFF && xSignifier != 0) return NaN; else if (xExponent > 16397) return xNegative ? POSITIVE_ZERO : POSITIVE_INFINITY; else if (xExponent < 16255) return 0x3FFF0000000000000000000000000000; else { if (xExponent == 0) xExponent = 1; else xSignifier |= 0x10000000000000000000000000000; if (xExponent > 16367) xSignifier <<= xExponent - 16367; else if (xExponent < 16367) xSignifier >>= 16367 - xExponent; if (xNegative && xSignifier > 0x406E00000000000000000000000000000000) return POSITIVE_ZERO; if (!xNegative && xSignifier > 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) return POSITIVE_INFINITY; uint256 resultExponent = xSignifier >> 128; xSignifier &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; if (xNegative && xSignifier != 0) { xSignifier = ~xSignifier; resultExponent += 1; } uint256 resultSignifier = 0x80000000000000000000000000000000; if (xSignifier & 0x80000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128; if (xSignifier & 0x40000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128; if (xSignifier & 0x20000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128; if (xSignifier & 0x10000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10B5586CF9890F6298B92B71842A98363 >> 128; if (xSignifier & 0x8000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1059B0D31585743AE7C548EB68CA417FD >> 128; if (xSignifier & 0x4000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128; if (xSignifier & 0x2000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128; if (xSignifier & 0x1000000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128; if (xSignifier & 0x800000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128; if (xSignifier & 0x400000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128; if (xSignifier & 0x200000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100162F3904051FA128BCA9C55C31E5DF >> 128; if (xSignifier & 0x100000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000B175EFFDC76BA38E31671CA939725 >> 128; if (xSignifier & 0x80000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128; if (xSignifier & 0x40000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128; if (xSignifier & 0x20000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000162E525EE054754457D5995292026 >> 128; if (xSignifier & 0x10000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000B17255775C040618BF4A4ADE83FC >> 128; if (xSignifier & 0x8000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128; if (xSignifier & 0x4000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128; if (xSignifier & 0x2000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000162E43F4F831060E02D839A9D16D >> 128; if (xSignifier & 0x1000000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000B1721BCFC99D9F890EA06911763 >> 128; if (xSignifier & 0x800000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128; if (xSignifier & 0x400000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128; if (xSignifier & 0x200000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000162E430E5A18F6119E3C02282A5 >> 128; if (xSignifier & 0x100000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000B1721835514B86E6D96EFD1BFE >> 128; if (xSignifier & 0x80000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128; if (xSignifier & 0x40000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000002C5C8601CC6B9E94213C72737A >> 128; if (xSignifier & 0x20000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000162E42FFF037DF38AA2B219F06 >> 128; if (xSignifier & 0x10000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000B17217FBA9C739AA5819F44F9 >> 128; if (xSignifier & 0x8000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128; if (xSignifier & 0x4000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128; if (xSignifier & 0x2000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000162E42FF0999CE3541B9FFFCF >> 128; if (xSignifier & 0x1000000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000B17217F80F4EF5AADDA45554 >> 128; if (xSignifier & 0x800000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000058B90BFBF8479BD5A81B51AD >> 128; if (xSignifier & 0x400000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128; if (xSignifier & 0x200000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000162E42FEFB2FED257559BDAA >> 128; if (xSignifier & 0x100000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128; if (xSignifier & 0x80000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128; if (xSignifier & 0x40000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128; if (xSignifier & 0x20000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000162E42FEFA494F1478FDE05 >> 128; if (xSignifier & 0x10000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000B17217F7D20CF927C8E94C >> 128; if (xSignifier & 0x8000000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128; if (xSignifier & 0x4000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000002C5C85FDF477B662B26945 >> 128; if (xSignifier & 0x2000000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000162E42FEFA3AE53369388C >> 128; if (xSignifier & 0x1000000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000B17217F7D1D351A389D40 >> 128; if (xSignifier & 0x800000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128; if (xSignifier & 0x400000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000002C5C85FDF4741BEA6E77E >> 128; if (xSignifier & 0x200000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000162E42FEFA39FE95583C2 >> 128; if (xSignifier & 0x100000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000B17217F7D1CFB72B45E1 >> 128; if (xSignifier & 0x80000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128; if (xSignifier & 0x40000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000002C5C85FDF473E242EA38 >> 128; if (xSignifier & 0x20000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000162E42FEFA39F02B772C >> 128; if (xSignifier & 0x10000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000B17217F7D1CF7D83C1A >> 128; if (xSignifier & 0x8000000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128; if (xSignifier & 0x4000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000002C5C85FDF473DEA871F >> 128; if (xSignifier & 0x2000000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000162E42FEFA39EF44D91 >> 128; if (xSignifier & 0x1000000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000B17217F7D1CF79E949 >> 128; if (xSignifier & 0x800000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000058B90BFBE8E7BCE544 >> 128; if (xSignifier & 0x400000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000002C5C85FDF473DE6ECA >> 128; if (xSignifier & 0x200000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000162E42FEFA39EF366F >> 128; if (xSignifier & 0x100000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000B17217F7D1CF79AFA >> 128; if (xSignifier & 0x80000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000058B90BFBE8E7BCD6D >> 128; if (xSignifier & 0x40000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000002C5C85FDF473DE6B2 >> 128; if (xSignifier & 0x20000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000162E42FEFA39EF358 >> 128; if (xSignifier & 0x10000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000B17217F7D1CF79AB >> 128; if (xSignifier & 0x8000000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000058B90BFBE8E7BCD5 >> 128; if (xSignifier & 0x4000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000002C5C85FDF473DE6A >> 128; if (xSignifier & 0x2000000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000162E42FEFA39EF34 >> 128; if (xSignifier & 0x1000000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000B17217F7D1CF799 >> 128; if (xSignifier & 0x800000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000058B90BFBE8E7BCC >> 128; if (xSignifier & 0x400000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000002C5C85FDF473DE5 >> 128; if (xSignifier & 0x200000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000162E42FEFA39EF2 >> 128; if (xSignifier & 0x100000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000B17217F7D1CF78 >> 128; if (xSignifier & 0x80000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000058B90BFBE8E7BB >> 128; if (xSignifier & 0x40000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000002C5C85FDF473DD >> 128; if (xSignifier & 0x20000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000162E42FEFA39EE >> 128; if (xSignifier & 0x10000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000B17217F7D1CF6 >> 128; if (xSignifier & 0x8000000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000058B90BFBE8E7A >> 128; if (xSignifier & 0x4000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000002C5C85FDF473C >> 128; if (xSignifier & 0x2000000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000162E42FEFA39D >> 128; if (xSignifier & 0x1000000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000B17217F7D1CE >> 128; if (xSignifier & 0x800000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000058B90BFBE8E6 >> 128; if (xSignifier & 0x400000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000002C5C85FDF472 >> 128; if (xSignifier & 0x200000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000162E42FEFA38 >> 128; if (xSignifier & 0x100000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000B17217F7D1B >> 128; if (xSignifier & 0x80000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000058B90BFBE8D >> 128; if (xSignifier & 0x40000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000002C5C85FDF46 >> 128; if (xSignifier & 0x20000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000162E42FEFA2 >> 128; if (xSignifier & 0x10000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000B17217F7D0 >> 128; if (xSignifier & 0x8000000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000058B90BFBE7 >> 128; if (xSignifier & 0x4000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000002C5C85FDF3 >> 128; if (xSignifier & 0x2000000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000162E42FEF9 >> 128; if (xSignifier & 0x1000000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000B17217F7C >> 128; if (xSignifier & 0x800000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000058B90BFBD >> 128; if (xSignifier & 0x400000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000002C5C85FDE >> 128; if (xSignifier & 0x200000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000162E42FEE >> 128; if (xSignifier & 0x100000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000B17217F6 >> 128; if (xSignifier & 0x80000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000058B90BFA >> 128; if (xSignifier & 0x40000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000002C5C85FC >> 128; if (xSignifier & 0x20000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000162E42FD >> 128; if (xSignifier & 0x10000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000B17217E >> 128; if (xSignifier & 0x8000000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000058B90BE >> 128; if (xSignifier & 0x4000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000002C5C85E >> 128; if (xSignifier & 0x2000000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000162E42E >> 128; if (xSignifier & 0x1000000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000B17216 >> 128; if (xSignifier & 0x800000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000058B90A >> 128; if (xSignifier & 0x400000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000002C5C84 >> 128; if (xSignifier & 0x200000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000162E41 >> 128; if (xSignifier & 0x100000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000B1720 >> 128; if (xSignifier & 0x80000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000058B8F >> 128; if (xSignifier & 0x40000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000002C5C7 >> 128; if (xSignifier & 0x20000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000162E3 >> 128; if (xSignifier & 0x10000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000B171 >> 128; if (xSignifier & 0x8000 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000058B8 >> 128; if (xSignifier & 0x4000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000002C5B >> 128; if (xSignifier & 0x2000 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000162D >> 128; if (xSignifier & 0x1000 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000B16 >> 128; if (xSignifier & 0x800 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000058A >> 128; if (xSignifier & 0x400 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000002C4 >> 128; if (xSignifier & 0x200 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000161 >> 128; if (xSignifier & 0x100 > 0) resultSignifier = resultSignifier * 0x1000000000000000000000000000000B0 >> 128; if (xSignifier & 0x80 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000057 >> 128; if (xSignifier & 0x40 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000002B >> 128; if (xSignifier & 0x20 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000015 >> 128; if (xSignifier & 0x10 > 0) resultSignifier = resultSignifier * 0x10000000000000000000000000000000A >> 128; if (xSignifier & 0x8 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000004 >> 128; if (xSignifier & 0x4 > 0) resultSignifier = resultSignifier * 0x100000000000000000000000000000001 >> 128; if (!xNegative) { resultSignifier = resultSignifier >> 15 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; resultExponent += 0x3FFF; } else if (resultExponent <= 0x3FFE) { resultSignifier = resultSignifier >> 15 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; resultExponent = 0x3FFF - resultExponent; } else { resultSignifier = resultSignifier >> resultExponent - 16367; resultExponent = 0; } return bytes16 (uint128 (resultExponent << 112 | resultSignifier)); } } } /** * Calculate e^x. * * @param x quadruple precision number * @return quadruple precision number */ function exp (bytes16 x) internal pure returns (bytes16) { unchecked { return pow_2 (mul (x, 0x3FFF71547652B82FE1777D0FFDA0D23A)); } } /** * Get index of the most significant non-zero bit in binary representation of * x. Reverts if x is zero. * * @return index of the most significant non-zero bit in binary representation * of x */ function mostSignificantBit (uint256 x) private pure returns (uint256) { unchecked { require (x > 0); uint256 result = 0; if (x >= 0x100000000000000000000000000000000) { x >>= 128; result += 128; } if (x >= 0x10000000000000000) { x >>= 64; result += 64; } if (x >= 0x100000000) { x >>= 32; result += 32; } if (x >= 0x10000) { x >>= 16; result += 16; } if (x >= 0x100) { x >>= 8; result += 8; } if (x >= 0x10) { x >>= 4; result += 4; } if (x >= 0x4) { x >>= 2; result += 2; } if (x >= 0x2) result += 1; // No need to shift x anymore return result; } } }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for Noun Auction Houses /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; interface INounsAuctionHouse { struct Auction { // ID for the Noun (ERC721 token ID) uint256 nounId; // The current highest bid amount uint256 amount; // The time that the auction started uint256 startTime; // The time that the auction is scheduled to end uint256 endTime; // The address of the current highest bid address payable bidder; // Whether or not the auction has been settled bool settled; } event AuctionCreated(uint256 indexed nounId, uint256 startTime, uint256 endTime); event AuctionBid(uint256 indexed nounId, address sender, uint256 value, bool extended); event AuctionExtended(uint256 indexed nounId, uint256 endTime); event AuctionSettled(uint256 indexed nounId, address winner, uint256 amount); event AuctionTimeBufferUpdated(uint256 timeBuffer); event AuctionReservePriceUpdated(uint256 reservePrice); event AuctionMinBidIncrementPercentageUpdated(uint256 minBidIncrementPercentage); function settleAuction() external; function settleCurrentAndCreateNewAuction() external; function createBid(uint256 nounId) external payable; function pause() external; function unpause() external; function setTimeBuffer(uint256 timeBuffer) external; function setReservePrice(uint256 reservePrice) external; function setMinBidIncrementPercentage(uint8 minBidIncrementPercentage) external; }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for NounsToken /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; import { IERC721 } from '@openzeppelin/contracts/token/ERC721/IERC721.sol'; import { INounsDescriptorMinimal } from './INounsDescriptorMinimal.sol'; import { INounsSeeder } from './INounsSeeder.sol'; interface INounsToken is IERC721 { event NounCreated(uint256 indexed tokenId, INounsSeeder.Seed seed); event NounBurned(uint256 indexed tokenId); event NoundersDAOUpdated(address noundersDAO); event MinterUpdated(address minter); event MinterLocked(); event DescriptorUpdated(INounsDescriptorMinimal descriptor); event DescriptorLocked(); event SeederUpdated(INounsSeeder seeder); event SeederLocked(); function mint() external returns (uint256); function burn(uint256 tokenId) external; function dataURI(uint256 tokenId) external returns (string memory); function setNoundersDAO(address noundersDAO) external; function setMinter(address minter) external; function lockMinter() external; function setDescriptor(INounsDescriptorMinimal descriptor) external; function lockDescriptor() external; function setSeeder(INounsSeeder seeder) external; function lockSeeder() external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.6; interface IWETH { function deposit() external payable; function withdraw(uint256 wad) external; function transfer(address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal initializer { __Context_init_unchained(); } function __Context_init_unchained() internal initializer { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-3.0 /// @title Common interface for NounsDescriptor versions, as used by NounsToken and NounsSeeder. /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; // LICENSE // This file is a modified version of nounsDAO's INounsDescriptorMinimal.sol: // https://github.com/nounsDAO/nouns-monorepo/blob/854b9b64770401da71503972c65c4f9eda060ba6/packages/nouns-contracts/contracts/interfaces/INounsDescriptorMinimal.sol // // INounsDescriptorMinimal.sol licensed under the GPL-3.0 license. // With modifications by CNNouns DAO. import { INounsSeeder } from './INounsSeeder.sol'; interface INounsDescriptorMinimal { /// /// USED BY TOKEN /// function tokenURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view returns (string memory); function dataURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view returns (string memory); /// /// USED BY SEEDER /// function backgroundCount() external view returns (uint256); function bodyCount() external view returns (uint256); function headCount() external view returns (uint256); function glassesCount() external view returns (uint256); function skillCount() external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for NounsSeeder /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.6; // LICENSE // This file is a modified version of nounsDAO's INounsSeeder.sol: // https://github.com/nounsDAO/nouns-monorepo/blob/854b9b64770401da71503972c65c4f9eda060ba6/packages/nouns-contracts/contracts/interfaces/INounsSeeder.sol // // INounsSeeder.sol licensed under the GPL-3.0 license. // With modifications by CNNouns DAO. import { INounsDescriptorMinimal } from './INounsDescriptorMinimal.sol'; interface INounsSeeder { struct Seed { uint48 background; uint48 body; uint48 head; uint48 glasses; uint48 skill; } function generateSeed(uint256 nounId, INounsDescriptorMinimal descriptor) external view returns (Seed memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.0 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nounId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bool","name":"extended","type":"bool"}],"name":"AuctionBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nounId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"AuctionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nounId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"AuctionExtended","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minBidIncrementPercentage","type":"uint256"}],"name":"AuctionMinBidIncrementPercentageUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reservePrice","type":"uint256"}],"name":"AuctionReservePriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nounId","type":"uint256"},{"indexed":false,"internalType":"address","name":"winner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AuctionSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timeBuffer","type":"uint256"}],"name":"AuctionTimeBufferUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"auction","outputs":[{"internalType":"uint256","name":"nounId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"address payable","name":"bidder","type":"address"},{"internalType":"bool","name":"settled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nounId","type":"uint256"}],"name":"createBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract INounsToken","name":"_nouns","type":"address"},{"internalType":"address","name":"_weth","type":"address"},{"internalType":"uint256","name":"_timeBuffer","type":"uint256"},{"internalType":"uint256","name":"_reservePrice","type":"uint256"},{"internalType":"uint8","name":"_minBidIncrementPercentage","type":"uint8"},{"internalType":"uint256","name":"_baseDuration","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minBidIncrementPercentage","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nouns","outputs":[{"internalType":"contract INounsToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"origin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reservePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_minBidIncrementPercentage","type":"uint8"}],"name":"setMinBidIncrementPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reservePrice","type":"uint256"}],"name":"setReservePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timeBuffer","type":"uint256"}],"name":"setTimeBuffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleCurrentAndCreateNewAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timeBuffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50614300806100206000396000f3fe60806040526004361061016a5760003560e01c806387f49f54116100cb578063ce9c7c0d1161007f578063ec91f2a411610059578063ec91f2a414610445578063f25efffc1461045b578063f2fde38b1461047057600080fd5b8063ce9c7c0d146103f9578063db2e1eed14610419578063dcf1ed2b1461042f57600080fd5b8063938b5f32116100b0578063938b5f3214610394578063a4d0a17e146103b8578063b296024d146103cd57600080fd5b806387f49f54146103495780638da5cb5b1461036957600080fd5b8063659dd2b411610122578063715018a611610107578063715018a6146102805780637d9f6db5146102955780638456cb591461033457600080fd5b8063659dd2b41461024d5780637120334b1461026057600080fd5b80633f4ba83a116101535780633f4ba83a146101e85780633fc8cef3146101fd5780635c975abb1461022a57600080fd5b80632de45f181461016f57806336ebdb38146101c6575b600080fd5b34801561017b57600080fd5b5060c95461019c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101d257600080fd5b506101e66101e1366004613f4f565b610490565b005b3480156101f457600080fd5b506101e6610563565b34801561020957600080fd5b5060ca5461019c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561023657600080fd5b5060335460ff1660405190151581526020016101bd565b6101e661025b366004613f6a565b61060a565b34801561026c57600080fd5b506101e661027b366004613f6a565b61098d565b34801561028c57600080fd5b506101e6610a29565b3480156102a157600080fd5b5060d05460d15460d25460d35460d4546102ef949392919073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900460ff1686565b60408051968752602087019590955293850192909252606084015273ffffffffffffffffffffffffffffffffffffffff166080830152151560a082015260c0016101bd565b34801561034057600080fd5b506101e6610a9a565b34801561035557600080fd5b506101e6610364366004613fa5565b610b09565b34801561037557600080fd5b5060975473ffffffffffffffffffffffffffffffffffffffff1661019c565b3480156103a057600080fd5b506103aa60cf5481565b6040519081526020016101bd565b3480156103c457600080fd5b506101e6610ca5565b3480156103d957600080fd5b5060cd546103e79060ff1681565b60405160ff90911681526020016101bd565b34801561040557600080fd5b506101e6610414366004613f6a565b610d5d565b34801561042557600080fd5b506103aa60cc5481565b34801561043b57600080fd5b506103aa60ce5481565b34801561045157600080fd5b506103aa60cb5481565b34801561046757600080fd5b506101e6610df9565b34801561047c57600080fd5b506101e661048b366004614008565b610eb3565b60975473ffffffffffffffffffffffffffffffffffffffff1633146104fc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b60cd80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff83169081179091556040519081527fec5ccd96cc77b6219e9d44143df916af68fc169339ea7de5008ff15eae13450d906020015b60405180910390a150565b60975473ffffffffffffffffffffffffffffffffffffffff1633146105ca5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b6105d2610faf565b60d25415806105fb575060d45474010000000000000000000000000000000000000000900460ff165b1561060857610608611076565b565b60026065540361065c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016104f3565b60026065556040805160c08101825260d05480825260d154602083015260d2549282019290925260d354606082015260d45473ffffffffffffffffffffffffffffffffffffffff8116608083015274010000000000000000000000000000000000000000900460ff16151560a082015290821461071b5760405162461bcd60e51b815260206004820152601760248201527f4e6f756e206e6f7420757020666f722061756374696f6e00000000000000000060448201526064016104f3565b8060600151421061076e5760405162461bcd60e51b815260206004820152600f60248201527f41756374696f6e2065787069726564000000000000000000000000000000000060448201526064016104f3565b60cc543410156107c05760405162461bcd60e51b815260206004820152601f60248201527f4d7573742073656e64206174206c65617374207265736572766550726963650060448201526064016104f3565b60cd5460208201516064916107da9160ff90911690614054565b6107e4919061409a565b81602001516107f391906140d5565b34101561086a576040805162461bcd60e51b81526020600482015260248101919091527f4d7573742073656e64206d6f7265207468616e206c617374206269642062792060448201527f6d696e426964496e6372656d656e7450657263656e7461676520616d6f756e7460648201526084016104f3565b608081015173ffffffffffffffffffffffffffffffffffffffff81161561089957610899818360200151611221565b3460d15560d480547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905560cb546060830151600091906108de9042906140e8565b10905080156108ff5760cb546108f490426140d5565b6060840181905260d3555b8251604080513381523460208201528315158183015290517f1159164c56f277e6fc99c11731bd380e0347deb969b75523398734c252706ea39181900360600190a2801561098257825160608401516040519081527f6e912a3a9105bdd2af817ba5adc14e6c127c1035b5b648faa29ca0d58ab8ff4e9060200160405180910390a25b505060016065555050565b60975473ffffffffffffffffffffffffffffffffffffffff1633146109f45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b60cb8190556040518181527f1b55d9f7002bda4490f467e326f22a4a847629c0f2d1ed421607d318d25b410d90602001610558565b60975473ffffffffffffffffffffffffffffffffffffffff163314610a905760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b6106086000611356565b60975473ffffffffffffffffffffffffffffffffffffffff163314610b015760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b6106086113cd565b600054610100900460ff1680610b22575060005460ff16155b610b945760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015610bb6576000805461ffff19166101011790555b610bbe611473565b610bc6611561565b610bce611616565b610bd66113cd565b60c9805473ffffffffffffffffffffffffffffffffffffffff808a167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560ca80549289169290911691909117905560cb85905560cc84905560cd805460ff85167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617905560ce8290554260cf558015610c9c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b50505050505050565b60335460ff16610cf75760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016104f3565b600260655403610d495760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016104f3565b6002606555610d566116d3565b6001606555565b60975473ffffffffffffffffffffffffffffffffffffffff163314610dc45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b60cc8190556040518181527f6ab2e127d7fdf53b8f304e59d3aab5bfe97979f52a85479691a6fab27a28a6b290602001610558565b600260655403610e4b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016104f3565b600260655560335460ff1615610ea35760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016104f3565b610eab6116d3565b610d56611076565b60975473ffffffffffffffffffffffffffffffffffffffff163314610f1a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b73ffffffffffffffffffffffffffffffffffffffff8116610fa35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016104f3565b610fac81611356565b50565b60335460ff166110015760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016104f3565b603380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60c960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631249c58b6040518163ffffffff1660e01b81526004016020604051808303816000875af192505050801561111f575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261111c918101906140fb565b60015b61115e5761112b614114565b806308c379a003611152575061113f6141a2565b8061114a5750611154565b610fac6113cd565b505b3d6000803e3d6000fd5b42600061116a82611a4e565b61117490836140d5565b6040805160c08101825285815260006020808301829052828401879052606083018590526080830182905260a090920181905260d087905560d15560d285905560d383905560d480547fffffffffffffffffffffff000000000000000000000000000000000000000000169055815185815290810183905291925084917fd6eddd1118d71820909c1197aa966dbc15ed6f508554252169cc3d5ccac756ca910160405180910390a2505050565b61122b8282611acf565b6113525760ca60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561129957600080fd5b505af11580156112ad573d6000803e3d6000fd5b505060ca546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260248201879052909116935063a9059cbb925060440190506020604051808303816000875af115801561132c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611350919061424a565b505b5050565b6097805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335460ff16156114205760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016104f3565b603380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861104c3390565b600054610100900460ff168061148c575060005460ff16155b6114fe5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015611520576000805461ffff19166101011790555b611528611b5c565b611530611c39565b8015610fac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff168061157a575060005460ff16155b6115ec5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff1615801561160e576000805461ffff19166101011790555b611530611d3f565b600054610100900460ff168061162f575060005460ff16155b6116a15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff161580156116c3576000805461ffff19166101011790555b6116cb611b5c565b611530611e22565b6040805160c08101825260d054815260d154602082015260d25491810182905260d354606082015260d45473ffffffffffffffffffffffffffffffffffffffff8116608083015274010000000000000000000000000000000000000000900460ff16151560a08201529060000361178c5760405162461bcd60e51b815260206004820152601460248201527f41756374696f6e206861736e277420626567756e00000000000000000000000060448201526064016104f3565b8060a00151156117de5760405162461bcd60e51b815260206004820181905260248201527f41756374696f6e2068617320616c7265616479206265656e20736574746c656460448201526064016104f3565b80606001514210156118325760405162461bcd60e51b815260206004820152601860248201527f41756374696f6e206861736e277420636f6d706c65746564000000000000000060448201526064016104f3565b60d480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055608081015173ffffffffffffffffffffffffffffffffffffffff166119215760c95481516040517f42966c6800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909216916342966c68916118ea9160040190815260200190565b600060405180830381600087803b15801561190457600080fd5b505af1158015611918573d6000803e3d6000fd5b505050506119bb565b60c954608082015182516040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff928316602482015260448101919091529116906323b872dd90606401600060405180830381600087803b1580156119a257600080fd5b505af11580156119b6573d6000803e3d6000fd5b505050505b6020810151156119f1576119f16119e760975473ffffffffffffffffffffffffffffffffffffffff1690565b8260200151611221565b805160808201516020808401516040805173ffffffffffffffffffffffffffffffffffffffff9094168452918301527fc9f72b276a388619c6d185d146697036241880c36654b1a3ffdad07c24038d99910160405180910390a250565b60008060cf5483611a5f91906140e8565b90506343ab3e008110611a7857506302a3000092915050565b6000611a8382611ed8565b9050611a9b81611a96630784ce00611ed8565b611f4b565b9050611aa6816123cc565b9050611abc81611ab760ce54611ed8565b6139d7565b9050611ac781613dcf565b949350505050565b60408051600080825260208201909252819073ffffffffffffffffffffffffffffffffffffffff851690617530908590604051611b0c919061426c565b600060405180830381858888f193505050503d8060008114611b4a576040519150601f19603f3d011682016040523d82523d6000602084013e611b4f565b606091505b5090925050505b92915050565b600054610100900460ff1680611b75575060005460ff16155b611be75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015611530576000805461ffff19166101011790558015610fac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff1680611c52575060005460ff16155b611cc45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015611ce6576000805461ffff19166101011790555b603380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558015610fac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff1680611d58575060005460ff16155b611dca5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015611dec576000805461ffff19166101011790555b60016065558015610fac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff1680611e3b575060005460ff16155b611ead5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015611ecf576000805461ffff19166101011790555b61153033611356565b600081600003611eea57506000919050565b816000611ef682613e8e565b90506070811015611f0f578060700382901b9150611f22565b6070811115611f22576070810382901c91505b613fff0160701b6dffffffffffffffffffffffffffff919091161760801b92915050565b919050565b6000617fff60f084811c8216919084901c811690829003611fc75780617fff03611f9a57507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b5050507f800000000000000000000000000000000000000000000000000000000000000081168218611b56565b80617fff0361204e577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561202157507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b5050508082187f800000000000000000000000000000000000000000000000000000000000000016611b56565b7f7fffffffffffffffffffffffffffffff00000000000000000000000000000000841660000361211c577f7fffffffffffffffffffffffffffffff0000000000000000000000000000000085166000036120cd57507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b5050508082187f8000000000000000000000000000000000000000000000000000000000000000167f7fff00000000000000000000000000000000000000000000000000000000000017611b56565b6dffffffffffffffffffffffffffff608085901c1660008290036121435760019150612155565b6e010000000000000000000000000000175b6dffffffffffffffffffffffffffff608087901c1660008490036121bd5780156121b857600061218482613e8e565b6001955060e2039384017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e01939190911b90505b6121d2565b6e0100000000000000000000000000001760721b5b8181816121e1576121e161406b565b04905080600003612249577f80000000000000000000000000000000000000000000000000000000000000008787181661221c57600061223e565b7f80000000000000000000000000000000000000000000000000000000000000005b945050505050611b56565b6d10000000000000000000000000008110156122675761226761429b565b60006e0800000000000000000000000000008210156122c7576e0400000000000000000000000000008210156122bc576e0200000000000000000000000000008210156122b55760706122bf565b60716122bf565b60725b60ff166122d0565b6122d082613e8e565b9050836140710181860111156122ee57617fff945060009150612388565b83818601613ffc011015612309576000945060009150612388565b83818601613f8c011015612356578385613ffc011115612334578385613ffc010382901b915061234d565b8385613ffc01101561234d57613ffc8585030382901c91505b60009450612388565b6070811115612369576070810382901c91505b6dffffffffffffffffffffffffffff8216915083818601613f8d010394505b81607086901b888a186f8000000000000000000000000000000060801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050611b56565b60006f80000000000000000000000000000000608083901c90811190617fff60f085901c8116916dffffffffffffffffffffffffffff16908214801561241157508015155b1561244057507f7fff800000000000000000000000000000000000000000000000000000000000949350505050565b61400d8211156124815782612475577f7fff000000000000000000000000000000000000000000000000000000000000612478565b60005b95945050505050565b613f7f8210156124b557507f3fff000000000000000000000000000000000000000000000000000000000000949350505050565b816000036124c657600191506124d8565b6e010000000000000000000000000000175b613fef82111561250b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01182011b61251d565b613fef82101561251d57613fef8290031c5b82801561253b575071406e0000000000000000000000000000000081115b1561254b57506000949350505050565b8215801561256a5750713fffffffffffffffffffffffffffffffffff81115b1561259957507f7fff000000000000000000000000000000000000000000000000000000000000949350505050565b6fffffffffffffffffffffffffffffffff81169060801c8380156125bc57508115155b156125c8579019906001015b6f80000000000000000000000000000000828116156125f85770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b6f40000000000000000000000000000000831615612627577001306fe0a31b7152de8d5a46305c85edec0260801c5b6f20000000000000000000000000000000831615612656577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b6f100000000000000000000000000000008316156126855770010b5586cf9890f6298b92b71842a983630260801c5b6f080000000000000000000000000000008316156126b4577001059b0d31585743ae7c548eb68ca417fd0260801c5b6f040000000000000000000000000000008316156126e357700102c9a3e778060ee6f7caca4f7a29bde80260801c5b6f020000000000000000000000000000008316156127125770010163da9fb33356d84a66ae336dcdfa3f0260801c5b6f0100000000000000000000000000000083161561274157700100b1afa5abcbed6129ab13ec11dc95430260801c5b6e80000000000000000000000000000083161561276f5770010058c86da1c09ea1ff19d294cf2f679b0260801c5b6e40000000000000000000000000000083161561279d577001002c605e2e8cec506d21bfc89a23a00f0260801c5b6e2000000000000000000000000000008316156127cb57700100162f3904051fa128bca9c55c31e5df0260801c5b6e1000000000000000000000000000008316156127f9577001000b175effdc76ba38e31671ca9397250260801c5b6e08000000000000000000000000000083161561282757700100058ba01fb9f96d6cacd4b180917c3d0260801c5b6e0400000000000000000000000000008316156128555770010002c5cc37da9491d0985c348c68e7b30260801c5b6e020000000000000000000000000000831615612883577001000162e525ee054754457d59952920260260801c5b6e0100000000000000000000000000008316156128b15770010000b17255775c040618bf4a4ade83fc0260801c5b6d80000000000000000000000000008316156128de577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6d400000000000000000000000000083161561290b57700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6d20000000000000000000000000008316156129385770010000162e43f4f831060e02d839a9d16d0260801c5b6d100000000000000000000000000083161561296557700100000b1721bcfc99d9f890ea069117630260801c5b6d08000000000000000000000000008316156129925770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6d04000000000000000000000000008316156129bf577001000002c5c863b73f016468f6bac5ca2b0260801c5b6d02000000000000000000000000008316156129ec57700100000162e430e5a18f6119e3c02282a50260801c5b6d0100000000000000000000000000831615612a19577001000000b1721835514b86e6d96efd1bfe0260801c5b6c80000000000000000000000000831615612a4557700100000058b90c0b48c6be5df846c5b2ef0260801c5b6c40000000000000000000000000831615612a715770010000002c5c8601cc6b9e94213c72737a0260801c5b6c20000000000000000000000000831615612a9d577001000000162e42fff037df38aa2b219f060260801c5b6c10000000000000000000000000831615612ac95770010000000b17217fba9c739aa5819f44f90260801c5b6c08000000000000000000000000831615612af5577001000000058b90bfcdee5acd3c1cedc8230260801c5b6c04000000000000000000000000831615612b2157700100000002c5c85fe31f35a6a30da1be500260801c5b6c02000000000000000000000000831615612b4d5770010000000162e42ff0999ce3541b9fffcf0260801c5b6c01000000000000000000000000831615612b7957700100000000b17217f80f4ef5aadda455540260801c5b6b800000000000000000000000831615612ba45770010000000058b90bfbf8479bd5a81b51ad0260801c5b6b400000000000000000000000831615612bcf577001000000002c5c85fdf84bd62ae30a74cc0260801c5b6b200000000000000000000000831615612bfa57700100000000162e42fefb2fed257559bdaa0260801c5b6b100000000000000000000000831615612c25577001000000000b17217f7d5a7716bba4a9ae0260801c5b6b080000000000000000000000831615612c5057700100000000058b90bfbe9ddbac5e109cce0260801c5b6b040000000000000000000000831615612c7b5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b6b020000000000000000000000831615612ca6577001000000000162e42fefa494f1478fde050260801c5b6b010000000000000000000000831615612cd15770010000000000b17217f7d20cf927c8e94c0260801c5b6a8000000000000000000000831615612cfb577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6a4000000000000000000000831615612d2557700100000000002c5c85fdf477b662b269450260801c5b6a2000000000000000000000831615612d4f5770010000000000162e42fefa3ae53369388c0260801c5b6a1000000000000000000000831615612d7957700100000000000b17217f7d1d351a389d400260801c5b6a0800000000000000000000831615612da35770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6a0400000000000000000000831615612dcd577001000000000002c5c85fdf4741bea6e77e0260801c5b6a0200000000000000000000831615612df757700100000000000162e42fefa39fe95583c20260801c5b6a0100000000000000000000831615612e21577001000000000000b17217f7d1cfb72b45e10260801c5b6980000000000000000000831615612e4a57700100000000000058b90bfbe8e7cc35c3f00260801c5b6940000000000000000000831615612e735770010000000000002c5c85fdf473e242ea380260801c5b6920000000000000000000831615612e9c577001000000000000162e42fefa39f02b772c0260801c5b6910000000000000000000831615612ec55770010000000000000b17217f7d1cf7d83c1a0260801c5b6908000000000000000000831615612eee577001000000000000058b90bfbe8e7bdcbe2e0260801c5b6904000000000000000000831615612f1757700100000000000002c5c85fdf473dea871f0260801c5b6902000000000000000000831615612f405770010000000000000162e42fefa39ef44d910260801c5b6901000000000000000000831615612f6957700100000000000000b17217f7d1cf79e9490260801c5b68800000000000000000831615612f915770010000000000000058b90bfbe8e7bce5440260801c5b68400000000000000000831615612fb9577001000000000000002c5c85fdf473de6eca0260801c5b68200000000000000000831615612fe157700100000000000000162e42fefa39ef366f0260801c5b68100000000000000000831615613009577001000000000000000b17217f7d1cf79afa0260801c5b6808000000000000000083161561303157700100000000000000058b90bfbe8e7bcd6d0260801c5b680400000000000000008316156130595770010000000000000002c5c85fdf473de6b20260801c5b68020000000000000000831615613081577001000000000000000162e42fefa39ef3580260801c5b680100000000000000008316156130a95770010000000000000000b17217f7d1cf79ab0260801c5b6780000000000000008316156130d0577001000000000000000058b90bfbe8e7bcd50260801c5b6740000000000000008316156130f757700100000000000000002c5c85fdf473de6a0260801c5b67200000000000000083161561311e5770010000000000000000162e42fefa39ef340260801c5b67100000000000000083161561314557700100000000000000000b17217f7d1cf7990260801c5b67080000000000000083161561316c5770010000000000000000058b90bfbe8e7bcc0260801c5b670400000000000000831615613193577001000000000000000002c5c85fdf473de50260801c5b6702000000000000008316156131ba57700100000000000000000162e42fefa39ef20260801c5b6701000000000000008316156131e1577001000000000000000000b17217f7d1cf780260801c5b668000000000000083161561320757700100000000000000000058b90bfbe8e7bb0260801c5b664000000000000083161561322d5770010000000000000000002c5c85fdf473dd0260801c5b6620000000000000831615613253577001000000000000000000162e42fefa39ee0260801c5b66100000000000008316156132795770010000000000000000000b17217f7d1cf60260801c5b660800000000000083161561329f577001000000000000000000058b90bfbe8e7a0260801c5b66040000000000008316156132c557700100000000000000000002c5c85fdf473c0260801c5b66020000000000008316156132eb5770010000000000000000000162e42fefa39d0260801c5b660100000000000083161561331157700100000000000000000000b17217f7d1ce0260801c5b658000000000008316156133365770010000000000000000000058b90bfbe8e60260801c5b6540000000000083161561335b577001000000000000000000002c5c85fdf4720260801c5b6520000000000083161561338057700100000000000000000000162e42fefa380260801c5b651000000000008316156133a5577001000000000000000000000b17217f7d1b0260801c5b650800000000008316156133ca57700100000000000000000000058b90bfbe8d0260801c5b650400000000008316156133ef5770010000000000000000000002c5c85fdf460260801c5b65020000000000831615613414577001000000000000000000000162e42fefa20260801c5b650100000000008316156134395770010000000000000000000000b17217f7d00260801c5b64800000000083161561345d577001000000000000000000000058b90bfbe70260801c5b64400000000083161561348157700100000000000000000000002c5c85fdf30260801c5b6420000000008316156134a55770010000000000000000000000162e42fef90260801c5b6410000000008316156134c957700100000000000000000000000b17217f7c0260801c5b6408000000008316156134ed5770010000000000000000000000058b90bfbd0260801c5b640400000000831615613511577001000000000000000000000002c5c85fde0260801c5b64020000000083161561353557700100000000000000000000000162e42fee0260801c5b640100000000831615613559577001000000000000000000000000b17217f60260801c5b638000000083161561357c57700100000000000000000000000058b90bfa0260801c5b634000000083161561359f5770010000000000000000000000002c5c85fc0260801c5b63200000008316156135c2577001000000000000000000000000162e42fd0260801c5b63100000008316156135e55770010000000000000000000000000b17217e0260801c5b6308000000831615613608577001000000000000000000000000058b90be0260801c5b630400000083161561362b57700100000000000000000000000002c5c85e0260801c5b630200000083161561364e5770010000000000000000000000000162e42e0260801c5b630100000083161561367157700100000000000000000000000000b172160260801c5b628000008316156136935770010000000000000000000000000058b90a0260801c5b624000008316156136b5577001000000000000000000000000002c5c840260801c5b622000008316156136d757700100000000000000000000000000162e410260801c5b621000008316156136f9577001000000000000000000000000000b17200260801c5b6208000083161561371b57700100000000000000000000000000058b8f0260801c5b6204000083161561373d5770010000000000000000000000000002c5c70260801c5b6202000083161561375f577001000000000000000000000000000162e30260801c5b620100008316156137815770010000000000000000000000000000b1710260801c5b6180008316156137a2577001000000000000000000000000000058b80260801c5b6140008316156137c357700100000000000000000000000000002c5b0260801c5b6120008316156137e45770010000000000000000000000000000162d0260801c5b61100083161561380557700100000000000000000000000000000b160260801c5b6108008316156138265770010000000000000000000000000000058a0260801c5b610400831615613847577001000000000000000000000000000002c40260801c5b610200831615613868577001000000000000000000000000000001610260801c5b610100831615613889577001000000000000000000000000000000b00260801c5b60808316156138a9577001000000000000000000000000000000570260801c5b60408316156138c95770010000000000000000000000000000002b0260801c5b60208316156138e9577001000000000000000000000000000000150260801c5b60108316156139095770010000000000000000000000000000000a0260801c5b6008831615613929577001000000000000000000000000000000040260801c5b6004831615613949577001000000000000000000000000000000010260801c5b8461397157600f81901c6dffffffffffffffffffffffffffff169050613fff820191506139c4565b613ffe821161399d57600f81901c6dffffffffffffffffffffffffffff16905081613fff0391506139c4565b6000917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc011011c5b60709190911b1760801b95945050505050565b6000617fff60f084811c8216919084901c811690829003613b2a5780617fff03613ad5577fffffffffffffffffffffffffffffffff0000000000000000000000000000000080851690861603613a54575050507f800000000000000000000000000000000000000000000000000000000000000081168218611b56565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000858518167f800000000000000000000000000000000000000000000000000000000000000003613aaa57505050818117611b56565b507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b7f7fffffffffffffffffffffffffffffff000000000000000000000000000000008416600003611f9a57507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b80617fff03613bb5577f7fffffffffffffffffffffffffffffff000000000000000000000000000000008516600003613b8857507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b5050507f800000000000000000000000000000000000000000000000000000000000000082168118611b56565b6dffffffffffffffffffffffffffff608086901c166000839003613bdc5760019250613bee565b6e010000000000000000000000000000175b6dffffffffffffffffffffffffffff608086901c166000839003613c155760019250613c27565b6e010000000000000000000000000000175b808202915081600003613c64577f80000000000000000000000000000000000000000000000000000000000000008787181661221c57600061223e565b9282019260007c0200000000000000000000000000000000000000000000000000000000831015613cc9577c0100000000000000000000000000000000000000000000000000000000831015613cc257613cbd83613e8e565b613ccc565b60e0613ccc565b60e15b90506140708186011015613ce7576000945060009250613d8b565b6140e08186011015613d2a57614070851015613d0c57846140700383901c9250613d21565b614070851115613d2157614070850383901b92505b60009450613d8b565b61c0dd8186011115613d4457617fff945060009250613d8b565b6070811115613d5b576070810383901c9250613d6e565b6070811015613d6e578060700383901b92505b6dffffffffffffffffffffffffffff831692506140df8186010394505b82607086901b888a186f8000000000000000000000000000000060801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050611b56565b6000617fff60f083901c16613fff811015613ded5750600092915050565b6f80000000000000000000000000000000608084901c10613e0d57600080fd5b6140fe811115613e1c57600080fd5b6e0100000000000000000000000000006dffffffffffffffffffffffffffff608085901c161761406f821015613e585761406f8290031c613e87565b61406f821115613e87577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf9182011b5b9392505050565b6000808211613e9c57600080fd5b60007001000000000000000000000000000000008310613ebe57608092831c92015b680100000000000000008310613ed657604092831c92015b6401000000008310613eea57602092831c92015b620100008310613efc57601092831c92015b6101008310613f0d57600892831c92015b60108310613f1d57600492831c92015b60048310613f2d57600292831c92015b60028310611b565760010192915050565b803560ff81168114611f4657600080fd5b600060208284031215613f6157600080fd5b613e8782613f3e565b600060208284031215613f7c57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610fac57600080fd5b60008060008060008060c08789031215613fbe57600080fd5b8635613fc981613f83565b95506020870135613fd981613f83565b94506040870135935060608701359250613ff560808801613f3e565b915060a087013590509295509295509295565b60006020828403121561401a57600080fd5b8135613e8781613f83565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417611b5657611b56614025565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826140d0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115611b5657611b56614025565b81810381811115611b5657611b56614025565b60006020828403121561410d57600080fd5b5051919050565b600060033d111561412d5760046000803e5060005160e01c5b90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff8211171561419b577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040525050565b600060443d10156141b05790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff81602484011181841117156141fe57505050505090565b82850191508151818111156142165750505050505090565b843d87010160208285010111156142305750505050505090565b61423f60208286010187614130565b509095945050505050565b60006020828403121561425c57600080fd5b81518015158114613e8757600080fd5b6000825160005b8181101561428d5760208186018101518583015201614273565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea264697066735822122025851a8223583f6101efb0b7681a9f0447b8bfc27a8d10e92d5c9ee7642e7abf64736f6c63430008110033
Deployed Bytecode
0x60806040526004361061016a5760003560e01c806387f49f54116100cb578063ce9c7c0d1161007f578063ec91f2a411610059578063ec91f2a414610445578063f25efffc1461045b578063f2fde38b1461047057600080fd5b8063ce9c7c0d146103f9578063db2e1eed14610419578063dcf1ed2b1461042f57600080fd5b8063938b5f32116100b0578063938b5f3214610394578063a4d0a17e146103b8578063b296024d146103cd57600080fd5b806387f49f54146103495780638da5cb5b1461036957600080fd5b8063659dd2b411610122578063715018a611610107578063715018a6146102805780637d9f6db5146102955780638456cb591461033457600080fd5b8063659dd2b41461024d5780637120334b1461026057600080fd5b80633f4ba83a116101535780633f4ba83a146101e85780633fc8cef3146101fd5780635c975abb1461022a57600080fd5b80632de45f181461016f57806336ebdb38146101c6575b600080fd5b34801561017b57600080fd5b5060c95461019c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101d257600080fd5b506101e66101e1366004613f4f565b610490565b005b3480156101f457600080fd5b506101e6610563565b34801561020957600080fd5b5060ca5461019c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561023657600080fd5b5060335460ff1660405190151581526020016101bd565b6101e661025b366004613f6a565b61060a565b34801561026c57600080fd5b506101e661027b366004613f6a565b61098d565b34801561028c57600080fd5b506101e6610a29565b3480156102a157600080fd5b5060d05460d15460d25460d35460d4546102ef949392919073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900460ff1686565b60408051968752602087019590955293850192909252606084015273ffffffffffffffffffffffffffffffffffffffff166080830152151560a082015260c0016101bd565b34801561034057600080fd5b506101e6610a9a565b34801561035557600080fd5b506101e6610364366004613fa5565b610b09565b34801561037557600080fd5b5060975473ffffffffffffffffffffffffffffffffffffffff1661019c565b3480156103a057600080fd5b506103aa60cf5481565b6040519081526020016101bd565b3480156103c457600080fd5b506101e6610ca5565b3480156103d957600080fd5b5060cd546103e79060ff1681565b60405160ff90911681526020016101bd565b34801561040557600080fd5b506101e6610414366004613f6a565b610d5d565b34801561042557600080fd5b506103aa60cc5481565b34801561043b57600080fd5b506103aa60ce5481565b34801561045157600080fd5b506103aa60cb5481565b34801561046757600080fd5b506101e6610df9565b34801561047c57600080fd5b506101e661048b366004614008565b610eb3565b60975473ffffffffffffffffffffffffffffffffffffffff1633146104fc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b60cd80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff83169081179091556040519081527fec5ccd96cc77b6219e9d44143df916af68fc169339ea7de5008ff15eae13450d906020015b60405180910390a150565b60975473ffffffffffffffffffffffffffffffffffffffff1633146105ca5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b6105d2610faf565b60d25415806105fb575060d45474010000000000000000000000000000000000000000900460ff165b1561060857610608611076565b565b60026065540361065c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016104f3565b60026065556040805160c08101825260d05480825260d154602083015260d2549282019290925260d354606082015260d45473ffffffffffffffffffffffffffffffffffffffff8116608083015274010000000000000000000000000000000000000000900460ff16151560a082015290821461071b5760405162461bcd60e51b815260206004820152601760248201527f4e6f756e206e6f7420757020666f722061756374696f6e00000000000000000060448201526064016104f3565b8060600151421061076e5760405162461bcd60e51b815260206004820152600f60248201527f41756374696f6e2065787069726564000000000000000000000000000000000060448201526064016104f3565b60cc543410156107c05760405162461bcd60e51b815260206004820152601f60248201527f4d7573742073656e64206174206c65617374207265736572766550726963650060448201526064016104f3565b60cd5460208201516064916107da9160ff90911690614054565b6107e4919061409a565b81602001516107f391906140d5565b34101561086a576040805162461bcd60e51b81526020600482015260248101919091527f4d7573742073656e64206d6f7265207468616e206c617374206269642062792060448201527f6d696e426964496e6372656d656e7450657263656e7461676520616d6f756e7460648201526084016104f3565b608081015173ffffffffffffffffffffffffffffffffffffffff81161561089957610899818360200151611221565b3460d15560d480547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905560cb546060830151600091906108de9042906140e8565b10905080156108ff5760cb546108f490426140d5565b6060840181905260d3555b8251604080513381523460208201528315158183015290517f1159164c56f277e6fc99c11731bd380e0347deb969b75523398734c252706ea39181900360600190a2801561098257825160608401516040519081527f6e912a3a9105bdd2af817ba5adc14e6c127c1035b5b648faa29ca0d58ab8ff4e9060200160405180910390a25b505060016065555050565b60975473ffffffffffffffffffffffffffffffffffffffff1633146109f45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b60cb8190556040518181527f1b55d9f7002bda4490f467e326f22a4a847629c0f2d1ed421607d318d25b410d90602001610558565b60975473ffffffffffffffffffffffffffffffffffffffff163314610a905760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b6106086000611356565b60975473ffffffffffffffffffffffffffffffffffffffff163314610b015760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b6106086113cd565b600054610100900460ff1680610b22575060005460ff16155b610b945760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015610bb6576000805461ffff19166101011790555b610bbe611473565b610bc6611561565b610bce611616565b610bd66113cd565b60c9805473ffffffffffffffffffffffffffffffffffffffff808a167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560ca80549289169290911691909117905560cb85905560cc84905560cd805460ff85167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617905560ce8290554260cf558015610c9c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b50505050505050565b60335460ff16610cf75760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016104f3565b600260655403610d495760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016104f3565b6002606555610d566116d3565b6001606555565b60975473ffffffffffffffffffffffffffffffffffffffff163314610dc45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b60cc8190556040518181527f6ab2e127d7fdf53b8f304e59d3aab5bfe97979f52a85479691a6fab27a28a6b290602001610558565b600260655403610e4b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016104f3565b600260655560335460ff1615610ea35760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016104f3565b610eab6116d3565b610d56611076565b60975473ffffffffffffffffffffffffffffffffffffffff163314610f1a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b73ffffffffffffffffffffffffffffffffffffffff8116610fa35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016104f3565b610fac81611356565b50565b60335460ff166110015760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016104f3565b603380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b60c960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631249c58b6040518163ffffffff1660e01b81526004016020604051808303816000875af192505050801561111f575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261111c918101906140fb565b60015b61115e5761112b614114565b806308c379a003611152575061113f6141a2565b8061114a5750611154565b610fac6113cd565b505b3d6000803e3d6000fd5b42600061116a82611a4e565b61117490836140d5565b6040805160c08101825285815260006020808301829052828401879052606083018590526080830182905260a090920181905260d087905560d15560d285905560d383905560d480547fffffffffffffffffffffff000000000000000000000000000000000000000000169055815185815290810183905291925084917fd6eddd1118d71820909c1197aa966dbc15ed6f508554252169cc3d5ccac756ca910160405180910390a2505050565b61122b8282611acf565b6113525760ca60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561129957600080fd5b505af11580156112ad573d6000803e3d6000fd5b505060ca546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260248201879052909116935063a9059cbb925060440190506020604051808303816000875af115801561132c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611350919061424a565b505b5050565b6097805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335460ff16156114205760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016104f3565b603380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861104c3390565b600054610100900460ff168061148c575060005460ff16155b6114fe5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015611520576000805461ffff19166101011790555b611528611b5c565b611530611c39565b8015610fac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff168061157a575060005460ff16155b6115ec5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff1615801561160e576000805461ffff19166101011790555b611530611d3f565b600054610100900460ff168061162f575060005460ff16155b6116a15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff161580156116c3576000805461ffff19166101011790555b6116cb611b5c565b611530611e22565b6040805160c08101825260d054815260d154602082015260d25491810182905260d354606082015260d45473ffffffffffffffffffffffffffffffffffffffff8116608083015274010000000000000000000000000000000000000000900460ff16151560a08201529060000361178c5760405162461bcd60e51b815260206004820152601460248201527f41756374696f6e206861736e277420626567756e00000000000000000000000060448201526064016104f3565b8060a00151156117de5760405162461bcd60e51b815260206004820181905260248201527f41756374696f6e2068617320616c7265616479206265656e20736574746c656460448201526064016104f3565b80606001514210156118325760405162461bcd60e51b815260206004820152601860248201527f41756374696f6e206861736e277420636f6d706c65746564000000000000000060448201526064016104f3565b60d480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055608081015173ffffffffffffffffffffffffffffffffffffffff166119215760c95481516040517f42966c6800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909216916342966c68916118ea9160040190815260200190565b600060405180830381600087803b15801561190457600080fd5b505af1158015611918573d6000803e3d6000fd5b505050506119bb565b60c954608082015182516040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff928316602482015260448101919091529116906323b872dd90606401600060405180830381600087803b1580156119a257600080fd5b505af11580156119b6573d6000803e3d6000fd5b505050505b6020810151156119f1576119f16119e760975473ffffffffffffffffffffffffffffffffffffffff1690565b8260200151611221565b805160808201516020808401516040805173ffffffffffffffffffffffffffffffffffffffff9094168452918301527fc9f72b276a388619c6d185d146697036241880c36654b1a3ffdad07c24038d99910160405180910390a250565b60008060cf5483611a5f91906140e8565b90506343ab3e008110611a7857506302a3000092915050565b6000611a8382611ed8565b9050611a9b81611a96630784ce00611ed8565b611f4b565b9050611aa6816123cc565b9050611abc81611ab760ce54611ed8565b6139d7565b9050611ac781613dcf565b949350505050565b60408051600080825260208201909252819073ffffffffffffffffffffffffffffffffffffffff851690617530908590604051611b0c919061426c565b600060405180830381858888f193505050503d8060008114611b4a576040519150601f19603f3d011682016040523d82523d6000602084013e611b4f565b606091505b5090925050505b92915050565b600054610100900460ff1680611b75575060005460ff16155b611be75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015611530576000805461ffff19166101011790558015610fac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff1680611c52575060005460ff16155b611cc45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015611ce6576000805461ffff19166101011790555b603380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558015610fac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff1680611d58575060005460ff16155b611dca5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015611dec576000805461ffff19166101011790555b60016065558015610fac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905550565b600054610100900460ff1680611e3b575060005460ff16155b611ead5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016104f3565b600054610100900460ff16158015611ecf576000805461ffff19166101011790555b61153033611356565b600081600003611eea57506000919050565b816000611ef682613e8e565b90506070811015611f0f578060700382901b9150611f22565b6070811115611f22576070810382901c91505b613fff0160701b6dffffffffffffffffffffffffffff919091161760801b92915050565b919050565b6000617fff60f084811c8216919084901c811690829003611fc75780617fff03611f9a57507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b5050507f800000000000000000000000000000000000000000000000000000000000000081168218611b56565b80617fff0361204e577dffffffffffffffffffffffffffff0000000000000000000000000000000084161561202157507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b5050508082187f800000000000000000000000000000000000000000000000000000000000000016611b56565b7f7fffffffffffffffffffffffffffffff00000000000000000000000000000000841660000361211c577f7fffffffffffffffffffffffffffffff0000000000000000000000000000000085166000036120cd57507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b5050508082187f8000000000000000000000000000000000000000000000000000000000000000167f7fff00000000000000000000000000000000000000000000000000000000000017611b56565b6dffffffffffffffffffffffffffff608085901c1660008290036121435760019150612155565b6e010000000000000000000000000000175b6dffffffffffffffffffffffffffff608087901c1660008490036121bd5780156121b857600061218482613e8e565b6001955060e2039384017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e01939190911b90505b6121d2565b6e0100000000000000000000000000001760721b5b8181816121e1576121e161406b565b04905080600003612249577f80000000000000000000000000000000000000000000000000000000000000008787181661221c57600061223e565b7f80000000000000000000000000000000000000000000000000000000000000005b945050505050611b56565b6d10000000000000000000000000008110156122675761226761429b565b60006e0800000000000000000000000000008210156122c7576e0400000000000000000000000000008210156122bc576e0200000000000000000000000000008210156122b55760706122bf565b60716122bf565b60725b60ff166122d0565b6122d082613e8e565b9050836140710181860111156122ee57617fff945060009150612388565b83818601613ffc011015612309576000945060009150612388565b83818601613f8c011015612356578385613ffc011115612334578385613ffc010382901b915061234d565b8385613ffc01101561234d57613ffc8585030382901c91505b60009450612388565b6070811115612369576070810382901c91505b6dffffffffffffffffffffffffffff8216915083818601613f8d010394505b81607086901b888a186f8000000000000000000000000000000060801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050611b56565b60006f80000000000000000000000000000000608083901c90811190617fff60f085901c8116916dffffffffffffffffffffffffffff16908214801561241157508015155b1561244057507f7fff800000000000000000000000000000000000000000000000000000000000949350505050565b61400d8211156124815782612475577f7fff000000000000000000000000000000000000000000000000000000000000612478565b60005b95945050505050565b613f7f8210156124b557507f3fff000000000000000000000000000000000000000000000000000000000000949350505050565b816000036124c657600191506124d8565b6e010000000000000000000000000000175b613fef82111561250b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01182011b61251d565b613fef82101561251d57613fef8290031c5b82801561253b575071406e0000000000000000000000000000000081115b1561254b57506000949350505050565b8215801561256a5750713fffffffffffffffffffffffffffffffffff81115b1561259957507f7fff000000000000000000000000000000000000000000000000000000000000949350505050565b6fffffffffffffffffffffffffffffffff81169060801c8380156125bc57508115155b156125c8579019906001015b6f80000000000000000000000000000000828116156125f85770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b6f40000000000000000000000000000000831615612627577001306fe0a31b7152de8d5a46305c85edec0260801c5b6f20000000000000000000000000000000831615612656577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b6f100000000000000000000000000000008316156126855770010b5586cf9890f6298b92b71842a983630260801c5b6f080000000000000000000000000000008316156126b4577001059b0d31585743ae7c548eb68ca417fd0260801c5b6f040000000000000000000000000000008316156126e357700102c9a3e778060ee6f7caca4f7a29bde80260801c5b6f020000000000000000000000000000008316156127125770010163da9fb33356d84a66ae336dcdfa3f0260801c5b6f0100000000000000000000000000000083161561274157700100b1afa5abcbed6129ab13ec11dc95430260801c5b6e80000000000000000000000000000083161561276f5770010058c86da1c09ea1ff19d294cf2f679b0260801c5b6e40000000000000000000000000000083161561279d577001002c605e2e8cec506d21bfc89a23a00f0260801c5b6e2000000000000000000000000000008316156127cb57700100162f3904051fa128bca9c55c31e5df0260801c5b6e1000000000000000000000000000008316156127f9577001000b175effdc76ba38e31671ca9397250260801c5b6e08000000000000000000000000000083161561282757700100058ba01fb9f96d6cacd4b180917c3d0260801c5b6e0400000000000000000000000000008316156128555770010002c5cc37da9491d0985c348c68e7b30260801c5b6e020000000000000000000000000000831615612883577001000162e525ee054754457d59952920260260801c5b6e0100000000000000000000000000008316156128b15770010000b17255775c040618bf4a4ade83fc0260801c5b6d80000000000000000000000000008316156128de577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6d400000000000000000000000000083161561290b57700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6d20000000000000000000000000008316156129385770010000162e43f4f831060e02d839a9d16d0260801c5b6d100000000000000000000000000083161561296557700100000b1721bcfc99d9f890ea069117630260801c5b6d08000000000000000000000000008316156129925770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6d04000000000000000000000000008316156129bf577001000002c5c863b73f016468f6bac5ca2b0260801c5b6d02000000000000000000000000008316156129ec57700100000162e430e5a18f6119e3c02282a50260801c5b6d0100000000000000000000000000831615612a19577001000000b1721835514b86e6d96efd1bfe0260801c5b6c80000000000000000000000000831615612a4557700100000058b90c0b48c6be5df846c5b2ef0260801c5b6c40000000000000000000000000831615612a715770010000002c5c8601cc6b9e94213c72737a0260801c5b6c20000000000000000000000000831615612a9d577001000000162e42fff037df38aa2b219f060260801c5b6c10000000000000000000000000831615612ac95770010000000b17217fba9c739aa5819f44f90260801c5b6c08000000000000000000000000831615612af5577001000000058b90bfcdee5acd3c1cedc8230260801c5b6c04000000000000000000000000831615612b2157700100000002c5c85fe31f35a6a30da1be500260801c5b6c02000000000000000000000000831615612b4d5770010000000162e42ff0999ce3541b9fffcf0260801c5b6c01000000000000000000000000831615612b7957700100000000b17217f80f4ef5aadda455540260801c5b6b800000000000000000000000831615612ba45770010000000058b90bfbf8479bd5a81b51ad0260801c5b6b400000000000000000000000831615612bcf577001000000002c5c85fdf84bd62ae30a74cc0260801c5b6b200000000000000000000000831615612bfa57700100000000162e42fefb2fed257559bdaa0260801c5b6b100000000000000000000000831615612c25577001000000000b17217f7d5a7716bba4a9ae0260801c5b6b080000000000000000000000831615612c5057700100000000058b90bfbe9ddbac5e109cce0260801c5b6b040000000000000000000000831615612c7b5770010000000002c5c85fdf4b15de6f17eb0d0260801c5b6b020000000000000000000000831615612ca6577001000000000162e42fefa494f1478fde050260801c5b6b010000000000000000000000831615612cd15770010000000000b17217f7d20cf927c8e94c0260801c5b6a8000000000000000000000831615612cfb577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6a4000000000000000000000831615612d2557700100000000002c5c85fdf477b662b269450260801c5b6a2000000000000000000000831615612d4f5770010000000000162e42fefa3ae53369388c0260801c5b6a1000000000000000000000831615612d7957700100000000000b17217f7d1d351a389d400260801c5b6a0800000000000000000000831615612da35770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6a0400000000000000000000831615612dcd577001000000000002c5c85fdf4741bea6e77e0260801c5b6a0200000000000000000000831615612df757700100000000000162e42fefa39fe95583c20260801c5b6a0100000000000000000000831615612e21577001000000000000b17217f7d1cfb72b45e10260801c5b6980000000000000000000831615612e4a57700100000000000058b90bfbe8e7cc35c3f00260801c5b6940000000000000000000831615612e735770010000000000002c5c85fdf473e242ea380260801c5b6920000000000000000000831615612e9c577001000000000000162e42fefa39f02b772c0260801c5b6910000000000000000000831615612ec55770010000000000000b17217f7d1cf7d83c1a0260801c5b6908000000000000000000831615612eee577001000000000000058b90bfbe8e7bdcbe2e0260801c5b6904000000000000000000831615612f1757700100000000000002c5c85fdf473dea871f0260801c5b6902000000000000000000831615612f405770010000000000000162e42fefa39ef44d910260801c5b6901000000000000000000831615612f6957700100000000000000b17217f7d1cf79e9490260801c5b68800000000000000000831615612f915770010000000000000058b90bfbe8e7bce5440260801c5b68400000000000000000831615612fb9577001000000000000002c5c85fdf473de6eca0260801c5b68200000000000000000831615612fe157700100000000000000162e42fefa39ef366f0260801c5b68100000000000000000831615613009577001000000000000000b17217f7d1cf79afa0260801c5b6808000000000000000083161561303157700100000000000000058b90bfbe8e7bcd6d0260801c5b680400000000000000008316156130595770010000000000000002c5c85fdf473de6b20260801c5b68020000000000000000831615613081577001000000000000000162e42fefa39ef3580260801c5b680100000000000000008316156130a95770010000000000000000b17217f7d1cf79ab0260801c5b6780000000000000008316156130d0577001000000000000000058b90bfbe8e7bcd50260801c5b6740000000000000008316156130f757700100000000000000002c5c85fdf473de6a0260801c5b67200000000000000083161561311e5770010000000000000000162e42fefa39ef340260801c5b67100000000000000083161561314557700100000000000000000b17217f7d1cf7990260801c5b67080000000000000083161561316c5770010000000000000000058b90bfbe8e7bcc0260801c5b670400000000000000831615613193577001000000000000000002c5c85fdf473de50260801c5b6702000000000000008316156131ba57700100000000000000000162e42fefa39ef20260801c5b6701000000000000008316156131e1577001000000000000000000b17217f7d1cf780260801c5b668000000000000083161561320757700100000000000000000058b90bfbe8e7bb0260801c5b664000000000000083161561322d5770010000000000000000002c5c85fdf473dd0260801c5b6620000000000000831615613253577001000000000000000000162e42fefa39ee0260801c5b66100000000000008316156132795770010000000000000000000b17217f7d1cf60260801c5b660800000000000083161561329f577001000000000000000000058b90bfbe8e7a0260801c5b66040000000000008316156132c557700100000000000000000002c5c85fdf473c0260801c5b66020000000000008316156132eb5770010000000000000000000162e42fefa39d0260801c5b660100000000000083161561331157700100000000000000000000b17217f7d1ce0260801c5b658000000000008316156133365770010000000000000000000058b90bfbe8e60260801c5b6540000000000083161561335b577001000000000000000000002c5c85fdf4720260801c5b6520000000000083161561338057700100000000000000000000162e42fefa380260801c5b651000000000008316156133a5577001000000000000000000000b17217f7d1b0260801c5b650800000000008316156133ca57700100000000000000000000058b90bfbe8d0260801c5b650400000000008316156133ef5770010000000000000000000002c5c85fdf460260801c5b65020000000000831615613414577001000000000000000000000162e42fefa20260801c5b650100000000008316156134395770010000000000000000000000b17217f7d00260801c5b64800000000083161561345d577001000000000000000000000058b90bfbe70260801c5b64400000000083161561348157700100000000000000000000002c5c85fdf30260801c5b6420000000008316156134a55770010000000000000000000000162e42fef90260801c5b6410000000008316156134c957700100000000000000000000000b17217f7c0260801c5b6408000000008316156134ed5770010000000000000000000000058b90bfbd0260801c5b640400000000831615613511577001000000000000000000000002c5c85fde0260801c5b64020000000083161561353557700100000000000000000000000162e42fee0260801c5b640100000000831615613559577001000000000000000000000000b17217f60260801c5b638000000083161561357c57700100000000000000000000000058b90bfa0260801c5b634000000083161561359f5770010000000000000000000000002c5c85fc0260801c5b63200000008316156135c2577001000000000000000000000000162e42fd0260801c5b63100000008316156135e55770010000000000000000000000000b17217e0260801c5b6308000000831615613608577001000000000000000000000000058b90be0260801c5b630400000083161561362b57700100000000000000000000000002c5c85e0260801c5b630200000083161561364e5770010000000000000000000000000162e42e0260801c5b630100000083161561367157700100000000000000000000000000b172160260801c5b628000008316156136935770010000000000000000000000000058b90a0260801c5b624000008316156136b5577001000000000000000000000000002c5c840260801c5b622000008316156136d757700100000000000000000000000000162e410260801c5b621000008316156136f9577001000000000000000000000000000b17200260801c5b6208000083161561371b57700100000000000000000000000000058b8f0260801c5b6204000083161561373d5770010000000000000000000000000002c5c70260801c5b6202000083161561375f577001000000000000000000000000000162e30260801c5b620100008316156137815770010000000000000000000000000000b1710260801c5b6180008316156137a2577001000000000000000000000000000058b80260801c5b6140008316156137c357700100000000000000000000000000002c5b0260801c5b6120008316156137e45770010000000000000000000000000000162d0260801c5b61100083161561380557700100000000000000000000000000000b160260801c5b6108008316156138265770010000000000000000000000000000058a0260801c5b610400831615613847577001000000000000000000000000000002c40260801c5b610200831615613868577001000000000000000000000000000001610260801c5b610100831615613889577001000000000000000000000000000000b00260801c5b60808316156138a9577001000000000000000000000000000000570260801c5b60408316156138c95770010000000000000000000000000000002b0260801c5b60208316156138e9577001000000000000000000000000000000150260801c5b60108316156139095770010000000000000000000000000000000a0260801c5b6008831615613929577001000000000000000000000000000000040260801c5b6004831615613949577001000000000000000000000000000000010260801c5b8461397157600f81901c6dffffffffffffffffffffffffffff169050613fff820191506139c4565b613ffe821161399d57600f81901c6dffffffffffffffffffffffffffff16905081613fff0391506139c4565b6000917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc011011c5b60709190911b1760801b95945050505050565b6000617fff60f084811c8216919084901c811690829003613b2a5780617fff03613ad5577fffffffffffffffffffffffffffffffff0000000000000000000000000000000080851690861603613a54575050507f800000000000000000000000000000000000000000000000000000000000000081168218611b56565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000858518167f800000000000000000000000000000000000000000000000000000000000000003613aaa57505050818117611b56565b507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b7f7fffffffffffffffffffffffffffffff000000000000000000000000000000008416600003611f9a57507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b80617fff03613bb5577f7fffffffffffffffffffffffffffffff000000000000000000000000000000008516600003613b8857507f7fff8000000000000000000000000000000000000000000000000000000000009150611b569050565b5050507f800000000000000000000000000000000000000000000000000000000000000082168118611b56565b6dffffffffffffffffffffffffffff608086901c166000839003613bdc5760019250613bee565b6e010000000000000000000000000000175b6dffffffffffffffffffffffffffff608086901c166000839003613c155760019250613c27565b6e010000000000000000000000000000175b808202915081600003613c64577f80000000000000000000000000000000000000000000000000000000000000008787181661221c57600061223e565b9282019260007c0200000000000000000000000000000000000000000000000000000000831015613cc9577c0100000000000000000000000000000000000000000000000000000000831015613cc257613cbd83613e8e565b613ccc565b60e0613ccc565b60e15b90506140708186011015613ce7576000945060009250613d8b565b6140e08186011015613d2a57614070851015613d0c57846140700383901c9250613d21565b614070851115613d2157614070850383901b92505b60009450613d8b565b61c0dd8186011115613d4457617fff945060009250613d8b565b6070811115613d5b576070810383901c9250613d6e565b6070811015613d6e578060700383901b92505b6dffffffffffffffffffffffffffff831692506140df8186010394505b82607086901b888a186f8000000000000000000000000000000060801b1660801c6fffffffffffffffffffffffffffffffff16171760801b95505050505050611b56565b6000617fff60f083901c16613fff811015613ded5750600092915050565b6f80000000000000000000000000000000608084901c10613e0d57600080fd5b6140fe811115613e1c57600080fd5b6e0100000000000000000000000000006dffffffffffffffffffffffffffff608085901c161761406f821015613e585761406f8290031c613e87565b61406f821115613e87577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf9182011b5b9392505050565b6000808211613e9c57600080fd5b60007001000000000000000000000000000000008310613ebe57608092831c92015b680100000000000000008310613ed657604092831c92015b6401000000008310613eea57602092831c92015b620100008310613efc57601092831c92015b6101008310613f0d57600892831c92015b60108310613f1d57600492831c92015b60048310613f2d57600292831c92015b60028310611b565760010192915050565b803560ff81168114611f4657600080fd5b600060208284031215613f6157600080fd5b613e8782613f3e565b600060208284031215613f7c57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610fac57600080fd5b60008060008060008060c08789031215613fbe57600080fd5b8635613fc981613f83565b95506020870135613fd981613f83565b94506040870135935060608701359250613ff560808801613f3e565b915060a087013590509295509295509295565b60006020828403121561401a57600080fd5b8135613e8781613f83565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417611b5657611b56614025565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826140d0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820180821115611b5657611b56614025565b81810381811115611b5657611b56614025565b60006020828403121561410d57600080fd5b5051919050565b600060033d111561412d5760046000803e5060005160e01c5b90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff8211171561419b577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040525050565b600060443d10156141b05790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff81602484011181841117156141fe57505050505090565b82850191508151818111156142165750505050505090565b843d87010160208285010111156142305750505050505090565b61423f60208286010187614130565b509095945050505050565b60006020828403121561425c57600080fd5b81518015158114613e8757600080fd5b6000825160005b8181101561428d5760208186018101518583015201614273565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea264697066735822122025851a8223583f6101efb0b7681a9f0447b8bfc27a8d10e92d5c9ee7642e7abf64736f6c63430008110033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.