Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 15552372 | 183 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
BlacksmithCrafting
Compiler Version
v0.8.30+commit.73712a01
ZkSolc Version
v1.5.15
Optimization Enabled:
Yes with Mode 3
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;
import {Ownable} from "solady/auth/Ownable.sol";
import {UUPSUpgradeable} from "solady/utils/UUPSUpgradeable.sol";
import {EnumerableMapLib} from "solady/utils/EnumerableMapLib.sol";
import {IERC20} from "../interfaces/IERC20.sol";
import {IOCHItems} from "../interfaces/IOCHItems.sol";
/// @dev This contract is a proxy contract for BlacksmithCrafting.
/// @author Onchain-Heroes (https://www.onchainheroes.xyz/)
/// @author atarpara (https://www.github.com/atarpara)
contract BlacksmithCrafting is Ownable, UUPSUpgradeable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Revert if recipe is not running.
error RecipeNotRunning();
/// @dev Revert if length of itemId and qtys is not equal.
error InvalidLength();
/// @dev Revert if recipe is already running.
error RecipeAlreadyRunning();
/// @dev Revert if contract is paused.
error Paused();
/// @dev Revert if price is zero.
error PriceIsZero();
/// @dev Revert if length is zero.
error LengthIsZero();
/// @dev Revert if qty is zero.
error QtyIsZero();
/// @dev Revert if outputId is zero.
error InvalidOutputId();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Emitted when recipes are cooked.
event CookedRecipes(address owner, uint256 recipeId, uint256 price, uint256[] itemId, uint256[] qtys);
/// @dev Emitted when recipe is added.
event RecipeAdded(uint256 recipeId, uint256 recipePrice, uint256[] itemId, uint256[] qtys);
/// @dev Emitted when recipe is updated.
event RecipeUpdated(uint256 recipeId, uint256 recipePrice, uint256[] itemId, uint256[] qtys);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANT */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Address of $HERO20 contract.
IERC20 internal constant hero20 = IERC20(0x33EE11cE309854a45B65368C078616ABcb5c6e3d);
/// @dev Address of OCHItems contract.
IOCHItems internal constant items = IOCHItems(0x14f926D2751F4bb0200e9b016B6aE4A1E4B207Bd);
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STRUCT */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Recipe struct.
struct Recipe {
/// @dev Whether recipe is running or not.
uint8 isRunning;
/// @dev Price of recipe.
uint248 price;
/// @dev Item id array.
uint256[] itemId;
/// @dev Qtys array.
uint256[] qty;
}
/// @dev BlacksmithCrafting storage.
struct BlacksmithCraftingStorage {
/// @dev Mapping of recipeId to Recipe.
mapping(uint256 recipeId => Recipe) recipes;
/// @dev Pause flag for contract.
uint8 pauseFlag;
}
constructor(address _owner) {
_initializeOwner(_owner);
}
/// @dev Init contract with `_owner`.
function init(address _owner) external {
if (owner() != address(0)) revert AlreadyInitialized();
_initializeOwner(_owner);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Cook recipes with `recipeId`.
function cookRecipes(uint256[] calldata recipeId) external {
// Get storage.
BlacksmithCraftingStorage storage $ = _getStorage();
// Check if contract is paused.
if ($.pauseFlag != 0) revert Paused();
uint256 len = recipeId.length;
for (uint256 i = 0; i < len; ++i) {
uint256 id = recipeId[i];
// Get recipe.
Recipe storage recipe = $.recipes[id];
// Check if recipe is running.
if (recipe.isRunning == 0) revert RecipeNotRunning();
// Check if price is zero.
if (recipe.price == 0) revert PriceIsZero();
// Transfer $HERO20 to this contract.
hero20.transferFrom(msg.sender, address(this), recipe.price);
uint256 keyLen_ = recipe.itemId.length;
uint256[] memory itemId = new uint256[](keyLen_);
uint256[] memory qtys = new uint256[](keyLen_);
for (uint256 z; z < keyLen_; ++z) {
itemId[z] = recipe.itemId[z];
qtys[z] = recipe.qty[z];
// Burn items.
items.burn(msg.sender, itemId[z], qtys[z]);
}
// Emit `CookedRecipes`.
emit CookedRecipes(msg.sender, id, recipe.price, itemId, qtys);
// Mint item.
items.mint(msg.sender, id, 1);
}
}
/// @dev Add recipe with `outputId`, `recipePrice`, `itemId` and `qtys`.
function addRecipe(uint256 outputId, uint256 recipePrice, uint256[] calldata itemId, uint256[] calldata qtys)
external
onlyOwner
{
if (outputId == 0) revert InvalidOutputId();
// Get storage.
BlacksmithCraftingStorage storage $ = _getStorage();
// Check if length of itemId and qtys is not equal.
if (itemId.length != qtys.length) revert InvalidLength();
// Get recipe.
Recipe storage recipe = $.recipes[outputId];
// Check if recipe is already running.
if (recipe.isRunning != 0) revert RecipeAlreadyRunning();
// Set recipe as running.
recipe.isRunning = uint8(1);
// Set recipe price.
recipe.price = uint248(recipePrice);
uint256 len = itemId.length;
if (len == 0) revert LengthIsZero();
recipe.itemId = new uint256[](len);
recipe.qty = new uint256[](len);
for (uint256 i = 0; i < len; ++i) {
if (qtys[i] == 0) revert QtyIsZero();
// Set itemId and qty.
recipe.itemId[i] = itemId[i];
recipe.qty[i] = qtys[i];
}
// Emit `RecipeAdded`.
emit RecipeAdded(outputId, recipePrice, itemId, qtys);
}
/// @dev Update recipe with `outputId`, `recipePrice`, `itemId` and `qtys`.
function updateRecipe(uint256 outputId, uint256 recipePrice, uint256[] calldata itemId, uint256[] calldata qtys)
external
onlyOwner
{
// Check if outputId is zero.
if (outputId == 0) revert InvalidOutputId();
// Get storage.
BlacksmithCraftingStorage storage $ = _getStorage();
// Check if length of itemId and qtys is not equal.
if (itemId.length != qtys.length) revert InvalidLength();
// Get recipe.
Recipe storage recipe = $.recipes[outputId];
// Set recipe price.
recipe.price = uint248(recipePrice);
uint256 len = itemId.length;
if (len == 0) revert LengthIsZero();
recipe.itemId = new uint256[](len);
recipe.qty = new uint256[](len);
for (uint256 i = 0; i < len; ++i) {
if (qtys[i] == 0) revert QtyIsZero();
// Set itemId and qty.
recipe.itemId[i] = itemId[i];
recipe.qty[i] = qtys[i];
}
// Emit `RecipeUpdated`.
emit RecipeUpdated(outputId, recipePrice, itemId, qtys);
}
/// @dev Set recipe start flag.
function setRecipeStartFlag(uint256 outputId, bool flag) external onlyOwner {
BlacksmithCraftingStorage storage $ = _getStorage();
$.recipes[outputId].isRunning = flag ? uint8(1) : uint8(0);
}
/// @dev Set pause flag.
function setPauseFlag(bool flag) external onlyOwner {
BlacksmithCraftingStorage storage $ = _getStorage();
$.pauseFlag = flag ? uint8(1) : uint8(0);
}
/// @dev Withdraw $HERO20.
function withdraw() external onlyOwner {
uint256 balance = hero20.balanceOf(address(this));
hero20.transfer(msg.sender, balance);
}
/// @dev Get storage pointer.
function _getStorage() internal pure returns (BlacksmithCraftingStorage storage $) {
uint256 s = uint72(bytes9(keccak256("BLACKSMITH_CRAFTING_STORAGE")));
assembly ("memory-safe") {
$.slot := s
}
}
/// @dev Get recipe details.
function getRecipe(uint256 outputId)
external
view
returns (bool isRunning, uint256 price, uint256[] memory itemId, uint256[] memory qtys)
{
BlacksmithCraftingStorage storage $ = _getStorage();
Recipe storage recipe = $.recipes[outputId];
return (recipe.isRunning != 0, uint256(recipe.price), recipe.itemId, recipe.qty);
}
/// @dev Authorize upgrade.
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
}// 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 UUPS proxy mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/UUPSUpgradeable.sol)
/// @author Modified from OpenZeppelin
/// (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/utils/UUPSUpgradeable.sol)
///
/// @dev Note:
/// - This implementation is intended to be used with ERC1967 proxies.
/// See: `LibClone.deployERC1967` and related functions.
/// - This implementation is NOT compatible with legacy OpenZeppelin proxies
/// which do not store the implementation at `_ERC1967_IMPLEMENTATION_SLOT`.
abstract contract UUPSUpgradeable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The upgrade failed.
error UpgradeFailed();
/// @dev The call is from an unauthorized call context.
error UnauthorizedCallContext();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* IMMUTABLES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev For checking if the context is a delegate call.
uint256 private immutable __self = uint256(uint160(address(this)));
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Emitted when the proxy's implementation is upgraded.
event Upgraded(address indexed implementation);
/// @dev `keccak256(bytes("Upgraded(address)"))`.
uint256 private constant _UPGRADED_EVENT_SIGNATURE =
0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ERC-1967 storage slot for the implementation in the proxy.
/// `uint256(keccak256("eip1967.proxy.implementation")) - 1`.
bytes32 internal constant _ERC1967_IMPLEMENTATION_SLOT =
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* UUPS OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Please override this function to check if `msg.sender` is authorized
/// to upgrade the proxy to `newImplementation`, reverting if not.
/// ```
/// function _authorizeUpgrade(address) internal override onlyOwner {}
/// ```
function _authorizeUpgrade(address newImplementation) internal virtual;
/// @dev Returns the storage slot used by the implementation,
/// as specified in [ERC1822](https://eips.ethereum.org/EIPS/eip-1822).
///
/// Note: The `notDelegated` modifier prevents accidental upgrades to
/// an implementation that is a proxy contract.
function proxiableUUID() public view virtual notDelegated returns (bytes32) {
// This function must always return `_ERC1967_IMPLEMENTATION_SLOT` to comply with ERC1967.
return _ERC1967_IMPLEMENTATION_SLOT;
}
/// @dev Upgrades the proxy's implementation to `newImplementation`.
/// Emits a {Upgraded} event.
///
/// Note: Passing in empty `data` skips the delegatecall to `newImplementation`.
function upgradeToAndCall(address newImplementation, bytes calldata data)
public
payable
virtual
onlyProxy
{
_authorizeUpgrade(newImplementation);
/// @solidity memory-safe-assembly
assembly {
newImplementation := shr(96, shl(96, newImplementation)) // Clears upper 96 bits.
mstore(0x00, returndatasize())
mstore(0x01, 0x52d1902d) // `proxiableUUID()`.
let s := _ERC1967_IMPLEMENTATION_SLOT
// Check if `newImplementation` implements `proxiableUUID` correctly.
if iszero(eq(mload(staticcall(gas(), newImplementation, 0x1d, 0x04, 0x01, 0x20)), s)) {
mstore(0x01, 0x55299b49) // `UpgradeFailed()`.
revert(0x1d, 0x04)
}
// Emit the {Upgraded} event.
log2(codesize(), 0x00, _UPGRADED_EVENT_SIGNATURE, newImplementation)
sstore(s, newImplementation) // Updates the implementation.
// Perform a delegatecall to `newImplementation` if `data` is non-empty.
if data.length {
// Forwards the `data` to `newImplementation` via delegatecall.
let m := mload(0x40)
calldatacopy(m, data.offset, data.length)
if iszero(delegatecall(gas(), newImplementation, m, data.length, codesize(), 0x00))
{
// Bubble up the revert if the call reverts.
returndatacopy(m, 0x00, returndatasize())
revert(m, returndatasize())
}
}
}
}
/// @dev Requires that the execution is performed through a proxy.
modifier onlyProxy() {
uint256 s = __self;
/// @solidity memory-safe-assembly
assembly {
// To enable use cases with an immutable default implementation in the bytecode,
// (see: ERC6551Proxy), we don't require that the proxy address must match the
// value stored in the implementation slot, which may not be initialized.
if eq(s, address()) {
mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.
revert(0x1c, 0x04)
}
}
_;
}
/// @dev Requires that the execution is NOT performed via delegatecall.
/// This is the opposite of `onlyProxy`.
modifier notDelegated() {
uint256 s = __self;
/// @solidity memory-safe-assembly
assembly {
if iszero(eq(s, address())) {
mstore(0x00, 0x9f03a026) // `UnauthorizedCallContext()`.
revert(0x1c, 0x04)
}
}
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {EnumerableSetLib} from "./EnumerableSetLib.sol";
/// @notice Library for managing enumerable maps in storage.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EnumerableMapLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/EnumerableMap.sol)
library EnumerableMapLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The key does not exist in the enumerable map.
error EnumerableMapKeyNotFound();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STRUCTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev A enumerable map of `bytes32` to `bytes32`.
struct Bytes32ToBytes32Map {
EnumerableSetLib.Bytes32Set _keys;
mapping(bytes32 => bytes32) _values;
}
/// @dev A enumerable map of `bytes32` to `uint256`.
struct Bytes32ToUint256Map {
EnumerableSetLib.Bytes32Set _keys;
mapping(bytes32 => uint256) _values;
}
/// @dev A enumerable map of `bytes32` to `address`.
struct Bytes32ToAddressMap {
EnumerableSetLib.Bytes32Set _keys;
mapping(bytes32 => address) _values;
}
/// @dev A enumerable map of `uint256` to `bytes32`.
struct Uint256ToBytes32Map {
EnumerableSetLib.Uint256Set _keys;
mapping(uint256 => bytes32) _values;
}
/// @dev A enumerable map of `uint256` to `uint256`.
struct Uint256ToUint256Map {
EnumerableSetLib.Uint256Set _keys;
mapping(uint256 => uint256) _values;
}
/// @dev A enumerable map of `uint256` to `address`.
struct Uint256ToAddressMap {
EnumerableSetLib.Uint256Set _keys;
mapping(uint256 => address) _values;
}
/// @dev A enumerable map of `address` to `bytes32`.
struct AddressToBytes32Map {
EnumerableSetLib.AddressSet _keys;
mapping(address => bytes32) _values;
}
/// @dev A enumerable map of `address` to `uint256`.
struct AddressToUint256Map {
EnumerableSetLib.AddressSet _keys;
mapping(address => uint256) _values;
}
/// @dev A enumerable map of `address` to `address`.
struct AddressToAddressMap {
EnumerableSetLib.AddressSet _keys;
mapping(address => address) _values;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* GETTERS / SETTERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Adds a key-value pair to the map, or updates the value for an existing key.
/// Returns true if `key` was added to the map, that is if it was not already present.
function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value)
internal
returns (bool)
{
map._values[key] = value;
return EnumerableSetLib.add(map._keys, key);
}
/// @dev Removes a key-value pair from the map.
/// Returns true if `key` was removed from the map, that is if it was present.
function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return EnumerableSetLib.remove(map._keys, key);
}
/// @dev Returns true if the key is in the map.
function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
return EnumerableSetLib.contains(map._keys, key);
}
/// @dev Returns the number of key-value pairs in the map.
function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
return EnumerableSetLib.length(map._keys);
}
/// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
function at(Bytes32ToBytes32Map storage map, uint256 i)
internal
view
returns (bytes32 key, bytes32 value)
{
value = map._values[key = EnumerableSetLib.at(map._keys, i)];
}
/// @dev Tries to return the value associated with the key.
function tryGet(Bytes32ToBytes32Map storage map, bytes32 key)
internal
view
returns (bool exists, bytes32 value)
{
exists = (value = map._values[key]) != bytes32(0) || contains(map, key);
}
/// @dev Returns the value for the key. Reverts if the key is not found.
function get(Bytes32ToBytes32Map storage map, bytes32 key)
internal
view
returns (bytes32 value)
{
if ((value = map._values[key]) == bytes32(0)) if (!contains(map, key)) _revertNotFound();
}
/// @dev Returns the keys. May run out-of-gas if the map is too big.
function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) {
return EnumerableSetLib.values(map._keys);
}
/// @dev Adds a key-value pair to the map, or updates the value for an existing key.
/// Returns true if `key` was added to the map, that is if it was not already present.
function set(Bytes32ToUint256Map storage map, bytes32 key, uint256 value)
internal
returns (bool)
{
map._values[key] = value;
return EnumerableSetLib.add(map._keys, key);
}
/// @dev Removes a key-value pair from the map.
/// Returns true if `key` was removed from the map, that is if it was present.
function remove(Bytes32ToUint256Map storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return EnumerableSetLib.remove(map._keys, key);
}
/// @dev Returns true if the key is in the map.
function contains(Bytes32ToUint256Map storage map, bytes32 key) internal view returns (bool) {
return EnumerableSetLib.contains(map._keys, key);
}
/// @dev Returns the number of key-value pairs in the map.
function length(Bytes32ToUint256Map storage map) internal view returns (uint256) {
return EnumerableSetLib.length(map._keys);
}
/// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
function at(Bytes32ToUint256Map storage map, uint256 i)
internal
view
returns (bytes32 key, uint256 value)
{
value = map._values[key = EnumerableSetLib.at(map._keys, i)];
}
/// @dev Tries to return the value associated with the key.
function tryGet(Bytes32ToUint256Map storage map, bytes32 key)
internal
view
returns (bool exists, uint256 value)
{
exists = (value = map._values[key]) != uint256(0) || contains(map, key);
}
/// @dev Returns the value for the key. Reverts if the key is not found.
function get(Bytes32ToUint256Map storage map, bytes32 key)
internal
view
returns (uint256 value)
{
if ((value = map._values[key]) == uint256(0)) if (!contains(map, key)) _revertNotFound();
}
/// @dev Returns the keys. May run out-of-gas if the map is too big.
function keys(Bytes32ToUint256Map storage map) internal view returns (bytes32[] memory) {
return EnumerableSetLib.values(map._keys);
}
/// @dev Adds a key-value pair to the map, or updates the value for an existing key.
/// Returns true if `key` was added to the map, that is if it was not already present.
function set(Bytes32ToAddressMap storage map, bytes32 key, address value)
internal
returns (bool)
{
map._values[key] = value;
return EnumerableSetLib.add(map._keys, key);
}
/// @dev Removes a key-value pair from the map.
/// Returns true if `key` was removed from the map, that is if it was present.
function remove(Bytes32ToAddressMap storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return EnumerableSetLib.remove(map._keys, key);
}
/// @dev Returns true if the key is in the map.
function contains(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool) {
return EnumerableSetLib.contains(map._keys, key);
}
/// @dev Returns the number of key-value pairs in the map.
function length(Bytes32ToAddressMap storage map) internal view returns (uint256) {
return EnumerableSetLib.length(map._keys);
}
/// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
function at(Bytes32ToAddressMap storage map, uint256 i)
internal
view
returns (bytes32 key, address value)
{
value = map._values[key = EnumerableSetLib.at(map._keys, i)];
}
/// @dev Tries to return the value associated with the key.
function tryGet(Bytes32ToAddressMap storage map, bytes32 key)
internal
view
returns (bool exists, address value)
{
exists = (value = map._values[key]) != address(0) || contains(map, key);
}
/// @dev Returns the value for the key. Reverts if the key is not found.
function get(Bytes32ToAddressMap storage map, bytes32 key)
internal
view
returns (address value)
{
if ((value = map._values[key]) == address(0)) if (!contains(map, key)) _revertNotFound();
}
/// @dev Returns the keys. May run out-of-gas if the map is too big.
function keys(Bytes32ToAddressMap storage map) internal view returns (bytes32[] memory) {
return EnumerableSetLib.values(map._keys);
}
/// @dev Adds a key-value pair to the map, or updates the value for an existing key.
/// Returns true if `key` was added to the map, that is if it was not already present.
function set(Uint256ToBytes32Map storage map, uint256 key, bytes32 value)
internal
returns (bool)
{
map._values[key] = value;
return EnumerableSetLib.add(map._keys, key);
}
/// @dev Removes a key-value pair from the map.
/// Returns true if `key` was removed from the map, that is if it was present.
function remove(Uint256ToBytes32Map storage map, uint256 key) internal returns (bool) {
delete map._values[key];
return EnumerableSetLib.remove(map._keys, key);
}
/// @dev Returns true if the key is in the map.
function contains(Uint256ToBytes32Map storage map, uint256 key) internal view returns (bool) {
return EnumerableSetLib.contains(map._keys, key);
}
/// @dev Returns the number of key-value pairs in the map.
function length(Uint256ToBytes32Map storage map) internal view returns (uint256) {
return EnumerableSetLib.length(map._keys);
}
/// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
function at(Uint256ToBytes32Map storage map, uint256 i)
internal
view
returns (uint256 key, bytes32 value)
{
value = map._values[key = EnumerableSetLib.at(map._keys, i)];
}
/// @dev Tries to return the value associated with the key.
function tryGet(Uint256ToBytes32Map storage map, uint256 key)
internal
view
returns (bool exists, bytes32 value)
{
exists = (value = map._values[key]) != bytes32(0) || contains(map, key);
}
/// @dev Returns the value for the key. Reverts if the key is not found.
function get(Uint256ToBytes32Map storage map, uint256 key)
internal
view
returns (bytes32 value)
{
if ((value = map._values[key]) == bytes32(0)) if (!contains(map, key)) _revertNotFound();
}
/// @dev Returns the keys. May run out-of-gas if the map is too big.
function keys(Uint256ToBytes32Map storage map) internal view returns (uint256[] memory) {
return EnumerableSetLib.values(map._keys);
}
/// @dev Adds a key-value pair to the map, or updates the value for an existing key.
/// Returns true if `key` was added to the map, that is if it was not already present.
function set(Uint256ToUint256Map storage map, uint256 key, uint256 value)
internal
returns (bool)
{
map._values[key] = value;
return EnumerableSetLib.add(map._keys, key);
}
/// @dev Removes a key-value pair from the map.
/// Returns true if `key` was removed from the map, that is if it was present.
function remove(Uint256ToUint256Map storage map, uint256 key) internal returns (bool) {
delete map._values[key];
return EnumerableSetLib.remove(map._keys, key);
}
/// @dev Returns true if the key is in the map.
function contains(Uint256ToUint256Map storage map, uint256 key) internal view returns (bool) {
return EnumerableSetLib.contains(map._keys, key);
}
/// @dev Returns the number of key-value pairs in the map.
function length(Uint256ToUint256Map storage map) internal view returns (uint256) {
return EnumerableSetLib.length(map._keys);
}
/// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
function at(Uint256ToUint256Map storage map, uint256 i)
internal
view
returns (uint256 key, uint256 value)
{
value = map._values[key = EnumerableSetLib.at(map._keys, i)];
}
/// @dev Tries to return the value associated with the key.
function tryGet(Uint256ToUint256Map storage map, uint256 key)
internal
view
returns (bool exists, uint256 value)
{
exists = (value = map._values[key]) != uint256(0) || contains(map, key);
}
/// @dev Returns the value for the key. Reverts if the key is not found.
function get(Uint256ToUint256Map storage map, uint256 key)
internal
view
returns (uint256 value)
{
if ((value = map._values[key]) == uint256(0)) if (!contains(map, key)) _revertNotFound();
}
/// @dev Returns the keys. May run out-of-gas if the map is too big.
function keys(Uint256ToUint256Map storage map) internal view returns (uint256[] memory) {
return EnumerableSetLib.values(map._keys);
}
/// @dev Adds a key-value pair to the map, or updates the value for an existing key.
/// Returns true if `key` was added to the map, that is if it was not already present.
function set(Uint256ToAddressMap storage map, uint256 key, address value)
internal
returns (bool)
{
map._values[key] = value;
return EnumerableSetLib.add(map._keys, key);
}
/// @dev Removes a key-value pair from the map.
/// Returns true if `key` was removed from the map, that is if it was present.
function remove(Uint256ToAddressMap storage map, uint256 key) internal returns (bool) {
delete map._values[key];
return EnumerableSetLib.remove(map._keys, key);
}
/// @dev Returns true if the key is in the map.
function contains(Uint256ToAddressMap storage map, uint256 key) internal view returns (bool) {
return EnumerableSetLib.contains(map._keys, key);
}
/// @dev Returns the number of key-value pairs in the map.
function length(Uint256ToAddressMap storage map) internal view returns (uint256) {
return EnumerableSetLib.length(map._keys);
}
/// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
function at(Uint256ToAddressMap storage map, uint256 i)
internal
view
returns (uint256 key, address value)
{
value = map._values[key = EnumerableSetLib.at(map._keys, i)];
}
/// @dev Tries to return the value associated with the key.
function tryGet(Uint256ToAddressMap storage map, uint256 key)
internal
view
returns (bool exists, address value)
{
exists = (value = map._values[key]) != address(0) || contains(map, key);
}
/// @dev Returns the value for the key. Reverts if the key is not found.
function get(Uint256ToAddressMap storage map, uint256 key)
internal
view
returns (address value)
{
if ((value = map._values[key]) == address(0)) if (!contains(map, key)) _revertNotFound();
}
/// @dev Returns the keys. May run out-of-gas if the map is too big.
function keys(Uint256ToAddressMap storage map) internal view returns (uint256[] memory) {
return EnumerableSetLib.values(map._keys);
}
/// @dev Adds a key-value pair to the map, or updates the value for an existing key.
/// Returns true if `key` was added to the map, that is if it was not already present.
function set(AddressToBytes32Map storage map, address key, bytes32 value)
internal
returns (bool)
{
map._values[key] = value;
return EnumerableSetLib.add(map._keys, key);
}
/// @dev Removes a key-value pair from the map.
/// Returns true if `key` was removed from the map, that is if it was present.
function remove(AddressToBytes32Map storage map, address key) internal returns (bool) {
delete map._values[key];
return EnumerableSetLib.remove(map._keys, key);
}
/// @dev Returns true if the key is in the map.
function contains(AddressToBytes32Map storage map, address key) internal view returns (bool) {
return EnumerableSetLib.contains(map._keys, key);
}
/// @dev Returns the number of key-value pairs in the map.
function length(AddressToBytes32Map storage map) internal view returns (uint256) {
return EnumerableSetLib.length(map._keys);
}
/// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
function at(AddressToBytes32Map storage map, uint256 i)
internal
view
returns (address key, bytes32 value)
{
value = map._values[key = EnumerableSetLib.at(map._keys, i)];
}
/// @dev Tries to return the value associated with the key.
function tryGet(AddressToBytes32Map storage map, address key)
internal
view
returns (bool exists, bytes32 value)
{
exists = (value = map._values[key]) != bytes32(0) || contains(map, key);
}
/// @dev Returns the value for the key. Reverts if the key is not found.
function get(AddressToBytes32Map storage map, address key)
internal
view
returns (bytes32 value)
{
if ((value = map._values[key]) == bytes32(0)) if (!contains(map, key)) _revertNotFound();
}
/// @dev Returns the keys. May run out-of-gas if the map is too big.
function keys(AddressToBytes32Map storage map) internal view returns (address[] memory) {
return EnumerableSetLib.values(map._keys);
}
/// @dev Adds a key-value pair to the map, or updates the value for an existing key.
/// Returns true if `key` was added to the map, that is if it was not already present.
function set(AddressToUint256Map storage map, address key, uint256 value)
internal
returns (bool)
{
map._values[key] = value;
return EnumerableSetLib.add(map._keys, key);
}
/// @dev Removes a key-value pair from the map.
/// Returns true if `key` was removed from the map, that is if it was present.
function remove(AddressToUint256Map storage map, address key) internal returns (bool) {
delete map._values[key];
return EnumerableSetLib.remove(map._keys, key);
}
/// @dev Returns true if the key is in the map.
function contains(AddressToUint256Map storage map, address key) internal view returns (bool) {
return EnumerableSetLib.contains(map._keys, key);
}
/// @dev Returns the number of key-value pairs in the map.
function length(AddressToUint256Map storage map) internal view returns (uint256) {
return EnumerableSetLib.length(map._keys);
}
/// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
function at(AddressToUint256Map storage map, uint256 i)
internal
view
returns (address key, uint256 value)
{
value = map._values[key = EnumerableSetLib.at(map._keys, i)];
}
/// @dev Tries to return the value associated with the key.
function tryGet(AddressToUint256Map storage map, address key)
internal
view
returns (bool exists, uint256 value)
{
exists = (value = map._values[key]) != uint256(0) || contains(map, key);
}
/// @dev Returns the value for the key. Reverts if the key is not found.
function get(AddressToUint256Map storage map, address key)
internal
view
returns (uint256 value)
{
if ((value = map._values[key]) == uint256(0)) if (!contains(map, key)) _revertNotFound();
}
/// @dev Returns the keys. May run out-of-gas if the map is too big.
function keys(AddressToUint256Map storage map) internal view returns (address[] memory) {
return EnumerableSetLib.values(map._keys);
}
/// @dev Adds a key-value pair to the map, or updates the value for an existing key.
/// Returns true if `key` was added to the map, that is if it was not already present.
function set(AddressToAddressMap storage map, address key, address value)
internal
returns (bool)
{
map._values[key] = value;
return EnumerableSetLib.add(map._keys, key);
}
/// @dev Removes a key-value pair from the map.
/// Returns true if `key` was removed from the map, that is if it was present.
function remove(AddressToAddressMap storage map, address key) internal returns (bool) {
delete map._values[key];
return EnumerableSetLib.remove(map._keys, key);
}
/// @dev Returns true if the key is in the map.
function contains(AddressToAddressMap storage map, address key) internal view returns (bool) {
return EnumerableSetLib.contains(map._keys, key);
}
/// @dev Returns the number of key-value pairs in the map.
function length(AddressToAddressMap storage map) internal view returns (uint256) {
return EnumerableSetLib.length(map._keys);
}
/// @dev Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds.
function at(AddressToAddressMap storage map, uint256 i)
internal
view
returns (address key, address value)
{
value = map._values[key = EnumerableSetLib.at(map._keys, i)];
}
/// @dev Tries to return the value associated with the key.
function tryGet(AddressToAddressMap storage map, address key)
internal
view
returns (bool exists, address value)
{
exists = (value = map._values[key]) != address(0) || contains(map, key);
}
/// @dev Returns the value for the key. Reverts if the key is not found.
function get(AddressToAddressMap storage map, address key)
internal
view
returns (address value)
{
if ((value = map._values[key]) == address(0)) if (!contains(map, key)) _revertNotFound();
}
/// @dev Returns the keys. May run out-of-gas if the map is too big.
function keys(AddressToAddressMap storage map) internal view returns (address[] memory) {
return EnumerableSetLib.values(map._keys);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PRIVATE HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Reverts with `EnumerableMapKeyNotFound()`.
function _revertNotFound() private pure {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, 0x88682bf3) // `EnumerableMapKeyNotFound()`.
revert(0x1c, 0x04)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
function mint(address to, uint256 amount) external;
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function transfer(address to, uint256 amount) external returns (bool);
function balanceOf(address to) external returns (uint256);
function burn(uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
interface IOCHItems {
function mint(address to, uint256 id, uint256 amount) external;
function burn(address from, uint256 id, uint256 amount) external;
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Library for managing enumerable sets in storage.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EnumerableSetLib.sol)
///
/// @dev Note:
/// In many applications, the number of elements in an enumerable set is small.
/// This enumerable set implementation avoids storing the length and indices
/// for up to 3 elements. Once the length exceeds 3 for the first time, the length
/// and indices will be initialized. The amortized cost of adding elements is O(1).
///
/// The AddressSet implementation packs the length with the 0th entry.
///
/// All enumerable sets except Uint8Set use a pop and swap mechanism to remove elements.
/// This means that the iteration order of elements can change between element removals.
library EnumerableSetLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The index must be less than the length.
error IndexOutOfBounds();
/// @dev The value cannot be the zero sentinel.
error ValueIsZeroSentinel();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev A sentinel value to denote the zero value in storage.
/// No elements can be equal to this value.
/// `uint72(bytes9(keccak256(bytes("_ZERO_SENTINEL"))))`.
uint256 private constant _ZERO_SENTINEL = 0xfbb67fda52d4bfb8bf;
/// @dev The storage layout is given by:
/// ```
/// mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED)
/// mstore(0x00, set.slot)
/// let rootSlot := keccak256(0x00, 0x24)
/// mstore(0x20, rootSlot)
/// mstore(0x00, shr(96, shl(96, value)))
/// let positionSlot := keccak256(0x00, 0x40)
/// let valueSlot := add(rootSlot, sload(positionSlot))
/// let valueInStorage := shr(96, sload(valueSlot))
/// let lazyLength := shr(160, shl(160, sload(rootSlot)))
/// ```
uint256 private constant _ENUMERABLE_ADDRESS_SET_SLOT_SEED = 0x978aab92;
/// @dev The storage layout is given by:
/// ```
/// mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED)
/// mstore(0x00, set.slot)
/// let rootSlot := keccak256(0x00, 0x24)
/// mstore(0x20, rootSlot)
/// mstore(0x00, value)
/// let positionSlot := keccak256(0x00, 0x40)
/// let valueSlot := add(rootSlot, sload(positionSlot))
/// let valueInStorage := sload(valueSlot)
/// let lazyLength := sload(not(rootSlot))
/// ```
uint256 private constant _ENUMERABLE_WORD_SET_SLOT_SEED = 0x18fb5864;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STRUCTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev An enumerable address set in storage.
struct AddressSet {
uint256 _spacer;
}
/// @dev An enumerable bytes32 set in storage.
struct Bytes32Set {
uint256 _spacer;
}
/// @dev An enumerable uint256 set in storage.
struct Uint256Set {
uint256 _spacer;
}
/// @dev An enumerable int256 set in storage.
struct Int256Set {
uint256 _spacer;
}
/// @dev An enumerable uint8 set in storage. Useful for enums.
struct Uint8Set {
uint256 data;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* GETTERS / SETTERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the number of elements in the set.
function length(AddressSet storage set) internal view returns (uint256 result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
let rootPacked := sload(rootSlot)
let n := shr(160, shl(160, rootPacked))
result := shr(1, n)
for {} iszero(or(iszero(shr(96, rootPacked)), n)) {} {
result := 1
if iszero(sload(add(rootSlot, result))) { break }
result := 2
if iszero(sload(add(rootSlot, result))) { break }
result := 3
break
}
}
}
/// @dev Returns the number of elements in the set.
function length(Bytes32Set storage set) internal view returns (uint256 result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
let n := sload(not(rootSlot))
result := shr(1, n)
for {} iszero(n) {} {
result := 0
if iszero(sload(add(rootSlot, result))) { break }
result := 1
if iszero(sload(add(rootSlot, result))) { break }
result := 2
if iszero(sload(add(rootSlot, result))) { break }
result := 3
break
}
}
}
/// @dev Returns the number of elements in the set.
function length(Uint256Set storage set) internal view returns (uint256 result) {
result = length(_toBytes32Set(set));
}
/// @dev Returns the number of elements in the set.
function length(Int256Set storage set) internal view returns (uint256 result) {
result = length(_toBytes32Set(set));
}
/// @dev Returns the number of elements in the set.
function length(Uint8Set storage set) internal view returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
for { let packed := sload(set.slot) } packed { result := add(1, result) } {
packed := xor(packed, and(packed, add(1, not(packed))))
}
}
}
/// @dev Returns whether `value` is in the set.
function contains(AddressSet storage set, address value) internal view returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
value := shr(96, shl(96, value))
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
let rootPacked := sload(rootSlot)
for {} 1 {} {
if iszero(shr(160, shl(160, rootPacked))) {
result := 1
if eq(shr(96, rootPacked), value) { break }
if eq(shr(96, sload(add(rootSlot, 1))), value) { break }
if eq(shr(96, sload(add(rootSlot, 2))), value) { break }
result := 0
break
}
mstore(0x20, rootSlot)
mstore(0x00, value)
result := iszero(iszero(sload(keccak256(0x00, 0x40))))
break
}
}
}
/// @dev Returns whether `value` is in the set.
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
for {} 1 {} {
if iszero(sload(not(rootSlot))) {
result := 1
if eq(sload(rootSlot), value) { break }
if eq(sload(add(rootSlot, 1)), value) { break }
if eq(sload(add(rootSlot, 2)), value) { break }
result := 0
break
}
mstore(0x20, rootSlot)
mstore(0x00, value)
result := iszero(iszero(sload(keccak256(0x00, 0x40))))
break
}
}
}
/// @dev Returns whether `value` is in the set.
function contains(Uint256Set storage set, uint256 value) internal view returns (bool result) {
result = contains(_toBytes32Set(set), bytes32(value));
}
/// @dev Returns whether `value` is in the set.
function contains(Int256Set storage set, int256 value) internal view returns (bool result) {
result = contains(_toBytes32Set(set), bytes32(uint256(value)));
}
/// @dev Returns whether `value` is in the set.
function contains(Uint8Set storage set, uint8 value) internal view returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := and(1, shr(and(0xff, value), sload(set.slot)))
}
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
function add(AddressSet storage set, address value) internal returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
value := shr(96, shl(96, value))
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
let rootPacked := sload(rootSlot)
for { let n := shr(160, shl(160, rootPacked)) } 1 {} {
mstore(0x20, rootSlot)
if iszero(n) {
let v0 := shr(96, rootPacked)
if iszero(v0) {
sstore(rootSlot, shl(96, value))
result := 1
break
}
if eq(v0, value) { break }
let v1 := shr(96, sload(add(rootSlot, 1)))
if iszero(v1) {
sstore(add(rootSlot, 1), shl(96, value))
result := 1
break
}
if eq(v1, value) { break }
let v2 := shr(96, sload(add(rootSlot, 2)))
if iszero(v2) {
sstore(add(rootSlot, 2), shl(96, value))
result := 1
break
}
if eq(v2, value) { break }
mstore(0x00, v0)
sstore(keccak256(0x00, 0x40), 1)
mstore(0x00, v1)
sstore(keccak256(0x00, 0x40), 2)
mstore(0x00, v2)
sstore(keccak256(0x00, 0x40), 3)
rootPacked := or(rootPacked, 7)
n := 7
}
mstore(0x00, value)
let p := keccak256(0x00, 0x40)
if iszero(sload(p)) {
n := shr(1, n)
result := 1
sstore(p, add(1, n))
if iszero(n) {
sstore(rootSlot, or(3, shl(96, value)))
break
}
sstore(add(rootSlot, n), shl(96, value))
sstore(rootSlot, add(2, rootPacked))
break
}
break
}
}
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
function add(Bytes32Set storage set, bytes32 value) internal returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
for { let n := sload(not(rootSlot)) } 1 {} {
mstore(0x20, rootSlot)
if iszero(n) {
let v0 := sload(rootSlot)
if iszero(v0) {
sstore(rootSlot, value)
result := 1
break
}
if eq(v0, value) { break }
let v1 := sload(add(rootSlot, 1))
if iszero(v1) {
sstore(add(rootSlot, 1), value)
result := 1
break
}
if eq(v1, value) { break }
let v2 := sload(add(rootSlot, 2))
if iszero(v2) {
sstore(add(rootSlot, 2), value)
result := 1
break
}
if eq(v2, value) { break }
mstore(0x00, v0)
sstore(keccak256(0x00, 0x40), 1)
mstore(0x00, v1)
sstore(keccak256(0x00, 0x40), 2)
mstore(0x00, v2)
sstore(keccak256(0x00, 0x40), 3)
n := 7
}
mstore(0x00, value)
let p := keccak256(0x00, 0x40)
if iszero(sload(p)) {
n := shr(1, n)
sstore(add(rootSlot, n), value)
sstore(p, add(1, n))
sstore(not(rootSlot), or(1, shl(1, add(1, n))))
result := 1
break
}
break
}
}
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
function add(Uint256Set storage set, uint256 value) internal returns (bool result) {
result = add(_toBytes32Set(set), bytes32(value));
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
function add(Int256Set storage set, int256 value) internal returns (bool result) {
result = add(_toBytes32Set(set), bytes32(uint256(value)));
}
/// @dev Adds `value` to the set. Returns whether `value` was not in the set.
function add(Uint8Set storage set, uint8 value) internal returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(set.slot)
let mask := shl(and(0xff, value), 1)
sstore(set.slot, or(result, mask))
result := iszero(and(result, mask))
}
}
/// @dev Removes `value` from the set. Returns whether `value` was in the set.
function remove(AddressSet storage set, address value) internal returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
value := shr(96, shl(96, value))
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
let rootPacked := sload(rootSlot)
for { let n := shr(160, shl(160, rootPacked)) } 1 {} {
if iszero(n) {
result := 1
if eq(shr(96, rootPacked), value) {
sstore(rootSlot, sload(add(rootSlot, 1)))
sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
sstore(add(rootSlot, 2), 0)
break
}
if eq(shr(96, sload(add(rootSlot, 1))), value) {
sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
sstore(add(rootSlot, 2), 0)
break
}
if eq(shr(96, sload(add(rootSlot, 2))), value) {
sstore(add(rootSlot, 2), 0)
break
}
result := 0
break
}
mstore(0x20, rootSlot)
mstore(0x00, value)
let p := keccak256(0x00, 0x40)
let position := sload(p)
if iszero(position) { break }
n := sub(shr(1, n), 1)
if iszero(eq(sub(position, 1), n)) {
let lastValue := shr(96, sload(add(rootSlot, n)))
sstore(add(rootSlot, sub(position, 1)), shl(96, lastValue))
mstore(0x00, lastValue)
sstore(keccak256(0x00, 0x40), position)
}
sstore(rootSlot, or(shl(96, shr(96, sload(rootSlot))), or(shl(1, n), 1)))
sstore(p, 0)
result := 1
break
}
}
}
/// @dev Removes `value` from the set. Returns whether `value` was in the set.
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
if eq(value, _ZERO_SENTINEL) {
mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
revert(0x1c, 0x04)
}
if iszero(value) { value := _ZERO_SENTINEL }
for { let n := sload(not(rootSlot)) } 1 {} {
if iszero(n) {
result := 1
if eq(sload(rootSlot), value) {
sstore(rootSlot, sload(add(rootSlot, 1)))
sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
sstore(add(rootSlot, 2), 0)
break
}
if eq(sload(add(rootSlot, 1)), value) {
sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
sstore(add(rootSlot, 2), 0)
break
}
if eq(sload(add(rootSlot, 2)), value) {
sstore(add(rootSlot, 2), 0)
break
}
result := 0
break
}
mstore(0x20, rootSlot)
mstore(0x00, value)
let p := keccak256(0x00, 0x40)
let position := sload(p)
if iszero(position) { break }
n := sub(shr(1, n), 1)
if iszero(eq(sub(position, 1), n)) {
let lastValue := sload(add(rootSlot, n))
sstore(add(rootSlot, sub(position, 1)), lastValue)
mstore(0x00, lastValue)
sstore(keccak256(0x00, 0x40), position)
}
sstore(not(rootSlot), or(shl(1, n), 1))
sstore(p, 0)
result := 1
break
}
}
}
/// @dev Removes `value` from the set. Returns whether `value` was in the set.
function remove(Uint256Set storage set, uint256 value) internal returns (bool result) {
result = remove(_toBytes32Set(set), bytes32(value));
}
/// @dev Removes `value` from the set. Returns whether `value` was in the set.
function remove(Int256Set storage set, int256 value) internal returns (bool result) {
result = remove(_toBytes32Set(set), bytes32(uint256(value)));
}
/// @dev Removes `value` from the set. Returns whether `value` was in the set.
function remove(Uint8Set storage set, uint8 value) internal returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(set.slot)
let mask := shl(and(0xff, value), 1)
sstore(set.slot, and(result, not(mask)))
result := iszero(iszero(and(result, mask)))
}
}
/// @dev Returns all of the values in the set.
/// Note: This can consume more gas than the block gas limit for large sets.
function values(AddressSet storage set) internal view returns (address[] memory result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
let zs := _ZERO_SENTINEL
let rootPacked := sload(rootSlot)
let n := shr(160, shl(160, rootPacked))
result := mload(0x40)
let o := add(0x20, result)
let v := shr(96, rootPacked)
mstore(o, mul(v, iszero(eq(v, zs))))
for {} 1 {} {
if iszero(n) {
if v {
n := 1
v := shr(96, sload(add(rootSlot, n)))
if v {
n := 2
mstore(add(o, 0x20), mul(v, iszero(eq(v, zs))))
v := shr(96, sload(add(rootSlot, n)))
if v {
n := 3
mstore(add(o, 0x40), mul(v, iszero(eq(v, zs))))
}
}
}
break
}
n := shr(1, n)
for { let i := 1 } lt(i, n) { i := add(i, 1) } {
v := shr(96, sload(add(rootSlot, i)))
mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs))))
}
break
}
mstore(result, n)
mstore(0x40, add(o, shl(5, n)))
}
}
/// @dev Returns all of the values in the set.
/// Note: This can consume more gas than the block gas limit for large sets.
function values(Bytes32Set storage set) internal view returns (bytes32[] memory result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
let zs := _ZERO_SENTINEL
let n := sload(not(rootSlot))
result := mload(0x40)
let o := add(0x20, result)
for {} 1 {} {
if iszero(n) {
let v := sload(rootSlot)
if v {
n := 1
mstore(o, mul(v, iszero(eq(v, zs))))
v := sload(add(rootSlot, n))
if v {
n := 2
mstore(add(o, 0x20), mul(v, iszero(eq(v, zs))))
v := sload(add(rootSlot, n))
if v {
n := 3
mstore(add(o, 0x40), mul(v, iszero(eq(v, zs))))
}
}
}
break
}
n := shr(1, n)
for { let i := 0 } lt(i, n) { i := add(i, 1) } {
let v := sload(add(rootSlot, i))
mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs))))
}
break
}
mstore(result, n)
mstore(0x40, add(o, shl(5, n)))
}
}
/// @dev Returns all of the values in the set.
/// Note: This can consume more gas than the block gas limit for large sets.
function values(Uint256Set storage set) internal view returns (uint256[] memory result) {
result = _toUints(values(_toBytes32Set(set)));
}
/// @dev Returns all of the values in the set.
/// Note: This can consume more gas than the block gas limit for large sets.
function values(Int256Set storage set) internal view returns (int256[] memory result) {
result = _toInts(values(_toBytes32Set(set)));
}
/// @dev Returns all of the values in the set.
function values(Uint8Set storage set) internal view returns (uint8[] memory result) {
/// @solidity memory-safe-assembly
assembly {
result := mload(0x40)
let ptr := add(result, 0x20)
let o := 0
for { let packed := sload(set.slot) } packed {} {
if iszero(and(packed, 0xffff)) {
o := add(o, 16)
packed := shr(16, packed)
continue
}
mstore(ptr, o)
ptr := add(ptr, shl(5, and(packed, 1)))
o := add(o, 1)
packed := shr(1, packed)
}
mstore(result, shr(5, sub(ptr, add(result, 0x20))))
mstore(0x40, ptr)
}
}
/// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
function at(AddressSet storage set, uint256 i) internal view returns (address result) {
bytes32 rootSlot = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
result := shr(96, sload(add(rootSlot, i)))
result := mul(result, iszero(eq(result, _ZERO_SENTINEL)))
}
if (i >= length(set)) revert IndexOutOfBounds();
}
/// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
function at(Bytes32Set storage set, uint256 i) internal view returns (bytes32 result) {
result = _rootSlot(set);
/// @solidity memory-safe-assembly
assembly {
result := sload(add(result, i))
result := mul(result, iszero(eq(result, _ZERO_SENTINEL)))
}
if (i >= length(set)) revert IndexOutOfBounds();
}
/// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
function at(Uint256Set storage set, uint256 i) internal view returns (uint256 result) {
result = uint256(at(_toBytes32Set(set), i));
}
/// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
function at(Int256Set storage set, uint256 i) internal view returns (int256 result) {
result = int256(uint256(at(_toBytes32Set(set), i)));
}
/// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
function at(Uint8Set storage set, uint256 i) internal view returns (uint8 result) {
/// @solidity memory-safe-assembly
assembly {
let packed := sload(set.slot)
for {} 1 {
mstore(0x00, 0x4e23d035) // `IndexOutOfBounds()`.
revert(0x1c, 0x04)
} {
if iszero(lt(i, 256)) { continue }
for { let j := 0 } iszero(eq(i, j)) {} {
packed := xor(packed, and(packed, add(1, not(packed))))
j := add(j, 1)
}
if iszero(packed) { continue }
break
}
// Find first set subroutine, optimized for smaller bytecode size.
let x := and(packed, add(1, not(packed)))
let r := shl(7, iszero(iszero(shr(128, x))))
r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
// For the lower 5 bits of the result, use a De Bruijn lookup.
// forgefmt: disable-next-item
result := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f),
0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PRIVATE HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the root slot.
function _rootSlot(AddressSet storage s) private pure returns (bytes32 r) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED)
mstore(0x00, s.slot)
r := keccak256(0x00, 0x24)
}
}
/// @dev Returns the root slot.
function _rootSlot(Bytes32Set storage s) private pure returns (bytes32 r) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED)
mstore(0x00, s.slot)
r := keccak256(0x00, 0x24)
}
}
/// @dev Casts to a Bytes32Set.
function _toBytes32Set(Uint256Set storage s) private pure returns (Bytes32Set storage c) {
/// @solidity memory-safe-assembly
assembly {
c.slot := s.slot
}
}
/// @dev Casts to a Bytes32Set.
function _toBytes32Set(Int256Set storage s) private pure returns (Bytes32Set storage c) {
/// @solidity memory-safe-assembly
assembly {
c.slot := s.slot
}
}
/// @dev Casts to a uint256 array.
function _toUints(bytes32[] memory a) private pure returns (uint256[] memory c) {
/// @solidity memory-safe-assembly
assembly {
c := a
}
}
/// @dev Casts to a int256 array.
function _toInts(bytes32[] memory a) private pure returns (int256[] memory c) {
/// @solidity memory-safe-assembly
assembly {
c := a
}
}
}{
"viaIR": false,
"codegen": "yul",
"remappings": [
"@limitbreak/permit-c/=lib/creator-token-standards/lib/PermitC/src/",
"@opensea/tstorish/=lib/creator-token-standards/lib/tstorish/src/",
"@openzeppelin/=lib/creator-token-standards/lib/openzeppelin-contracts/",
"@rari-capital/solmate/=lib/creator-token-standards/lib/PermitC/lib/solmate/",
"ERC721A/=lib/ERC721A/contracts/",
"PermitC/=lib/creator-token-standards/lib/PermitC/",
"creator-token-standards/=lib/creator-token-standards/",
"delegate-registry/=lib/delegate-registry/",
"ds-test/=lib/delegate-registry/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/delegate-registry/lib/openzeppelin-contracts/lib/erc4626-tests/",
"erc721a/=lib/creator-token-standards/lib/ERC721A/",
"forge-gas-metering/=lib/creator-token-standards/lib/PermitC/lib/forge-gas-metering/",
"forge-std/=lib/forge-std/src/",
"forge-zksync-std/=lib/forge-zksync-std/src/",
"murky/=lib/creator-token-standards/lib/murky/",
"openzeppelin-contracts/=lib/creator-token-standards/lib/openzeppelin-contracts/",
"openzeppelin/=lib/delegate-registry/lib/openzeppelin-contracts/contracts/",
"solady/=lib/solady/src/",
"solmate/=lib/creator-token-standards/lib/PermitC/lib/solmate/src/",
"tstorish/=lib/creator-token-standards/lib/tstorish/src/"
],
"evmVersion": "cancun",
"outputSelection": {
"*": {
"*": [
"abi"
]
}
},
"optimizer": {
"enabled": true,
"mode": "3",
"size_fallback": false,
"disable_system_request_memoization": true
},
"metadata": {},
"libraries": {},
"enableEraVMExtensions": false,
"forceEVMLA": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"InvalidOutputId","type":"error"},{"inputs":[],"name":"LengthIsZero","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"PriceIsZero","type":"error"},{"inputs":[],"name":"QtyIsZero","type":"error"},{"inputs":[],"name":"RecipeAlreadyRunning","type":"error"},{"inputs":[],"name":"RecipeNotRunning","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnauthorizedCallContext","type":"error"},{"inputs":[],"name":"UpgradeFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"recipeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"name":"CookedRecipes","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"recipeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"recipePrice","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"name":"RecipeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"recipeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"recipePrice","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"name":"RecipeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"uint256","name":"outputId","type":"uint256"},{"internalType":"uint256","name":"recipePrice","type":"uint256"},{"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"name":"addRecipe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"recipeId","type":"uint256[]"}],"name":"cookRecipes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"outputId","type":"uint256"}],"name":"getRecipe","outputs":[{"internalType":"bool","name":"isRunning","type":"bool"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"init","outputs":[],"stateMutability":"nonpayable","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":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"flag","type":"bool"}],"name":"setPauseFlag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"outputId","type":"uint256"},{"internalType":"bool","name":"flag","type":"bool"}],"name":"setRecipeStartFlag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"outputId","type":"uint256"},{"internalType":"uint256","name":"recipePrice","type":"uint256"},{"internalType":"uint256[]","name":"itemId","type":"uint256[]"},{"internalType":"uint256[]","name":"qtys","type":"uint256[]"}],"name":"updateRecipe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
9c4d535b00000000000000000000000000000000000000000000000000000000000000000100028db759cf39cc34156f866b5caf35b5a08eb0965502ce143062a6a231b5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000001b2c84dd7957b1e207cd7b01ded77984ec16fdef
Deployed Bytecode
0x0003000000000002000f00000000000200020000000103550000006003100270000002320030019d000002320330019700000001002001900000002d0000c13d0000008002000039000000400020043f000000040030008c000004cc0000413d000000000201043b000000e0022002700000023a0020009c000000690000a13d0000023b0020009c000000980000a13d0000023c0020009c000001d00000a13d0000023d0020009c0000037c0000613d0000023e0020009c0000038d0000613d0000023f0020009c000004cc0000c13d0000000002000416000000000002004b000004cc0000c13d000000240030008c000004cc0000413d0000000401100370000000000101043b000002350010009c000004cc0000213d00000252020000410000000c0020043f000000000010043f0000000c01000039000000200200003908c508a10000040f000000000101041a000000800010043f0000025301000041000008c60001042e0000000002000416000000000002004b000004cc0000c13d0000001f023000390000023302200197000000a002200039000000400020043f0000001f0430018f0000023405300198000000a0025000390000003e0000613d000000a006000039000000000701034f000000007807043c0000000006860436000000000026004b0000003a0000c13d000000000004004b0000004b0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000200030008c000004cc0000413d000000a00600043d000002350060009c000004cc0000213d0000000001000410000000800010043f0000023601000041000000000061041b0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000003030000390000023804000041000000000500001908c508b60000040f0000000100200190000004cc0000613d000000800100043d0000014000000443000001600010044300000020010000390000010000100443000000010100003900000120001004430000023901000041000008c60001042e000002470020009c000000ad0000213d0000024d0020009c000000ee0000213d000002500020009c000003c60000613d000002510020009c000004cc0000c13d00000252010000410000000c0010043f0000000001000411000000000010043f000002580100004100000000001004430000000001000414000002320010009c0000023201008041000000c00110021000000259011001c70000800b0200003908c508bb0000040f0000000100200190000006880000613d000000000101043b000f00000001001d0000000001000414000002320010009c0000023201008041000000c00110021000000257011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000f02000029000002840220009a000000000021041b0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000002030000390000028504000041000000ca0000013d000002420020009c000000d00000213d000002450020009c000002030000613d000002460020009c000004cc0000c13d0000000002000416000000000002004b000004cc0000c13d000000240030008c000004cc0000413d0000000401100370000000000101043b000f00000001001d000000010010008c000004cc0000213d08c508800000040f0000025c01000041000000000201041a0000028702200197000000ea0000013d000002480020009c000001b70000213d0000024b0020009c000003e10000613d0000024c0020009c000004cc0000c13d00000252010000410000000c0010043f0000000001000411000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000257011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b000000000001041b0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000002030000390000027604000041000000000500041108c508b60000040f0000000100200190000004cc0000613d0000000001000019000008c60001042e000002430020009c0000020c0000613d000002440020009c000004cc0000c13d0000000002000416000000000002004b000004cc0000c13d000000440030008c000004cc0000413d0000002401100370000000000101043b000f00000001001d000000010010008c000004cc0000213d08c508800000040f00000004010000390000000201100367000000000101043b000000000010043f0000025401000041000000200010043f0000004002000039000000000100001908c508a10000040f000000000301041a00000287023001970000000f022001af000000000021041b0000000001000019000008c60001042e0000024e0020009c000003fe0000613d0000024f0020009c000004cc0000c13d000000440030008c000004cc0000413d0000000402100370000000000202043b000f00000002001d000002350020009c000004cc0000213d0000002402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d000d00040020003d0000000d01100360000000000101043b000e00000001001d0000025b0010009c000004cc0000213d0000000e012000290000002401100039000000000031004b000004cc0000213d000002770100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002320010009c0000023201008041000000c00110021000000278011001c7000080050200003908c508bb0000040f0000000100200190000006880000613d000000000101043b0000000002000410000000000021004b000004ce0000613d0000023601000041000000000101041a0000000002000411000000000012004b000004b00000c13d0000000101000031000000000010043f0000024b01000041000000010010043f0000000001000414000002320010009c0000023201008041000000c0011002100000027b011001c70000000f0200002908c508bb0000040f00000060031002700000023203300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf0000013b0000613d0000000107000039000000000801034f000000008908043c0000000007970436000000000047004b000001370000c13d000000010220018f000000000005004b000001490000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000100000003001f0000000001020433000002790010009c0000069f0000c13d0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000002030000390000027d040000410000000f0500002908c508b60000040f0000000100200190000004cc0000613d00000279010000410000000f02000029000000000021041b0000000e0000006b000000ce0000613d0000000e0300002900000288023001980000001f0330018f000000400100043d000c00000001001d00000000012100190000000d04000029000000200440003900000002044003670000016e0000613d000000000504034f0000000c06000029000000005705043c0000000006760436000000000016004b0000016a0000c13d000000000003004b0000017b0000613d000000000224034f0000000303300210000000000401043300000000043401cf000000000434022f000000000202043b0000010003300089000000000232022f00000000023201cf000000000242019f000000000021043500000265010000410000000000100443000000000100041200000004001004430000000001000414000002320010009c0000023201008041000000c00110021000000267011001c7000080020200003908c508bb0000040f0000000100200190000006880000613d0000000e01000029000002320010009c000002320100804100000060011002100000000002000414000002320020009c0000023202008041000000c002200210000000000112019f0000000c02000029000002320020009c0000023202008041000e0040002002180000000e011001af0000000f0200002908c508c00000040f0000006003100270000102320030019d0000000100200190000000ce0000c13d00000232023001970000001f0420018f00000234052001980000000c080000290000000003580019000001a70000613d000000000601034f000000006706043c0000000008780436000000000038004b000001a30000c13d000000000004004b000001b40000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000013043500000060012002100000000e011001af000008c700010430000002490020009c000004720000613d0000024a0020009c000004cc0000c13d0000023601000041000000000501041a0000000001000411000000000051004b000004b00000c13d0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000003030000390000023804000041000000000600001908c508b60000040f0000000100200190000004cc0000613d0000023601000041000000000001041b0000000001000019000008c60001042e000002400020009c000004b40000613d000002410020009c000004cc0000c13d000000240030008c000004cc0000413d0000000401100370000000000101043b000f00000001001d000002350010009c000004cc0000213d0000023601000041000000000101041a0000000002000411000000000012004b000004b00000c13d00000252010000410000000c0010043f0000000f01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000257011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b000d00000001001d000000000101041a000e00000001001d000002580100004100000000001004430000000001000414000002320010009c0000023201008041000000c00110021000000259011001c70000800b0200003908c508bb0000040f0000000100200190000006880000613d000000000101043b0000000e0010006c000006990000a13d0000025a01000041000000000010043f0000025601000041000008c7000104300000000001000416000000000001004b000004cc0000c13d0000023601000041000000000101041a0000023501100197000000800010043f0000025301000041000008c60001042e0000000002000416000000000002004b000004cc0000c13d000000840030008c000004cc0000413d0000002402100370000000000202043b000c00000002001d0000000402100370000000000202043b000d00000002001d0000004402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d0000000404200039000000000441034f000000000404043b000f00000004001d0000025b0040009c000004cc0000213d00000024042000390000000f020000290000000502200210000700000004001d000500000002001d0000000002420019000000000032004b000004cc0000213d0000006402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d0000000404200039000000000141034f000000000101043b0000025b0010009c000004cc0000213d00000024042000390000000502100210000400000002001d000600000004001d0000000002420019000000000032004b000004cc0000213d0000023602000041000000000202041a0000000003000411000000000023004b000004b00000c13d0000000d0000006b000004ac0000613d0000000f0010006b000006c00000c13d0000000d01000029000000000010043f0000025401000041000000200010043f0000000001000414000002320010009c0000023201008041000000c0011002100000025f011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b000e00000001001d000000000101041a000000ff00100190000006d10000c13d0000000c01000029000000080110021000000001011001bf0000000e02000029000000000012041b0000000f0000006b000006bc0000613d00000005010000290000003f01100039000a02630010019b000000400100043d0000000a02100029000000000012004b000000000300003900000001030040390000025b0020009c000006f60000213d0000000100300190000006f60000c13d000000400020043f0000000f020000290000000002210436000800000002001d00000005020000290003001f00200193000000000002004b0000027d0000613d0000000804000029000000050240002900000000030000310000000203300367000000003503043c0000000004540436000000000024004b000002790000c13d000000030000006b0000000001010433000900000001001d0000025b0010009c000006f60000213d0000000e010000290000000101100039000000000301041a000b00000001001d0000000902000029000000000021041b000200000003001d000000000032004b0000029f0000813d0000000b01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000201043b00000009012000290000000202200029000000000021004b0000029f0000813d000000000001041b0000000101100039000000000021004b0000029b0000413d0000000b01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000906000029000000000006004b0000000805000029000002b60000613d000000000200001900000000031200190000000054050434000000000043041b0000000102200039000000000062004b000002b00000413d000000400100043d0000000a02100029000000000012004b000000000300003900000001030040390000025b0020009c000006f60000213d0000000100300190000006f60000c13d000000400020043f0000000f020000290000000002210436000800000002001d000000050000006b000002cd0000613d0000000804000029000000050240002900000000030000310000000203300367000000003503043c0000000004540436000000000024004b000002c90000c13d000000030000006b0000000001010433000900000001001d0000025b0010009c000006f60000213d0000000e010000290000000201100039000000000301041a000a00000001001d0000000902000029000000000021041b000e00000003001d000000000032004b000002ef0000813d0000000a01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000201043b00000009012000290000000e02200029000000000021004b000002ef0000813d000000000001041b0000000101100039000000000021004b000002eb0000413d0000000a01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000906000029000000000006004b0000000805000029000003060000613d000000000200001900000000031200190000000054050434000000000043041b0000000102200039000000000062004b000003000000413d0000000004000019000000050140021000000006031000290000000202300367000000000202043b000000000002004b0000081d0000613d000900000003001d00000007011000290000000201100367000000000101043b000800000001001d0000000b01000029000000000101041a000e00000004001d000000000041004b000008170000a13d0000000b01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000e011000290000000803000029000000000031041b00000009010000290000000201100367000000000101043b000900000001001d0000000a01000029000000000101041a0000000e0010006c000008170000a13d0000000a01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f00000001002001900000008003000039000004cc0000613d000000000101043b0000000e0400002900000000014100190000000902000029000000000021041b00000001044000390000000f0040006c000003070000413d000000400100043d00000080021000390000000f0400002900000000004204350000004002100039000000000032043500000020021000390000000c0300002900000000003204350000000d020000290000000000210435000000a00410003900000005034000290000000202000367000000050000006b000003570000613d0000000705200360000000005605043c0000000004640436000000000034004b000003530000c13d000000030000006b0000000004130049000000600510003900000000004504350000000f04000029000000000343043600000004050000290000001f0450018f000000000005004b000003680000613d000000060220036000000004053000290000000006030019000000002702043c0000000006760436000000000056004b000003640000c13d000000000004004b00000004021000690000000002320019000002320020009c00000232020080410000006002200210000002320010009c00000232010080410000004001100210000000000112019f0000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000237011001c70000800d0200003900000001030000390000026e04000041000008160000013d000000240030008c000004cc0000413d0000000401100370000000000101043b000002350010009c000004cc0000213d0000023602000041000000000202041a0000000003000411000000000023004b000004b00000c13d000000000001004b0000069c0000c13d0000025501000041000000000010043f0000025601000041000008c7000104300000000002000416000000000002004b000004cc0000c13d000000240030008c000004cc0000413d0000000401100370000000000101043b000000000010043f0000025401000041000000200010043f0000004002000039000000000100001908c508a10000040f0000000002010019000f00000001001d000000000101041a000d00000001001d000000010120003908c5084b0000040f000e00000001001d0000000f01000029000000020110003908c5084b0000040f0000000d050000290000000802500270000000400400043d000f00000004001d00000020034000390000000000230435000000400240003900000080030000390000000000320435000000ff005001900000000002000039000000010200c0390000000000240435000d00000001001d00000080024000390000000e0100002908c508210000040f00000000020100190000000f030000290000000001310049000000600330003900000000001304350000000d0100002908c508210000040f0000000f020000290000000001210049000002320020009c00000232020080410000004002200210000002320010009c00000232010080410000006001100210000000000121019f000008c60001042e0000000002000416000000000002004b000004cc0000c13d000000240030008c000004cc0000413d0000000401100370000000000601043b000002350060009c000004cc0000213d0000023601000041000000000201041a0000023500200198000004f00000c13d000000000061041b0000000001000414000002320010009c0000023201008041000000c00110021000000237011001c70000800d0200003900000003030000390000023804000041000000000500001908c508b60000040f0000000100200190000004cc0000613d000000ce0000013d0000000001000416000000000001004b000004cc0000c13d000002770100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002320010009c0000023201008041000000c00110021000000278011001c7000080050200003908c508bb0000040f0000000100200190000006880000613d000000000101043b0000000002000410000000000021004b000004ce0000c13d000000400100043d00000279020000410000000000210435000002320010009c000002320100804100000040011002100000027a011001c7000008c60001042e0000000001000416000000000001004b000004cc0000c13d0000023601000041000000000201041a0000000001000411000000000021004b000004b00000c13d000e00000002001d0000028001000041000000800010043f0000000001000410000000840010043f0000000001000414000002320010009c0000023201008041000000c00110021000000281011001c7000002620200004108c508b60000040f000000800a00003900000060031002700000023203300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000004210000613d000000000801034f000000008908043c000000000a9a043600000000005a004b0000041d0000c13d000000000006004b0000042e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f0000000100200190000004d20000613d0000001f01400039000000600110018f00000080021001bf000f00000002001d000000400020043f000000200030008c000004cc0000413d000000800200043d00000282030000410000000f05000029000000000035043500000084031001bf0000000e040000290000000000430435000000a40110003900000000002104350000000001000414000002320010009c0000023201008041000000c0011002100000004002500210000000000121019f00000283011001c7000002620200004108c508b60000040f00000060031002700000023203300197000000200030008c000000200a000039000000000a0340190000001f05a0018f0000002006a001900000000f04600029000004590000613d000000000701034f0000000f08000029000000007907043c0000000008980436000000000048004b000004550000c13d000000000005004b000004660000613d000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000100000003001f0000000100200190000006890000613d0000000f0100002900000000020a0019000e0000000a001d08c5082e0000040f0000000f010000290000000e0210002908c508400000040f0000000001000019000008c60001042e0000000002000416000000000002004b000004cc0000c13d000000840030008c000004cc0000413d0000002402100370000000000202043b000800000002001d0000000402100370000000000202043b000900000002001d0000004402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d0000000404200039000000000441034f000000000404043b000e00000004001d0000025b0040009c000004cc0000213d00000024042000390000000e020000290000000502200210000700000004001d000500000002001d0000000002420019000000000032004b000004cc0000213d0000006402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d0000000404200039000000000141034f000000000101043b0000025b0010009c000004cc0000213d00000024042000390000000502100210000400000002001d000600000004001d0000000002420019000000000032004b000004cc0000213d0000023602000041000000000202041a0000000003000411000000000023004b000004b00000c13d000000090000006b000006a30000c13d0000027501000041000000000010043f0000025e01000041000008c7000104300000027f01000041000000000010043f0000025601000041000008c7000104300000000002000416000000000002004b000004cc0000c13d000000240030008c000004cc0000413d0000000402100370000000000202043b0000025b0020009c000004cc0000213d0000002304200039000000000034004b000004cc0000813d0000000404200039000000000141034f000000000101043b000200000001001d0000025b0010009c000004cc0000213d000100240020003d000000020100002900000005011002100000000101100029000000000031004b000004f40000a13d0000000001000019000008c7000104300000027e01000041000000000010043f0000025601000041000008c7000104300000001f0530018f0000023406300198000000400200043d0000000004620019000004dd0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000004d90000c13d000000000005004b000004ea0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000002320020009c00000232020080410000004002200210000000000112019f000008c7000104300000028601000041000000000010043f0000025e01000041000008c7000104300000025c01000041000000000101041a000000ff00100190000006950000c13d000000020000006b000000ce0000613d000400000000001d0000000401000029000000050110021000000001011000290000000201100367000000000101043b000300000001001d000000000010043f0000025401000041000000200010043f0000000001000414000002320010009c0000023201008041000000c0011002100000025f011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b000500000001001d000000000101041a000000ff00100190000006fc0000613d0000000801100272000007000000613d000000400300043d000f00000003001d0000004402300039000000000012043500000024013000390000000002000410000000000021043500000260010000410000000000130435000000040130003900000000020004110000000000210435000002320030009c0000023201000041000000000103401900000040011002100000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000261011001c7000002620200004108c508b60000040f0000000f0a00002900000060031002700000023203300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000053b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000005370000c13d0000001f07400190000005480000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000100000003001f0000000100200190000007040000613d0000001f01400039000000600110018f0000000002a10019000000000012004b00000000010000390000000101004039000e00000002001d0000025b0020009c000006f60000213d0000000100100190000006f60000c13d0000000e01000029000000400010043f000000200030008c000004cc0000413d00000000010a0433000000010010008c000004cc0000213d00000005010000290000000101100039000c00000001001d000000000101041a000800000001001d0000025b0010009c000006f60000213d000000080100002900000005021002100000003f0120003900000263041001970000000e014000290000025b0010009c000006f60000213d000000400010043f0000000e0100002900000008030000290000000001310436000700000001001d00000000010000310000000201100367000000000002004b0000057b0000613d00000007060000290000000003260019000000000501034f000000005705043c0000000006760436000000000036004b000005770000c13d0000001f03200190000000400500043d0000000004450019000d00000005001d000000000054004b000000000500003900000001050040390000025b0040009c000006f60000213d0000000100500190000006f60000c13d000000400040043f0000000d0400002900000008050000290000000004540436000600000004001d000000000002004b000005930000613d00000006040000290000000002240019000000001501043c0000000004540436000000000024004b0000058f0000c13d000000000003004b000000080000006b000006120000613d0000000501000029000b00020010003d00000000020000190000000c01000029000000000101041a000000000021004b000008170000a13d000f00000002001d0000000c01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d0000000e0200002900000000020204330000000f03000029000000000032004b000008170000a13d0000000504300210000a00000004001d0000000702400029000000000101043b0000000001310019000000000101041a000900000002001d00000000001204350000000b01000029000000000101041a000000000031004b000008170000a13d0000000b01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000d0200002900000000020204330000000f03000029000000000032004b000008170000a13d0000000001310019000000000201041a0000000a040000290000000601400029000a00000002001d00000000002104350000000e010000290000000001010433000000000031004b000008170000a13d0000000d010000290000000001010433000000000031004b000008170000a13d00000009010000290000000001010433000900000001001d00000265010000410000000000100443000002660100004100000004001004430000000001000414000002320010009c0000023201008041000000c00110021000000267011001c7000080020200003908c508bb0000040f0000000100200190000006880000613d000000000101043b000000000001004b000004cc0000613d000000400300043d00000044013000390000000a02000029000000000021043500000024013000390000000902000029000000000021043500000268010000410000000000130435000000040130003900000000020004110000000000210435000002320030009c000a00000003001d0000023201000041000000000103401900000040011002100000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000261011001c7000002660200004108c508b60000040f0000006003100270000102320030019d0000000100200190000006c40000613d0000000a060000290000025b0060009c000006f60000213d000000400060043f0000000f020000290000000102200039000000080020006c000005990000413d000006130000013d000000400600043d0000000501000029000000000101041a000000000200041100000000002604350000006002600039000000a00300003900000000003204350000000801100270000000400260003900000000001204350000002001600039000000030200002900000000002104350000000e050000290000000002050433000000a0016000390000000000210435000000c001600039000000000002004b0000062e0000613d00000000030000190000002005500039000000000405043300000000014104360000000103300039000000000023004b000006280000413d0000000002610049000000800360003900000000002304350000000d0500002900000000020504330000000001210436000000000002004b0000063d0000613d00000000030000190000002005500039000000000405043300000000014104360000000103300039000000000023004b000006370000413d0000000001610049000002320010009c00000232010080410000006001100210000002320060009c00000232060080410000004002600210000000000121019f0000000002000414000002320020009c0000023202008041000000c002200210000000000121019f00000237011001c70000800d020000390000000103000039000002690400004108c508b60000040f0000000100200190000004cc0000613d00000265010000410000000000100443000002660100004100000004001004430000000001000414000002320010009c0000023201008041000000c00110021000000267011001c7000080020200003908c508bb0000040f0000000100200190000006880000613d000000000101043b000000000001004b000004cc0000613d000000400300043d0000004401300039000000010200003900000000002104350000002401300039000000030200002900000000002104350000026a010000410000000000130435000000040130003900000000020004110000000000210435000002320030009c000f00000003001d0000023201000041000000000103401900000040011002100000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000261011001c7000002660200004108c508b60000040f0000006003100270000102320030019d0000000100200190000007100000613d0000000f010000290000025b0010009c000006f60000213d000000400010043f00000004020000290000000102200039000400000002001d000000020020006c000004fb0000413d000000ce0000013d000000000001042f0000001f0530018f0000023406300198000000400200043d0000000004620019000004dd0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006900000c13d000004dd0000013d0000025d01000041000000000010043f0000025e01000041000008c7000104300000000d01000029000000000001041b0000000f0100002908c5088a0000040f0000000001000019000008c60001042e0000027c01000041000000010010043f0000027b01000041000008c7000104300000000e0010006b000006c00000c13d0000000901000029000000000010043f0000025401000041000000200010043f0000000001000414000002320010009c0000023201008041000000c0011002100000025f011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d00000008020000290000000802200210000000000301043b000000000103041a000000ff0110018f000000000121019f000f00000003001d000000000013041b0000000e0000006b000006d50000c13d0000027401000041000000000010043f0000025e01000041000008c7000104300000026f01000041000000000010043f0000025e01000041000008c70001043000000232033001970000001f0530018f0000023406300198000000400200043d0000000004620019000004dd0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006cc0000c13d000004dd0000013d0000026d01000041000000000010043f0000025e01000041000008c70001043000000005010000290000003f01100039000c02630010019b000000400100043d0000000c02100029000000000012004b000000000300003900000001030040390000025b0020009c000006f60000213d0000000100300190000006f60000c13d000000400020043f0000000e020000290000000002210436000a00000002001d00000005020000290003001f00200193000000000002004b000006f10000613d0000000a04000029000000050240002900000000030000310000000203300367000000003503043c0000000004540436000000000024004b000006ed0000c13d000000030000006b0000000001010433000b00000001001d0000025b0010009c0000071d0000a13d0000027001000041000000000010043f0000004101000039000000040010043f0000027101000041000008c7000104300000026c01000041000000000010043f0000025e01000041000008c7000104300000026b01000041000000000010043f0000025e01000041000008c7000104300000001f0530018f0000023406300198000000400200043d0000000004620019000004dd0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000070b0000c13d000004dd0000013d00000232033001970000001f0530018f0000023406300198000000400200043d0000000004620019000004dd0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000007180000c13d000004dd0000013d0000000f010000290000000101100039000000000301041a000d00000001001d0000000b02000029000000000021041b000200000003001d000000000032004b0000073a0000813d0000000d01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000201043b0000000b012000290000000202200029000000000021004b0000073a0000813d000000000001041b0000000101100039000000000021004b000007360000413d0000000d01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000b06000029000000000006004b0000000a05000029000007510000613d000000000200001900000000031200190000000054050434000000000043041b0000000102200039000000000062004b0000074b0000413d000000400100043d0000000c02100029000000000012004b000000000300003900000001030040390000025b0020009c000006f60000213d0000000100300190000006f60000c13d000000400020043f0000000e020000290000000002210436000a00000002001d000000050000006b000007680000613d0000000a04000029000000050240002900000000030000310000000203300367000000003503043c0000000004540436000000000024004b000007640000c13d000000030000006b0000000001010433000b00000001001d0000025b0010009c000006f60000213d0000000f010000290000000201100039000000000301041a000c00000001001d0000000b02000029000000000021041b000f00000003001d000000000032004b0000078a0000813d0000000c01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000201043b0000000b012000290000000f02200029000000000021004b0000078a0000813d000000000001041b0000000101100039000000000021004b000007860000413d0000000c01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000b06000029000000000006004b0000000a05000029000007a10000613d000000000200001900000000031200190000000054050434000000000043041b0000000102200039000000000062004b0000079b0000413d0000000004000019000000050140021000000006031000290000000202300367000000000202043b000000000002004b0000081d0000613d000b00000003001d00000007011000290000000201100367000000000101043b000a00000001001d0000000d01000029000000000101041a000f00000004001d000000000041004b000008170000a13d0000000d01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000004cc0000613d000000000101043b0000000f011000290000000a03000029000000000031041b0000000b010000290000000201100367000000000101043b000b00000001001d0000000c01000029000000000101041a0000000f0010006c000008170000a13d0000000c01000029000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f00000001002001900000008003000039000004cc0000613d000000000101043b0000000f0400002900000000014100190000000b02000029000000000021041b00000001044000390000000e0040006c000007a20000413d000000400100043d00000080021000390000000e0400002900000000004204350000004002100039000000000032043500000020021000390000000803000029000000000032043500000009020000290000000000210435000000a00410003900000005034000290000000202000367000000050000006b000007f20000613d0000000705200360000000005605043c0000000004640436000000000034004b000007ee0000c13d000000030000006b0000000004130049000000600510003900000000004504350000000e04000029000000000343043600000004050000290000001f0450018f000000000005004b000008030000613d000000060220036000000004053000290000000006030019000000002702043c0000000006760436000000000056004b000007ff0000c13d000000000004004b00000004021000690000000002320019000002320020009c00000232020080410000006002200210000002320010009c00000232010080410000004001100210000000000112019f0000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000237011001c70000800d0200003900000001030000390000027204000041000000cb0000013d0000027001000041000000000010043f0000003201000039000000040010043f0000027101000041000008c7000104300000027301000041000000000010043f0000025e01000041000008c700010430000000000301001900000000040104330000000001420436000000000004004b0000082d0000613d00000000020000190000002003300039000000000503043300000000015104360000000102200039000000000042004b000008270000413d000000000001042d0000001f0220003900000288022001970000000001120019000000000021004b000000000200003900000001020040390000025b0010009c0000083a0000213d00000001002001900000083a0000c13d000000400010043f000000000001042d0000027001000041000000000010043f0000004101000039000000040010043f0000027101000041000008c7000104300000000002120049000002890020009c000008490000213d0000001f0020008c000008490000a13d0000000001010433000000010010008c000008490000213d000000000001042d0000000001000019000008c7000104300003000000000002000000000301041a000000400200043d000300000002001d000100000003001d0000000002320436000200000002001d000000000010043f0000000001000414000002320010009c0000023201008041000000c00110021000000264011001c7000080100200003908c508bb0000040f0000000100200190000008780000613d0000000105000029000000000005004b000008690000613d000000000101043b00000000020000190000000204000029000000000301041a000000000434043600000001011000390000000102200039000000000052004b000008620000413d0000086a0000013d0000000204000029000000030100002900000000021400490000001f0320003900000288023001970000000003120019000000000023004b000000000200003900000001020040390000025b0030009c0000087a0000213d00000001002001900000087a0000c13d000000400030043f000000000001042d0000000001000019000008c7000104300000027001000041000000000010043f0000004101000039000000040010043f0000027101000041000008c7000104300000023601000041000000000101041a0000000002000411000000000012004b000008860000c13d000000000001042d0000027f01000041000000000010043f0000025601000041000008c70001043000010000000000020000023602000041000000000502041a00000000020004140000023506100197000002320020009c0000023202008041000000c00120021000000237011001c70000800d0200003900000003030000390000023804000041000100000006001d08c508b60000040f00000001002001900000089e0000613d00000236010000410000000102000029000000000021041b000000000001042d0000000001000019000008c700010430000000000001042f000002320010009c00000232010080410000004001100210000002320020009c00000232020080410000006002200210000000000112019f0000000002000414000002320020009c0000023202008041000000c002200210000000000112019f00000237011001c7000080100200003908c508bb0000040f0000000100200190000008b40000613d000000000101043b000000000001042d0000000001000019000008c700010430000008b9002104210000000102000039000000000001042d0000000002000019000000000001042d000008be002104230000000102000039000000000001042d0000000002000019000000000001042d000008c3002104250000000102000039000000000001042d0000000002000019000000000001042d000008c500000432000008c60001042e000008c70001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392702000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e00000000200000000000000000000000000000080000001000000000000000000000000000000000000000000000000000000000000000000000000008da5cb5a00000000000000000000000000000000000000000000000000000000eb62ce8500000000000000000000000000000000000000000000000000000000f2fde38a00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000f8d12a4100000000000000000000000000000000000000000000000000000000fee81cf400000000000000000000000000000000000000000000000000000000eb62ce8600000000000000000000000000000000000000000000000000000000f04e283e00000000000000000000000000000000000000000000000000000000ad428ba900000000000000000000000000000000000000000000000000000000ad428baa00000000000000000000000000000000000000000000000000000000df7a4b9a000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000008da92e710000000000000000000000000000000000000000000000000000000052d1902c0000000000000000000000000000000000000000000000000000000064ae249d0000000000000000000000000000000000000000000000000000000064ae249e00000000000000000000000000000000000000000000000000000000715018a60000000000000000000000000000000000000000000000000000000052d1902d0000000000000000000000000000000000000000000000000000000054d1f13d000000000000000000000000000000000000000000000000000000003ccfd60a000000000000000000000000000000000000000000000000000000003ccfd60b000000000000000000000000000000000000000000000000000000004f1ef2860000000000000000000000000000000000000000000000000000000019ab453c000000000000000000000000000000000000000000000000000000002569296200000000000000000000000000000000000000000000000000000000389a75e10000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000059500cb63f71b71a86000000000000000000000000000000000000000000000000000000007448fbae00000000000000000000000000000000000000040000001c000000000000000002000000000000000000000000000000000000200000000c0000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000006f5e8818000000000000000000000000000000000000000000000000ffffffffffffffff000000000000000000000000000000000000000000000059500cb63f71b71a879e87fac8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000020000000000000000000000000000000000004000000000000000000000000023b872dd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000033ee11ce309854a45b65368c078616abcb5c6e3d00000000000000000000000000000000000000000000003fffffffffffffffe002000000000000000000000000000000000000200000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8300000000000000000000000014f926d2751f4bb0200e9b016b6ae4a1e4b207bd0200000200000000000000000000000000000024000000000000000000000000f5298aca00000000000000000000000000000000000000000000000000000000c259359a889be310ee009908708eb5cf8b76b6a87d85a5f2feaa2cc35d43ca0a156e29f600000000000000000000000000000000000000000000000000000000907adecd000000000000000000000000000000000000000000000000000000001a9e6e1500000000000000000000000000000000000000000000000000000000ed17b0ac000000000000000000000000000000000000000000000000000000002679c8af4390c9ade41a4ccdb614490d83c940b6f84c746d29765c3dcc45f513947d5a84000000000000000000000000000000000000000000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000007d9b171d1be5a58940ea2f76358ecf144e532d6d156e16496f0f316b5c19dff64c233bda000000000000000000000000000000000000000000000000000000000c71ec17000000000000000000000000000000000000000000000000000000002f97ff7a00000000000000000000000000000000000000000000000000000000fa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0200000200000000000000000000000000000044000000000000000000000000360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040000001d00000000000000000000000000000000000000000000000000000000000000000000000055299b49bc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b000000000000000000000000000000000000000000000000000000009f03a0260000000000000000000000000000000000000000000000000000000082b4290070a08231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000800000000000000000a9059cbb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d00dbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d0dc149f000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000a26469706673582212200fb530da0837a6bf82a167cb4634253da8be16415ce6ebcdfc83e8634aff315a64736f6c6378247a6b736f6c633a312e352e31353b736f6c633a302e382e33303b6c6c766d3a312e302e320055
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001b2c84dd7957b1e207cd7b01ded77984ec16fdef
-----Decoded View---------------
Arg [0] : _owner (address): 0x1B2C84dd7957b1e207Cd7b01Ded77984eC16fDEf
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000001b2c84dd7957b1e207cd7b01ded77984ec16fdef
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.