Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 17,268 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transfer | 21365459 | 13 days ago | IN | 0 ETH | 0.00128331 | ||||
Buy Pleb | 20502863 | 134 days ago | IN | 0.4 ETH | 0.00002797 | ||||
Buy Pleb | 20101917 | 190 days ago | IN | 0.43 ETH | 0.00489105 | ||||
Transfer | 20093781 | 191 days ago | IN | 0 ETH | 0.00006297 | ||||
Buy Pleb | 20089274 | 191 days ago | IN | 5 ETH | 0.00025312 | ||||
Buy Pleb | 20089274 | 191 days ago | IN | 0.15 ETH | 0.00025312 | ||||
Buy Pleb | 20089274 | 191 days ago | IN | 1 ETH | 0.00025312 | ||||
Buy Community Mi... | 20086616 | 192 days ago | IN | 1 ETH | 0.00019958 | ||||
Buy Community An... | 20085141 | 192 days ago | IN | 0.24999904 ETH | 0.0005464 | ||||
Buy Community Re... | 20085141 | 192 days ago | IN | 0.24999904 ETH | 0.00053501 | ||||
Buy Holder | 20085141 | 192 days ago | IN | 1 ETH | 0.00051245 | ||||
Buy Pleb | 20085141 | 192 days ago | IN | 0.6 ETH | 0.00065247 | ||||
Buy Pleb | 20084976 | 192 days ago | IN | 2 ETH | 0.00033833 | ||||
Buy Holder | 20084976 | 192 days ago | IN | 0.3 ETH | 0.00042073 | ||||
Buy Pleb | 20084976 | 192 days ago | IN | 0.2 ETH | 0.00033833 | ||||
Buy Pleb | 20084976 | 192 days ago | IN | 1 ETH | 0.00033833 | ||||
Buy Pleb | 20084976 | 192 days ago | IN | 0.4 ETH | 0.00033865 | ||||
Buy Pleb | 20083588 | 192 days ago | IN | 0.05 ETH | 0.00114994 | ||||
Buy Pleb | 20081909 | 192 days ago | IN | 0.12 ETH | 0.00054897 | ||||
Buy Pleb | 20081893 | 192 days ago | IN | 0.0001 ETH | 0.00070454 | ||||
Buy Pleb | 20081860 | 192 days ago | IN | 0.0001 ETH | 0.00090807 | ||||
Buy Pleb | 20081858 | 192 days ago | IN | 0.035 ETH | 0.00068614 | ||||
Buy Pleb | 20081834 | 192 days ago | IN | 0.01 ETH | 0.00077534 | ||||
Buy Holder | 20081829 | 192 days ago | IN | 0.000756 ETH | 0.00097725 | ||||
Buy Pleb | 20081792 | 192 days ago | IN | 0.04 ETH | 0.0008833 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
20082096 | 192 days ago | 5,860.85 ETH | ||||
20082071 | 192 days ago | 1 ETH | ||||
20082017 | 192 days ago | 1 wei | ||||
20081893 | 192 days ago | 0.00009999 ETH | ||||
20081860 | 192 days ago | 0.00009793 ETH | ||||
20081858 | 192 days ago | 0.035 ETH | ||||
20081834 | 192 days ago | 0.01 ETH | ||||
20081829 | 192 days ago | 0.00013031 ETH | ||||
20081792 | 192 days ago | 0.04 ETH | ||||
20081781 | 192 days ago | 0.00198427 ETH | ||||
20081766 | 192 days ago | 0.01000572 ETH | ||||
20081763 | 192 days ago | 0.00400195 ETH | ||||
20081759 | 192 days ago | 0.00040219 ETH | ||||
20081754 | 192 days ago | 0.00999508 ETH | ||||
20081754 | 192 days ago | 0.00575872 ETH | ||||
20081753 | 192 days ago | 0.00219215 ETH | ||||
20081753 | 192 days ago | 0.01989133 ETH | ||||
20081753 | 192 days ago | 0.03998544 ETH | ||||
20081750 | 192 days ago | 0.05998492 ETH | ||||
20081750 | 192 days ago | 0.05800311 ETH | ||||
20081750 | 192 days ago | 0.0484223 ETH | ||||
20081748 | 192 days ago | 0.02000022 ETH | ||||
20081745 | 192 days ago | 0.0100003 ETH | ||||
20081744 | 192 days ago | 0.01990147 ETH | ||||
20081744 | 192 days ago | 0.04978835 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Sale
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 1000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LicenseRef-VPL WITH AGPL-3.0-only pragma solidity ^0.8.25; import { Ownable } from "solady/auth/Ownable.sol"; import { MerkleProofLib } from "solady/utils/MerkleProofLib.sol"; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { ReentrancyGuard } from "soledge/utils/ReentrancyGuard.sol"; /** This is the interface for determining particular ERC-721 or ERC-20 ownership. */ interface IBalanceOf { /** Retrieve the balance that a particular `_owner` has of this token. @param _owner The owner to query the balance for. @return _ The token balance of `_owner`. */ function balanceOf ( address _owner ) external view returns (uint256); } /** @custom:benediction DEVS BENEDICAT ET PROTEGAT CONTRACTVM MEVM @title A contract to sell the future Remilia ERC-20 token. @author Tim Clancy <tim-clancy.eth> @custom:terry "God is just. Work is rewarded with blessing if not money. Luck is the most important thing, but really it's God." A contract to sell the future Remilia ERC-20 token. No seed raise, no investors, no burdens, no promises, just conviction. I love you. @custom:date May 22nd, 2024. */ contract Sale is Ownable, ReentrancyGuard { /// An error emitted if the Sale is paused. error Paused (); /// An error emitted if a caller underpays. error InsufficientPayment (); /// An error emitted if a caller is not eligible per a snapshot. error Ineligible (); /// An error emitted if a round has sold out. error SoldOut (); /// An error emitted if a caller is over their allocation. error OverAllocated (); /// An error emitted if a caller is over the maximum size per call. error OverMax (); /// An error emitted if the caller is a loser. error Loser (); /** This struct represents the configuration options for this sale. @param owner The address of the initial contract owner. @param steps The number of discrete steps to apply for holder sales. @param maxSpend The maximum spend in Ether able to be purchased in one call. @param anyFill Total slots available to purchase in the any round of the community sale. @param miladyFill Total slots available to purchase in the Milady round of the community sale. @param remilioFill Total slots available to purchase in the Remilio round of the community sale. @param plebPremium The premium paid by plebs, in basis points. @param loserPremium The premium paid by losers, in basis points. @param basePrice The base price of the public round, in nanoether. @param endPrice The end price of the public round, in nanoether. @param available The total amount of `token` intended to be sold, 1e18. @param milady The address of the Milady NFT. @param communityPrice The nanoether price per token of the community round. @param remilio The address of the Remilio NFT. @param communityAllo The amount of `token` sold in each community slot. @param anyRoot The hash tree root of the any community snapshot. @param miladyRoot The hash tree root of the Milady community snapshot. @param remilioRoot The hash tree root of the Remilio community snapshot. @param losers An array of token collection addresses whose holders are losers. */ struct Configuration { address owner; uint8 steps; uint8 maxSpend; uint16 anyFill; uint16 miladyFill; uint16 remilioFill; uint16 plebPremium; uint16 loserPremium; uint32 basePrice; uint32 endPrice; uint32 available; address milady; uint32 communityPrice; address remilio; uint96 communityAllo; bytes32 anyRoot; bytes32 miladyRoot; bytes32 remilioRoot; address[] losers; } /// The configuration of this sale. Configuration public config; /// Precalculate and cache a community round spend amount. uint256 private communitySpend; /// Track the total number of future token sold. uint256 public totalSold; /// Track the receipt balance of each address sold to. mapping ( address => uint256 ) public receiptBalance; /// A mapping to record community sale fill progress. mapping ( bytes32 => uint16 ) public communityFill; /// A mapping to record caller participation in the community sales. mapping ( address => mapping ( bytes32 => bool ) ) public participation; /// Whether or not interacting with the sale is paused. bool public paused = true; /** This struct represents the current prices to be paid by either Remilia community members or the general non-holding public for sale participation. @param remilia The nanoether price paid by Remilia holders. @param pleb The nanoether price paid by the general public. @param loser The nanoether premium price paid by losers. */ struct CurrentPrices { uint256 remilia; uint256 pleb; uint256 loser; } /** This event is emitted whenever an address is credited with tokens. @param destination The address credited with tokens. @param amount The amount of tokens credited. */ event Credit ( address indexed destination, uint256 amount ); /** A modifier to revert an operation if the owner has paused. */ modifier notPaused () { if (paused) { revert Paused(); } _; } /** Construct a new instance of the sale contract. @param _config A `Configuration` to prepare this sale. */ constructor ( Configuration memory _config ) { _initializeOwner(_config.owner); config = _config; communitySpend = _config.communityPrice * _config.communityAllo / 1e9; communityFill[_config.anyRoot] = _config.anyFill; communityFill[_config.miladyRoot] = _config.miladyFill; communityFill[_config.remilioRoot] = _config.remilioFill; } /** Return the amount of future tokens credited to an address. @param _holder The address to retrieve future token credits for. @return _ The amount of future token credited to `_holder`. */ function balanceOf ( address _holder ) external view returns (uint256) { return receiptBalance[_holder]; } /** Allow the owner to pause or unpause the sale. @param _status The pause status to set. */ function setPaused ( bool _status ) external onlyOwner { paused = _status; } /** A utility function to help transfer Ether out of this contract. @param _to The address to transfer Ether to. @param _amount The amount of Ether to transfer. */ function _transferEther ( address _to, uint256 _amount ) private { bool success = SafeTransferLib.trySafeTransferETH( _to, _amount, SafeTransferLib.GAS_STIPEND_NO_STORAGE_WRITES ); if (!success) { SafeTransferLib.forceSafeTransferETH(_to, _amount); } } /** This is a private helper function to handle the different possible community buy options. It exists to be wrapped in normie-digestible names. @param _destination An address to receive the purchased tokens. @param _root The hash tree root. @param _proof A hash tree proof of snapshot eligibility. */ function _processCommunityBuy ( address _destination, bytes32 _root, bytes32[] memory _proof ) private { // Determine payment required. if (communitySpend > msg.value) { revert InsufficientPayment(); } // Determine snapshot eligibility. if (!MerkleProofLib.verify( _proof, _root, keccak256(abi.encodePacked(msg.sender)) )) { revert Ineligible(); } // Prevent overallocating to a single caller. if (participation[msg.sender][_root]) { revert OverAllocated(); } // Prevent overselling this round. if ( communityFill[_root] == 0 || totalSold + config.communityAllo > uint256(config.available) * 1e18 ) { revert SoldOut(); } // Update state. totalSold += config.communityAllo; communityFill[_root] = communityFill[_root] - 1; participation[msg.sender][_root] = true; // Credit the `_destination` the purchased tokens. receiptBalance[_destination] = receiptBalance[_destination] + config.communityAllo; emit Credit(_destination, config.communityAllo); // Prevent infiltration by losers. for (uint256 i = 0; i < config.losers.length; i++) { if (IBalanceOf(config.losers[i]).balanceOf(msg.sender) > 0) { revert Loser(); } } // Refund the caller any excess payment. if (msg.value > communitySpend) { uint256 excess = msg.value - communitySpend; _transferEther(msg.sender, excess); } } /** The Sale has a special, limited portion set aside at the lowest rate for any Remilia holder to purchase based on a snapshot. The quanitity available for each wallet to purchase is limited. @param _destination An address to receive the purchased tokens. @param _proof A hash tree proof of snapshot eligibility. */ function buyCommunityAny ( address _destination, bytes32[] memory _proof ) external payable nonReentrant notPaused { _processCommunityBuy( _destination, config.anyRoot, _proof ); } /** The Sale has a special, limited portion set aside at the lowest rate for Milady holders to purchase based on a snapshot. The quanitity available for each wallet to purchase is limited. @param _destination An address to receive the purchased tokens. @param _proof A hash tree proof of snapshot eligibility. */ function buyCommunityMilady ( address _destination, bytes32[] memory _proof ) external payable nonReentrant notPaused { _processCommunityBuy( _destination, config.miladyRoot, _proof ); } /** The Sale has a special, limited portion set aside at the lowest rate for Remilio holders to purchase based on a snapshot. The quanitity available for each wallet to purchase is limited. @param _destination An address to receive the purchased tokens. @param _proof A hash tree proof of snapshot eligibility. */ function buyCommunityRemilio ( address _destination, bytes32[] memory _proof ) external payable nonReentrant notPaused { _processCommunityBuy( _destination, config.remilioRoot, _proof ); } /** Returns the current prices of the esteemed Remilia token. The price of the token depends on the elapsed progress of the sale. @return _ The current prices paid by different classes of buyers, refer to the `CurrentPrices` struct. */ function currentPrices () public view returns (CurrentPrices memory) { uint256 currentBalance = (uint256(config.available) * 1e18) - totalSold; uint256 range = uint256(config.endPrice - config.basePrice) * 1e9; uint256 sold = (uint256(config.available) * 1e18) - currentBalance; uint256 progress = sold * 1e30 / (uint256(config.available) * 1e18); uint256 currentPrice = uint256(config.basePrice) * 1e9 + (range * progress) / 1e30; // Progress is stepwise for holders. uint256 stepSize = (uint256(config.available) * 1e18) / config.steps; uint256 currentStep = sold / stepSize; uint256 stepIncrease = range / config.steps; uint256 holderPrice = uint256(config.basePrice) * 1e9 + (currentStep * stepIncrease); return CurrentPrices({ remilia: holderPrice, pleb: currentPrice * (100_00 + config.plebPremium) / 100_00, loser: currentPrice * (100_00 + config.loserPremium) / 100_00 }); } /** Allow the caller to purchase some of the esteemed Remilia token as an esteemed Remilia holder. @param _amount The amount of token the caller is trying to buy. @param _destination An address to receive the purchased tokens. @param _proof A hash tree proof of snapshot eligibility. */ function buyHolder ( uint256 _amount, address _destination, bytes32[] memory _proof ) external payable nonReentrant notPaused { uint256 currentPrice = currentPrices().remilia; // Determine payment required. uint256 spent = currentPrice * _amount / 1e18; uint256 value = msg.value; if (spent > value) { revert InsufficientPayment(); } // Determine snapshot eligibility. if (!MerkleProofLib.verify( _proof, config.anyRoot, keccak256(abi.encodePacked(msg.sender)) ) && IBalanceOf(config.milady).balanceOf(msg.sender) == 0 && IBalanceOf(config.remilio).balanceOf(msg.sender) == 0) { revert Ineligible(); } // Prevent infiltration by losers. for (uint256 i = 0; i < config.losers.length; i++) { if (IBalanceOf(config.losers[i]).balanceOf(msg.sender) > 0) { revert Loser(); } } // Prevent overpurchasing in one call. if (value > uint256(config.maxSpend) * 1e18) { revert OverMax(); } // Prevent overselling this round. if (totalSold + _amount > uint256(config.available) * 1e18) { revert SoldOut(); } // Credit the `_destination` the purchased tokens. totalSold += _amount; receiptBalance[_destination] = receiptBalance[_destination] + _amount; emit Credit(_destination, _amount); // Refund the caller any excess payment. if (value > spent) { uint256 excess = value - spent; _transferEther(msg.sender, excess); } } /** Allow the caller to purchase some of the esteemed Remilia token. @param _amount The amount of token the caller is trying to buy. @param _destination An address to receive the purchased tokens. */ function buyPleb ( uint256 _amount, address _destination ) external payable nonReentrant notPaused { uint256 currentPrice = currentPrices().pleb; // Determine payment required. uint256 spent = currentPrice * _amount / 1e18; uint256 value = msg.value; if (spent > value) { revert InsufficientPayment(); } // Prevent infiltration by losers. for (uint256 i = 0; i < config.losers.length; i++) { if (IBalanceOf(config.losers[i]).balanceOf(msg.sender) > 0) { revert Loser(); } } // Prevent overpurchasing in one call. if (value > uint256(config.maxSpend) * 1e18) { revert OverMax(); } // Prevent overselling this round. if (totalSold + _amount > uint256(config.available) * 1e18) { revert SoldOut(); } // Credit the `_destination` the purchased tokens. totalSold += _amount; receiptBalance[_destination] = receiptBalance[_destination] + _amount; emit Credit(_destination, _amount); // Refund the caller any excess payment. if (value > spent) { uint256 excess = value - spent; _transferEther(msg.sender, excess); } } /** Allow the caller to purchase some of the esteemed Remilia token. Even if they are a loser. @param _amount The amount of token the caller is trying to buy. @param _destination An address to receive the purchased tokens. */ function buyLoser ( uint256 _amount, address _destination ) external payable nonReentrant notPaused { uint256 currentPrice = currentPrices().loser; // Determine payment required. uint256 spent = currentPrice * _amount / 1e18; uint256 value = msg.value; if (spent > value) { revert InsufficientPayment(); } // Prevent overpurchasing in one call. if (value > uint256(config.maxSpend) * 1e18) { revert OverMax(); } // Prevent overselling this round. if (totalSold + _amount > uint256(config.available) * 1e18) { revert SoldOut(); } // Credit the `_destination` the purchased tokens. totalSold += _amount; receiptBalance[_destination] = receiptBalance[_destination] + _amount; emit Credit(_destination, _amount); // Refund the caller any excess payment. if (value > spent) { uint256 excess = value - spent; _transferEther(msg.sender, excess); } } /** Allow the owner to reconfigure this instance of the sale contract. @param _config A `Configuration` to prepare this sale. */ function reconfigure ( Configuration memory _config ) external payable onlyOwner { config = _config; communitySpend = _config.communityPrice * _config.communityAllo / 1e9; communityFill[_config.anyRoot] = _config.anyFill; communityFill[_config.miladyRoot] = _config.miladyFill; communityFill[_config.remilioRoot] = _config.remilioFill; } /** Allow the owner to transfer Ether out of this contract. @param _to The address to transfer Ether to. @param _amount The amount of Ether to transfer. */ function transferEther ( address _to, uint256 _amount ) external payable onlyOwner { _transferEther(_to, _amount); } /** Allow the owner of the Sale to transfer ERC-20 tokens out of this contract. This is only needed in case we need to save someone very very stupid. @param _token The address of the ERC-20 token to transfer. @param _to The address to transfer the ERC-20 `_token` to. @param _amount The amount of `_token` to transfer. */ function transferToken ( address _token, address _to, uint256 _amount ) external payable onlyOwner { SafeTransferLib.safeTransfer(_token, _to, _amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// /// @dev Note: /// This implementation does NOT auto-initialize the owner to `msg.sender`. /// You MUST call the `_initializeOwner` in the constructor / initializer. /// /// While the ownable portion follows /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, /// the nomenclature for the 2-step ownership handover may be unique to this codebase. abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /// @dev The `pendingOwner` does not have a valid handover request. error NoHandoverRequest(); /// @dev Cannot double-initialize. error AlreadyInitialized(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev An ownership handover to `pendingOwner` has been requested. event OwnershipHandoverRequested(address indexed pendingOwner); /// @dev The ownership handover to `pendingOwner` has been canceled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE = 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d; /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE = 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. /// It is intentionally chosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. bytes32 internal constant _OWNER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927; /// The ownership handover slot of `newOwner` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED)) /// let handoverSlot := keccak256(0x00, 0x20) /// ``` /// It stores the expiry timestamp of the two-step ownership handover. uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override to return true to make `_initializeOwner` prevent double-initialization. function _guardInitializeOwner() internal pure virtual returns (bool guard) {} /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT if sload(ownerSlot) { mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } else { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(_OWNER_SLOT, newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) } } else { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } } /// @dev Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(_OWNER_SLOT))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. /// Override to return a different value if needed. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ownershipHandoverValidFor() internal view virtual returns (uint64) { return 48 * 3600; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`. revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(0)); } /// @dev Request a two-step ownership handover to the caller. /// The request will automatically expire in 48 hours (172800 seconds) by default. function requestOwnershipHandover() public payable virtual { unchecked { uint256 expires = block.timestamp + _ownershipHandoverValidFor(); /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to `expires`. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), expires) // Emit the {OwnershipHandoverRequested} event. log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller()) } } } /// @dev Cancels the two-step ownership handover to the caller, if any. function cancelOwnershipHandover() public payable virtual { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), 0) // Emit the {OwnershipHandoverCanceled} event. log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller()) } } /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`. /// Reverts if there is no existing ownership handover requested by `pendingOwner`. function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) let handoverSlot := keccak256(0x0c, 0x20) // If the handover does not exist, or has expired. if gt(timestamp(), sload(handoverSlot)) { mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`. revert(0x1c, 0x04) } // Set the handover slot to 0. sstore(handoverSlot, 0) } _setOwner(pendingOwner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { result := sload(_OWNER_SLOT) } } /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. function ownershipHandoverExpiresAt(address pendingOwner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the handover slot. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) // Load the handover slot. result := sload(keccak256(0x0c, 0x20)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol) library MerkleProofLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MERKLE PROOF VERIFICATION OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if mload(proof) { // Initialize `offset` to the offset of `proof` elements in memory. let offset := add(proof, 0x20) // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(offset, shl(5, mload(proof))) // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, mload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), mload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if proof.length { // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(proof.offset, shl(5, proof.length)) // Initialize `offset` to the offset of `proof` in the calldata. let offset := proof.offset // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, calldataload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), calldataload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`, /// given `proof` and `flags`. /// /// Note: /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length` /// will always return false. /// - The sum of the lengths of `proof` and `leaves` must never overflow. /// - Any non-zero word in the `flags` array is treated as true. /// - The memory offset of `proof` must be non-zero /// (i.e. `proof` is not pointing to the scratch space). function verifyMultiProof( bytes32[] memory proof, bytes32 root, bytes32[] memory leaves, bool[] memory flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leaves` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). /// @solidity memory-safe-assembly assembly { // Cache the lengths of the arrays. let leavesLength := mload(leaves) let proofLength := mload(proof) let flagsLength := mload(flags) // Advance the pointers of the arrays to point to the data. leaves := add(0x20, leaves) proof := add(0x20, proof) flags := add(0x20, flags) // If the number of flags is correct. for {} eq(add(leavesLength, proofLength), add(flagsLength, 1)) {} { // For the case where `proof.length + leaves.length == 1`. if iszero(flagsLength) { // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`. isValid := eq(mload(xor(leaves, mul(xor(proof, leaves), proofLength))), root) break } // The required final proof offset if `flagsLength` is not zero, otherwise zero. let proofEnd := add(proof, shl(5, proofLength)) // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) // Copy the leaves into the hashes. // Sometimes, a little memory expansion costs less than branching. // Should cost less, even with a high free memory offset of 0x7d00. leavesLength := shl(5, leavesLength) for { let i := 0 } iszero(eq(i, leavesLength)) { i := add(i, 0x20) } { mstore(add(hashesFront, i), mload(add(leaves, i))) } // Compute the back of the hashes. let hashesBack := add(hashesFront, leavesLength) // This is the end of the memory for the queue. // We recycle `flagsLength` to save on stack variables (sometimes save gas). flagsLength := add(hashesBack, shl(5, flagsLength)) for {} 1 {} { // Pop from `hashes`. let a := mload(hashesFront) // Pop from `hashes`. let b := mload(add(hashesFront, 0x20)) hashesFront := add(hashesFront, 0x40) // If the flag is false, load the next proof, // else, pops from the queue. if iszero(mload(flags)) { // Loads the next proof. b := mload(proof) proof := add(proof, 0x20) // Unpop from `hashes`. hashesFront := sub(hashesFront, 0x20) } // Advance to the next flag. flags := add(flags, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) if iszero(lt(hashesBack, flagsLength)) { break } } isValid := and( // Checks if the last value in the queue is same as the root. eq(mload(sub(hashesBack, 0x20)), root), // And whether all the proofs are used, if required. eq(proofEnd, proof) ) break } } } /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`, /// given `proof` and `flags`. /// /// Note: /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length` /// will always return false. /// - Any non-zero word in the `flags` array is treated as true. /// - The calldata offset of `proof` must be non-zero /// (i.e. `proof` is from a regular Solidity function with a 4-byte selector). function verifyMultiProofCalldata( bytes32[] calldata proof, bytes32 root, bytes32[] calldata leaves, bool[] calldata flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leaves` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). /// @solidity memory-safe-assembly assembly { // If the number of flags is correct. for {} eq(add(leaves.length, proof.length), add(flags.length, 1)) {} { // For the case where `proof.length + leaves.length == 1`. if iszero(flags.length) { // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`. // forgefmt: disable-next-item isValid := eq( calldataload( xor(leaves.offset, mul(xor(proof.offset, leaves.offset), proof.length)) ), root ) break } // The required final proof offset if `flagsLength` is not zero, otherwise zero. let proofEnd := add(proof.offset, shl(5, proof.length)) // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) // Copy the leaves into the hashes. // Sometimes, a little memory expansion costs less than branching. // Should cost less, even with a high free memory offset of 0x7d00. calldatacopy(hashesFront, leaves.offset, shl(5, leaves.length)) // Compute the back of the hashes. let hashesBack := add(hashesFront, shl(5, leaves.length)) // This is the end of the memory for the queue. // We recycle `flagsLength` to save on stack variables (sometimes save gas). flags.length := add(hashesBack, shl(5, flags.length)) // We don't need to make a copy of `proof.offset` or `flags.offset`, // as they are pass-by-value (this trick may not always save gas). for {} 1 {} { // Pop from `hashes`. let a := mload(hashesFront) // Pop from `hashes`. let b := mload(add(hashesFront, 0x20)) hashesFront := add(hashesFront, 0x40) // If the flag is false, load the next proof, // else, pops from the queue. if iszero(calldataload(flags.offset)) { // Loads the next proof. b := calldataload(proof.offset) proof.offset := add(proof.offset, 0x20) // Unpop from `hashes`. hashesFront := sub(hashesFront, 0x20) } // Advance to the next flag offset. flags.offset := add(flags.offset, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) if iszero(lt(hashesBack, flags.length)) { break } } isValid := and( // Checks if the last value in the queue is same as the root. eq(mload(sub(hashesBack, 0x20)), root), // And whether all the proofs are used, if required. eq(proofEnd, proof.offset) ) break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes32 array. function emptyProof() internal pure returns (bytes32[] calldata proof) { /// @solidity memory-safe-assembly assembly { proof.length := 0 } } /// @dev Returns an empty calldata bytes32 array. function emptyLeaves() internal pure returns (bytes32[] calldata leaves) { /// @solidity memory-safe-assembly assembly { leaves.length := 0 } } /// @dev Returns an empty calldata bool array. function emptyFlags() internal pure returns (bool[] calldata flags) { /// @solidity memory-safe-assembly assembly { flags.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @author Permit2 operations from (https://github.com/Uniswap/permit2/blob/main/src/libraries/Permit2Lib.sol) /// /// @dev Note: /// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection. /// - For ERC20s, this implementation won't check that a token has code, /// responsibility is delegated to the caller. library SafeTransferLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ETH transfer has failed. error ETHTransferFailed(); /// @dev The ERC20 `transferFrom` has failed. error TransferFromFailed(); /// @dev The ERC20 `transfer` has failed. error TransferFailed(); /// @dev The ERC20 `approve` has failed. error ApproveFailed(); /// @dev The Permit2 operation has failed. error Permit2Failed(); /// @dev The Permit2 amount must be less than `2**160 - 1`. error Permit2AmountOverflow(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes. uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300; /// @dev Suggested gas stipend for contract receiving ETH to perform a few /// storage reads and writes, but low enough to prevent griefing. uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000; /// @dev The unique EIP-712 domain domain separator for the DAI token contract. bytes32 internal constant DAI_DOMAIN_SEPARATOR = 0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7; /// @dev The address for the WETH9 contract on Ethereum mainnet. address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; /// @dev The canonical Permit2 address. /// [Github](https://github.com/Uniswap/permit2) /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants. // // The regular variants: // - Forwards all remaining gas to the target. // - Reverts if the target reverts. // - Reverts if the current contract has insufficient balance. // // The force variants: // - Forwards with an optional gas stipend // (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases). // - If the target reverts, or if the gas stipend is exhausted, // creates a temporary contract to force send the ETH via `SELFDESTRUCT`. // Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758. // - Reverts if the current contract has insufficient balance. // // The try variants: // - Forwards with a mandatory gas stipend. // - Instead of reverting, returns whether the transfer succeeded. /// @dev Sends `amount` (in wei) ETH to `to`. function safeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Sends all the ETH in the current contract to `to`. function safeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // Transfer all the ETH and check if it succeeded or not. if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { if lt(selfbalance(), amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`. function forceSafeTransferAllETH(address to, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`. function forceSafeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if lt(selfbalance(), amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`. function forceSafeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // forgefmt: disable-next-item if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00) } } /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`. function trySafeTransferAllETH(address to, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferFrom(address token, address from, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, amount) // Store the `amount` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// /// The `from` account must have at least `amount` approved for the current contract to manage. function trySafeTransferFrom(address token, address from, address to, uint256 amount) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, amount) // Store the `amount` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`. success := and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends all of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have their entire balance approved for the current contract to manage. function safeTransferAllFrom(address token, address from, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`. // Read the balance, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`. amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransfer(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sends all of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransferAll(address token, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, address()) // Store the address of the current contract. // Read the balance, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x14, to) // Store the `to` argument. amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// Reverts upon failure. function safeApprove(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// If the initial attempt to approve fails, attempts to reset the approved amount to zero, /// then retries the approval again (some tokens, e.g. USDT, requires this). /// Reverts upon failure. function safeApproveWithRetry(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, retrying upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x34, 0) // Store 0 for the `amount`. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval. mstore(0x34, amount) // Store back the original `amount`. // Retry the approval, reverting upon failure. if iszero( and( or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Returns the amount of ERC20 `token` owned by `account`. /// Returns zero if the `token` does not exist. function balanceOf(address token, address account) internal view returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x14, account) // Store the `account` argument. mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`. amount := mul( // The arguments of `mul` are evaluated from right to left. mload(0x20), and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20) ) ) } } /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// If the initial attempt fails, try to use Permit2 to transfer the token. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for the current contract to manage. function safeTransferFrom2(address token, address from, address to, uint256 amount) internal { if (!trySafeTransferFrom(token, from, to, amount)) { permit2TransferFrom(token, from, to, amount); } } /// @dev Sends `amount` of ERC20 `token` from `from` to `to` via Permit2. /// Reverts upon failure. function permit2TransferFrom(address token, address from, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) mstore(add(m, 0x74), shr(96, shl(96, token))) mstore(add(m, 0x54), amount) mstore(add(m, 0x34), to) mstore(add(m, 0x20), shl(96, from)) // `transferFrom(address,address,uint160,address)`. mstore(m, 0x36c78516000000000000000000000000) let p := PERMIT2 let exists := eq(chainid(), 1) if iszero(exists) { exists := iszero(iszero(extcodesize(p))) } if iszero(and(call(gas(), p, 0, add(m, 0x10), 0x84, codesize(), 0x00), exists)) { mstore(0x00, 0x7939f4248757f0fd) // `TransferFromFailed()` or `Permit2AmountOverflow()`. revert(add(0x18, shl(2, iszero(iszero(shr(160, amount))))), 0x04) } } } /// @dev Permit a user to spend a given amount of /// another user's tokens via native EIP-2612 permit if possible, falling /// back to Permit2 if native permit fails or is not implemented on the token. function permit2( address token, address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { bool success; /// @solidity memory-safe-assembly assembly { for {} shl(96, xor(token, WETH9)) {} { mstore(0x00, 0x3644e515) // `DOMAIN_SEPARATOR()`. if iszero( and( // The arguments of `and` are evaluated from right to left. lt(iszero(mload(0x00)), eq(returndatasize(), 0x20)), // Returns 1 non-zero word. // Gas stipend to limit gas burn for tokens that don't refund gas when // an non-existing function is called. 5K should be enough for a SLOAD. staticcall(5000, token, 0x1c, 0x04, 0x00, 0x20) ) ) { break } // After here, we can be sure that token is a contract. let m := mload(0x40) mstore(add(m, 0x34), spender) mstore(add(m, 0x20), shl(96, owner)) mstore(add(m, 0x74), deadline) if eq(mload(0x00), DAI_DOMAIN_SEPARATOR) { mstore(0x14, owner) mstore(0x00, 0x7ecebe00000000000000000000000000) // `nonces(address)`. mstore(add(m, 0x94), staticcall(gas(), token, 0x10, 0x24, add(m, 0x54), 0x20)) mstore(m, 0x8fcbaf0c000000000000000000000000) // `IDAIPermit.permit`. // `nonces` is already at `add(m, 0x54)`. // `1` is already stored at `add(m, 0x94)`. mstore(add(m, 0xb4), and(0xff, v)) mstore(add(m, 0xd4), r) mstore(add(m, 0xf4), s) success := call(gas(), token, 0, add(m, 0x10), 0x104, codesize(), 0x00) break } mstore(m, 0xd505accf000000000000000000000000) // `IERC20Permit.permit`. mstore(add(m, 0x54), amount) mstore(add(m, 0x94), and(0xff, v)) mstore(add(m, 0xb4), r) mstore(add(m, 0xd4), s) success := call(gas(), token, 0, add(m, 0x10), 0xe4, codesize(), 0x00) break } } if (!success) simplePermit2(token, owner, spender, amount, deadline, v, r, s); } /// @dev Simple permit on the Permit2 contract. function simplePermit2( address token, address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) mstore(m, 0x927da105) // `allowance(address,address,address)`. { let addressMask := shr(96, not(0)) mstore(add(m, 0x20), and(addressMask, owner)) mstore(add(m, 0x40), and(addressMask, token)) mstore(add(m, 0x60), and(addressMask, spender)) mstore(add(m, 0xc0), and(addressMask, spender)) } let p := mul(PERMIT2, iszero(shr(160, amount))) if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x5f), // Returns 3 words: `amount`, `expiration`, `nonce`. staticcall(gas(), p, add(m, 0x1c), 0x64, add(m, 0x60), 0x60) ) ) { mstore(0x00, 0x6b836e6b8757f0fd) // `Permit2Failed()` or `Permit2AmountOverflow()`. revert(add(0x18, shl(2, iszero(p))), 0x04) } mstore(m, 0x2b67b570) // `Permit2.permit` (PermitSingle variant). // `owner` is already `add(m, 0x20)`. // `token` is already at `add(m, 0x40)`. mstore(add(m, 0x60), amount) mstore(add(m, 0x80), 0xffffffffffff) // `expiration = type(uint48).max`. // `nonce` is already at `add(m, 0xa0)`. // `spender` is already at `add(m, 0xc0)`. mstore(add(m, 0xe0), deadline) mstore(add(m, 0x100), 0x100) // `signature` offset. mstore(add(m, 0x120), 0x41) // `signature` length. mstore(add(m, 0x140), r) mstore(add(m, 0x160), s) mstore(add(m, 0x180), shl(248, v)) if iszero(call(gas(), p, 0, add(m, 0x1c), 0x184, codesize(), 0x00)) { mstore(0x00, 0x6b836e6b) // `Permit2Failed()`. revert(0x1c, 0x04) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /// @notice Reentrancy guard mixin. /// @author Soledge (https://github.com/vectorized/soledge/blob/main/src/utils/ReentrancyGuard.sol) /// /// Note: This implementation utilizes the `TSTORE` and `TLOAD` opcodes. /// Please ensure that the chain you are deploying on supports them. abstract contract ReentrancyGuard { /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/ /* CUSTOM ERRORS */ /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/ /// @dev Unauthorized reentrant call. error Reentrancy(); /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/ /* STORAGE */ /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/ /// @dev Equivalent to: `uint72(bytes9(keccak256("_REENTRANCY_GUARD_SLOT")))`. /// 9 bytes is large enough to avoid collisions in practice, /// but not too large to result in excessive bytecode bloat. uint256 private constant _REENTRANCY_GUARD_SLOT = 0x929eee149b4bd21268; /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/ /* REENTRANCY GUARD */ /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/ /// @dev Guards a function from reentrancy. modifier nonReentrant() virtual { /// @solidity memory-safe-assembly assembly { if tload(_REENTRANCY_GUARD_SLOT) { mstore(0x00, 0xab143c06) // `Reentrancy()`. revert(0x1c, 0x04) } tstore(_REENTRANCY_GUARD_SLOT, address()) } _; /// @solidity memory-safe-assembly assembly { tstore(_REENTRANCY_GUARD_SLOT, 0) } } /// @dev Guards a view function from read-only reentrancy. modifier nonReadReentrant() virtual { /// @solidity memory-safe-assembly assembly { if tload(_REENTRANCY_GUARD_SLOT) { mstore(0x00, 0xab143c06) // `Reentrancy()`. revert(0x1c, 0x04) } } _; } }
{ "remappings": [ "forge-std/=lib/forge-std/src/", "solady/=lib/solady/src/", "soledge/=lib/soledge/src/" ], "optimizer": { "enabled": true, "runs": 1000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"steps","type":"uint8"},{"internalType":"uint8","name":"maxSpend","type":"uint8"},{"internalType":"uint16","name":"anyFill","type":"uint16"},{"internalType":"uint16","name":"miladyFill","type":"uint16"},{"internalType":"uint16","name":"remilioFill","type":"uint16"},{"internalType":"uint16","name":"plebPremium","type":"uint16"},{"internalType":"uint16","name":"loserPremium","type":"uint16"},{"internalType":"uint32","name":"basePrice","type":"uint32"},{"internalType":"uint32","name":"endPrice","type":"uint32"},{"internalType":"uint32","name":"available","type":"uint32"},{"internalType":"address","name":"milady","type":"address"},{"internalType":"uint32","name":"communityPrice","type":"uint32"},{"internalType":"address","name":"remilio","type":"address"},{"internalType":"uint96","name":"communityAllo","type":"uint96"},{"internalType":"bytes32","name":"anyRoot","type":"bytes32"},{"internalType":"bytes32","name":"miladyRoot","type":"bytes32"},{"internalType":"bytes32","name":"remilioRoot","type":"bytes32"},{"internalType":"address[]","name":"losers","type":"address[]"}],"internalType":"struct Sale.Configuration","name":"_config","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"Ineligible","type":"error"},{"inputs":[],"name":"InsufficientPayment","type":"error"},{"inputs":[],"name":"Loser","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"OverAllocated","type":"error"},{"inputs":[],"name":"OverMax","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"SoldOut","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Credit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"address","name":"_holder","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_destination","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"buyCommunityAny","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_destination","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"buyCommunityMilady","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_destination","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"buyCommunityRemilio","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_destination","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"buyHolder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_destination","type":"address"}],"name":"buyLoser","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_destination","type":"address"}],"name":"buyPleb","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"communityFill","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"config","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"steps","type":"uint8"},{"internalType":"uint8","name":"maxSpend","type":"uint8"},{"internalType":"uint16","name":"anyFill","type":"uint16"},{"internalType":"uint16","name":"miladyFill","type":"uint16"},{"internalType":"uint16","name":"remilioFill","type":"uint16"},{"internalType":"uint16","name":"plebPremium","type":"uint16"},{"internalType":"uint16","name":"loserPremium","type":"uint16"},{"internalType":"uint32","name":"basePrice","type":"uint32"},{"internalType":"uint32","name":"endPrice","type":"uint32"},{"internalType":"uint32","name":"available","type":"uint32"},{"internalType":"address","name":"milady","type":"address"},{"internalType":"uint32","name":"communityPrice","type":"uint32"},{"internalType":"address","name":"remilio","type":"address"},{"internalType":"uint96","name":"communityAllo","type":"uint96"},{"internalType":"bytes32","name":"anyRoot","type":"bytes32"},{"internalType":"bytes32","name":"miladyRoot","type":"bytes32"},{"internalType":"bytes32","name":"remilioRoot","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPrices","outputs":[{"components":[{"internalType":"uint256","name":"remilia","type":"uint256"},{"internalType":"uint256","name":"pleb","type":"uint256"},{"internalType":"uint256","name":"loser","type":"uint256"}],"internalType":"struct Sale.CurrentPrices","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"participation","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"receiptBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"steps","type":"uint8"},{"internalType":"uint8","name":"maxSpend","type":"uint8"},{"internalType":"uint16","name":"anyFill","type":"uint16"},{"internalType":"uint16","name":"miladyFill","type":"uint16"},{"internalType":"uint16","name":"remilioFill","type":"uint16"},{"internalType":"uint16","name":"plebPremium","type":"uint16"},{"internalType":"uint16","name":"loserPremium","type":"uint16"},{"internalType":"uint32","name":"basePrice","type":"uint32"},{"internalType":"uint32","name":"endPrice","type":"uint32"},{"internalType":"uint32","name":"available","type":"uint32"},{"internalType":"address","name":"milady","type":"address"},{"internalType":"uint32","name":"communityPrice","type":"uint32"},{"internalType":"address","name":"remilio","type":"address"},{"internalType":"uint96","name":"communityAllo","type":"uint96"},{"internalType":"bytes32","name":"anyRoot","type":"bytes32"},{"internalType":"bytes32","name":"miladyRoot","type":"bytes32"},{"internalType":"bytes32","name":"remilioRoot","type":"bytes32"},{"internalType":"address[]","name":"losers","type":"address[]"}],"internalType":"struct Sale.Configuration","name":"_config","type":"tuple"}],"name":"reconfigure","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"_status","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferEther","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferToken","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
608060405234610597576120c1803803908161001a8161059b565b9182396020818381010312610597578051906001600160401b038211610597576102608282018483010312610597576040519261026084016001600160401b03811185821017610568576040526100728383016105c0565b84526100826020848401016105d4565b60208501526100956040848401016105d4565b60408501526100a86060848401016105e2565b60608501526100bb6080848401016105e2565b60808501526100ce60a0848401016105e2565b60a08501526100e160c0848401016105e2565b60c08501526100f460e0848401016105e2565b60e0850152610108610100848401016105f1565b61010085015261011d610120848401016105f1565b610120850152610132610140848401016105f1565b610140850152610147610160848401016105c0565b61016085015261015c610180848401016105f1565b6101808501526101716101a0848401016105c0565b6101a08501528183016101c001516001600160601b0381168103610597576101c08501528183016101e08181015190860152610200808201519086015261022080820151908601526102400151926001600160401b03841161059757818301601f858386010101121561059757828101840151936001600160401b038511610568578460051b90602061020581840161059b565b8097815201938501602083838689010101011161059757848301810160200193925b60208383838901010101851061057c576102408801878152600d805460ff1916600117905588516001600160a01b0316638b78c6d8198190558991905f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a38151602080840151604080860151606080880151608089015160a08a81015160c0808d015160e0808f01519a90941b60ff60a01b166001600160a01b039c909c169b909b1760a89790971b60ff60a81b169690961760b09490941b61ffff60b01b16939093179190941b61ffff60c01b161760d09190911b61ffff60d01b16179590911b61ffff60e01b169490941760f09290921b6001600160f01b031916919091175f5561010085015161012086015161014087015161016088015191851b67ffffffff000000001663ffffffff93841617931b6bffffffff000000000000000016929092179190931b6001600160601b031990811691909117600155610180850151600280546101a08801516001600160c01b03199190911692909516919091179390921b600160201b600160c01b03169290921790556101c0830151600380549092166001600160601b03919091161790556101e0820151600455610200820151600555610220820151600655518051906001600160401b038211610568576801000000000000000082116105685760075482600755808310610524575b5060200160075f5260205f205f5b838110610507576101808501516101c0860151869163ffffffff166001600160601b03918216029081169081036104f357633b9aca0090046001600160601b031660085560608101516101e08201515f908152600b6020526040808220805461ffff1990811661ffff95861617909155608085015161020086015184528284208054831691861691909117905560a0850151610220909501518352918190208054909216939092169290921790915551611abe90816106038239f35b634e487b7160e01b5f52601160045260245ffd5b82516001600160a01b031681830155602090920191600101610437565b60075f527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889081019083015b81811061055d5750610429565b5f8155600101610550565b634e487b7160e01b5f52604160045260245ffd5b602080809561058a886105c0565b8152019501949350610227565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761056857604052565b51906001600160a01b038216820361059757565b519060ff8216820361059757565b519061ffff8216820361059757565b519063ffffffff821682036105975756fe60806040526004361015610011575f80fd5b5f3560e01c806305b1137b146113535780630c26fbcb1461132557806316c38b3c146112ed57806325692962146112a4578063259bfdd71461126e57806331abae3d14610f0357806335c7d1d314610fdb57806343d5b5c414610fa157806354d1f13d14610f5d5780635c975abb14610f3b57806370a0823114610f03578063715018a614610eba57806379502c5514610db65780637c05399f14610d1c5780638c1ee1e914610ce25780638da5cb5b14610cb85780639106d7ba14610c9b578063b281281c146109fb578063cb42f3571461097e578063db9341e61461029f578063f04e283e14610252578063f2fde38b14610215578063f5537ede146101ab578063f7a924db146101625763fee81cf41461012c575f80fd5b3461015e57602036600319011261015e5761014561137b565b63389a75e1600c525f52602080600c2054604051908152f35b5f80fd5b3461015e57604036600319011261015e576001600160a01b0361018361137b565b165f52600c60205260405f206024355f52602052602060ff60405f2054166040519015158152f35b606036600319011261015e5760205f60446010826101c761137b565b6101cf611391565b6101d7611706565b60145283356034526fa9059cbb00000000000000000000000082525af13d1560015f5114171615610208575f603452005b6390b8ec185f526004601cfd5b602036600319011261015e5761022961137b565b610231611706565b8060601b156102455761024390611a4a565b005b637448fbae5f526004601cfd5b602036600319011261015e5761026661137b565b61026e611706565b63389a75e1600c52805f526020600c209081544211610292575f6102439255611a4a565b636f5e88185f526004601cfd5b602036600319011261015e5767ffffffffffffffff6004351161015e576102606004353603600319011261015e57604051610260810181811067ffffffffffffffff82111761094a576040526102f96004356004016113a7565b81526103096024600435016114b1565b602082015261031c6044600435016114b1565b604082015261032f6064600435016114bf565b60608201526103426084600435016114bf565b608082015261035560a4600435016114bf565b60a082015261036860c4600435016114bf565b60c082015261037b60e4600435016114bf565b60e082015261038f610104600435016114ce565b6101008201526103a4610124600435016114ce565b6101208201526103b9610144600435016114ce565b6101408201526103ce610164600435016113a7565b6101608201526103e3610184600435016114ce565b6101808201526103f86101a4600435016113a7565b6101a08201526101c460043501356bffffffffffffffffffffffff8116810361015e576101c08201526004356101e48101356101e0830152610204810135610200830152610224810135610220830152610244013567ffffffffffffffff811161015e57366023826004350101121561015e57600481813501013561047c816113f9565b9161048a60405193846113d7565b81835260208301903660246004358301600586901b01011161015e576024816004350101915b60246004358301600586901b0101831061095e57858561024082019081526104d6611706565b81516001600160a01b03165f5490602084015160a01b74ff000000000000000000000000000000000000000016604085015160a81b75ff00000000000000000000000000000000000000000016606086015160b01b77ffff0000000000000000000000000000000000000000000016608087015160c01b79ffff000000000000000000000000000000000000000000000000169160a088015160d01b7bffff0000000000000000000000000000000000000000000000000000169360c089015160e01b7dffff00000000000000000000000000000000000000000000000000000000169560e08a015160f01b7fffff00000000000000000000000000000000000000000000000000000000000016977fffffffffffffffffffff0000000000000000000000000000000000000000000016177fffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffff16177fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff16177fffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffff16177fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff16177dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff161717175f5561010082015163ffffffff1663ffffffff19600154161760015561012082015160015461014084015160401b6bffffffff000000000000000016906bffffffffffffffffffffffff1961016086015160601b169260201b67ffffffff00000000169063ffffffff1617171760015561018082015163ffffffff1663ffffffff1960025416176002556101a08201516002549060201b77ffffffffffffffffffffffffffffffffffffffff0000000016907fffffffffffffffff0000000000000000000000000000000000000000ffffffff16176002556101c08201516bffffffffffffffffffffffff166bffffffffffffffffffffffff1960035416176003556101e08201516004556102008201516005556102208201516006555180519067ffffffffffffffff821161094a5768010000000000000000821161094a5760075482600755808310610906575b5060200160075f5260205f205f5b8381106108e9578463ffffffff610180820151166bffffffffffffffffffffffff6101c083015116026bffffffffffffffffffffffff81169081036108d557633b9aca0090046bffffffffffffffffffffffff1660085560608101516101e08201515f908152600b6020526040808220805461ffff1990811661ffff95861617909155608085015161020086015184528284208054831691861691909117905560a08501516102209095015183529120805490911692909116919091179055005b634e487b7160e01b5f52601160045260245ffd5b60019060206001600160a01b038551169401938184015501610814565b60075f527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889081019083015b81811061093f5750610806565b5f8155600101610932565b634e487b7160e01b5f52604160045260245ffd5b602091828060049361096f876113a7565b815201940193915091506104b0565b6109873661146e565b68929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c6576004546109b8926117c5565b5f68929eee149b4bd212685d005b7f9e87fac8000000000000000000000000000000000000000000000000000000005f5260045ffd5b63ab143c065f526004601cfd5b604036600319011261015e57600435610a12611391565b9068929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c657670de0b6b3a7640000610a56826020610a4f61153e565b01516114df565b0491348311610c73576007545f5b818110610bbe57505060ff5f5460a81c16670de0b6b3a7640000810290808204670de0b6b3a764000014901517156108d5573411610b965760095490610aaa838361151d565b63ffffffff60015460401c1690670de0b6b3a7640000820291808304670de0b6b3a764000014901517156108d55711610b6e576001600160a01b03602091610b13857f1bbf55d483639f8103dc4e035af71a4fbdb16c80be740fa3eef81198acefa0949561151d565b6009551692835f52600a8252610b2d8160405f205461151d565b845f52600a835260405f2055604051908152a2803411610b55575f68929eee149b4bd212685d005b610b62610b6891346114f2565b33611722565b806109b8565b7f52df9fe5000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f8529eb36000000000000000000000000000000000000000000000000000000005f5260045ffd5b602460206001600160a01b03610bd3846116da565b90549060031b1c16604051928380926370a0823160e01b82523360048301525afa908115610c68575f91610c37575b50610c0f57600101610a64565b7fe95dadd7000000000000000000000000000000000000000000000000000000005f5260045ffd5b90506020813d8211610c60575b81610c51602093836113d7565b8101031261015e575186610c02565b3d9150610c44565b6040513d5f823e3d90fd5b7fcd1c8867000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461015e575f36600319011261015e576020600954604051908152f35b3461015e575f36600319011261015e576020638b78c6d819546001600160a01b0360405191168152f35b610ceb3661146e565b68929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c6576005546109b8926117c5565b604036600319011261015e57600435610d33611391565b9068929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c657670de0b6b3a7640000610d70826040610a4f61153e565b0491348311610c735760ff5f5460a81c16670de0b6b3a7640000810290808204670de0b6b3a764000014901517156108d5573411610b965760095490610aaa838361151d565b3461015e575f36600319011261015e576102405f546001546002546bffffffffffffffffffffffff60035416600454906001600160a01b03600554936006549560405197838116895260ff8160a01c1660208a015260ff8160a81c1660408a015261ffff8160b01c1660608a015261ffff8160c01c1660808a015261ffff8160d01c1660a08a015261ffff8160e01c1660c08a015260f01c60e089015263ffffffff811661010089015263ffffffff8160201c1661012089015263ffffffff8160401c1661014089015260601c61016088015263ffffffff811661018088015260201c166101a08601526101c08501526101e0840152610200830152610220820152f35b5f36600319011261015e57610ecd611706565b5f638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a35f638b78c6d81955005b3461015e57602036600319011261015e576001600160a01b03610f2461137b565b165f52600a602052602060405f2054604051908152f35b3461015e575f36600319011261015e57602060ff600d54166040519015158152f35b5f36600319011261015e5763389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2005b610faa3661146e565b68929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c6576006546109b8926117c5565b606036600319011261015e57600435610ff2611391565b9060443567ffffffffffffffff811161015e57611013903690600401611411565b9168929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c657670de0b6b3a76400006110548361104e61153e565b516114df565b0492348411610c735761108a9060045460405160208101903360601b8252601481526110816034826113d7565b5190209161177a565b1580611203575b80611190575b611168576007545f5b8181106110e657505060ff5f5460a81c16670de0b6b3a7640000810290808204670de0b6b3a764000014901517156108d5573411610b965760095490610aaa838361151d565b602460206001600160a01b036110fb846116da565b90549060031b1c16604051928380926370a0823160e01b82523360048301525afa908115610c68575f91611137575b50610c0f576001016110a0565b90506020813d8211611160575b81611151602093836113d7565b8101031261015e57518661112a565b3d9150611144565b7f3cb97240000000000000000000000000000000000000000000000000000000005f5260045ffd5b50602460206001600160a01b03600254821c16604051928380926370a0823160e01b82523360048301525afa908115610c68575f916111d1575b5015611097565b90506020813d6020116111fb575b816111ec602093836113d7565b8101031261015e5751846111ca565b3d91506111df565b506024602060015460601c604051928380926370a0823160e01b82523360048301525afa908115610c68575f9161123c575b5015611091565b90506020813d602011611266575b81611257602093836113d7565b8101031261015e575184611235565b3d915061124a565b3461015e575f36600319011261015e57606061128861153e565b6040805191805183526020810151602084015201516040820152f35b5f36600319011261015e5763389a75e1600c52335f526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a2005b3461015e57602036600319011261015e5760043580151580910361015e57611313611706565b60ff8019600d5416911617600d555f80f35b3461015e57602036600319011261015e576004355f52600b602052602061ffff60405f205416604051908152f35b604036600319011261015e5761024361136a61137b565b611372611706565b60243590611722565b600435906001600160a01b038216820361015e57565b602435906001600160a01b038216820361015e57565b35906001600160a01b038216820361015e57565b6060810190811067ffffffffffffffff82111761094a57604052565b90601f8019910116810190811067ffffffffffffffff82111761094a57604052565b67ffffffffffffffff811161094a5760051b60200190565b9080601f8301121561015e578135611428816113f9565b9261143660405194856113d7565b81845260208085019260051b82010192831161015e57602001905b82821061145e5750505090565b8135815260209182019101611451565b90604060031983011261015e576004356001600160a01b038116810361015e57916024359067ffffffffffffffff821161015e576114ae91600401611411565b90565b359060ff8216820361015e57565b359061ffff8216820361015e57565b359063ffffffff8216820361015e57565b818102929181159184041417156108d557565b919082039182116108d557565b8115611509570490565b634e487b7160e01b5f52601260045260245ffd5b919082018092116108d557565b61ffff16612710019061ffff82116108d557565b5f6040805161154c816113bb565b828152826020820152015260015463ffffffff8160401c1690670de0b6b3a7640000820291808304670de0b6b3a764000014901517156108d55763ffffffff611597600954846114f2565b9181811691829160201c160363ffffffff81116108d55763ffffffff1691633b9aca00830292808404633b9aca0014901517156108d5576115d890846114f2565b916c0c9f2c9cd04674edea4000000083028381046c0c9f2c9cd04674edea4000000014841517156108d5578461160d916114ff565b90633b9aca00830292808404633b9aca0014901517156108d557612710926116848261167e61165a6c0c9f2c9cd04674edea400000006116536116bc9861168a986114df565b048561151d565b986116785f549961167260ff8c60a01c1680946114ff565b906114ff565b926114ff565b906114df565b9061151d565b9361ffff6116b5846116ab836116a4818a60e01c1661152a565b16856114df565b049560f01c61152a565b16906114df565b0490604051926116cb846113bb565b83526020830152604082015290565b6007548110156116f25760075f5260205f2001905f90565b634e487b7160e01b5f52603260045260245ffd5b638b78c6d81954330361171557565b6382b429005f526004601cfd5b5f38818085856108fcf115611735575050565b81471061176d575f3881808585620186a0f115611750575050565b601691600b915f526073825360ff602053f01561176957565b3838fd5b63b12d13eb5f526004601cfd5b90918151918261178c575b5090501490565b8060208092019360051b0101905b8251811160051b90815260208351911852602060405f2092019181831061179a57915050805f611785565b90916008543410610c73576117f2908360405160208101903360601b8252601481526110816034826113d7565b1561116857335f52600c60205260405f20825f5260205260ff60405f205416611a2257815f52600b60205261ffff60405f2054161580156119d0575b610b6e5761184e6bffffffffffffffffffffffff6003541660095461151d565b600955815f52600b6020525f1961ffff60405f205416019161ffff83116108d5576001600160a01b0392815f52600b60205261ffff60405f20911661ffff19825416179055335f52600c60205260405f20905f5260205260405f20600160ff1982541617905516805f52600a6020526118dc60405f20546bffffffffffffffffffffffff600354169061151d565b815f52600a60205260405f20557f1bbf55d483639f8103dc4e035af71a4fbdb16c80be740fa3eef81198acefa09460206bffffffffffffffffffffffff60035416604051908152a26007545f5b81811061194e57505060085480341161193f5750565b610b6261194c91346114f2565b565b602460206001600160a01b03611963846116da565b90549060031b1c16604051928380926370a0823160e01b82523360048301525afa908115610c68575f9161199f575b50610c0f57600101611929565b90506020813d82116119c8575b816119b9602093836113d7565b8101031261015e57515f611992565b3d91506119ac565b506119ee6009546bffffffffffffffffffffffff600354169061151d565b63ffffffff60015460401c1690670de0b6b3a7640000820291808304670de0b6b3a764000014901517156108d5571161182e565b7f5088d84e000000000000000000000000000000000000000000000000000000005f5260045ffd5b6001600160a01b031680638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3638b78c6d8195556fea2646970667358221220c69d82867dbab0b1dbe4f2abc91d12b24c00afdf28aec9001e8ed83e0be47f6864736f6c634300081a00330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000f120916a94780633c372e89132262a378d02f8f50000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000017a60000000000000000000000000000000000000000000000000000000059682f000000000000000000000000005af0d9827e0c53e4799bb226655a1de152a425a500000000000000000000000000000000000000000000000000000000000005e9000000000000000000000000d3d9ddd0cf0a5f0bfb8f7fceae075df687eaebab0000000000000000000000000000000000000000000022fd5a6400bf7e880000f9aa34f50c8f3c1c0af2dc07104467e3757130801b85c6e0b9b3e76c8846a3666032a3bdce699fd2161cd712aaa7d0cd1053bbdb4458b4fd078d3d272b760c6f16d28be8f9647d24d66f6fcb4ad91ac859f29edb99528bffcdfa2e1d53bbba0800000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000bc4ca0eda7647a8ab7c2061c2e118a18a936f13d00000000000000000000000060e4d786628fea6478f785a6d7e704777c86a7c6
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c806305b1137b146113535780630c26fbcb1461132557806316c38b3c146112ed57806325692962146112a4578063259bfdd71461126e57806331abae3d14610f0357806335c7d1d314610fdb57806343d5b5c414610fa157806354d1f13d14610f5d5780635c975abb14610f3b57806370a0823114610f03578063715018a614610eba57806379502c5514610db65780637c05399f14610d1c5780638c1ee1e914610ce25780638da5cb5b14610cb85780639106d7ba14610c9b578063b281281c146109fb578063cb42f3571461097e578063db9341e61461029f578063f04e283e14610252578063f2fde38b14610215578063f5537ede146101ab578063f7a924db146101625763fee81cf41461012c575f80fd5b3461015e57602036600319011261015e5761014561137b565b63389a75e1600c525f52602080600c2054604051908152f35b5f80fd5b3461015e57604036600319011261015e576001600160a01b0361018361137b565b165f52600c60205260405f206024355f52602052602060ff60405f2054166040519015158152f35b606036600319011261015e5760205f60446010826101c761137b565b6101cf611391565b6101d7611706565b60145283356034526fa9059cbb00000000000000000000000082525af13d1560015f5114171615610208575f603452005b6390b8ec185f526004601cfd5b602036600319011261015e5761022961137b565b610231611706565b8060601b156102455761024390611a4a565b005b637448fbae5f526004601cfd5b602036600319011261015e5761026661137b565b61026e611706565b63389a75e1600c52805f526020600c209081544211610292575f6102439255611a4a565b636f5e88185f526004601cfd5b602036600319011261015e5767ffffffffffffffff6004351161015e576102606004353603600319011261015e57604051610260810181811067ffffffffffffffff82111761094a576040526102f96004356004016113a7565b81526103096024600435016114b1565b602082015261031c6044600435016114b1565b604082015261032f6064600435016114bf565b60608201526103426084600435016114bf565b608082015261035560a4600435016114bf565b60a082015261036860c4600435016114bf565b60c082015261037b60e4600435016114bf565b60e082015261038f610104600435016114ce565b6101008201526103a4610124600435016114ce565b6101208201526103b9610144600435016114ce565b6101408201526103ce610164600435016113a7565b6101608201526103e3610184600435016114ce565b6101808201526103f86101a4600435016113a7565b6101a08201526101c460043501356bffffffffffffffffffffffff8116810361015e576101c08201526004356101e48101356101e0830152610204810135610200830152610224810135610220830152610244013567ffffffffffffffff811161015e57366023826004350101121561015e57600481813501013561047c816113f9565b9161048a60405193846113d7565b81835260208301903660246004358301600586901b01011161015e576024816004350101915b60246004358301600586901b0101831061095e57858561024082019081526104d6611706565b81516001600160a01b03165f5490602084015160a01b74ff000000000000000000000000000000000000000016604085015160a81b75ff00000000000000000000000000000000000000000016606086015160b01b77ffff0000000000000000000000000000000000000000000016608087015160c01b79ffff000000000000000000000000000000000000000000000000169160a088015160d01b7bffff0000000000000000000000000000000000000000000000000000169360c089015160e01b7dffff00000000000000000000000000000000000000000000000000000000169560e08a015160f01b7fffff00000000000000000000000000000000000000000000000000000000000016977fffffffffffffffffffff0000000000000000000000000000000000000000000016177fffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffff16177fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff16177fffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffff16177fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff16177dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff161717175f5561010082015163ffffffff1663ffffffff19600154161760015561012082015160015461014084015160401b6bffffffff000000000000000016906bffffffffffffffffffffffff1961016086015160601b169260201b67ffffffff00000000169063ffffffff1617171760015561018082015163ffffffff1663ffffffff1960025416176002556101a08201516002549060201b77ffffffffffffffffffffffffffffffffffffffff0000000016907fffffffffffffffff0000000000000000000000000000000000000000ffffffff16176002556101c08201516bffffffffffffffffffffffff166bffffffffffffffffffffffff1960035416176003556101e08201516004556102008201516005556102208201516006555180519067ffffffffffffffff821161094a5768010000000000000000821161094a5760075482600755808310610906575b5060200160075f5260205f205f5b8381106108e9578463ffffffff610180820151166bffffffffffffffffffffffff6101c083015116026bffffffffffffffffffffffff81169081036108d557633b9aca0090046bffffffffffffffffffffffff1660085560608101516101e08201515f908152600b6020526040808220805461ffff1990811661ffff95861617909155608085015161020086015184528284208054831691861691909117905560a08501516102209095015183529120805490911692909116919091179055005b634e487b7160e01b5f52601160045260245ffd5b60019060206001600160a01b038551169401938184015501610814565b60075f527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6889081019083015b81811061093f5750610806565b5f8155600101610932565b634e487b7160e01b5f52604160045260245ffd5b602091828060049361096f876113a7565b815201940193915091506104b0565b6109873661146e565b68929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c6576004546109b8926117c5565b5f68929eee149b4bd212685d005b7f9e87fac8000000000000000000000000000000000000000000000000000000005f5260045ffd5b63ab143c065f526004601cfd5b604036600319011261015e57600435610a12611391565b9068929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c657670de0b6b3a7640000610a56826020610a4f61153e565b01516114df565b0491348311610c73576007545f5b818110610bbe57505060ff5f5460a81c16670de0b6b3a7640000810290808204670de0b6b3a764000014901517156108d5573411610b965760095490610aaa838361151d565b63ffffffff60015460401c1690670de0b6b3a7640000820291808304670de0b6b3a764000014901517156108d55711610b6e576001600160a01b03602091610b13857f1bbf55d483639f8103dc4e035af71a4fbdb16c80be740fa3eef81198acefa0949561151d565b6009551692835f52600a8252610b2d8160405f205461151d565b845f52600a835260405f2055604051908152a2803411610b55575f68929eee149b4bd212685d005b610b62610b6891346114f2565b33611722565b806109b8565b7f52df9fe5000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f8529eb36000000000000000000000000000000000000000000000000000000005f5260045ffd5b602460206001600160a01b03610bd3846116da565b90549060031b1c16604051928380926370a0823160e01b82523360048301525afa908115610c68575f91610c37575b50610c0f57600101610a64565b7fe95dadd7000000000000000000000000000000000000000000000000000000005f5260045ffd5b90506020813d8211610c60575b81610c51602093836113d7565b8101031261015e575186610c02565b3d9150610c44565b6040513d5f823e3d90fd5b7fcd1c8867000000000000000000000000000000000000000000000000000000005f5260045ffd5b3461015e575f36600319011261015e576020600954604051908152f35b3461015e575f36600319011261015e576020638b78c6d819546001600160a01b0360405191168152f35b610ceb3661146e565b68929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c6576005546109b8926117c5565b604036600319011261015e57600435610d33611391565b9068929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c657670de0b6b3a7640000610d70826040610a4f61153e565b0491348311610c735760ff5f5460a81c16670de0b6b3a7640000810290808204670de0b6b3a764000014901517156108d5573411610b965760095490610aaa838361151d565b3461015e575f36600319011261015e576102405f546001546002546bffffffffffffffffffffffff60035416600454906001600160a01b03600554936006549560405197838116895260ff8160a01c1660208a015260ff8160a81c1660408a015261ffff8160b01c1660608a015261ffff8160c01c1660808a015261ffff8160d01c1660a08a015261ffff8160e01c1660c08a015260f01c60e089015263ffffffff811661010089015263ffffffff8160201c1661012089015263ffffffff8160401c1661014089015260601c61016088015263ffffffff811661018088015260201c166101a08601526101c08501526101e0840152610200830152610220820152f35b5f36600319011261015e57610ecd611706565b5f638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a35f638b78c6d81955005b3461015e57602036600319011261015e576001600160a01b03610f2461137b565b165f52600a602052602060405f2054604051908152f35b3461015e575f36600319011261015e57602060ff600d54166040519015158152f35b5f36600319011261015e5763389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2005b610faa3661146e565b68929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c6576006546109b8926117c5565b606036600319011261015e57600435610ff2611391565b9060443567ffffffffffffffff811161015e57611013903690600401611411565b9168929eee149b4bd212685c6109ee573068929eee149b4bd212685d60ff600d54166109c657670de0b6b3a76400006110548361104e61153e565b516114df565b0492348411610c735761108a9060045460405160208101903360601b8252601481526110816034826113d7565b5190209161177a565b1580611203575b80611190575b611168576007545f5b8181106110e657505060ff5f5460a81c16670de0b6b3a7640000810290808204670de0b6b3a764000014901517156108d5573411610b965760095490610aaa838361151d565b602460206001600160a01b036110fb846116da565b90549060031b1c16604051928380926370a0823160e01b82523360048301525afa908115610c68575f91611137575b50610c0f576001016110a0565b90506020813d8211611160575b81611151602093836113d7565b8101031261015e57518661112a565b3d9150611144565b7f3cb97240000000000000000000000000000000000000000000000000000000005f5260045ffd5b50602460206001600160a01b03600254821c16604051928380926370a0823160e01b82523360048301525afa908115610c68575f916111d1575b5015611097565b90506020813d6020116111fb575b816111ec602093836113d7565b8101031261015e5751846111ca565b3d91506111df565b506024602060015460601c604051928380926370a0823160e01b82523360048301525afa908115610c68575f9161123c575b5015611091565b90506020813d602011611266575b81611257602093836113d7565b8101031261015e575184611235565b3d915061124a565b3461015e575f36600319011261015e57606061128861153e565b6040805191805183526020810151602084015201516040820152f35b5f36600319011261015e5763389a75e1600c52335f526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a2005b3461015e57602036600319011261015e5760043580151580910361015e57611313611706565b60ff8019600d5416911617600d555f80f35b3461015e57602036600319011261015e576004355f52600b602052602061ffff60405f205416604051908152f35b604036600319011261015e5761024361136a61137b565b611372611706565b60243590611722565b600435906001600160a01b038216820361015e57565b602435906001600160a01b038216820361015e57565b35906001600160a01b038216820361015e57565b6060810190811067ffffffffffffffff82111761094a57604052565b90601f8019910116810190811067ffffffffffffffff82111761094a57604052565b67ffffffffffffffff811161094a5760051b60200190565b9080601f8301121561015e578135611428816113f9565b9261143660405194856113d7565b81845260208085019260051b82010192831161015e57602001905b82821061145e5750505090565b8135815260209182019101611451565b90604060031983011261015e576004356001600160a01b038116810361015e57916024359067ffffffffffffffff821161015e576114ae91600401611411565b90565b359060ff8216820361015e57565b359061ffff8216820361015e57565b359063ffffffff8216820361015e57565b818102929181159184041417156108d557565b919082039182116108d557565b8115611509570490565b634e487b7160e01b5f52601260045260245ffd5b919082018092116108d557565b61ffff16612710019061ffff82116108d557565b5f6040805161154c816113bb565b828152826020820152015260015463ffffffff8160401c1690670de0b6b3a7640000820291808304670de0b6b3a764000014901517156108d55763ffffffff611597600954846114f2565b9181811691829160201c160363ffffffff81116108d55763ffffffff1691633b9aca00830292808404633b9aca0014901517156108d5576115d890846114f2565b916c0c9f2c9cd04674edea4000000083028381046c0c9f2c9cd04674edea4000000014841517156108d5578461160d916114ff565b90633b9aca00830292808404633b9aca0014901517156108d557612710926116848261167e61165a6c0c9f2c9cd04674edea400000006116536116bc9861168a986114df565b048561151d565b986116785f549961167260ff8c60a01c1680946114ff565b906114ff565b926114ff565b906114df565b9061151d565b9361ffff6116b5846116ab836116a4818a60e01c1661152a565b16856114df565b049560f01c61152a565b16906114df565b0490604051926116cb846113bb565b83526020830152604082015290565b6007548110156116f25760075f5260205f2001905f90565b634e487b7160e01b5f52603260045260245ffd5b638b78c6d81954330361171557565b6382b429005f526004601cfd5b5f38818085856108fcf115611735575050565b81471061176d575f3881808585620186a0f115611750575050565b601691600b915f526073825360ff602053f01561176957565b3838fd5b63b12d13eb5f526004601cfd5b90918151918261178c575b5090501490565b8060208092019360051b0101905b8251811160051b90815260208351911852602060405f2092019181831061179a57915050805f611785565b90916008543410610c73576117f2908360405160208101903360601b8252601481526110816034826113d7565b1561116857335f52600c60205260405f20825f5260205260ff60405f205416611a2257815f52600b60205261ffff60405f2054161580156119d0575b610b6e5761184e6bffffffffffffffffffffffff6003541660095461151d565b600955815f52600b6020525f1961ffff60405f205416019161ffff83116108d5576001600160a01b0392815f52600b60205261ffff60405f20911661ffff19825416179055335f52600c60205260405f20905f5260205260405f20600160ff1982541617905516805f52600a6020526118dc60405f20546bffffffffffffffffffffffff600354169061151d565b815f52600a60205260405f20557f1bbf55d483639f8103dc4e035af71a4fbdb16c80be740fa3eef81198acefa09460206bffffffffffffffffffffffff60035416604051908152a26007545f5b81811061194e57505060085480341161193f5750565b610b6261194c91346114f2565b565b602460206001600160a01b03611963846116da565b90549060031b1c16604051928380926370a0823160e01b82523360048301525afa908115610c68575f9161199f575b50610c0f57600101611929565b90506020813d82116119c8575b816119b9602093836113d7565b8101031261015e57515f611992565b3d91506119ac565b506119ee6009546bffffffffffffffffffffffff600354169061151d565b63ffffffff60015460401c1690670de0b6b3a7640000820291808304670de0b6b3a764000014901517156108d5571161182e565b7f5088d84e000000000000000000000000000000000000000000000000000000005f5260045ffd5b6001600160a01b031680638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3638b78c6d8195556fea2646970667358221220c69d82867dbab0b1dbe4f2abc91d12b24c00afdf28aec9001e8ed83e0be47f6864736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000f120916a94780633c372e89132262a378d02f8f50000000000000000000000000000000000000000000000000000000000000078000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000007d000000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000017a60000000000000000000000000000000000000000000000000000000059682f000000000000000000000000005af0d9827e0c53e4799bb226655a1de152a425a500000000000000000000000000000000000000000000000000000000000005e9000000000000000000000000d3d9ddd0cf0a5f0bfb8f7fceae075df687eaebab0000000000000000000000000000000000000000000022fd5a6400bf7e880000f9aa34f50c8f3c1c0af2dc07104467e3757130801b85c6e0b9b3e76c8846a3666032a3bdce699fd2161cd712aaa7d0cd1053bbdb4458b4fd078d3d272b760c6f16d28be8f9647d24d66f6fcb4ad91ac859f29edb99528bffcdfa2e1d53bbba0800000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000bc4ca0eda7647a8ab7c2061c2e118a18a936f13d00000000000000000000000060e4d786628fea6478f785a6d7e704777c86a7c6
-----Decoded View---------------
Arg [0] : _config (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
23 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 000000000000000000000000f120916a94780633c372e89132262a378d02f8f5
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000078
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [4] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [5] : 00000000000000000000000000000000000000000000000000000000000000fa
Arg [6] : 00000000000000000000000000000000000000000000000000000000000000fa
Arg [7] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [8] : 00000000000000000000000000000000000000000000000000000000000007d0
Arg [9] : 00000000000000000000000000000000000000000000000000000000000005e9
Arg [10] : 00000000000000000000000000000000000000000000000000000000000017a6
Arg [11] : 0000000000000000000000000000000000000000000000000000000059682f00
Arg [12] : 0000000000000000000000005af0d9827e0c53e4799bb226655a1de152a425a5
Arg [13] : 00000000000000000000000000000000000000000000000000000000000005e9
Arg [14] : 000000000000000000000000d3d9ddd0cf0a5f0bfb8f7fceae075df687eaebab
Arg [15] : 0000000000000000000000000000000000000000000022fd5a6400bf7e880000
Arg [16] : f9aa34f50c8f3c1c0af2dc07104467e3757130801b85c6e0b9b3e76c8846a366
Arg [17] : 6032a3bdce699fd2161cd712aaa7d0cd1053bbdb4458b4fd078d3d272b760c6f
Arg [18] : 16d28be8f9647d24d66f6fcb4ad91ac859f29edb99528bffcdfa2e1d53bbba08
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000260
Arg [20] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [21] : 000000000000000000000000bc4ca0eda7647a8ab7c2061c2e118a18a936f13d
Arg [22] : 00000000000000000000000060e4d786628fea6478f785a6d7e704777c86a7c6
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.