Overview
APE Balance
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
RankedAuctionMechanic
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 1 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "./MechanicMintManagerClientUpgradeable.sol"; import "../../erc721/interfaces/IEditionCollection.sol"; import "../../erc721/interfaces/IERC721GeneralSupplyMetadata.sol"; import "../../observability/IGengineObservability.sol"; import "./interfaces/IManifold1155Burn.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; /** * @notice Ranked auctions * @author highlight.xyz */ contract RankedAuctionMechanic is MechanicMintManagerClientUpgradeable, UUPSUpgradeable { using EnumerableSet for EnumerableSet.UintSet; using EnumerableSet for EnumerableSet.Bytes32Set; /** * @notice Throw when an action is unauthorized */ error Unauthorized(); /** * @notice Throw when signer of signature is invalid */ error InvalidSigner(); /** * @notice Throw when it is invalid to mint on a vector */ error InvalidMint(); /** * @notice Throw when it is invalid to mint a number of tokens */ error InvalidMintAmount(); /** * @notice Throw when it is invalid to bid */ error InvalidBid(); /** * @notice Throw when a vector is already created with a mechanic vector ID */ error VectorAlreadyCreated(); /** * @notice Throw when the vector update is invalid */ error InvalidUpdate(); /** * @notice Throw when code gets into impossible state */ error ImpossibleState(); /** * @notice Throw when an internal transfer of ether fails */ error EtherSendFailed(); /** * @notice Throw when a claim is invalid */ error InvalidClaim(); /** * @notice Throw when a claim signature is invalid */ error InvalidSignature(); /** * @notice Errors to throw when adding / removing bids from user bid ids */ error BidAlreadyAdded(); error BidAlreadyReclaimed(); /** * @notice On-chain mint vector (stored data) * @param startTimestamp When minting opens on vector * @param endTimestamp When minting ends on vector * @param paymentRecipient Payment recipient * @param maxUserClaimableViaVector Max number of tokens that can be minted by user via vector * @param maxTotalClaimableViaVector Max number of tokens that can be minted via vector * @param latestBidId Total number of bids (valid or invalid, deleted or not) * @param currency Currency used for payment. Native gas token, if zero address * @param bidFundsClaimed Bid funds claimed * @param reserveBid Reserve bid * @param maxEndTimestamp Maximium time the auction can go till (given extensions) * @param actionId Action ID (create / update bid) */ struct Vector { uint48 startTimestamp; uint48 endTimestamp; address payable paymentRecipient; uint32 maxUserClaimableViaVector; uint32 maxTotalClaimableViaVector; uint32 latestBidId; address currency; bool bidFundsClaimed; uint96 reserveBid; uint48 maxEndTimestamp; uint96 actionId; } /** * @notice Bid * @dev Only handles bids below ~10B ether * @param bidAmount Amount of bid * @param bidder Bidder */ struct Bid { uint96 bidAmount; address bidder; } /** * @notice User bids' metadata * @param numClaimed Number of valid bids redeemed for a token (after mint ends) * @param numBids Number of bids by user */ struct UserBidsMetadata { uint32 numClaimed; uint32 numBids; } /** * @notice Config used to control updating of fields in Vector */ struct VectorUpdateConfig { bool updateStartTimestamp; bool updateEndTimestamp; bool updateMaxEndTimestamp; bool updateMaxUserClaimableViaVector; bool updateMaxTotalClaimableViaVector; bool updatePaymentRecipient; bool updateCurrency; bool updateReserveBid; } /** * @notice Used to claim funds from an invalid bid, mint tokens + claim rebate if eligible, claim auction earnings */ struct RankedAuctionsClaim { bytes32 mechanicVectorId; uint256 rebateAmount; address claimer; uint32 claimerNumValidBids; uint48 claimExpiryTimestamp; uint256 cumulativeBidAmount; uint32 bidId; uint8 claimType; } /** * @notice Constants that help with EIP-712, signature based minting */ bytes32 private constant _DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"); /* solhint-disable max-line-length */ bytes32 private constant _CLAIM_TYPEHASH = keccak256( "RankedAuctionsClaim(bytes32 mechanicVectorId,uint256 rebateAmount,address claimer,uint32 claimerNumValidBids,uint48 claimExpiryTimestamp,uint256 cumulativeBidAmount,uint32 bidId,uint8 claimType)" ); /* solhint-enable max-line-length */ /** * @notice Stores seed based vector, indexed by global mechanic vector id */ mapping(bytes32 => Vector) private vector; /** * @notice Stores vector's current validity hash */ mapping(bytes32 => bytes32) private vectorValidityHash; /** * @notice System-wide vector ids to bids by their ids */ mapping(bytes32 => mapping(uint32 => Bid)) public bids; /** * @notice System-wide vector ids to user's bids metadata */ mapping(bytes32 => mapping(address => UserBidsMetadata)) private _userBidsMetadata; /** * @notice System-wide vector ids to user's bid ids */ mapping(bytes32 => mapping(address => EnumerableSet.UintSet)) private _userBidIds; /** * @notice System-wide used claims */ mapping(bytes32 => EnumerableSet.Bytes32Set) private _usedClaims; /** * @notice Emitted when a mint vector is created */ event RankedAuctionCreated(bytes32 indexed mechanicVectorId); /** * @notice Emitted when a mint vector is updated */ event RankedAuctionUpdated(bytes32 indexed mechanicVectorId); /** * @notice Emitted when a bid is created or updated */ event BidCreatedOrUpdated( bytes32 indexed mechanicVectorId, bytes32 indexed newValidityHash, uint96 indexed actionId, uint32 bidId, address bidder, uint96 bidAmount, address currency, bool created ); /** * @notice Emitted when bid funds are reclaimed */ event BidReclaimed(bytes32 indexed mechanicVectorId, uint32 indexed bidId, uint96 amount, address currency); /** * @notice Emitted when bid funds are claimed */ event AuctionEarningsClaimed( bytes32 indexed mechanicVectorId, uint256 earnings, address paymentRecipient, address currency ); /** * @notice Emitted when auction is lengthened */ event AuctionLengthened(bytes32 indexed mechanicVectorId, uint48 newEndTimestamp); /** * @notice Initialize mechanic contract * @param _mintManager Mint manager address * @param platform Platform owning the contract */ function initialize(address _mintManager, address platform) external initializer { __MechanicMintManagerClientUpgradeable_initialize(_mintManager, platform); } /** * @notice Create a seed based vector * @param mechanicVectorId Global mechanic vector ID * @param vectorData Vector data, to be deserialized into seed based vector data */ function createVector(bytes32 mechanicVectorId, bytes memory vectorData) external onlyMintManager { // precaution, although MintManager tightly controls creation and prevents double creation if (vector[mechanicVectorId].startTimestamp != 0) { _revert(VectorAlreadyCreated.selector); } ( uint48 startTimestamp, uint48 endTimestamp, uint48 maxEndTimestamp, address paymentRecipient, uint32 maxUserClaimableViaVector, uint32 maxTotalClaimableViaVector, uint96 reserveBid, address currency ) = abi.decode(vectorData, (uint48, uint48, uint48, address, uint32, uint32, uint96, address)); if (maxTotalClaimableViaVector == 0) { _revert(InvalidUpdate.selector); } uint48 st = startTimestamp == 0 ? uint48(block.timestamp) : startTimestamp; Vector memory _vector = Vector( st, endTimestamp == 0 ? uint48(st + 604800) : endTimestamp, // arbitrarily set for a week payable(paymentRecipient), maxUserClaimableViaVector, maxTotalClaimableViaVector, 0, currency, false, reserveBid, maxEndTimestamp, 0 ); vector[mechanicVectorId] = _vector; emit RankedAuctionCreated(mechanicVectorId); } /* solhint-disable code-complexity */ /** * @notice Update a seed based vector * @param mechanicVectorId Global mechanic vector ID * @param newVector New vector fields * @param updateConfig Config denoting what fields on vector to update */ function updateVector( bytes32 mechanicVectorId, Vector calldata newVector, VectorUpdateConfig calldata updateConfig ) external { MechanicVectorMetadata memory metadata = _getMechanicVectorMetadata(mechanicVectorId); if ( OwnableUpgradeable(metadata.contractAddress).owner() != msg.sender && metadata.contractAddress != msg.sender ) { _revert(Unauthorized.selector); } // rather than updating entire vector, update per-field if (updateConfig.updateStartTimestamp) { vector[mechanicVectorId].startTimestamp = newVector.startTimestamp == 0 ? uint48(block.timestamp) : newVector.startTimestamp; } if (updateConfig.updateEndTimestamp) { if (newVector.endTimestamp == 0) { _revert(InvalidUpdate.selector); } vector[mechanicVectorId].endTimestamp = newVector.endTimestamp; } if (updateConfig.updateMaxEndTimestamp) { if (newVector.maxEndTimestamp == 0) { _revert(InvalidUpdate.selector); } vector[mechanicVectorId].maxEndTimestamp = newVector.maxEndTimestamp; } if (updateConfig.updateMaxUserClaimableViaVector) { vector[mechanicVectorId].maxUserClaimableViaVector = newVector.maxUserClaimableViaVector; } if (updateConfig.updateMaxTotalClaimableViaVector) { if ( newVector.maxTotalClaimableViaVector == 0 || newVector.maxTotalClaimableViaVector < vector[mechanicVectorId].maxTotalClaimableViaVector ) { _revert(InvalidUpdate.selector); } vector[mechanicVectorId].maxTotalClaimableViaVector = newVector.maxTotalClaimableViaVector; } if (updateConfig.updateCurrency) { if (vector[mechanicVectorId].latestBidId > 0) { _revert(InvalidUpdate.selector); } vector[mechanicVectorId].currency = newVector.currency; } if (updateConfig.updatePaymentRecipient) { vector[mechanicVectorId].paymentRecipient = newVector.paymentRecipient; } if (updateConfig.updateReserveBid) { if (vector[mechanicVectorId].latestBidId > 0) { _revert(InvalidUpdate.selector); } vector[mechanicVectorId].reserveBid = newVector.reserveBid; } emit RankedAuctionUpdated(mechanicVectorId); } /** * @notice Create a new bid */ function bid(bytes32 mechanicVectorId, uint96 bidAmount) external payable { Vector memory _vector = vector[mechanicVectorId]; uint32 newUserNumBids = _userBidsMetadata[mechanicVectorId][msg.sender].numBids + 1; if ( _vector.endTimestamp < uint48(block.timestamp) || _vector.startTimestamp > uint48(block.timestamp) || bidAmount < _vector.reserveBid || bidAmount != msg.value || (_vector.maxUserClaimableViaVector != 0 && newUserNumBids > uint256(_vector.maxUserClaimableViaVector)) ) { _revert(InvalidBid.selector); } _vector.latestBidId += 1; _vector.actionId += 1; bids[mechanicVectorId][_vector.latestBidId] = Bid(bidAmount, msg.sender); if (!_userBidIds[mechanicVectorId][msg.sender].add(uint256(_vector.latestBidId))) { // impossible state _revert(BidAlreadyAdded.selector); } _userBidsMetadata[mechanicVectorId][msg.sender].numBids = newUserNumBids; vector[mechanicVectorId].latestBidId = _vector.latestBidId; vector[mechanicVectorId].actionId = _vector.actionId; if (_vector.endTimestamp - uint48(block.timestamp) <= 300) { _vector.endTimestamp = _vector.maxEndTimestamp != 0 ? ( _vector.maxEndTimestamp > uint48(block.timestamp) + 300 ? uint48(block.timestamp) + 300 : _vector.maxEndTimestamp ) : uint48(block.timestamp) + 300; vector[mechanicVectorId].endTimestamp = _vector.endTimestamp; emit AuctionLengthened(mechanicVectorId, _vector.endTimestamp); } bytes32 newValidityHash = _updateValidityHash(mechanicVectorId, _vector.latestBidId, bidAmount); emit BidCreatedOrUpdated( mechanicVectorId, newValidityHash, _vector.actionId, _vector.latestBidId, msg.sender, bidAmount, _vector.currency, true ); } /** * @notice Update a bid */ function updateBid(bytes32 mechanicVectorId, uint32 bidId, uint96 newBidAmount) external payable { Vector memory _vector = vector[mechanicVectorId]; Bid memory _bid = bids[mechanicVectorId][bidId]; if ( newBidAmount <= _bid.bidAmount || _bid.bidder == address(0) || _vector.endTimestamp < uint48(block.timestamp) || _vector.startTimestamp > uint48(block.timestamp) || newBidAmount < _vector.reserveBid || msg.value != newBidAmount - _bid.bidAmount ) { _revert(InvalidBid.selector); } if (_bid.bidder != msg.sender) { _revert(Unauthorized.selector); } _vector.actionId += 1; bids[mechanicVectorId][bidId].bidAmount = newBidAmount; vector[mechanicVectorId].actionId = _vector.actionId; if (_vector.endTimestamp - uint48(block.timestamp) <= 300) { uint48 newEndTimestamp = _vector.maxEndTimestamp != 0 ? ( _vector.maxEndTimestamp > uint48(block.timestamp) + 300 ? uint48(block.timestamp) + 300 : _vector.maxEndTimestamp ) : uint48(block.timestamp) + 300; vector[mechanicVectorId].endTimestamp = newEndTimestamp; emit AuctionLengthened(mechanicVectorId, newEndTimestamp); } bytes32 newValidityHash = _updateValidityHash(mechanicVectorId, bidId, newBidAmount); emit BidCreatedOrUpdated( mechanicVectorId, newValidityHash, _vector.actionId, bidId, msg.sender, newBidAmount, _vector.currency, false ); } /** * @notice Claim back funds for a bid that is currently invalid (effectively deleting the bid) */ function reclaimBid(RankedAuctionsClaim calldata claim, bytes calldata claimSignature) external { // validate signature _validateClaim(claim, msg.sender, 1, claimSignature); Bid memory _bid = bids[claim.mechanicVectorId][claim.bidId]; if (_bid.bidder != claim.claimer) { _revert(Unauthorized.selector); } _sendEther(_bid.bidAmount, payable(_bid.bidder)); emit BidReclaimed(claim.mechanicVectorId, claim.bidId, _bid.bidAmount, vector[claim.mechanicVectorId].currency); // remove bid _userBidsMetadata[claim.mechanicVectorId][claim.claimer].numBids -= 1; if (!_userBidIds[claim.mechanicVectorId][claim.claimer].remove(claim.bidId)) { _revert(BidAlreadyReclaimed.selector); } delete bids[claim.mechanicVectorId][claim.bidId]; } /** * @notice Withdraw auction earnings to payment recipient */ function withdrawAuctionEarnings(RankedAuctionsClaim calldata claim, bytes calldata claimSignature) external { _validateClaim(claim, msg.sender, 2, claimSignature); Vector memory _vector = vector[claim.mechanicVectorId]; // currently, only native gas token supported if ( uint48(block.timestamp) <= _vector.endTimestamp || _vector.currency != address(0) || _vector.bidFundsClaimed ) { _revert(InvalidClaim.selector); } // 5% to platform uint256 platformAmount = (claim.cumulativeBidAmount * 500) / 10000; _sendEther(platformAmount, payable(owner())); _sendEther(claim.cumulativeBidAmount - platformAmount, _vector.paymentRecipient); vector[claim.mechanicVectorId].bidFundsClaimed = true; emit AuctionEarningsClaimed( claim.mechanicVectorId, claim.cumulativeBidAmount, _vector.paymentRecipient, _vector.currency ); } /** * @notice See {IMechanic-processNumMint} */ function processNumMint( bytes32 mechanicVectorId, address recipient, uint32 numToMint, address minter, MechanicVectorMetadata calldata mechanicVectorMetadata, bytes calldata data ) external payable onlyMintManager { _processMint(mechanicVectorId, minter, numToMint, data); } /** * @notice See {IMechanic-processChooseMint} */ function processChooseMint( bytes32 mechanicVectorId, address recipient, uint256[] calldata tokenIds, address minter, MechanicVectorMetadata calldata mechanicVectorMetadata, bytes calldata data ) external payable onlyMintManager { // currently we don't support "choose token to mint" functionality for seed based mints _revert(InvalidMint.selector); } /** * @notice State readers */ function getRawVector(bytes32 mechanicVectorId) external view returns (Vector memory _vector) { _vector = vector[mechanicVectorId]; } function getVectorState( bytes32 mechanicVectorId ) external view returns (Vector memory _vector, bytes32 validityHash, uint256 collectionSupply, uint256 collectionSize) { _vector = vector[mechanicVectorId]; validityHash = vectorValidityHash[mechanicVectorId]; (collectionSupply, collectionSize) = _collectionSupplyAndSize(mechanicVectorId); } function getBids(bytes32 mechanicVectorId, uint32[] calldata bidIds) external view returns (Bid[] memory) { uint256 bidIdsLength = bidIds.length; Bid[] memory _bids = new Bid[](bidIdsLength); for (uint256 i = 0; i < bidIdsLength; i++) { _bids[i] = bids[mechanicVectorId][bidIds[i]]; } return _bids; } function getUserBids( bytes32 mechanicVectorId, address user ) external view returns (Bid[] memory, uint256[] memory bidIds, uint32 numBids, uint32 numClaimed) { UserBidsMetadata memory metadata = _userBidsMetadata[mechanicVectorId][user]; uint256[] memory _bidIds = _userBidIds[mechanicVectorId][user].values(); uint256 bidIdsLength = _bidIds.length; Bid[] memory _bids = new Bid[](bidIdsLength); for (uint256 i = 0; i < bidIdsLength; i++) { _bids[i] = bids[mechanicVectorId][uint32(_bidIds[i])]; } return (_bids, _bidIds, metadata.numBids, metadata.numClaimed); } /* solhint-disable no-empty-blocks */ /** * @notice Limit upgrades of contract to SeedBasedMintMechanic owner * @param // New implementation address */ function _authorizeUpgrade(address) internal override onlyOwner {} /** * @notice Process sequential mint logic * @param mechanicVectorId Mechanic vector ID * @param minter Minter * @param numToMint Number of tokens to mint * @param data Mechanic mint data (signature) */ function _processMint(bytes32 mechanicVectorId, address minter, uint32 numToMint, bytes calldata data) private { (RankedAuctionsClaim memory _claim, bytes memory claimSignature) = _unwrapRankedAuctionClaim( mechanicVectorId, data ); _validateClaim(_claim, minter, 3, claimSignature); if (vector[mechanicVectorId].endTimestamp >= uint48(block.timestamp)) { _revert(InvalidMint.selector); } uint32 numClaimed = _userBidsMetadata[mechanicVectorId][minter].numClaimed; if (numToMint + numClaimed > _claim.claimerNumValidBids) { _revert(InvalidMintAmount.selector); } _userBidsMetadata[mechanicVectorId][minter].numClaimed = numClaimed + numToMint; // handle rebate if (_claim.rebateAmount > 0) { _sendEther(_claim.rebateAmount, payable(_claim.claimer)); } } /** * @notice Send ether to a recipient */ function _sendEther(uint256 amount, address payable recipient) private { (bool sent, ) = recipient.call{ value: amount }(""); if (!sent) { _revert(EtherSendFailed.selector); } } /** * @notice Update vector's validity hash */ function _updateValidityHash(bytes32 mechanicVectorId, uint32 bidId, uint96 bidAmount) private returns (bytes32) { bytes32 newValidityHash = keccak256( abi.encodePacked(vectorValidityHash[mechanicVectorId], mechanicVectorId, bidId, bidAmount) ); vectorValidityHash[mechanicVectorId] = newValidityHash; return newValidityHash; } /** * @notice Validate claim * @param claim Claim * @param expectedClaimer Expected claimer * @param expectedClaimType Expected claim type * @param claimSignature Claim signature */ function _validateClaim( RankedAuctionsClaim memory claim, address expectedClaimer, uint8 expectedClaimType, bytes memory claimSignature ) private { if (claim.claimer != expectedClaimer) { _revert(Unauthorized.selector); } if (claim.claimType != expectedClaimType) { _revert(InvalidClaim.selector); } bytes32 claimId = keccak256( abi.encode( _CLAIM_TYPEHASH, claim.mechanicVectorId, claim.rebateAmount, claim.claimer, claim.claimerNumValidBids, claim.claimExpiryTimestamp, claim.cumulativeBidAmount, claim.bidId, claim.claimType ) ); bytes32 digest = keccak256(abi.encodePacked("\x19\x01", _getDomainSeperator(), claimId)); address signer = ECDSA.recover(digest, claimSignature); if ( signer == address(0) || !_isPlatformExecutor(signer) || uint48(block.timestamp) > claim.claimExpiryTimestamp ) { _revert(InvalidSignature.selector); } if (!_usedClaims[claim.mechanicVectorId].add(claimId)) { // claim already used _revert(InvalidClaim.selector); } } /** * @notice Validate mint claim * @param mechanicVectorId Mechanic vector id * @param data Mint data */ function _unwrapRankedAuctionClaim( bytes32 mechanicVectorId, bytes calldata data ) private returns (RankedAuctionsClaim memory, bytes memory) { ( uint256 rebateAmount, address claimer, uint32 claimerNumValidBids, uint48 claimExpiryTimestamp, uint256 cumulativeBidAmount, uint32 bidId, uint8 claimType, bytes memory claimSignature ) = abi.decode(data, (uint256, address, uint32, uint48, uint256, uint32, uint8, bytes)); return ( RankedAuctionsClaim( mechanicVectorId, rebateAmount, claimer, claimerNumValidBids, claimExpiryTimestamp, cumulativeBidAmount, bidId, claimType ), claimSignature ); } /** * @notice Returns a collection's current supply * @param mechanicVectorId Mechanic vector ID */ function _collectionSupplyAndSize(bytes32 mechanicVectorId) private view returns (uint256 supply, uint256 size) { MechanicVectorMetadata memory metadata = _getMechanicVectorMetadata(mechanicVectorId); if (metadata.contractAddress == address(0)) { revert("Vector doesn't exist"); } if (metadata.isEditionBased) { IEditionCollection.EditionDetails memory edition = IEditionCollection(metadata.contractAddress) .getEditionDetails(metadata.editionId); supply = edition.supply; size = edition.size; } else { // supply holds a tighter constraint (no burns), some old contracts don't have it try IERC721GeneralSupplyMetadata(metadata.contractAddress).supply() returns (uint256 _supply) { supply = _supply; } catch { supply = IERC721GeneralSupplyMetadata(metadata.contractAddress).totalSupply(); } size = IERC721GeneralSupplyMetadata(metadata.contractAddress).limitSupply(); } } /** * @notice Return EIP712 domain seperator */ function _getDomainSeperator() private view returns (bytes32) { return keccak256( abi.encode( _DOMAIN_TYPEHASH, keccak256("RankedAuctionMechanic"), keccak256("1"), block.chainid, address(this), 0x960bb3ecd14c38754109e5fe3a3b72aa0434091106c0fea200392fd413d44da0 // ranked auction mechanic salt ) ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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 onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @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 proxied contracts do not make use of 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. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * 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 prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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 onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822.sol"; import "../ERC1967/ERC1967Upgrade.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeTo(address newImplementation) public virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Interfaces with the details of editions on collections * @author highlight.xyz */ interface IEditionCollection { /** * @notice Edition details * @param name Edition name * @param size Edition size * @param supply Total number of tokens minted on edition * @param initialTokenId Token id of first token minted in edition */ struct EditionDetails { string name; uint256 size; uint256 supply; uint256 initialTokenId; } /** * @notice Get the edition a token belongs to * @param tokenId The token id of the token */ function getEditionId(uint256 tokenId) external view returns (uint256); /** * @notice Get an edition's details * @param editionId Edition id */ function getEditionDetails(uint256 editionId) external view returns (EditionDetails memory); /** * @notice Get the details and uris of a number of editions * @param editionIds List of editions to get info for */ function getEditionsDetailsAndUri( uint256[] calldata editionIds ) external view returns (EditionDetails[] memory, string[] memory uris); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Get a Series based collection's supply metadata * @author highlight.xyz */ interface IERC721GeneralSupplyMetadata { /** * @notice Get a series based collection's supply, burned tokens notwithstanding */ function supply() external view returns (uint256); /** * @notice Get a series based collection's total supply */ function totalSupply() external view returns (uint256); /** * @notice Get a series based collection's supply cap */ function limitSupply() external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Interface to burn tokens on a Manifold 1155 Creator contract */ interface IManifold1155Burn { function burn(address account, uint256[] memory tokenIds, uint256[] memory amounts) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "./IMechanicData.sol"; /** * @notice Interface that mint mechanics are forced to adhere to, * provided they support both collector's choice and sequential minting */ interface IMechanic is IMechanicData { /** * @notice Create a mechanic vector on the mechanic * @param mechanicVectorId Global mechanic vector ID * @param vectorData Mechanic vector data */ function createVector(bytes32 mechanicVectorId, bytes calldata vectorData) external; /** * @notice Process a sequential mint * @param mechanicVectorId Global ID identifying mint vector, using this mechanic * @param recipient Mint recipient * @param numToMint Number of tokens to mint * @param minter Account that called mint on the MintManager * @param mechanicVectorMetadata Mechanic vector metadata * @param data Custom data that can be deserialized and processed according to implementation */ function processNumMint( bytes32 mechanicVectorId, address recipient, uint32 numToMint, address minter, MechanicVectorMetadata calldata mechanicVectorMetadata, bytes calldata data ) external payable; /** * @notice Process a collector's choice mint * @param mechanicVectorId Global ID identifying mint vector, using this mechanic * @param recipient Mint recipient * @param tokenIds IDs of tokens to mint * @param minter Account that called mint on the MintManager * @param mechanicVectorMetadata Mechanic vector metadata * @param data Custom data that can be deserialized and processed according to implementation */ function processChooseMint( bytes32 mechanicVectorId, address recipient, uint256[] calldata tokenIds, address minter, MechanicVectorMetadata calldata mechanicVectorMetadata, bytes calldata data ) external payable; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Defines a mechanic's metadata on the MintManager */ interface IMechanicData { /** * @notice A mechanic's metadata * @param contractAddress Collection contract address * @param editionId Edition ID if the collection is edition based * @param mechanic Address of mint mechanic contract * @param isEditionBased True if collection is edition based * @param isChoose True if collection uses a collector's choice mint paradigm * @param paused True if mechanic vector is paused */ struct MechanicVectorMetadata { address contractAddress; uint96 editionId; address mechanic; bool isEditionBased; bool isChoose; bool paused; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "./IMechanicData.sol"; interface IMechanicMintManagerView is IMechanicData { /** * @notice Get a mechanic vector's metadata * @param mechanicVectorId Global mechanic vector ID */ function mechanicVectorMetadata(bytes32 mechanicVectorId) external view returns (MechanicVectorMetadata memory); /** * @notice Returns whether an address is a valid platform executor * @param _executor Address to be checked */ function isPlatformExecutor(address _executor) external view returns (bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./interfaces/IMechanic.sol"; import "./interfaces/IMechanicMintManagerView.sol"; /** * @notice MintManager client, to be used by mechanic contracts * @author highlight.xyz */ abstract contract MechanicMintManagerClientUpgradeable is OwnableUpgradeable, IMechanic { /** * @notice Throw when caller is not MintManager */ error NotMintManager(); /** * @notice Throw when input mint manager is invalid */ error InvalidMintManager(); /** * @notice Mint manager */ address public mintManager; /** * @notice Enforce caller to be mint manager */ modifier onlyMintManager() { if (msg.sender != mintManager) { _revert(NotMintManager.selector); } _; } /** * @notice Update the mint manager * @param _mintManager New mint manager */ function updateMintManager(address _mintManager) external onlyOwner { if (_mintManager == address(0)) { _revert(InvalidMintManager.selector); } mintManager = _mintManager; } /** * @notice Initialize mechanic mint manager client * @param _mintManager Mint manager address * @param platform Platform owning the contract */ function __MechanicMintManagerClientUpgradeable_initialize( address _mintManager, address platform ) internal onlyInitializing { __Ownable_init(); mintManager = _mintManager; _transferOwnership(platform); } /** * @notice Get a mechanic mint vector's metadata * @param mechanicVectorId Mechanic vector ID */ function _getMechanicVectorMetadata( bytes32 mechanicVectorId ) internal view returns (MechanicVectorMetadata memory) { return IMechanicMintManagerView(mintManager).mechanicVectorMetadata(mechanicVectorId); } function _isPlatformExecutor(address _executor) internal view returns (bool) { return IMechanicMintManagerView(mintManager).isPlatformExecutor(_executor); } /** * @dev For more efficient reverts. */ function _revert(bytes4 errorSelector) internal pure { assembly { mstore(0x00, errorSelector) revert(0x00, 0x04) } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @title IGengineObservability * @author highlight.xyz * @notice Interface to interact with the Highlight Gengine observability singleton * @dev Singleton to coalesce select Highlight Gengine protocol events */ interface IGengineObservability { /** * @notice Emitted when contract metadata is set * @param contractAddress Initial contract that emitted event * @param name New name * @param symbol New symbol * @param contractURI New contract uri */ event ContractMetadataSet(address indexed contractAddress, string name, string symbol, string contractURI); /** * @notice Emitted when limit supply is set * @param contractAddress Initial contract that emitted event * @param newLimitSupply Limit supply to set */ event LimitSupplySet(address indexed contractAddress, uint256 indexed newLimitSupply); /** * @notice Emits when a series collection has its base uri set * @param contractAddress Contract with updated base uri * @param newBaseUri New base uri */ event BaseUriSet(address indexed contractAddress, string newBaseUri); /************************** Deployment events **************************/ /** * @notice Emitted when Generative Series contract is deployed * @param deployer Contract deployer * @param contractAddress Address of contract that was deployed */ event GenerativeSeriesDeployed(address indexed deployer, address indexed contractAddress); /** * @notice Emitted when Series contract is deployed * @param deployer Contract deployer * @param contractAddress Address of contract that was deployed */ event SeriesDeployed(address indexed deployer, address indexed contractAddress); /************************** ERC721 events **************************/ /** * @notice Emitted on a mint where a number of tokens are minted * @param contractAddress Address of contract being minted on * @param numMinted Number of tokens minted */ event TokenMint(address indexed contractAddress, address indexed to, uint256 indexed numMinted); /** * @notice Emitted whenever the metadata for the token is updated * @param contractAddress NFT contract token resides on * @param tokenId Token being updated */ event TokenUpdated(address indexed contractAddress, uint256 indexed tokenId); /** * @notice Emitted when `tokenId` token is transferred from `from` to `to` on contractAddress * @param contractAddress NFT contract token resides on * @param from Token sender * @param to Token receiver * @param tokenId Token being sent */ event Transfer(address indexed contractAddress, address indexed from, address to, uint256 indexed tokenId); /** * @notice Emitted for the seed based data on mint * @param sender contract emitting the event * @param contractAddress NFT contract token resides on * @param data custom mint data */ event CustomMintData(address indexed sender, address indexed contractAddress, bytes data); /** * @notice Emitted to regenerate the generative art for a token * @param sender contract emitting the event * @param collection NFT contract token resides on * @param tokenId Token ID */ event HighlightRegenerate(address indexed sender, address indexed collection, uint256 indexed tokenId); /** * @notice Emit ContractMetadataSet */ function emitContractMetadataSet( string calldata name, string calldata symbol, string calldata contractURI ) external; /** * @notice Emit LimitSupplySet */ function emitLimitSupplySet(uint256 newLimitSupply) external; /** * @notice Emit BaseUriSet */ function emitBaseUriSet(string calldata newBaseUri) external; /** * @notice Emit GenerativeSeriesDeployed */ function emitGenerativeSeriesDeployed(address contractAddress) external; /** * @notice Emit SeriesDeployed */ function emitSeriesDeployed(address contractAddress) external; /** * @notice Emit Token Mint */ function emitTokenMint(address to, uint256 numMinted) external; /** * @notice Emit Token Updated */ function emitTokenUpdated(address contractAddress, uint256 tokenId) external; /** * @notice Emit Transfer */ function emitTransfer(address from, address to, uint256 tokenId) external; /** * @notice Emit Custom Mint Data */ function emitCustomMintData(address contractAddress, bytes calldata data) external; /** * @notice Emit HighlightRegenerate */ function emitHighlightRegenerate(address collection, uint256 tokenId) external; }
{ "metadata": { "bytecodeHash": "none" }, "optimizer": { "enabled": true, "runs": 1 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"BidAlreadyAdded","type":"error"},{"inputs":[],"name":"BidAlreadyReclaimed","type":"error"},{"inputs":[],"name":"EtherSendFailed","type":"error"},{"inputs":[],"name":"ImpossibleState","type":"error"},{"inputs":[],"name":"InvalidBid","type":"error"},{"inputs":[],"name":"InvalidClaim","type":"error"},{"inputs":[],"name":"InvalidMint","type":"error"},{"inputs":[],"name":"InvalidMintAmount","type":"error"},{"inputs":[],"name":"InvalidMintManager","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidUpdate","type":"error"},{"inputs":[],"name":"NotMintManager","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"VectorAlreadyCreated","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"earnings","type":"uint256"},{"indexed":false,"internalType":"address","name":"paymentRecipient","type":"address"},{"indexed":false,"internalType":"address","name":"currency","type":"address"}],"name":"AuctionEarningsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"indexed":false,"internalType":"uint48","name":"newEndTimestamp","type":"uint48"}],"name":"AuctionLengthened","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newValidityHash","type":"bytes32"},{"indexed":true,"internalType":"uint96","name":"actionId","type":"uint96"},{"indexed":false,"internalType":"uint32","name":"bidId","type":"uint32"},{"indexed":false,"internalType":"address","name":"bidder","type":"address"},{"indexed":false,"internalType":"uint96","name":"bidAmount","type":"uint96"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"bool","name":"created","type":"bool"}],"name":"BidCreatedOrUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"bidId","type":"uint32"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"},{"indexed":false,"internalType":"address","name":"currency","type":"address"}],"name":"BidReclaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","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":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"}],"name":"RankedAuctionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"}],"name":"RankedAuctionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"uint96","name":"bidAmount","type":"uint96"}],"name":"bid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"bids","outputs":[{"internalType":"uint96","name":"bidAmount","type":"uint96"},{"internalType":"address","name":"bidder","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"bytes","name":"vectorData","type":"bytes"}],"name":"createVector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"uint32[]","name":"bidIds","type":"uint32[]"}],"name":"getBids","outputs":[{"components":[{"internalType":"uint96","name":"bidAmount","type":"uint96"},{"internalType":"address","name":"bidder","type":"address"}],"internalType":"struct RankedAuctionMechanic.Bid[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"}],"name":"getRawVector","outputs":[{"components":[{"internalType":"uint48","name":"startTimestamp","type":"uint48"},{"internalType":"uint48","name":"endTimestamp","type":"uint48"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint32","name":"maxUserClaimableViaVector","type":"uint32"},{"internalType":"uint32","name":"maxTotalClaimableViaVector","type":"uint32"},{"internalType":"uint32","name":"latestBidId","type":"uint32"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"bool","name":"bidFundsClaimed","type":"bool"},{"internalType":"uint96","name":"reserveBid","type":"uint96"},{"internalType":"uint48","name":"maxEndTimestamp","type":"uint48"},{"internalType":"uint96","name":"actionId","type":"uint96"}],"internalType":"struct RankedAuctionMechanic.Vector","name":"_vector","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"address","name":"user","type":"address"}],"name":"getUserBids","outputs":[{"components":[{"internalType":"uint96","name":"bidAmount","type":"uint96"},{"internalType":"address","name":"bidder","type":"address"}],"internalType":"struct RankedAuctionMechanic.Bid[]","name":"","type":"tuple[]"},{"internalType":"uint256[]","name":"bidIds","type":"uint256[]"},{"internalType":"uint32","name":"numBids","type":"uint32"},{"internalType":"uint32","name":"numClaimed","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"}],"name":"getVectorState","outputs":[{"components":[{"internalType":"uint48","name":"startTimestamp","type":"uint48"},{"internalType":"uint48","name":"endTimestamp","type":"uint48"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint32","name":"maxUserClaimableViaVector","type":"uint32"},{"internalType":"uint32","name":"maxTotalClaimableViaVector","type":"uint32"},{"internalType":"uint32","name":"latestBidId","type":"uint32"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"bool","name":"bidFundsClaimed","type":"bool"},{"internalType":"uint96","name":"reserveBid","type":"uint96"},{"internalType":"uint48","name":"maxEndTimestamp","type":"uint48"},{"internalType":"uint96","name":"actionId","type":"uint96"}],"internalType":"struct RankedAuctionMechanic.Vector","name":"_vector","type":"tuple"},{"internalType":"bytes32","name":"validityHash","type":"bytes32"},{"internalType":"uint256","name":"collectionSupply","type":"uint256"},{"internalType":"uint256","name":"collectionSize","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_mintManager","type":"address"},{"internalType":"address","name":"platform","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"address","name":"minter","type":"address"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint96","name":"editionId","type":"uint96"},{"internalType":"address","name":"mechanic","type":"address"},{"internalType":"bool","name":"isEditionBased","type":"bool"},{"internalType":"bool","name":"isChoose","type":"bool"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IMechanicData.MechanicVectorMetadata","name":"mechanicVectorMetadata","type":"tuple"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"processChooseMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint32","name":"numToMint","type":"uint32"},{"internalType":"address","name":"minter","type":"address"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint96","name":"editionId","type":"uint96"},{"internalType":"address","name":"mechanic","type":"address"},{"internalType":"bool","name":"isEditionBased","type":"bool"},{"internalType":"bool","name":"isChoose","type":"bool"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IMechanicData.MechanicVectorMetadata","name":"mechanicVectorMetadata","type":"tuple"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"processNumMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"uint256","name":"rebateAmount","type":"uint256"},{"internalType":"address","name":"claimer","type":"address"},{"internalType":"uint32","name":"claimerNumValidBids","type":"uint32"},{"internalType":"uint48","name":"claimExpiryTimestamp","type":"uint48"},{"internalType":"uint256","name":"cumulativeBidAmount","type":"uint256"},{"internalType":"uint32","name":"bidId","type":"uint32"},{"internalType":"uint8","name":"claimType","type":"uint8"}],"internalType":"struct RankedAuctionMechanic.RankedAuctionsClaim","name":"claim","type":"tuple"},{"internalType":"bytes","name":"claimSignature","type":"bytes"}],"name":"reclaimBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"uint32","name":"bidId","type":"uint32"},{"internalType":"uint96","name":"newBidAmount","type":"uint96"}],"name":"updateBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_mintManager","type":"address"}],"name":"updateMintManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"components":[{"internalType":"uint48","name":"startTimestamp","type":"uint48"},{"internalType":"uint48","name":"endTimestamp","type":"uint48"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint32","name":"maxUserClaimableViaVector","type":"uint32"},{"internalType":"uint32","name":"maxTotalClaimableViaVector","type":"uint32"},{"internalType":"uint32","name":"latestBidId","type":"uint32"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"bool","name":"bidFundsClaimed","type":"bool"},{"internalType":"uint96","name":"reserveBid","type":"uint96"},{"internalType":"uint48","name":"maxEndTimestamp","type":"uint48"},{"internalType":"uint96","name":"actionId","type":"uint96"}],"internalType":"struct RankedAuctionMechanic.Vector","name":"newVector","type":"tuple"},{"components":[{"internalType":"bool","name":"updateStartTimestamp","type":"bool"},{"internalType":"bool","name":"updateEndTimestamp","type":"bool"},{"internalType":"bool","name":"updateMaxEndTimestamp","type":"bool"},{"internalType":"bool","name":"updateMaxUserClaimableViaVector","type":"bool"},{"internalType":"bool","name":"updateMaxTotalClaimableViaVector","type":"bool"},{"internalType":"bool","name":"updatePaymentRecipient","type":"bool"},{"internalType":"bool","name":"updateCurrency","type":"bool"},{"internalType":"bool","name":"updateReserveBid","type":"bool"}],"internalType":"struct RankedAuctionMechanic.VectorUpdateConfig","name":"updateConfig","type":"tuple"}],"name":"updateVector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"uint256","name":"rebateAmount","type":"uint256"},{"internalType":"address","name":"claimer","type":"address"},{"internalType":"uint32","name":"claimerNumValidBids","type":"uint32"},{"internalType":"uint48","name":"claimExpiryTimestamp","type":"uint48"},{"internalType":"uint256","name":"cumulativeBidAmount","type":"uint256"},{"internalType":"uint32","name":"bidId","type":"uint32"},{"internalType":"uint8","name":"claimType","type":"uint8"}],"internalType":"struct RankedAuctionMechanic.RankedAuctionsClaim","name":"claim","type":"tuple"},{"internalType":"bytes","name":"claimSignature","type":"bytes"}],"name":"withdrawAuctionEarnings","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523060805234801561001457600080fd5b5060805161458a61004c60003960008181610c3501528181610c7e01528181610f3e01528181610f7e0152610ffa015261458a6000f3fe6080604052600436106101055760003560e01c80630ae941031461010a57806313b5d9e6146101405780631a8d3792146101705780633012a1d0146101925780633659cfe6146101b2578063485cc955146101d2578063494a76d9146101f25780634f1ef2861461021f57806352d1902d146102325780635da320b414610255578063715018a6146102b657806377c14320146102cb5780637e4edf70146102eb5780638da5cb5b146103185780638dd918641461032d5780639cc163e51461034d578063c4804ce214610360578063c617bfa614610373578063ceab8e19146103a3578063dd48aaaf146103c3578063f2fde38b146103d6578063fae4e488146103f6575b600080fd5b34801561011657600080fd5b5061012a610125366004613546565b610409565b604051610137919061365b565b60405180910390f35b34801561014c57600080fd5b5061016061015b366004613546565b6104df565b604051610137949392919061366a565b34801561017c57600080fd5b5061019061018b366004613782565b6105d5565b005b34801561019e57600080fd5b506101906101ad366004613822565b610970565b3480156101be57600080fd5b506101906101cd36600461388c565b610c2a565b3480156101de57600080fd5b506101906101ed3660046138a9565b610cfc565b3480156101fe57600080fd5b5061021261020d366004613926565b610e18565b60405161013791906139bc565b61019061022d3660046139cf565b610f33565b34801561023e57600080fd5b50610247610fed565b604051908152602001610137565b34801561026157600080fd5b506102a8610270366004613a2a565b60686020908152600092835260408084209091529082529020546001600160601b03811690600160601b90046001600160a01b031682565b604051610137929190613a4f565b3480156102c257600080fd5b5061019061109b565b3480156102d757600080fd5b506101906102e6366004613822565b6110af565b3480156102f757600080fd5b5060655461030b906001600160a01b031681565b6040516101379190613a71565b34801561032457600080fd5b5061030b6112e2565b34801561033957600080fd5b50610190610348366004613a85565b6112f1565b61019061035b366004613ae3565b6117e2565b61019061036e366004613b7b565b61181a565b34801561037f57600080fd5b5061039361038e366004613c2f565b611856565b6040516101379493929190613c54565b3480156103af57600080fd5b506101906103be36600461388c565b6119e8565b6101906103d1366004613cd9565b611a30565b3480156103e257600080fd5b506101906103f136600461388c565b611dbb565b610190610404366004613d1b565b611e31565b6104116134d3565b50600090815260666020908152604091829020825161016081018452815465ffffffffffff8082168352600160301b82048116948301949094526001600160a01b03600160601b91829004811695830195909552600183015463ffffffff8082166060850152600160201b820481166080850152600160401b82041660a08401520490931660c08401526002015460ff8116151560e08401526001600160601b03610100808304821690850152600160681b8204909216610120840152600160981b90041661014082015290565b6104e76134d3565b506000818152606660209081526040808320815161016081018352815465ffffffffffff8082168352600160301b82048116838701526001600160a01b03600160601b92839004811684870152600185015463ffffffff8082166060870152600160201b820481166080870152600160401b82041660a08601529290920490911660c083015260029092015460ff8116151560e08301526001600160601b03610100808304821690840152600160681b8204909316610120830152600160981b900490911661014082015284845260679092528220549091806105c985612281565b94969395509392915050565b6065546001600160a01b031633146105f7576105f7639a04794d60e01b6124c0565b60008281526066602052604090205465ffffffffffff1615610623576106236366fa676560e11b6124c0565b600080600080600080600080888060200190518101906106439190613d54565b975097509750975097509750975097508263ffffffff166000141561067257610672637d5ba07f60e01b6124c0565b600065ffffffffffff891615610688578861068a565b425b905060006040518061016001604052808365ffffffffffff1681526020018a65ffffffffffff166000146106be578a6106cb565b6106cb8462093a80613e1a565b65ffffffffffff168152602001886001600160a01b031681526020018763ffffffff1681526020018663ffffffff168152602001600063ffffffff168152602001846001600160a01b03168152602001600015158152602001856001600160601b031681526020018965ffffffffffff16815260200160006001600160601b0316815250905080606660008e815260200190815260200160002060008201518160000160006101000a81548165ffffffffffff021916908365ffffffffffff16021790555060208201518160000160066101000a81548165ffffffffffff021916908365ffffffffffff160217905550604082015181600001600c6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160010160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160046101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555060c082015181600101600c6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160020160006101000a81548160ff0219169083151502179055506101008201518160020160016101000a8154816001600160601b0302191690836001600160601b0316021790555061012082015181600201600d6101000a81548165ffffffffffff021916908365ffffffffffff1602179055506101408201518160020160136101000a8154816001600160601b0302191690836001600160601b031602179055509050508b7f2a64ac2f583e4882d53a07723d8ba198e44c455bd84a12959f10f2dd220b67a760405160405180910390a2505050505050505050505050565b6109c161098236859003850185613e60565b33600185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124ca92505050565b82356000908152606860205260408120816109e260e0870160c08801613f14565b63ffffffff16815260208082019290925260409081016000208151808301835290546001600160601b0381168252600160601b90046001600160a01b031692810192909252909150610a3a906060860190860161388c565b6001600160a01b031681602001516001600160a01b031614610a6557610a656282b42960e81b6124c0565b610a8081600001516001600160601b0316826020015161277c565b610a9060e0850160c08601613f14565b815185356000818152606660205260409081902060010154905163ffffffff949094169391927fba85505a71c5b1789e1357fee7e9e22da158b6c570e1b711a6efe27b61be645d92610af292600160601b90046001600160a01b031690613a4f565b60405180910390a383356000908152606960205260408082206001929091610b20906060890190890161388c565b6001600160a01b0316815260208101919091526040016000208054600490610b56908490600160201b900463ffffffff16613f31565b92506101000a81548163ffffffff021916908363ffffffff160217905550610bd68460c0016020810190610b8a9190613f14565b85356000908152606a602052604080822063ffffffff93909316929190610bb79060608a01908a0161388c565b6001600160a01b031681526020810191909152604001600020906127e7565b610bea57610bea63a88a48e360e01b6124c0565b8335600090815260686020526040812090610c0b60e0870160c08801613f14565b63ffffffff168152602081019190915260400160009081205550505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415610c7c5760405162461bcd60e51b8152600401610c7390613f56565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610cae6127fc565b6001600160a01b031614610cd45760405162461bcd60e51b8152600401610c7390613f90565b610cdd81612818565b60408051600080825260208201909252610cf991839190612820565b50565b600054610100900460ff1615808015610d1c5750600054600160ff909116105b80610d3d5750610d2b3061298b565b158015610d3d575060005460ff166001145b610da05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c73565b6000805460ff191660011790558015610dc3576000805461ff0019166101001790555b610dcd838361299a565b8015610e13576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6060816000816001600160401b03811115610e3557610e35613697565b604051908082528060200260200182016040528015610e6e57816020015b610e5b61352f565b815260200190600190039081610e535790505b50905060005b82811015610f2957600087815260686020526040812090878784818110610e9d57610e9d613fca565b9050602002016020810190610eb29190613f14565b63ffffffff16815260208082019290925260409081016000208151808301909252546001600160601b0381168252600160601b90046001600160a01b0316918101919091528251839083908110610f0b57610f0b613fca565b60200260200101819052508080610f2190613fe0565b915050610e74565b5095945050505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415610f7c5760405162461bcd60e51b8152600401610c7390613f56565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610fae6127fc565b6001600160a01b031614610fd45760405162461bcd60e51b8152600401610c7390613f90565b610fdd82612818565b610fe982826001612820565b5050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146110885760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610c73565b5060008051602061451783398151915290565b6110a36129ed565b6110ad6000612a4c565b565b6111006110c136859003850185613e60565b33600285858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124ca92505050565b8235600090815260666020908152604091829020825161016081018452815465ffffffffffff8082168352600160301b820481169483018590526001600160a01b03600160601b92839004811696840196909652600184015463ffffffff8082166060860152600160201b820481166080860152600160401b82041660a08501529190910490941660c082015260029091015460ff8116151560e08301526001600160601b03610100808304821690840152600160681b82048516610120840152600160981b909104166101408201529142161115806111ec575060c08101516001600160a01b031615155b806111f857508060e001515b1561120d5761120d633b4f091f60e21b6124c0565b600061271061122260a08701356101f4613ffb565b61122c919061401a565b905061123f8161123a6112e2565b61277c565b61125a6112508260a088013561403c565b836040015161277c565b843560008181526066602052604090819020600201805460ff191660011790558381015160c085015191517f53c2a8252078e2d170ed485279f20e9fbc9a31edc453ea98250fa5cbfb6432d6926112d39260a08b0135929091909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a25050505050565b6033546001600160a01b031690565b60006112fc84612a9e565b9050336001600160a01b031681600001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190614053565b6001600160a01b03161415801561138f575080516001600160a01b03163314155b156113a3576113a36282b42960e81b6124c0565b6113b0602083018361407e565b1561140e576113c2602084018461409b565b65ffffffffffff16156113e1576113dc602084018461409b565b6113e3565b425b6000858152606660205260409020805465ffffffffffff191665ffffffffffff929092169190911790555b61141e604083016020840161407e565b1561149557611433604084016020850161409b565b65ffffffffffff1661144f5761144f637d5ba07f60e01b6124c0565b61145f604084016020850161409b565b6000858152606660205260409020805465ffffffffffff92909216600160301b0265ffffffffffff60301b199092169190911790555b6114a5606083016040840161407e565b15611523576114bc6101408401610120850161409b565b65ffffffffffff166114d8576114d8637d5ba07f60e01b6124c0565b6114ea6101408401610120850161409b565b6000858152606660205260409020600201805465ffffffffffff92909216600160681b0265ffffffffffff60681b199092169190911790555b611533608083016060840161407e565b15611572576115486080840160608501613f14565b6000858152606660205260409020600101805463ffffffff191663ffffffff929092169190911790555b61158260a083016080840161407e565b156116355761159760a0840160808501613f14565b63ffffffff1615806115db5750600084815260666020526040902060010154600160201b900463ffffffff166115d360a0850160808601613f14565b63ffffffff16105b156115f0576115f0637d5ba07f60e01b6124c0565b61160060a0840160808501613f14565b6000858152606660205260409020600101805463ffffffff92909216600160201b0263ffffffff60201b199092169190911790555b61164560e0830160c0840161407e565b156116c557600084815260666020526040902060010154600160401b900463ffffffff161561167e5761167e637d5ba07f60e01b6124c0565b61168e60e0840160c0850161388c565b600085815260666020526040902060010180546001600160a01b0392909216600160601b026001600160601b039092169190911790555b6116d560c0830160a0840161407e565b1561171e576116ea606084016040850161388c565b600085815260666020526040902080546001600160a01b0392909216600160601b026001600160601b039092169190911790555b61172f610100830160e0840161407e565b156117b157600084815260666020526040902060010154600160401b900463ffffffff161561176857611768637d5ba07f60e01b6124c0565b61177a610120840161010085016140b8565b600085815260666020526040902060020180546001600160601b039290921661010002610100600160681b03199092169190911790555b60405184907f5b6bcbd593bccf88b5035e118227608b2364ff5ab65aa173c15e29ed0f83881190600090a250505050565b6065546001600160a01b0316331461180457611804639a04794d60e01b6124c0565b6118118785878585612b38565b50505050505050565b6065546001600160a01b0316331461183c5761183c639a04794d60e01b6124c0565b61184c63201dc6f560e01b6124c0565b5050505050505050565b60008281526069602090815260408083206001600160a01b03851680855290835281842082518084018452905463ffffffff8082168352600160201b9091041681850152868552606a8452828520918552925282206060928392909182919082906118c090612c45565b80519091506000816001600160401b038111156118df576118df613697565b60405190808252806020026020018201604052801561191857816020015b61190561352f565b8152602001906001900390816118fd5790505b50905060005b828110156119ce57606860008c8152602001908152602001600020600085838151811061194d5761194d613fca565b60209081029190910181015163ffffffff1682528181019290925260409081016000208151808301909252546001600160601b0381168252600160601b90046001600160a01b03169181019190915282518390839081106119b0576119b0613fca565b602002602001018190525080806119c690613fe0565b91505061191e565b5060208401519351909a9299509297509195509350505050565b6119f06129ed565b6001600160a01b038116611a0e57611a0e63040b3bcf60e31b6124c0565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b6000838152606660209081526040808320815161016081018352815465ffffffffffff8082168352600160301b82048116838701526001600160a01b03600160601b92839004811684870152600185015463ffffffff8082166060870152600160201b820481166080870152600160401b8204811660a087015290849004821660c086015260029095015460ff8116151560e08601526001600160601b03610100808304821690870152600160681b8204909316610120860152600160981b900482166101408501528a885260688752858820948a168852938652958490208451808601909552548087168086529190049092169383019390935291929091908416111580611b4a575060208101516001600160a01b0316155b80611b6857504265ffffffffffff16826020015165ffffffffffff16105b80611b7e5750815165ffffffffffff4281169116115b80611b9f57508161010001516001600160601b0316836001600160601b0316105b80611bbe57508051611bb190846140d5565b6001600160601b03163414155b15611bd357611bd363c6388ef760e01b6124c0565b60208101516001600160a01b03163314611bf657611bf66282b42960e81b6124c0565b60018261014001818151611c0a91906140f5565b6001600160601b03908116909152600087815260686020908152604080832063ffffffff8a168452825280832080546001600160601b0319168986161790556101408701518a84526066835292206002018054600160981b600160f81b031916600160981b939094169290920292909217905583015161012c9150611c90904290614117565b65ffffffffffff1611611d6157600082610120015165ffffffffffff1660001415611cc657611cc14261012c613e1a565b611d04565b611cd24261012c613e1a565b65ffffffffffff1683610120015165ffffffffffff1611611cf857826101200151611d04565b611d044261012c613e1a565b600087815260666020908152604091829020805465ffffffffffff60301b1916600160301b65ffffffffffff8616908102919091179091559151918252919250879160008051602061455e833981519152910160405180910390a2505b6000611d6e868686612c59565b90508261014001516001600160601b031681876000805160206144d78339815191528833898960c001516000604051611dab959493929190614136565b60405180910390a4505050505050565b611dc36129ed565b6001600160a01b038116611e285760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c73565b610cf981612a4c565b6000828152606660209081526040808320815161016081018352815465ffffffffffff8082168352600160301b82048116838701526001600160a01b03600160601b9283900481168487015260018086015463ffffffff8082166060880152600160201b80830482166080890152600160401b8304821660a08901529590910490921660c086015260029095015460ff8116151560e08601526001600160601b03610100808304821690870152600160681b8204909316610120860152600160981b90049091166101408401528887526069865284872033885290955292852054909493611f23939091041690614177565b90504265ffffffffffff16826020015165ffffffffffff161080611f525750815165ffffffffffff4281169116115b80611f7357508161010001516001600160601b0316836001600160601b0316105b80611f87575034836001600160601b031614155b80611fb55750606082015163ffffffff1615801590611fb55750816060015163ffffffff168163ffffffff16115b15611fca57611fca63c6388ef760e01b6124c0565b60018260a001818151611fdd9190614177565b63ffffffff169052506101408201805160019190611ffc9083906140f5565b6001600160601b03908116909152604080518082018252868316815233602080830182815260008b81526068835285812060a08b01805163ffffffff9081168452918552878320965193516001600160a01b0316600160601b02939098169290921790945594518a8452606a825284842092845291905291902061208693509190811690612ccc16565b61209a5761209a630d45f68160e21b6124c0565b60008481526069602090815260408083203384528252808320805463ffffffff808716600160201b0263ffffffff60201b199092169190911790915560a0860151888552606684529190932060018101805492909416600160401b0263ffffffff60401b1990921691909117909255610140840151600290920180546001600160601b03909316600160981b02600160981b600160f81b03199093169290921790915582015161012c9061214f904290614117565b65ffffffffffff16116122205761012082015165ffffffffffff1661217f5761217a4261012c613e1a565b6121bd565b61218b4261012c613e1a565b65ffffffffffff1682610120015165ffffffffffff16116121b1578161012001516121bd565b6121bd4261012c613e1a565b65ffffffffffff9081166020848101828152600088815260668352604090819020805465ffffffffffff60301b1916600160301b90950294909417909355519151919092168152859160008051602061455e833981519152910160405180910390a25b6000612231858460a0015186612c59565b90508261014001516001600160601b031681866000805160206144d78339815191528660a0015133898960c001516001604051612272959493929190614136565b60405180910390a45050505050565b600080600061228f84612a9e565b80519091506001600160a01b03166122e05760405162461bcd60e51b8152602060048201526014602482015273159958dd1bdc88191bd95cdb89dd08195e1a5cdd60621b6044820152606401610c73565b80606001511561237f578051602082015160405163ddf990f960e01b81526001600160601b0390911660048201526000916001600160a01b03169063ddf990f990602401600060405180830381865afa158015612341573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261236991908101906141c2565b90508060400151935080602001519250506124ba565b80600001516001600160a01b031663047fc9aa6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156123dd575060408051601f3d908101601f191682019092526123da91810190614285565b60015b61244e5780600001516001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612423573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124479190614285565b9250612451565b92505b80600001516001600160a01b0316632ddcb21f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190614285565b91505b50915091565b8060005260046000fd5b826001600160a01b031684604001516001600160a01b0316146124f6576124f66282b42960e81b6124c0565b8160ff168460e0015160ff161461251757612517633b4f091f60e21b6124c0565b60007fa9accd45695a721aca33e1224254ff563220e1765ba1b89c350834a6ad4c54fd856000015186602001518760400151886060015189608001518a60a001518b60c001518c60e001516040516020016125d199989796959493929190988952602089019790975260408801959095526001600160a01b0393909316606087015263ffffffff918216608087015265ffffffffffff1660a086015260c08501919091521660e083015260ff166101008201526101200190565b60405160208183030381529060405280519060200120905060006126b9604080517fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac5647260208201527f42ef9e7ac4a9ac8ff505b5257b63e7b5f2271ba58e5fb6c9ef7bcfa02040957a918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201527f960bb3ecd14c38754109e5fe3a3b72aa0434091106c0fea200392fd413d44da060c082015260009060e00160405160208183030381529060405280519060200120905090565b60405161190160f01b602082015260228101919091526042810183905260620160405160208183030381529060405280519060200120905060006126fd8285612cd8565b90506001600160a01b038116158061271b575061271981612cfc565b155b806127395750866080015165ffffffffffff164265ffffffffffff16115b1561274e5761274e638baa579f60e01b6124c0565b86516000908152606b602052604090206127689084612ccc565b61181157611811633b4f091f60e21b6124c0565b6000816001600160a01b03168360405160006040518083038185875af1925050503d80600081146127c9576040519150601f19603f3d011682016040523d82523d6000602084013e6127ce565b606091505b5050905080610e1357610e13637cd69c3960e11b6124c0565b60006127f38383612d6e565b90505b92915050565b600080516020614517833981519152546001600160a01b031690565b610cf96129ed565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561285357610e1383612e61565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156128ad575060408051601f3d908101601f191682019092526128aa91810190614285565b60015b6129105760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610c73565b600080516020614517833981519152811461297f5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610c73565b50610e13838383612efb565b6001600160a01b03163b151590565b600054610100900460ff166129c15760405162461bcd60e51b8152600401610c739061429e565b6129c9612f26565b606580546001600160a01b0319166001600160a01b038416179055610fe981612a4c565b336129f66112e2565b6001600160a01b0316146110ad5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c73565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6040805160c081018252600080825260208201819052818301819052606082018190526080820181905260a0820152606554915162820a0360e31b81526004810184905290916001600160a01b03169063041050189060240160c060405180830381865afa158015612b14573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f691906142e9565b600080612b46878585612f55565b91509150612b5782876003846124ca565b60008781526066602052604090205465ffffffffffff428116600160301b9092041610612b8e57612b8e63201dc6f560e01b6124c0565b60008781526069602090815260408083206001600160a01b038a168452909152902054606083015163ffffffff9182169116612bca8288614177565b63ffffffff161115612be657612be663199f5a0360e31b6124c0565b612bf08682614177565b60008981526069602090815260408083206001600160a01b038c1684528252909120805463ffffffff191663ffffffff93909316929092179091558301511561184c5761184c8360200151846040015161277c565b60606000612c528361302c565b9392505050565b6000838152606760208181526040808420805482518085019190915280830189905260e09790971b6001600160e01b031916606088015260a09590951b6001600160a01b031916606487015280516050818803018152607090960190528451948101949094209490915290915281905590565b60006127f38383613088565b6000806000612ce785856130d7565b91509150612cf48161311d565b509392505050565b60655460405163717b358f60e11b81526000916001600160a01b03169063e2f66b1e90612d2d908590600401613a71565b602060405180830381865afa158015612d4a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f69190614393565b60008181526001830160205260408120548015612e57576000612d9260018361403c565b8554909150600090612da69060019061403c565b9050818114612e0b576000866000018281548110612dc657612dc6613fca565b9060005260206000200154905080876000018481548110612de957612de9613fca565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612e1c57612e1c6143b0565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506127f6565b60009150506127f6565b612e6a8161298b565b612ecc5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610c73565b60008051602061451783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b612f0483613266565b600082511180612f115750805b15610e1357612f2083836132a6565b50505050565b600054610100900460ff16612f4d5760405162461bcd60e51b8152600401610c739061429e565b6110ad6132cb565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101919091526060600080808080808080612fad8b8d018d6143c6565b975097509750975097509750975097506040518061010001604052808e8152602001898152602001886001600160a01b031681526020018763ffffffff1681526020018665ffffffffffff1681526020018581526020018463ffffffff1681526020018360ff1681525081995099505050505050505050935093915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561307c57602002820191906000526020600020905b815481526020019060010190808311613068575b50505050509050919050565b60008181526001830160205260408120546130cf575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556127f6565b5060006127f6565b60008082516041141561310e5760208301516040840151606085015160001a613102878285856132fb565b94509450505050613116565b506000905060025b9250929050565b600081600481111561313157613131614471565b141561313a5750565b600181600481111561314e5761314e614471565b14156131975760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401610c73565b60028160048111156131ab576131ab614471565b14156131f95760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c73565b600381600481111561320d5761320d614471565b1415610cf95760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610c73565b61326f81612e61565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606127f38383604051806060016040528060278152602001614537602791396133b5565b600054610100900460ff166132f25760405162461bcd60e51b8152600401610c739061429e565b6110ad33612a4c565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b0383111561332857506000905060036133ac565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561337c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166133a5576000600192509250506133ac565b9150600090505b94509492505050565b6060600080856001600160a01b0316856040516133d29190614487565b600060405180830381855af49150503d806000811461340d576040519150601f19603f3d011682016040523d82523d6000602084013e613412565b606091505b50915091506134238683838761342d565b9695505050505050565b60608315613497578251613490576134448561298b565b6134905760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c73565b50816134a1565b6134a183836134a9565b949350505050565b8151156134b95781518083602001fd5b8060405162461bcd60e51b8152600401610c7391906144a3565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915290565b604080518082019091526000808252602082015290565b60006020828403121561355857600080fd5b5035919050565b6001600160a01b03169052565b805165ffffffffffff1682526020810151613591602084018265ffffffffffff169052565b5060408101516135a4604084018261355f565b5060608101516135bc606084018263ffffffff169052565b5060808101516135d4608084018263ffffffff169052565b5060a08101516135ec60a084018263ffffffff169052565b5060c08101516135ff60c084018261355f565b5060e081015161361360e084018215159052565b50610100818101516001600160601b0381168483015250506101208181015165ffffffffffff8116848301525050610140818101516001600160601b03811684830152612f20565b61016081016127f6828461356c565b6101c08101613679828761356c565b8461016083015283610180830152826101a083015295945050505050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156136cf576136cf613697565b60405290565b604051601f8201601f191681016001600160401b03811182821017156136fd576136fd613697565b604052919050565b60006001600160401b0382111561371e5761371e613697565b50601f01601f191660200190565b600082601f83011261373d57600080fd5b813561375061374b82613705565b6136d5565b81815284602083860101111561376557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561379557600080fd5b8235915060208301356001600160401b038111156137b257600080fd5b6137be8582860161372c565b9150509250929050565b600061010082840312156137db57600080fd5b50919050565b60008083601f8401126137f357600080fd5b5081356001600160401b0381111561380a57600080fd5b60208301915083602082850101111561311657600080fd5b6000806000610120848603121561383857600080fd5b61384285856137c8565b92506101008401356001600160401b0381111561385e57600080fd5b61386a868287016137e1565b9497909650939450505050565b6001600160a01b0381168114610cf957600080fd5b60006020828403121561389e57600080fd5b8135612c5281613877565b600080604083850312156138bc57600080fd5b82356138c781613877565b915060208301356138d781613877565b809150509250929050565b60008083601f8401126138f457600080fd5b5081356001600160401b0381111561390b57600080fd5b6020830191508360208260051b850101111561311657600080fd5b60008060006040848603121561393b57600080fd5b8335925060208401356001600160401b0381111561395857600080fd5b61386a868287016138e2565b600081518084526020808501945080840160005b838110156139b157815180516001600160601b031688528301516001600160a01b03168388015260409096019590820190600101613978565b509495945050505050565b6020815260006127f36020830184613964565b600080604083850312156139e257600080fd5b82356139ed81613877565b915060208301356001600160401b038111156137b257600080fd5b63ffffffff81168114610cf957600080fd5b8035613a2581613a08565b919050565b60008060408385031215613a3d57600080fd5b8235915060208301356138d781613a08565b6001600160601b039290921682526001600160a01b0316602082015260400190565b6001600160a01b0391909116815260200190565b6000806000838503610280811215613a9c57600080fd5b84359350610160601f1982011215613ab357600080fd5b50602084019150613ac88561018086016137c8565b90509250925092565b600060c082840312156137db57600080fd5b6000806000806000806000610160888a031215613aff57600080fd5b873596506020880135613b1181613877565b95506040880135613b2181613a08565b94506060880135613b3181613877565b9350613b408960808a01613ad1565b92506101408801356001600160401b03811115613b5c57600080fd5b613b688a828b016137e1565b989b979a50959850939692959293505050565b600080600080600080600080610160898b031215613b9857600080fd5b883597506020890135613baa81613877565b965060408901356001600160401b0380821115613bc657600080fd5b613bd28c838d016138e2565b909850965060608b01359150613be782613877565b819550613bf78c60808d01613ad1565b94506101408b0135915080821115613c0e57600080fd5b50613c1b8b828c016137e1565b999c989b5096995094979396929594505050565b60008060408385031215613c4257600080fd5b8235915060208301356138d781613877565b608081526000613c676080830187613964565b82810360208481019190915286518083528782019282019060005b81811015613c9e57845183529383019391830191600101613c82565b505063ffffffff9687166040860152949095166060909301929092525090949350505050565b6001600160601b0381168114610cf957600080fd5b600080600060608486031215613cee57600080fd5b833592506020840135613d0081613a08565b91506040840135613d1081613cc4565b809150509250925092565b60008060408385031215613d2e57600080fd5b8235915060208301356138d781613cc4565b65ffffffffffff81168114610cf957600080fd5b600080600080600080600080610100898b031215613d7157600080fd5b8851613d7c81613d40565b60208a0151909850613d8d81613d40565b60408a0151909750613d9e81613d40565b60608a0151909650613daf81613877565b60808a0151909550613dc081613a08565b60a08a0151909450613dd181613a08565b60c08a0151909350613de281613cc4565b60e08a0151909250613df381613877565b809150509295985092959890939650565b634e487b7160e01b600052601160045260246000fd5b600065ffffffffffff808316818516808303821115613e3b57613e3b613e04565b01949350505050565b8035613a2581613d40565b803560ff81168114613a2557600080fd5b6000610100808385031215613e7457600080fd5b604051908101906001600160401b0382118183101715613e9657613e96613697565b81604052833581526020840135602082015260408401359150613eb882613877565b816040820152613eca60608501613a1a565b6060820152613edb60808501613e44565b608082015260a084013560a0820152613ef660c08501613a1a565b60c0820152613f0760e08501613e4f565b60e0820152949350505050565b600060208284031215613f2657600080fd5b8135612c5281613a08565b600063ffffffff83811690831681811015613f4e57613f4e613e04565b039392505050565b6020808252602c908201526000805160206144f783398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201526000805160206144f783398151915260408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b6000600019821415613ff457613ff4613e04565b5060010190565b600081600019048311821515161561401557614015613e04565b500290565b60008261403757634e487b7160e01b600052601260045260246000fd5b500490565b60008282101561404e5761404e613e04565b500390565b60006020828403121561406557600080fd5b8151612c5281613877565b8015158114610cf957600080fd5b60006020828403121561409057600080fd5b8135612c5281614070565b6000602082840312156140ad57600080fd5b8135612c5281613d40565b6000602082840312156140ca57600080fd5b8135612c5281613cc4565b60006001600160601b0383811690831681811015613f4e57613f4e613e04565b60006001600160601b03828116848216808303821115613e3b57613e3b613e04565b600065ffffffffffff83811690831681811015613f4e57613f4e613e04565b63ffffffff9590951685526001600160a01b0393841660208601526001600160601b0392909216604085015290911660608301521515608082015260a00190565b600063ffffffff808316818516808303821115613e3b57613e3b613e04565b60005b838110156141b1578181015183820152602001614199565b83811115612f205750506000910152565b600060208083850312156141d557600080fd5b82516001600160401b03808211156141ec57600080fd5b908401906080828703121561420057600080fd5b6142086136ad565b82518281111561421757600080fd5b83019150601f8201871361422a57600080fd5b815161423861374b82613705565b818152888683860101111561424c57600080fd5b61425b82878301888701614196565b82525082840151938101939093525060408082015190830152606090810151908201529392505050565b60006020828403121561429757600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060c082840312156142fb57600080fd5b60405160c081016001600160401b038111828210171561431d5761431d613697565b604052825161432b81613877565b8152602083015161433b81613cc4565b6020820152604083015161434e81613877565b6040820152606083015161436181614070565b6060820152608083015161437481614070565b608082015260a083015161438781614070565b60a08201529392505050565b6000602082840312156143a557600080fd5b8151612c5281614070565b634e487b7160e01b600052603160045260246000fd5b600080600080600080600080610100898b0312156143e357600080fd5b8835975060208901356143f581613877565b9650604089013561440581613a08565b9550606089013561441581613d40565b94506080890135935060a089013561442c81613a08565b925061443a60c08a01613e4f565b915060e08901356001600160401b0381111561445557600080fd5b6144618b828c0161372c565b9150509295985092959890939650565b634e487b7160e01b600052602160045260246000fd5b60008251614499818460208701614196565b9190910192915050565b60208152600082518060208401526144c2816040850160208701614196565b601f01601f1916919091016040019291505056fec0ba1da4c626584ae8d7891d28901f7f37729646868d75af81d3bd99c2c1a39646756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564bae677f66fd8fbcf032e7230df264d3a20efb007eca7bc6793304e0be8f7205aa164736f6c634300080a000a
Deployed Bytecode
0x6080604052600436106101055760003560e01c80630ae941031461010a57806313b5d9e6146101405780631a8d3792146101705780633012a1d0146101925780633659cfe6146101b2578063485cc955146101d2578063494a76d9146101f25780634f1ef2861461021f57806352d1902d146102325780635da320b414610255578063715018a6146102b657806377c14320146102cb5780637e4edf70146102eb5780638da5cb5b146103185780638dd918641461032d5780639cc163e51461034d578063c4804ce214610360578063c617bfa614610373578063ceab8e19146103a3578063dd48aaaf146103c3578063f2fde38b146103d6578063fae4e488146103f6575b600080fd5b34801561011657600080fd5b5061012a610125366004613546565b610409565b604051610137919061365b565b60405180910390f35b34801561014c57600080fd5b5061016061015b366004613546565b6104df565b604051610137949392919061366a565b34801561017c57600080fd5b5061019061018b366004613782565b6105d5565b005b34801561019e57600080fd5b506101906101ad366004613822565b610970565b3480156101be57600080fd5b506101906101cd36600461388c565b610c2a565b3480156101de57600080fd5b506101906101ed3660046138a9565b610cfc565b3480156101fe57600080fd5b5061021261020d366004613926565b610e18565b60405161013791906139bc565b61019061022d3660046139cf565b610f33565b34801561023e57600080fd5b50610247610fed565b604051908152602001610137565b34801561026157600080fd5b506102a8610270366004613a2a565b60686020908152600092835260408084209091529082529020546001600160601b03811690600160601b90046001600160a01b031682565b604051610137929190613a4f565b3480156102c257600080fd5b5061019061109b565b3480156102d757600080fd5b506101906102e6366004613822565b6110af565b3480156102f757600080fd5b5060655461030b906001600160a01b031681565b6040516101379190613a71565b34801561032457600080fd5b5061030b6112e2565b34801561033957600080fd5b50610190610348366004613a85565b6112f1565b61019061035b366004613ae3565b6117e2565b61019061036e366004613b7b565b61181a565b34801561037f57600080fd5b5061039361038e366004613c2f565b611856565b6040516101379493929190613c54565b3480156103af57600080fd5b506101906103be36600461388c565b6119e8565b6101906103d1366004613cd9565b611a30565b3480156103e257600080fd5b506101906103f136600461388c565b611dbb565b610190610404366004613d1b565b611e31565b6104116134d3565b50600090815260666020908152604091829020825161016081018452815465ffffffffffff8082168352600160301b82048116948301949094526001600160a01b03600160601b91829004811695830195909552600183015463ffffffff8082166060850152600160201b820481166080850152600160401b82041660a08401520490931660c08401526002015460ff8116151560e08401526001600160601b03610100808304821690850152600160681b8204909216610120840152600160981b90041661014082015290565b6104e76134d3565b506000818152606660209081526040808320815161016081018352815465ffffffffffff8082168352600160301b82048116838701526001600160a01b03600160601b92839004811684870152600185015463ffffffff8082166060870152600160201b820481166080870152600160401b82041660a08601529290920490911660c083015260029092015460ff8116151560e08301526001600160601b03610100808304821690840152600160681b8204909316610120830152600160981b900490911661014082015284845260679092528220549091806105c985612281565b94969395509392915050565b6065546001600160a01b031633146105f7576105f7639a04794d60e01b6124c0565b60008281526066602052604090205465ffffffffffff1615610623576106236366fa676560e11b6124c0565b600080600080600080600080888060200190518101906106439190613d54565b975097509750975097509750975097508263ffffffff166000141561067257610672637d5ba07f60e01b6124c0565b600065ffffffffffff891615610688578861068a565b425b905060006040518061016001604052808365ffffffffffff1681526020018a65ffffffffffff166000146106be578a6106cb565b6106cb8462093a80613e1a565b65ffffffffffff168152602001886001600160a01b031681526020018763ffffffff1681526020018663ffffffff168152602001600063ffffffff168152602001846001600160a01b03168152602001600015158152602001856001600160601b031681526020018965ffffffffffff16815260200160006001600160601b0316815250905080606660008e815260200190815260200160002060008201518160000160006101000a81548165ffffffffffff021916908365ffffffffffff16021790555060208201518160000160066101000a81548165ffffffffffff021916908365ffffffffffff160217905550604082015181600001600c6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160010160006101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160046101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555060c082015181600101600c6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160020160006101000a81548160ff0219169083151502179055506101008201518160020160016101000a8154816001600160601b0302191690836001600160601b0316021790555061012082015181600201600d6101000a81548165ffffffffffff021916908365ffffffffffff1602179055506101408201518160020160136101000a8154816001600160601b0302191690836001600160601b031602179055509050508b7f2a64ac2f583e4882d53a07723d8ba198e44c455bd84a12959f10f2dd220b67a760405160405180910390a2505050505050505050505050565b6109c161098236859003850185613e60565b33600185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124ca92505050565b82356000908152606860205260408120816109e260e0870160c08801613f14565b63ffffffff16815260208082019290925260409081016000208151808301835290546001600160601b0381168252600160601b90046001600160a01b031692810192909252909150610a3a906060860190860161388c565b6001600160a01b031681602001516001600160a01b031614610a6557610a656282b42960e81b6124c0565b610a8081600001516001600160601b0316826020015161277c565b610a9060e0850160c08601613f14565b815185356000818152606660205260409081902060010154905163ffffffff949094169391927fba85505a71c5b1789e1357fee7e9e22da158b6c570e1b711a6efe27b61be645d92610af292600160601b90046001600160a01b031690613a4f565b60405180910390a383356000908152606960205260408082206001929091610b20906060890190890161388c565b6001600160a01b0316815260208101919091526040016000208054600490610b56908490600160201b900463ffffffff16613f31565b92506101000a81548163ffffffff021916908363ffffffff160217905550610bd68460c0016020810190610b8a9190613f14565b85356000908152606a602052604080822063ffffffff93909316929190610bb79060608a01908a0161388c565b6001600160a01b031681526020810191909152604001600020906127e7565b610bea57610bea63a88a48e360e01b6124c0565b8335600090815260686020526040812090610c0b60e0870160c08801613f14565b63ffffffff168152602081019190915260400160009081205550505050565b306001600160a01b037f000000000000000000000000cebc3b3134fbef95ed13aecdf997d4371d022385161415610c7c5760405162461bcd60e51b8152600401610c7390613f56565b60405180910390fd5b7f000000000000000000000000cebc3b3134fbef95ed13aecdf997d4371d0223856001600160a01b0316610cae6127fc565b6001600160a01b031614610cd45760405162461bcd60e51b8152600401610c7390613f90565b610cdd81612818565b60408051600080825260208201909252610cf991839190612820565b50565b600054610100900460ff1615808015610d1c5750600054600160ff909116105b80610d3d5750610d2b3061298b565b158015610d3d575060005460ff166001145b610da05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c73565b6000805460ff191660011790558015610dc3576000805461ff0019166101001790555b610dcd838361299a565b8015610e13576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6060816000816001600160401b03811115610e3557610e35613697565b604051908082528060200260200182016040528015610e6e57816020015b610e5b61352f565b815260200190600190039081610e535790505b50905060005b82811015610f2957600087815260686020526040812090878784818110610e9d57610e9d613fca565b9050602002016020810190610eb29190613f14565b63ffffffff16815260208082019290925260409081016000208151808301909252546001600160601b0381168252600160601b90046001600160a01b0316918101919091528251839083908110610f0b57610f0b613fca565b60200260200101819052508080610f2190613fe0565b915050610e74565b5095945050505050565b306001600160a01b037f000000000000000000000000cebc3b3134fbef95ed13aecdf997d4371d022385161415610f7c5760405162461bcd60e51b8152600401610c7390613f56565b7f000000000000000000000000cebc3b3134fbef95ed13aecdf997d4371d0223856001600160a01b0316610fae6127fc565b6001600160a01b031614610fd45760405162461bcd60e51b8152600401610c7390613f90565b610fdd82612818565b610fe982826001612820565b5050565b6000306001600160a01b037f000000000000000000000000cebc3b3134fbef95ed13aecdf997d4371d02238516146110885760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610c73565b5060008051602061451783398151915290565b6110a36129ed565b6110ad6000612a4c565b565b6111006110c136859003850185613e60565b33600285858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124ca92505050565b8235600090815260666020908152604091829020825161016081018452815465ffffffffffff8082168352600160301b820481169483018590526001600160a01b03600160601b92839004811696840196909652600184015463ffffffff8082166060860152600160201b820481166080860152600160401b82041660a08501529190910490941660c082015260029091015460ff8116151560e08301526001600160601b03610100808304821690840152600160681b82048516610120840152600160981b909104166101408201529142161115806111ec575060c08101516001600160a01b031615155b806111f857508060e001515b1561120d5761120d633b4f091f60e21b6124c0565b600061271061122260a08701356101f4613ffb565b61122c919061401a565b905061123f8161123a6112e2565b61277c565b61125a6112508260a088013561403c565b836040015161277c565b843560008181526066602052604090819020600201805460ff191660011790558381015160c085015191517f53c2a8252078e2d170ed485279f20e9fbc9a31edc453ea98250fa5cbfb6432d6926112d39260a08b0135929091909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a25050505050565b6033546001600160a01b031690565b60006112fc84612a9e565b9050336001600160a01b031681600001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561134a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136e9190614053565b6001600160a01b03161415801561138f575080516001600160a01b03163314155b156113a3576113a36282b42960e81b6124c0565b6113b0602083018361407e565b1561140e576113c2602084018461409b565b65ffffffffffff16156113e1576113dc602084018461409b565b6113e3565b425b6000858152606660205260409020805465ffffffffffff191665ffffffffffff929092169190911790555b61141e604083016020840161407e565b1561149557611433604084016020850161409b565b65ffffffffffff1661144f5761144f637d5ba07f60e01b6124c0565b61145f604084016020850161409b565b6000858152606660205260409020805465ffffffffffff92909216600160301b0265ffffffffffff60301b199092169190911790555b6114a5606083016040840161407e565b15611523576114bc6101408401610120850161409b565b65ffffffffffff166114d8576114d8637d5ba07f60e01b6124c0565b6114ea6101408401610120850161409b565b6000858152606660205260409020600201805465ffffffffffff92909216600160681b0265ffffffffffff60681b199092169190911790555b611533608083016060840161407e565b15611572576115486080840160608501613f14565b6000858152606660205260409020600101805463ffffffff191663ffffffff929092169190911790555b61158260a083016080840161407e565b156116355761159760a0840160808501613f14565b63ffffffff1615806115db5750600084815260666020526040902060010154600160201b900463ffffffff166115d360a0850160808601613f14565b63ffffffff16105b156115f0576115f0637d5ba07f60e01b6124c0565b61160060a0840160808501613f14565b6000858152606660205260409020600101805463ffffffff92909216600160201b0263ffffffff60201b199092169190911790555b61164560e0830160c0840161407e565b156116c557600084815260666020526040902060010154600160401b900463ffffffff161561167e5761167e637d5ba07f60e01b6124c0565b61168e60e0840160c0850161388c565b600085815260666020526040902060010180546001600160a01b0392909216600160601b026001600160601b039092169190911790555b6116d560c0830160a0840161407e565b1561171e576116ea606084016040850161388c565b600085815260666020526040902080546001600160a01b0392909216600160601b026001600160601b039092169190911790555b61172f610100830160e0840161407e565b156117b157600084815260666020526040902060010154600160401b900463ffffffff161561176857611768637d5ba07f60e01b6124c0565b61177a610120840161010085016140b8565b600085815260666020526040902060020180546001600160601b039290921661010002610100600160681b03199092169190911790555b60405184907f5b6bcbd593bccf88b5035e118227608b2364ff5ab65aa173c15e29ed0f83881190600090a250505050565b6065546001600160a01b0316331461180457611804639a04794d60e01b6124c0565b6118118785878585612b38565b50505050505050565b6065546001600160a01b0316331461183c5761183c639a04794d60e01b6124c0565b61184c63201dc6f560e01b6124c0565b5050505050505050565b60008281526069602090815260408083206001600160a01b03851680855290835281842082518084018452905463ffffffff8082168352600160201b9091041681850152868552606a8452828520918552925282206060928392909182919082906118c090612c45565b80519091506000816001600160401b038111156118df576118df613697565b60405190808252806020026020018201604052801561191857816020015b61190561352f565b8152602001906001900390816118fd5790505b50905060005b828110156119ce57606860008c8152602001908152602001600020600085838151811061194d5761194d613fca565b60209081029190910181015163ffffffff1682528181019290925260409081016000208151808301909252546001600160601b0381168252600160601b90046001600160a01b03169181019190915282518390839081106119b0576119b0613fca565b602002602001018190525080806119c690613fe0565b91505061191e565b5060208401519351909a9299509297509195509350505050565b6119f06129ed565b6001600160a01b038116611a0e57611a0e63040b3bcf60e31b6124c0565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b6000838152606660209081526040808320815161016081018352815465ffffffffffff8082168352600160301b82048116838701526001600160a01b03600160601b92839004811684870152600185015463ffffffff8082166060870152600160201b820481166080870152600160401b8204811660a087015290849004821660c086015260029095015460ff8116151560e08601526001600160601b03610100808304821690870152600160681b8204909316610120860152600160981b900482166101408501528a885260688752858820948a168852938652958490208451808601909552548087168086529190049092169383019390935291929091908416111580611b4a575060208101516001600160a01b0316155b80611b6857504265ffffffffffff16826020015165ffffffffffff16105b80611b7e5750815165ffffffffffff4281169116115b80611b9f57508161010001516001600160601b0316836001600160601b0316105b80611bbe57508051611bb190846140d5565b6001600160601b03163414155b15611bd357611bd363c6388ef760e01b6124c0565b60208101516001600160a01b03163314611bf657611bf66282b42960e81b6124c0565b60018261014001818151611c0a91906140f5565b6001600160601b03908116909152600087815260686020908152604080832063ffffffff8a168452825280832080546001600160601b0319168986161790556101408701518a84526066835292206002018054600160981b600160f81b031916600160981b939094169290920292909217905583015161012c9150611c90904290614117565b65ffffffffffff1611611d6157600082610120015165ffffffffffff1660001415611cc657611cc14261012c613e1a565b611d04565b611cd24261012c613e1a565b65ffffffffffff1683610120015165ffffffffffff1611611cf857826101200151611d04565b611d044261012c613e1a565b600087815260666020908152604091829020805465ffffffffffff60301b1916600160301b65ffffffffffff8616908102919091179091559151918252919250879160008051602061455e833981519152910160405180910390a2505b6000611d6e868686612c59565b90508261014001516001600160601b031681876000805160206144d78339815191528833898960c001516000604051611dab959493929190614136565b60405180910390a4505050505050565b611dc36129ed565b6001600160a01b038116611e285760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c73565b610cf981612a4c565b6000828152606660209081526040808320815161016081018352815465ffffffffffff8082168352600160301b82048116838701526001600160a01b03600160601b9283900481168487015260018086015463ffffffff8082166060880152600160201b80830482166080890152600160401b8304821660a08901529590910490921660c086015260029095015460ff8116151560e08601526001600160601b03610100808304821690870152600160681b8204909316610120860152600160981b90049091166101408401528887526069865284872033885290955292852054909493611f23939091041690614177565b90504265ffffffffffff16826020015165ffffffffffff161080611f525750815165ffffffffffff4281169116115b80611f7357508161010001516001600160601b0316836001600160601b0316105b80611f87575034836001600160601b031614155b80611fb55750606082015163ffffffff1615801590611fb55750816060015163ffffffff168163ffffffff16115b15611fca57611fca63c6388ef760e01b6124c0565b60018260a001818151611fdd9190614177565b63ffffffff169052506101408201805160019190611ffc9083906140f5565b6001600160601b03908116909152604080518082018252868316815233602080830182815260008b81526068835285812060a08b01805163ffffffff9081168452918552878320965193516001600160a01b0316600160601b02939098169290921790945594518a8452606a825284842092845291905291902061208693509190811690612ccc16565b61209a5761209a630d45f68160e21b6124c0565b60008481526069602090815260408083203384528252808320805463ffffffff808716600160201b0263ffffffff60201b199092169190911790915560a0860151888552606684529190932060018101805492909416600160401b0263ffffffff60401b1990921691909117909255610140840151600290920180546001600160601b03909316600160981b02600160981b600160f81b03199093169290921790915582015161012c9061214f904290614117565b65ffffffffffff16116122205761012082015165ffffffffffff1661217f5761217a4261012c613e1a565b6121bd565b61218b4261012c613e1a565b65ffffffffffff1682610120015165ffffffffffff16116121b1578161012001516121bd565b6121bd4261012c613e1a565b65ffffffffffff9081166020848101828152600088815260668352604090819020805465ffffffffffff60301b1916600160301b90950294909417909355519151919092168152859160008051602061455e833981519152910160405180910390a25b6000612231858460a0015186612c59565b90508261014001516001600160601b031681866000805160206144d78339815191528660a0015133898960c001516001604051612272959493929190614136565b60405180910390a45050505050565b600080600061228f84612a9e565b80519091506001600160a01b03166122e05760405162461bcd60e51b8152602060048201526014602482015273159958dd1bdc88191bd95cdb89dd08195e1a5cdd60621b6044820152606401610c73565b80606001511561237f578051602082015160405163ddf990f960e01b81526001600160601b0390911660048201526000916001600160a01b03169063ddf990f990602401600060405180830381865afa158015612341573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261236991908101906141c2565b90508060400151935080602001519250506124ba565b80600001516001600160a01b031663047fc9aa6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156123dd575060408051601f3d908101601f191682019092526123da91810190614285565b60015b61244e5780600001516001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612423573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124479190614285565b9250612451565b92505b80600001516001600160a01b0316632ddcb21f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b79190614285565b91505b50915091565b8060005260046000fd5b826001600160a01b031684604001516001600160a01b0316146124f6576124f66282b42960e81b6124c0565b8160ff168460e0015160ff161461251757612517633b4f091f60e21b6124c0565b60007fa9accd45695a721aca33e1224254ff563220e1765ba1b89c350834a6ad4c54fd856000015186602001518760400151886060015189608001518a60a001518b60c001518c60e001516040516020016125d199989796959493929190988952602089019790975260408801959095526001600160a01b0393909316606087015263ffffffff918216608087015265ffffffffffff1660a086015260c08501919091521660e083015260ff166101008201526101200190565b60405160208183030381529060405280519060200120905060006126b9604080517fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac5647260208201527f42ef9e7ac4a9ac8ff505b5257b63e7b5f2271ba58e5fb6c9ef7bcfa02040957a918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201527f960bb3ecd14c38754109e5fe3a3b72aa0434091106c0fea200392fd413d44da060c082015260009060e00160405160208183030381529060405280519060200120905090565b60405161190160f01b602082015260228101919091526042810183905260620160405160208183030381529060405280519060200120905060006126fd8285612cd8565b90506001600160a01b038116158061271b575061271981612cfc565b155b806127395750866080015165ffffffffffff164265ffffffffffff16115b1561274e5761274e638baa579f60e01b6124c0565b86516000908152606b602052604090206127689084612ccc565b61181157611811633b4f091f60e21b6124c0565b6000816001600160a01b03168360405160006040518083038185875af1925050503d80600081146127c9576040519150601f19603f3d011682016040523d82523d6000602084013e6127ce565b606091505b5050905080610e1357610e13637cd69c3960e11b6124c0565b60006127f38383612d6e565b90505b92915050565b600080516020614517833981519152546001600160a01b031690565b610cf96129ed565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561285357610e1383612e61565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156128ad575060408051601f3d908101601f191682019092526128aa91810190614285565b60015b6129105760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610c73565b600080516020614517833981519152811461297f5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610c73565b50610e13838383612efb565b6001600160a01b03163b151590565b600054610100900460ff166129c15760405162461bcd60e51b8152600401610c739061429e565b6129c9612f26565b606580546001600160a01b0319166001600160a01b038416179055610fe981612a4c565b336129f66112e2565b6001600160a01b0316146110ad5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c73565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6040805160c081018252600080825260208201819052818301819052606082018190526080820181905260a0820152606554915162820a0360e31b81526004810184905290916001600160a01b03169063041050189060240160c060405180830381865afa158015612b14573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f691906142e9565b600080612b46878585612f55565b91509150612b5782876003846124ca565b60008781526066602052604090205465ffffffffffff428116600160301b9092041610612b8e57612b8e63201dc6f560e01b6124c0565b60008781526069602090815260408083206001600160a01b038a168452909152902054606083015163ffffffff9182169116612bca8288614177565b63ffffffff161115612be657612be663199f5a0360e31b6124c0565b612bf08682614177565b60008981526069602090815260408083206001600160a01b038c1684528252909120805463ffffffff191663ffffffff93909316929092179091558301511561184c5761184c8360200151846040015161277c565b60606000612c528361302c565b9392505050565b6000838152606760208181526040808420805482518085019190915280830189905260e09790971b6001600160e01b031916606088015260a09590951b6001600160a01b031916606487015280516050818803018152607090960190528451948101949094209490915290915281905590565b60006127f38383613088565b6000806000612ce785856130d7565b91509150612cf48161311d565b509392505050565b60655460405163717b358f60e11b81526000916001600160a01b03169063e2f66b1e90612d2d908590600401613a71565b602060405180830381865afa158015612d4a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f69190614393565b60008181526001830160205260408120548015612e57576000612d9260018361403c565b8554909150600090612da69060019061403c565b9050818114612e0b576000866000018281548110612dc657612dc6613fca565b9060005260206000200154905080876000018481548110612de957612de9613fca565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612e1c57612e1c6143b0565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506127f6565b60009150506127f6565b612e6a8161298b565b612ecc5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610c73565b60008051602061451783398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b612f0483613266565b600082511180612f115750805b15610e1357612f2083836132a6565b50505050565b600054610100900460ff16612f4d5760405162461bcd60e51b8152600401610c739061429e565b6110ad6132cb565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101919091526060600080808080808080612fad8b8d018d6143c6565b975097509750975097509750975097506040518061010001604052808e8152602001898152602001886001600160a01b031681526020018763ffffffff1681526020018665ffffffffffff1681526020018581526020018463ffffffff1681526020018360ff1681525081995099505050505050505050935093915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561307c57602002820191906000526020600020905b815481526020019060010190808311613068575b50505050509050919050565b60008181526001830160205260408120546130cf575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556127f6565b5060006127f6565b60008082516041141561310e5760208301516040840151606085015160001a613102878285856132fb565b94509450505050613116565b506000905060025b9250929050565b600081600481111561313157613131614471565b141561313a5750565b600181600481111561314e5761314e614471565b14156131975760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401610c73565b60028160048111156131ab576131ab614471565b14156131f95760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c73565b600381600481111561320d5761320d614471565b1415610cf95760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610c73565b61326f81612e61565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606127f38383604051806060016040528060278152602001614537602791396133b5565b600054610100900460ff166132f25760405162461bcd60e51b8152600401610c739061429e565b6110ad33612a4c565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b0383111561332857506000905060036133ac565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561337c573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166133a5576000600192509250506133ac565b9150600090505b94509492505050565b6060600080856001600160a01b0316856040516133d29190614487565b600060405180830381855af49150503d806000811461340d576040519150601f19603f3d011682016040523d82523d6000602084013e613412565b606091505b50915091506134238683838761342d565b9695505050505050565b60608315613497578251613490576134448561298b565b6134905760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c73565b50816134a1565b6134a183836134a9565b949350505050565b8151156134b95781518083602001fd5b8060405162461bcd60e51b8152600401610c7391906144a3565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915290565b604080518082019091526000808252602082015290565b60006020828403121561355857600080fd5b5035919050565b6001600160a01b03169052565b805165ffffffffffff1682526020810151613591602084018265ffffffffffff169052565b5060408101516135a4604084018261355f565b5060608101516135bc606084018263ffffffff169052565b5060808101516135d4608084018263ffffffff169052565b5060a08101516135ec60a084018263ffffffff169052565b5060c08101516135ff60c084018261355f565b5060e081015161361360e084018215159052565b50610100818101516001600160601b0381168483015250506101208181015165ffffffffffff8116848301525050610140818101516001600160601b03811684830152612f20565b61016081016127f6828461356c565b6101c08101613679828761356c565b8461016083015283610180830152826101a083015295945050505050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156136cf576136cf613697565b60405290565b604051601f8201601f191681016001600160401b03811182821017156136fd576136fd613697565b604052919050565b60006001600160401b0382111561371e5761371e613697565b50601f01601f191660200190565b600082601f83011261373d57600080fd5b813561375061374b82613705565b6136d5565b81815284602083860101111561376557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561379557600080fd5b8235915060208301356001600160401b038111156137b257600080fd5b6137be8582860161372c565b9150509250929050565b600061010082840312156137db57600080fd5b50919050565b60008083601f8401126137f357600080fd5b5081356001600160401b0381111561380a57600080fd5b60208301915083602082850101111561311657600080fd5b6000806000610120848603121561383857600080fd5b61384285856137c8565b92506101008401356001600160401b0381111561385e57600080fd5b61386a868287016137e1565b9497909650939450505050565b6001600160a01b0381168114610cf957600080fd5b60006020828403121561389e57600080fd5b8135612c5281613877565b600080604083850312156138bc57600080fd5b82356138c781613877565b915060208301356138d781613877565b809150509250929050565b60008083601f8401126138f457600080fd5b5081356001600160401b0381111561390b57600080fd5b6020830191508360208260051b850101111561311657600080fd5b60008060006040848603121561393b57600080fd5b8335925060208401356001600160401b0381111561395857600080fd5b61386a868287016138e2565b600081518084526020808501945080840160005b838110156139b157815180516001600160601b031688528301516001600160a01b03168388015260409096019590820190600101613978565b509495945050505050565b6020815260006127f36020830184613964565b600080604083850312156139e257600080fd5b82356139ed81613877565b915060208301356001600160401b038111156137b257600080fd5b63ffffffff81168114610cf957600080fd5b8035613a2581613a08565b919050565b60008060408385031215613a3d57600080fd5b8235915060208301356138d781613a08565b6001600160601b039290921682526001600160a01b0316602082015260400190565b6001600160a01b0391909116815260200190565b6000806000838503610280811215613a9c57600080fd5b84359350610160601f1982011215613ab357600080fd5b50602084019150613ac88561018086016137c8565b90509250925092565b600060c082840312156137db57600080fd5b6000806000806000806000610160888a031215613aff57600080fd5b873596506020880135613b1181613877565b95506040880135613b2181613a08565b94506060880135613b3181613877565b9350613b408960808a01613ad1565b92506101408801356001600160401b03811115613b5c57600080fd5b613b688a828b016137e1565b989b979a50959850939692959293505050565b600080600080600080600080610160898b031215613b9857600080fd5b883597506020890135613baa81613877565b965060408901356001600160401b0380821115613bc657600080fd5b613bd28c838d016138e2565b909850965060608b01359150613be782613877565b819550613bf78c60808d01613ad1565b94506101408b0135915080821115613c0e57600080fd5b50613c1b8b828c016137e1565b999c989b5096995094979396929594505050565b60008060408385031215613c4257600080fd5b8235915060208301356138d781613877565b608081526000613c676080830187613964565b82810360208481019190915286518083528782019282019060005b81811015613c9e57845183529383019391830191600101613c82565b505063ffffffff9687166040860152949095166060909301929092525090949350505050565b6001600160601b0381168114610cf957600080fd5b600080600060608486031215613cee57600080fd5b833592506020840135613d0081613a08565b91506040840135613d1081613cc4565b809150509250925092565b60008060408385031215613d2e57600080fd5b8235915060208301356138d781613cc4565b65ffffffffffff81168114610cf957600080fd5b600080600080600080600080610100898b031215613d7157600080fd5b8851613d7c81613d40565b60208a0151909850613d8d81613d40565b60408a0151909750613d9e81613d40565b60608a0151909650613daf81613877565b60808a0151909550613dc081613a08565b60a08a0151909450613dd181613a08565b60c08a0151909350613de281613cc4565b60e08a0151909250613df381613877565b809150509295985092959890939650565b634e487b7160e01b600052601160045260246000fd5b600065ffffffffffff808316818516808303821115613e3b57613e3b613e04565b01949350505050565b8035613a2581613d40565b803560ff81168114613a2557600080fd5b6000610100808385031215613e7457600080fd5b604051908101906001600160401b0382118183101715613e9657613e96613697565b81604052833581526020840135602082015260408401359150613eb882613877565b816040820152613eca60608501613a1a565b6060820152613edb60808501613e44565b608082015260a084013560a0820152613ef660c08501613a1a565b60c0820152613f0760e08501613e4f565b60e0820152949350505050565b600060208284031215613f2657600080fd5b8135612c5281613a08565b600063ffffffff83811690831681811015613f4e57613f4e613e04565b039392505050565b6020808252602c908201526000805160206144f783398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201526000805160206144f783398151915260408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b6000600019821415613ff457613ff4613e04565b5060010190565b600081600019048311821515161561401557614015613e04565b500290565b60008261403757634e487b7160e01b600052601260045260246000fd5b500490565b60008282101561404e5761404e613e04565b500390565b60006020828403121561406557600080fd5b8151612c5281613877565b8015158114610cf957600080fd5b60006020828403121561409057600080fd5b8135612c5281614070565b6000602082840312156140ad57600080fd5b8135612c5281613d40565b6000602082840312156140ca57600080fd5b8135612c5281613cc4565b60006001600160601b0383811690831681811015613f4e57613f4e613e04565b60006001600160601b03828116848216808303821115613e3b57613e3b613e04565b600065ffffffffffff83811690831681811015613f4e57613f4e613e04565b63ffffffff9590951685526001600160a01b0393841660208601526001600160601b0392909216604085015290911660608301521515608082015260a00190565b600063ffffffff808316818516808303821115613e3b57613e3b613e04565b60005b838110156141b1578181015183820152602001614199565b83811115612f205750506000910152565b600060208083850312156141d557600080fd5b82516001600160401b03808211156141ec57600080fd5b908401906080828703121561420057600080fd5b6142086136ad565b82518281111561421757600080fd5b83019150601f8201871361422a57600080fd5b815161423861374b82613705565b818152888683860101111561424c57600080fd5b61425b82878301888701614196565b82525082840151938101939093525060408082015190830152606090810151908201529392505050565b60006020828403121561429757600080fd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060c082840312156142fb57600080fd5b60405160c081016001600160401b038111828210171561431d5761431d613697565b604052825161432b81613877565b8152602083015161433b81613cc4565b6020820152604083015161434e81613877565b6040820152606083015161436181614070565b6060820152608083015161437481614070565b608082015260a083015161438781614070565b60a08201529392505050565b6000602082840312156143a557600080fd5b8151612c5281614070565b634e487b7160e01b600052603160045260246000fd5b600080600080600080600080610100898b0312156143e357600080fd5b8835975060208901356143f581613877565b9650604089013561440581613a08565b9550606089013561441581613d40565b94506080890135935060a089013561442c81613a08565b925061443a60c08a01613e4f565b915060e08901356001600160401b0381111561445557600080fd5b6144618b828c0161372c565b9150509295985092959890939650565b634e487b7160e01b600052602160045260246000fd5b60008251614499818460208701614196565b9190910192915050565b60208152600082518060208401526144c2816040850160208701614196565b601f01601f1916919091016040019291505056fec0ba1da4c626584ae8d7891d28901f7f37729646868d75af81d3bd99c2c1a39646756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564bae677f66fd8fbcf032e7230df264d3a20efb007eca7bc6793304e0be8f7205aa164736f6c634300080a000a
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.