More Info
Private Name Tags
ContractCreator
Latest 5 from a total of 5 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Legacy Bosu Pre ... | 5141797 | 4 days ago | IN | 1.232 ETH | 0.00000587 | ||||
Legacy Bosu Pre ... | 5100413 | 5 days ago | IN | 4.224 ETH | 0.00000695 | ||||
Legacy Bosu Pre ... | 5055081 | 5 days ago | IN | 2.464 ETH | 0.00000571 | ||||
Legacy Bosu Pre ... | 4995110 | 6 days ago | IN | 1.76 ETH | 0.00000536 | ||||
Legacy Bosu Pre ... | 4994187 | 6 days ago | IN | 5.456 ETH | 0.00000553 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
5308982 | 2 days ago | 0.095 ETH | ||||
5308961 | 2 days ago | 0.095 ETH | ||||
5308960 | 2 days ago | 0.095 ETH | ||||
5308957 | 2 days ago | 0.095 ETH | ||||
5308956 | 2 days ago | 0.095 ETH | ||||
5308956 | 2 days ago | 0.095 ETH | ||||
5308956 | 2 days ago | 0.095 ETH | ||||
5308955 | 2 days ago | 0.095 ETH | ||||
5308955 | 2 days ago | 0.095 ETH | ||||
5308955 | 2 days ago | 0.095 ETH | ||||
5308955 | 2 days ago | 0.095 ETH | ||||
5308955 | 2 days ago | 0.095 ETH | ||||
5308954 | 2 days ago | 0.095 ETH | ||||
5308954 | 2 days ago | 0.095 ETH | ||||
5308954 | 2 days ago | 0.095 ETH | ||||
5308954 | 2 days ago | 0.095 ETH | ||||
5308953 | 2 days ago | 0.095 ETH | ||||
5308953 | 2 days ago | 0.095 ETH | ||||
5308953 | 2 days ago | 0.095 ETH | ||||
5308952 | 2 days ago | 0.095 ETH | ||||
5308952 | 2 days ago | 0.095 ETH | ||||
5308952 | 2 days ago | 0.095 ETH | ||||
5308951 | 2 days ago | 0.095 ETH | ||||
5308951 | 2 days ago | 0.095 ETH | ||||
5308951 | 2 days ago | 0.095 ETH |
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 Source Code Verified (Exact Match)
Contract Name:
FinalBosuPreOrder
Compiler Version
v0.8.28+commit.7893614a
ZkSolc Version
v1.5.11
Optimization Enabled:
Yes with Mode 3
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {Ownable} from "solady/src/auth/Ownable.sol"; import {MerkleProofLib} from "solady/src/utils/MerkleProofLib.sol"; import {SafeTransferLib} from "solady/src/utils/ext/zksync/SafeTransferLib.sol"; import {IFinalBosuBadges} from "./interfaces/IFinalBosuBadges.sol"; import {IExclusiveDelegateResolver} from "./interfaces/IExclusiveDelegateResolver.sol"; /// @title Final Bosu Pre-Order Contract /// @notice Manages the pre-order sales for Final Bosu with multiple phases (Legacy Bosu, GTD, FCFS) /// @author @finalbosuX /// @dev Implements different pre-order phases with merkle-proof verification, whitelisting, and badge minting contract FinalBosuPreOrder is Ownable { /// @notice Thrown when a sale phase has ended or the pre-order limit is reached error SaleFinished(); /// @notice Thrown when the sent ETH amount doesn't match the required price error IncorrectPrice(); /// @notice Thrown when an address has already participated in a specific pre-order phase error AlreadyParticipant(); /// @notice Thrown when the provided merkle proof is invalid error IncorrectProof(); /// @notice Thrown when an operation is not allowed error NotAllowed(); /// @notice Thrown when the maximum pre-order limit is exceeded error MaxPreOrderExceeded(); /// @notice Thrown when setting an invalid treasury address error InvalidTreasury(); /// @notice Thrown when setting an invalid badge contract address error InvalidBadgeContract(); /// @notice Thrown when setting an invalid timestamp error InvalidTimestamp(); /// @notice Thrown when delegate resolver is not set error DelegateResolverNotSet(); /// @notice Thrown when caller is not delegated by the specified address error NotDelegated(); /// @notice Thrown when the pre-order limit is exceeded error PreOrderLimitReached(); /// @notice Thrown when the whitelist is invalid error InvalidWhitelist(); /// @notice Thrown when the amount is invalid (zero) error InvalidAmount(); /// @notice Emitted when an address participates in any pre-order phase /// @param participant The address that participated in the pre-sale /// @param amount The number of items pre-ordered event PresaleParticipant(address indexed participant, uint256 amount); /// @notice The rights for the exclusive delegate resolver bytes24 constant _AGW_LINK_RIGHTS = bytes24(keccak256("AGW_LINK")); /// @notice The price for pre-order in ETH /// @dev Initialized to 0.088 ETH uint256 public price = 0.088 ether; /// @notice Maximum number of participants eligible for pre-order uint256 public preOrderLimit = 3055; /// @notice Tracks whitelist allocation for legacy Bosu pre-order /// @dev Maps address to number of allowed pre-orders mapping(address => uint256) public legacyBosuWhitelist; /// @notice Timestamp when legacy Bosu pre-order phase starts uint40 public legacyBosuStartTime; /// @notice Timestamp when legacy Bosu pre-order phase ends uint40 public legacyBosuEndTime; /// @notice Tracks if an address has participated in GTD pre-order mapping(address => bool) public isGTDParticipant; /// @notice The merkle root for GTD whitelist verification bytes32 public gtdRoot; /// @notice Timestamp when GTD pre-order phase starts uint40 public gtdStartTime; /// @notice Timestamp when GTD pre-order phase ends uint40 public gtdEndTime; /// @notice Tracks if an address has participated in FCFS pre-order mapping(address => bool) public isFCFSParticipant; /// @notice The merkle root for FCFS whitelist verification bytes32 public fcfsRoot; /// @notice Timestamp when FCFS pre-order phase starts uint40 public fcfsStartTime; /// @notice Timestamp when FCFS pre-order phase ends uint40 public fcfsEndTime; /// @notice Counter for total pre-sale participants uint256 public presaleParticipantCounter; /// @notice Tracks address and amount owed to a pre-sale participant mapping(address => uint256) public presaleParticipants; /// @notice The badge contract address for minting SBT badges address public badgeContract; /// @notice Treasury wallet to receive the pre-sale proceeds address public treasury; /// @notice The delegate resolver address address public delegateResolver; /// @notice Checks if the msg.sender has delegated the rights to the delegate /// @param delegated The address of the delegated user modifier checkDelegate(address delegated) { if (delegateResolver == address(0)) revert DelegateResolverNotSet(); IExclusiveDelegateResolver instance = IExclusiveDelegateResolver( delegateResolver ); if ( msg.sender != instance.exclusiveWalletByRights(delegated, _AGW_LINK_RIGHTS) ) { revert NotDelegated(); } _; } /// @notice Checks if a phase is active based on start and end time /// @param startTime The phase start timestamp /// @param endTime The phase end timestamp modifier isPhaseActive(uint40 startTime, uint40 endTime) { if (startTime > block.timestamp || endTime <= block.timestamp) { revert SaleFinished(); } _; } /// @notice Checks if the pre-order limit is exceeded /// @param amount The number of items being pre-ordered modifier withinPreOrderLimit(uint256 amount) { if (presaleParticipantCounter + amount > preOrderLimit) { revert PreOrderLimitReached(); } _; } /// @notice Verifies that the correct ETH amount was sent /// @param amount The number of items being pre-ordered modifier correctPrice(uint256 amount) { if (msg.value != price * amount) { revert IncorrectPrice(); } _; } /// @notice Checks if an address has already participated in GTD phase /// @param account The address to check modifier notGTDParticipant(address account) { if (isGTDParticipant[account]) { revert AlreadyParticipant(); } _; } /// @notice Checks if an address has already participated in FCFS phase /// @param account The address to check modifier notFCFSParticipant(address account) { if (isFCFSParticipant[account]) { revert AlreadyParticipant(); } _; } /// @notice Checks if amount is within legacy Bosu allowance /// @param account The address to check /// @param amount The number of items being pre-ordered modifier withinLegacyBosuAllowance(address account, uint256 amount) { if (amount > legacyBosuWhitelist[account]) { revert MaxPreOrderExceeded(); } _; } /// @notice Verifies merkle proof for whitelist verification /// @param account The address to verify /// @param root The merkle root to verify against /// @param proof The merkle proof for verification modifier validProof(address account, bytes32 root, bytes32[] memory proof) { if (!MerkleProofLib.verify(proof, root, keccak256(abi.encodePacked(account)))) { revert IncorrectProof(); } _; } /// @notice Contract constructor /// @param _badgeContract Address of the Final Bosu Badges contract /// @param _treasury Address of the treasury to receive funds constructor(address _badgeContract, address _treasury, address _delegateResolver) { if (_treasury == address(0)) revert InvalidTreasury(); if (_badgeContract == address(0)) revert InvalidBadgeContract(); _initializeOwner(msg.sender); // Legacy bosu pre-order phase legacyBosuStartTime = 1742853600; legacyBosuEndTime = 1743026400; // GTD pre-order phase gtdStartTime = 1742853600; gtdEndTime = 1743026400; // FCFS pre-order phase fcfsStartTime = 1743026400; fcfsEndTime = 1745704800; // Set up external resources badgeContract = _badgeContract; treasury = _treasury; delegateResolver = _delegateResolver; } /// @notice Internal function to process pre-order participation /// @param to The address receiving the pre-order /// @param amount The number of items to pre-order /// @param badgeType The type of badge to mint /// @dev Handles common logic for all pre-order functions function _processPreOrder(address to, uint256 amount, uint256 badgeType) internal { presaleParticipants[to] += amount; presaleParticipantCounter += amount; // Mint badge (1 for legacy bosu, 2 for GTD/FCFS) IFinalBosuBadges(badgeContract).mint(to, badgeType, 1, ""); emit PresaleParticipant(to, amount); } /// @notice Participate in the Legacy Bosu pre-order phase /// @dev Requires the address to be whitelisted with sufficient allocation /// @param to The address receiving the pre-order and badge /// @param amount The number of items to pre-order function legacyBosuPreOrder(address to, uint256 amount) external payable isPhaseActive(legacyBosuStartTime, legacyBosuEndTime) correctPrice(amount) withinPreOrderLimit(amount) withinLegacyBosuAllowance(to, amount) { if(amount == 0) revert InvalidAmount(); legacyBosuWhitelist[to] -= amount; _processPreOrder(to, amount, 1); } /// @notice Participate in the Legacy Bosu pre-order phase through a delegate /// @dev Requires the caller to be delegated by the vault address /// @param to The address receiving the pre-order and badge /// @param amount The number of items to pre-order /// @param vault The address that delegated rights to the caller function legacyBosuPreOrderDelegate(address to, uint256 amount, address vault) external payable checkDelegate(vault) isPhaseActive(legacyBosuStartTime, legacyBosuEndTime) correctPrice(amount) withinPreOrderLimit(amount) withinLegacyBosuAllowance(vault, amount) { if(amount == 0) revert InvalidAmount(); legacyBosuWhitelist[vault] -= amount; _processPreOrder(to, amount, 1); } /// @notice Participate in the GTD (Guaranteed) pre-order phase /// @dev Requires merkle proof verification and allows only one item per address /// @param to The address receiving the pre-order and badge /// @param _proof The merkle proof verifying the address is on the GTD whitelist function gtdPreOrder(address to, bytes32[] memory _proof) external payable isPhaseActive(gtdStartTime, gtdEndTime) correctPrice(1) withinPreOrderLimit(1) notGTDParticipant(to) validProof(to, gtdRoot, _proof) { isGTDParticipant[to] = true; _processPreOrder(to, 1, 2); } /// @notice Participate in the GTD pre-order phase through a delegate /// @dev Requires the caller to be delegated by the vault address /// @param to The address receiving the pre-order and badge /// @param _proof The merkle proof verifying the address is on the GTD whitelist /// @param vault The address that delegated rights to the caller function gtdPreOrderDelegate(address to, bytes32[] memory _proof, address vault) external payable checkDelegate(vault) isPhaseActive(gtdStartTime, gtdEndTime) correctPrice(1) withinPreOrderLimit(1) notGTDParticipant(vault) validProof(vault, gtdRoot, _proof) { isGTDParticipant[vault] = true; _processPreOrder(to, 1, 2); } /// @notice Participate in the FCFS (First Come First Served) pre-order phase /// @dev Requires merkle proof verification and allows only one item per address /// @param to The address receiving the pre-order and badge /// @param _proof The merkle proof verifying the address is on the FCFS whitelist function fcfsPreOrder(address to, bytes32[] memory _proof) external payable isPhaseActive(fcfsStartTime, fcfsEndTime) correctPrice(1) withinPreOrderLimit(1) notFCFSParticipant(to) validProof(to, fcfsRoot, _proof) { isFCFSParticipant[to] = true; _processPreOrder(to, 1, 2); } /// @notice Participate in the FCFS pre-order phase through a delegate /// @dev Requires the caller to be delegated by the vault address /// @param to The address receiving the pre-order and badge /// @param _proof The merkle proof verifying the address is on the FCFS whitelist /// @param vault The address that delegated rights to the caller function fcfsPreOrderDelegate(address to, bytes32[] memory _proof, address vault) external payable checkDelegate(vault) isPhaseActive(fcfsStartTime, fcfsEndTime) correctPrice(1) withinPreOrderLimit(1) notFCFSParticipant(vault) validProof(vault, fcfsRoot, _proof) { isFCFSParticipant[vault] = true; _processPreOrder(to, 1, 2); } /// @notice Updates the badge contract address /// @param _badgeContract The new badge contract address function setBadgeContract(address _badgeContract) external onlyOwner { if (_badgeContract == address(0)) revert InvalidBadgeContract(); badgeContract = _badgeContract; } /// @notice Updates the pre-order price /// @param _price The new price in wei function setPrice(uint256 _price) external onlyOwner { price = _price; } /// @notice Sets the whitelist for Legacy Bosu pre-order /// @param _addresses Array of whitelisted addresses /// @param _amounts Array of allowed pre-order amounts corresponding to addresses function setLegacyBosuPreOrderWhitelist(address[] memory _addresses, uint256[] memory _amounts) external onlyOwner { if(_addresses.length != _amounts.length) revert InvalidWhitelist(); for (uint256 i = 0; i < _addresses.length; i++) { legacyBosuWhitelist[_addresses[i]] = _amounts[i]; } } /// @notice Sets the merkle root for GTD whitelist /// @param _gtdRoot The new merkle root function setGTDRoot(bytes32 _gtdRoot) external onlyOwner { gtdRoot = _gtdRoot; } /// @notice Sets the merkle root for FCFS whitelist /// @param _fcfsRoot The new merkle root function setFCFSRoot(bytes32 _fcfsRoot) external onlyOwner { fcfsRoot = _fcfsRoot; } /// @notice Updates all phase timestamps /// @param _legacyBosuStartTime Start time for Legacy Bosu phase /// @param _legacyBosuEndTime End time for Legacy Bosu phase /// @param _gtdStartTime Start time for GTD phase /// @param _gtdEndTime End time for GTD phase /// @param _fcfsStartTime Start time for FCFS phase /// @param _fcfsEndTime End time for FCFS phase function setPhaseTimestamps( uint40 _legacyBosuStartTime, uint40 _legacyBosuEndTime, uint40 _gtdStartTime, uint40 _gtdEndTime, uint40 _fcfsStartTime, uint40 _fcfsEndTime ) external onlyOwner { if ( _legacyBosuStartTime > _legacyBosuEndTime || _gtdStartTime > _gtdEndTime || _fcfsStartTime > _fcfsEndTime ) revert InvalidTimestamp(); legacyBosuStartTime = _legacyBosuStartTime; legacyBosuEndTime = _legacyBosuEndTime; gtdStartTime = _gtdStartTime; gtdEndTime = _gtdEndTime; fcfsStartTime = _fcfsStartTime; fcfsEndTime = _fcfsEndTime; } /// @notice Updates the maximum pre-order limit /// @param _preOrderLimit The new pre-order limit function setPreOrderLimit(uint256 _preOrderLimit) external onlyOwner { preOrderLimit = _preOrderLimit; } /// @notice Updates the treasury address /// @param _treasury The new treasury address function setTreasury(address _treasury) external onlyOwner { if (_treasury == address(0)) revert InvalidTreasury(); treasury = _treasury; } /// @notice Sets the delegate resolver for AGW /// @param delegateResolver_ The delegate resolver function setDelegateResolver(address delegateResolver_) public onlyOwner { delegateResolver = delegateResolver_; } /// @notice Withdraws all ETH to the treasury address function withdrawETH() external onlyOwner { SafeTransferLib.safeTransferAllETH(treasury); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; /// @title Exclusive Delegate Resolver Interface /// @notice Interface for resolving delegates with exclusive rights /// @dev Implemented by contracts that want to handle delegation interface IExclusiveDelegateResolver { /// @notice Returns the exclusive wallet address for a given address and rights /// @param addr The address to check delegation for /// @param rights The rights type to check /// @return The address of the delegated wallet, or address(0) if not delegated function exclusiveWalletByRights(address addr, bytes24 rights) external view returns (address); function DELEGATE_REGISTRY() external view returns (address); function GLOBAL_DELEGATION() external view returns (bytes24); function delegatedWalletsByRights( address wallet, bytes24 rights ) external view returns (address[] memory wallets); function exclusiveOwnerByRights( address contractAddress, uint256 tokenId, bytes24 rights ) external view returns (address owner); function decodeRightsExpiration( bytes32 rights ) external pure returns (bytes24 rightsIdentifier, uint40 expiration); function generateRightsWithExpiration( bytes24 rightsIdentifier, uint40 expiration ) external pure returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; /** * @title IFinalBosuBadges * @dev Minimal interface to interact with the updated FinalBosuBadges contract. * We only include the methods used by the exchange (burnFrom & mint). * If you need other methods (mintBatch, setTokenMetadata, etc.), * you can add them here as well. */ interface IFinalBosuBadges { /** * @notice Burns a token from `from` (admin/manager only). * @param from The address whose tokens are being burned. * @param id The token ID to burn. * @param amount The amount of tokens to burn. */ function burnFrom(address from, uint256 id, uint256 amount) external; /** * @notice Mints a token to `to` (admin/manager only). * @param to The address to mint tokens to. * @param id The token ID to mint. * @param amount The amount of tokens to mint. * @param data The data to attach to the mint (often empty). */ function mint( address to, uint256 id, uint256 amount, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// /// @dev Note: /// This implementation does NOT auto-initialize the owner to `msg.sender`. /// You MUST call the `_initializeOwner` in the constructor / initializer. /// /// While the ownable portion follows /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, /// the nomenclature for the 2-step ownership handover may be unique to this codebase. abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /// @dev The `pendingOwner` does not have a valid handover request. error NoHandoverRequest(); /// @dev Cannot double-initialize. error AlreadyInitialized(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev An ownership handover to `pendingOwner` has been requested. event OwnershipHandoverRequested(address indexed pendingOwner); /// @dev The ownership handover to `pendingOwner` has been canceled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE = 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d; /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE = 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. /// It is intentionally chosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. bytes32 internal constant _OWNER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927; /// The ownership handover slot of `newOwner` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED)) /// let handoverSlot := keccak256(0x00, 0x20) /// ``` /// It stores the expiry timestamp of the two-step ownership handover. uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override to return true to make `_initializeOwner` prevent double-initialization. function _guardInitializeOwner() internal pure virtual returns (bool guard) {} /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT if sload(ownerSlot) { mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } else { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(_OWNER_SLOT, newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) } } else { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } } /// @dev Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(_OWNER_SLOT))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. /// Override to return a different value if needed. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ownershipHandoverValidFor() internal view virtual returns (uint64) { return 48 * 3600; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`. revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(0)); } /// @dev Request a two-step ownership handover to the caller. /// The request will automatically expire in 48 hours (172800 seconds) by default. function requestOwnershipHandover() public payable virtual { unchecked { uint256 expires = block.timestamp + _ownershipHandoverValidFor(); /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to `expires`. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), expires) // Emit the {OwnershipHandoverRequested} event. log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller()) } } } /// @dev Cancels the two-step ownership handover to the caller, if any. function cancelOwnershipHandover() public payable virtual { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), 0) // Emit the {OwnershipHandoverCanceled} event. log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller()) } } /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`. /// Reverts if there is no existing ownership handover requested by `pendingOwner`. function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) let handoverSlot := keccak256(0x0c, 0x20) // If the handover does not exist, or has expired. if gt(timestamp(), sload(handoverSlot)) { mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`. revert(0x1c, 0x04) } // Set the handover slot to 0. sstore(handoverSlot, 0) } _setOwner(pendingOwner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { result := sload(_OWNER_SLOT) } } /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. function ownershipHandoverExpiresAt(address pendingOwner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the handover slot. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) // Load the handover slot. result := sload(keccak256(0x0c, 0x20)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol) library MerkleProofLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MERKLE PROOF VERIFICATION OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if mload(proof) { // Initialize `offset` to the offset of `proof` elements in memory. let offset := add(proof, 0x20) // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(offset, shl(5, mload(proof))) // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, mload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), mload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if proof.length { // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(proof.offset, shl(5, proof.length)) // Initialize `offset` to the offset of `proof` in the calldata. let offset := proof.offset // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, calldataload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), calldataload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`, /// given `proof` and `flags`. /// /// Note: /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length` /// will always return false. /// - The sum of the lengths of `proof` and `leaves` must never overflow. /// - Any non-zero word in the `flags` array is treated as true. /// - The memory offset of `proof` must be non-zero /// (i.e. `proof` is not pointing to the scratch space). function verifyMultiProof( bytes32[] memory proof, bytes32 root, bytes32[] memory leaves, bool[] memory flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leaves` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). /// @solidity memory-safe-assembly assembly { // Cache the lengths of the arrays. let leavesLength := mload(leaves) let proofLength := mload(proof) let flagsLength := mload(flags) // Advance the pointers of the arrays to point to the data. leaves := add(0x20, leaves) proof := add(0x20, proof) flags := add(0x20, flags) // If the number of flags is correct. for {} eq(add(leavesLength, proofLength), add(flagsLength, 1)) {} { // For the case where `proof.length + leaves.length == 1`. if iszero(flagsLength) { // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`. isValid := eq(mload(xor(leaves, mul(xor(proof, leaves), proofLength))), root) break } // The required final proof offset if `flagsLength` is not zero, otherwise zero. let proofEnd := add(proof, shl(5, proofLength)) // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) // Copy the leaves into the hashes. // Sometimes, a little memory expansion costs less than branching. // Should cost less, even with a high free memory offset of 0x7d00. leavesLength := shl(5, leavesLength) for { let i := 0 } iszero(eq(i, leavesLength)) { i := add(i, 0x20) } { mstore(add(hashesFront, i), mload(add(leaves, i))) } // Compute the back of the hashes. let hashesBack := add(hashesFront, leavesLength) // This is the end of the memory for the queue. // We recycle `flagsLength` to save on stack variables (sometimes save gas). flagsLength := add(hashesBack, shl(5, flagsLength)) for {} 1 {} { // Pop from `hashes`. let a := mload(hashesFront) // Pop from `hashes`. let b := mload(add(hashesFront, 0x20)) hashesFront := add(hashesFront, 0x40) // If the flag is false, load the next proof, // else, pops from the queue. if iszero(mload(flags)) { // Loads the next proof. b := mload(proof) proof := add(proof, 0x20) // Unpop from `hashes`. hashesFront := sub(hashesFront, 0x20) } // Advance to the next flag. flags := add(flags, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) if iszero(lt(hashesBack, flagsLength)) { break } } isValid := and( // Checks if the last value in the queue is same as the root. eq(mload(sub(hashesBack, 0x20)), root), // And whether all the proofs are used, if required. eq(proofEnd, proof) ) break } } } /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`, /// given `proof` and `flags`. /// /// Note: /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length` /// will always return false. /// - Any non-zero word in the `flags` array is treated as true. /// - The calldata offset of `proof` must be non-zero /// (i.e. `proof` is from a regular Solidity function with a 4-byte selector). function verifyMultiProofCalldata( bytes32[] calldata proof, bytes32 root, bytes32[] calldata leaves, bool[] calldata flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leaves` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). /// @solidity memory-safe-assembly assembly { // If the number of flags is correct. for {} eq(add(leaves.length, proof.length), add(flags.length, 1)) {} { // For the case where `proof.length + leaves.length == 1`. if iszero(flags.length) { // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`. // forgefmt: disable-next-item isValid := eq( calldataload( xor(leaves.offset, mul(xor(proof.offset, leaves.offset), proof.length)) ), root ) break } // The required final proof offset if `flagsLength` is not zero, otherwise zero. let proofEnd := add(proof.offset, shl(5, proof.length)) // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) // Copy the leaves into the hashes. // Sometimes, a little memory expansion costs less than branching. // Should cost less, even with a high free memory offset of 0x7d00. calldatacopy(hashesFront, leaves.offset, shl(5, leaves.length)) // Compute the back of the hashes. let hashesBack := add(hashesFront, shl(5, leaves.length)) // This is the end of the memory for the queue. // We recycle `flagsLength` to save on stack variables (sometimes save gas). flags.length := add(hashesBack, shl(5, flags.length)) // We don't need to make a copy of `proof.offset` or `flags.offset`, // as they are pass-by-value (this trick may not always save gas). for {} 1 {} { // Pop from `hashes`. let a := mload(hashesFront) // Pop from `hashes`. let b := mload(add(hashesFront, 0x20)) hashesFront := add(hashesFront, 0x40) // If the flag is false, load the next proof, // else, pops from the queue. if iszero(calldataload(flags.offset)) { // Loads the next proof. b := calldataload(proof.offset) proof.offset := add(proof.offset, 0x20) // Unpop from `hashes`. hashesFront := sub(hashesFront, 0x20) } // Advance to the next flag offset. flags.offset := add(flags.offset, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) if iszero(lt(hashesBack, flags.length)) { break } } isValid := and( // Checks if the last value in the queue is same as the root. eq(mload(sub(hashesBack, 0x20)), root), // And whether all the proofs are used, if required. eq(proofEnd, proof.offset) ) break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes32 array. function emptyProof() internal pure returns (bytes32[] calldata proof) { /// @solidity memory-safe-assembly assembly { proof.length := 0 } } /// @dev Returns an empty calldata bytes32 array. function emptyLeaves() internal pure returns (bytes32[] calldata leaves) { /// @solidity memory-safe-assembly assembly { leaves.length := 0 } } /// @dev Returns an empty calldata bool array. function emptyFlags() internal pure returns (bool[] calldata flags) { /// @solidity memory-safe-assembly assembly { flags.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {SingleUseETHVault} from "./SingleUseETHVault.sol"; /// @notice Library for force safe transferring ETH and ERC20s in ZKsync. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ext/zksync/SafeTransferLib.sol) library SafeTransferLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev A single use ETH vault has been created for `to`, with `amount`. event SingleUseETHVaultCreated(address indexed to, uint256 amount, address vault); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ETH transfer has failed. error ETHTransferFailed(); /// @dev The ERC20 `transferFrom` has failed. error TransferFromFailed(); /// @dev The ERC20 `transfer` has failed. error TransferFailed(); /// @dev The ERC20 `approve` has failed. error ApproveFailed(); /// @dev The ERC20 `totalSupply` query has failed. error TotalSupplyQueryFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Suggested gas stipend for contract receiving ETH to perform a few /// storage reads and writes, but low enough to prevent griefing. uint256 internal constant GAS_STIPEND_NO_GRIEF = 1000000; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants. // // The regular variants: // - Forwards all remaining gas to the target. // - Reverts if the target reverts. // - Reverts if the current contract has insufficient balance. // // The force variants: // - Forwards with an optional gas stipend // (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases). // - If the target reverts, or if the gas stipend is exhausted, // creates a temporary contract to force send the ETH via `SELFDESTRUCT`. // Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758. // - Reverts if the current contract has insufficient balance. // // The try variants: // - Forwards with a mandatory gas stipend. // - Instead of reverting, returns whether the transfer succeeded. /// @dev Sends `amount` (in wei) ETH to `to`. function safeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gas(), to, amount, 0x00, 0x00, 0x00, 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Sends all the ETH in the current contract to `to`. function safeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // Transfer all the ETH and check if it succeeded or not. if iszero(call(gas(), to, selfbalance(), 0x00, 0x00, 0x00, 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. /// If force transfer is used, returns the vault. Else returns `address(0)`. function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (address vault) { if (amount == uint256(0)) return address(0); // Early return if `amount` is zero. uint256 selfBalanceBefore = address(this).balance; /// @solidity memory-safe-assembly assembly { if lt(selfBalanceBefore, amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } pop(call(gasStipend, to, amount, 0x00, 0x00, 0x00, 0x00)) } if (address(this).balance == selfBalanceBefore) { vault = address(new SingleUseETHVault()); /// @solidity memory-safe-assembly assembly { mstore(0x00, shr(96, shl(96, to))) if iszero(call(gas(), vault, amount, 0x00, 0x20, 0x00, 0x00)) { revert(0x00, 0x00) } } emit SingleUseETHVaultCreated(to, amount, vault); } } /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`. /// If force transfer is used, returns the vault. Else returns `address(0)`. function forceSafeTransferAllETH(address to, uint256 gasStipend) internal returns (address vault) { vault = forceSafeTransferETH(to, address(this).balance, gasStipend); } /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`. /// If force transfer is used, returns the vault. Else returns `address(0)`. function forceSafeTransferETH(address to, uint256 amount) internal returns (address vault) { vault = forceSafeTransferETH(to, amount, GAS_STIPEND_NO_GRIEF); } /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`. /// If force transfer is used, returns the vault. Else returns `address(0)`. function forceSafeTransferAllETH(address to) internal returns (address vault) { vault = forceSafeTransferETH(to, address(this).balance, GAS_STIPEND_NO_GRIEF); } /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, amount, 0x00, 0x00, 0x00, 0x00) } } /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`. function trySafeTransferAllETH(address to, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, selfbalance(), 0x00, 0x00, 0x00, 0x00) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferFrom(address token, address from, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, amount) // Store the `amount` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`. let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) if iszero(and(eq(mload(0x00), 1), success)) { if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// /// The `from` account must have at least `amount` approved for the current contract to manage. function trySafeTransferFrom(address token, address from, address to, uint256 amount) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, amount) // Store the `amount` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`. success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) if iszero(and(eq(mload(0x00), 1), success)) { success := lt(or(iszero(extcodesize(token)), returndatasize()), success) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends all of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have their entire balance approved for the current contract to manage. function safeTransferAllFrom(address token, address from, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`. // Read the balance, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`. amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it. // Perform the transfer, reverting upon failure. let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) if iszero(and(eq(mload(0x00), 1), success)) { if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransfer(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) if iszero(and(eq(mload(0x00), 1), success)) { if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sends all of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransferAll(address token, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, address()) // Store the address of the current contract. // Read the balance, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x14, to) // Store the `to` argument. amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) if iszero(and(eq(mload(0x00), 1), success)) { if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// Reverts upon failure. function safeApprove(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) if iszero(and(eq(mload(0x00), 1), success)) { if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// If the initial attempt to approve fails, attempts to reset the approved amount to zero, /// then retries the approval again (some tokens, e.g. USDT, requires this). /// Reverts upon failure. function safeApproveWithRetry(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, retrying upon failure. let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) if iszero(and(eq(mload(0x00), 1), success)) { if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) { mstore(0x34, 0) // Store 0 for the `amount`. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. pop(call(gas(), token, 0, 0x10, 0x44, 0x00, 0x00)) // Reset the approval. mstore(0x34, amount) // Store back the original `amount`. // Retry the approval, reverting upon failure. success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) if iszero(and(eq(mload(0x00), 1), success)) { // Check the `extcodesize` again just in case the token selfdestructs lol. if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } } } } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Returns the amount of ERC20 `token` owned by `account`. /// Returns zero if the `token` does not exist. function balanceOf(address token, address account) internal view returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x14, account) // Store the `account` argument. mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`. amount := mul( // The arguments of `mul` are evaluated from right to left. mload(0x20), and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20) ) ) } } /// @dev Returns the total supply of the `token`. /// Reverts if the token does not exist or does not implement `totalSupply()`. function totalSupply(address token) internal view returns (uint256 result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x18160ddd) // `totalSupply()`. if iszero( and(gt(returndatasize(), 0x1f), staticcall(gas(), token, 0x1c, 0x04, 0x00, 0x20)) ) { mstore(0x00, 0x54cd9435) // `TotalSupplyQueryFailed()`. revert(0x1c, 0x04) } result := mload(0x00) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice A single-use vault that allows a designated caller to withdraw all ETH in it. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ext/zksync/SingleUseETHVault.sol) contract SingleUseETHVault { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Unable to withdraw all. error WithdrawAllFailed(); /// @dev Not authorized. error Unauthorized(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* WITHDRAW ALL */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ fallback() external payable virtual { /// @solidity memory-safe-assembly assembly { mstore(0x40, 0) // Optimization trick to remove free memory pointer initialization. let owner := sload(0) // Initialization. if iszero(owner) { sstore(0, calldataload(0x00)) // Store the owner. return(0x00, 0x00) // Early return. } // Authorization check. if iszero(eq(caller(), owner)) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } let to := calldataload(0x00) // If the calldata is less than 32 bytes, zero-left-pad it to 32 bytes. // Then use the rightmost 20 bytes of the word as the `to` address. // This allows for the calldata to be `abi.encode(to)` or `abi.encodePacked(to)`. to := shr(mul(lt(calldatasize(), 0x20), shl(3, sub(0x20, calldatasize()))), to) // If `to` is `address(0)`, set it to `msg.sender`. to := xor(mul(xor(to, caller()), iszero(to)), to) // Transfers the whole balance to `to`. if iszero(call(gas(), to, selfbalance(), 0x00, 0x00, 0x00, 0x00)) { mstore(0x00, 0x651aee10) // `WithdrawAllFailed()`. revert(0x1c, 0x04) } } } }
{ "evmVersion": "paris", "optimizer": { "enabled": true, "mode": "3", "runs": 10000 }, "outputSelection": { "*": { "*": [ "abi" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_badgeContract","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_delegateResolver","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AlreadyParticipant","type":"error"},{"inputs":[],"name":"DelegateResolverNotSet","type":"error"},{"inputs":[],"name":"IncorrectPrice","type":"error"},{"inputs":[],"name":"IncorrectProof","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidBadgeContract","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[],"name":"InvalidTreasury","type":"error"},{"inputs":[],"name":"InvalidWhitelist","type":"error"},{"inputs":[],"name":"MaxPreOrderExceeded","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NotAllowed","type":"error"},{"inputs":[],"name":"NotDelegated","type":"error"},{"inputs":[],"name":"PreOrderLimitReached","type":"error"},{"inputs":[],"name":"SaleFinished","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"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":true,"internalType":"address","name":"participant","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PresaleParticipant","type":"event"},{"inputs":[],"name":"badgeContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":[],"name":"delegateResolver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fcfsEndTime","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"fcfsPreOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"address","name":"vault","type":"address"}],"name":"fcfsPreOrderDelegate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"fcfsRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fcfsStartTime","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gtdEndTime","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"gtdPreOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"address","name":"vault","type":"address"}],"name":"gtdPreOrderDelegate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"gtdRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gtdStartTime","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isFCFSParticipant","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGTDParticipant","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"legacyBosuEndTime","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"legacyBosuPreOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"vault","type":"address"}],"name":"legacyBosuPreOrderDelegate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"legacyBosuStartTime","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"legacyBosuWhitelist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"preOrderLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleParticipantCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"presaleParticipants","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_badgeContract","type":"address"}],"name":"setBadgeContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegateResolver_","type":"address"}],"name":"setDelegateResolver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_fcfsRoot","type":"bytes32"}],"name":"setFCFSRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gtdRoot","type":"bytes32"}],"name":"setGTDRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"setLegacyBosuPreOrderWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40","name":"_legacyBosuStartTime","type":"uint40"},{"internalType":"uint40","name":"_legacyBosuEndTime","type":"uint40"},{"internalType":"uint40","name":"_gtdStartTime","type":"uint40"},{"internalType":"uint40","name":"_gtdEndTime","type":"uint40"},{"internalType":"uint40","name":"_fcfsStartTime","type":"uint40"},{"internalType":"uint40","name":"_fcfsEndTime","type":"uint40"}],"name":"setPhaseTimestamps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_preOrderLimit","type":"uint256"}],"name":"setPreOrderLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
9c4d535b0000000000000000000000000000000000000000000000000000000000000000010002e943327233c4f5ddcc4564b3ff430aece98605dfa6abe395688d88bca800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000fae7a013ccf023525a0d2696806f7fd0fd8a6ecd0000000000000000000000009995d38fe4f87c806ebf1c45046af3a6c612fc090000000000000000000000000000000078cc4cc1c14e27c0fa35ed6e5e58825d
Deployed Bytecode
0x00010000000000020005000000000002000000000001035500000060031002700000026f0330019700000001002001900000002c0000c13d0000008004000039000000400040043f000000040030008c000000560000413d000000000201043b000000e0022002700000027c0020009c000000580000a13d0000027d0020009c000000690000a13d0000027e0020009c000000870000a13d0000027f0020009c000001d80000213d000002830020009c000003870000613d000002840020009c000003b60000613d000002850020009c000000560000c13d000000240030008c000000560000413d0000000401100370000000000101043b000002720010009c000000560000213d0000027402000041000000000202041a0000000003000411000000000023004b000004cf0000c13d000000000001004b000007e40000c13d000002be01000041000000000010043f000002bf01000041000009bb000104300000000002000416000000000002004b000000560000c13d0000001f0230003900000270022001970000008002200039000000400020043f0000001f0430018f000002710530019800000080025000390000003d0000613d0000008006000039000000000701034f000000007807043c0000000006860436000000000026004b000000390000c13d000000000004004b0000004a0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000600030008c000000560000413d000000800500043d000002720050009c000000560000213d000000a00400043d000002720040009c000000560000213d000000c00100043d000500000001001d000002720010009c000001ed0000a13d0000000001000019000009bb00010430000002990020009c000000780000213d000002a70020009c000000bf0000213d000002ae0020009c000001f80000a13d000002af0020009c000003c80000613d000002b00020009c000003d40000613d000002b10020009c000000560000c13d0000000001000416000000000001004b000000560000c13d0000000301000039000004f90000013d0000028c0020009c000000b20000213d000002930020009c000002090000a13d000002940020009c000003d90000613d000002950020009c000003e00000613d000002960020009c000000560000c13d0000000001000416000000000001004b000000560000c13d0000000301000039000004a30000013d0000029a0020009c000000df0000213d000002a10020009c0000021a0000a13d000002a20020009c000003ec0000613d000002a30020009c000004750000613d000002a40020009c000000560000c13d0000000001000416000000000001004b000000560000c13d0000000e01000039000006570000013d000002860020009c000002230000a13d000002870020009c0000048a0000613d000002880020009c0000048f0000613d000002890020009c000000560000c13d0000000001000416000000000001004b000000560000c13d0000027401000041000000000101041a0000000002000411000000000012004b000004cf0000c13d0000000d01000039000000000101041a000500000001001d000002c40100004100000000001004430000000001000410000000040010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002c5011001c70000800a0200003909b909b40000040f0000000100200190000007be0000613d00000005020000290000027204200197000000000301043b00000000010004140000026f0010009c0000026f01008041000000c001100210000000000003004b000006920000c13d0000000002040019000006950000013d0000028d0020009c000003230000a13d0000028e0020009c0000049f0000613d0000028f0020009c000004a60000613d000002900020009c000000560000c13d0000000001000416000000000001004b000000560000c13d0000000901000039000004f90000013d000002a80020009c0000032c0000a13d000002a90020009c000004b80000613d000002aa0020009c000004d30000613d000002ab0020009c000000560000c13d000002b4010000410000000c0010043f0000000001000411000000000010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002c2011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000000001041b00000000010004140000026f0010009c0000026f01008041000000c00110021000000275011001c70000800d020000390000000203000039000002d1040000410000064d0000013d0000029b0020009c000003780000a13d0000029c0020009c000004e90000613d0000029d0020009c000004f50000613d0000029e0020009c000000560000c13d000000640030008c000000560000413d0000000402100370000000000202043b000500000002001d000002720020009c000000560000213d0000002402100370000000000202043b000002b60020009c000000560000213d0000002304200039000000000034004b000000560000813d0000000404200039000000000441034f000000000504043b000002b60050009c000006210000213d00000005045002100000003f06400039000002b706600197000002b80060009c000006210000213d0000008006600039000000400060043f000000800050043f00000024022000390000000004240019000000000034004b000000560000213d000000000005004b000001100000613d0000008003000039000000000521034f000000000505043b000000200330003900000000005304350000002002200039000000000042004b000001090000413d0000004401100370000000000101043b000200000001001d000002720010009c000000560000213d0000000e01000039000000000101041a0000027202100198000005bf0000613d000000400400043d000400000004001d0000002401400039000002c7030000410000000000310435000002c80100004100000000001404350000000401400039000000020300002900000000003104350000026f0040009c0000026f010000410000000001044019000000400110021000000000030004140000026f0030009c0000026f03008041000000c003300210000000000113019f000002c9011001c709b909b40000040f00000060031002700000026f03300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000040b00002900000004057000290000013e0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000013a0000c13d000000000006004b0000014b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000008040000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000002b60010009c000006210000213d0000000100200190000006210000c13d000000400010043f000000200030008c000000560000413d00000000010b0433000002720010009c000000560000213d0000000002000411000000000012004b000008000000c13d0000000601000039000000000101041a000400000001001d000002b901000041000000000010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002ba011001c70000800b0200003909b909b40000040f0000000100200190000007be0000613d000000000101043b0000000402000029000002bb02200197000000000012004b000007bf0000213d00000004020000290000002802200270000002bb02200197000000000012004b000007bf0000a13d000000000100041a0000000002000416000000000012004b000007e70000c13d0000000a01000039000000000101041a000002e00010009c000008380000613d0000000102000039000000000202041a000000000021004b000006050000813d0000000201000029000000000010043f0000000401000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000008470000c13d0000000501000039000000000101041a000100000001001d000000400100043d00000014020000390000000002210436000000020300002900000060033002100000000000320435000002bd0010009c000006210000213d0000004003100039000000400030043f0000026f0020009c0000026f02008041000000400220021000000000010104330000026f0010009c0000026f010080410000006001100210000000000121019f00000000020004140000026f0020009c0000026f02008041000000c002200210000000000112019f00000275011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000800300043d000000000003004b000001d20000613d000000a0020000390000000503300210000300a00030003d0000000043020434000400000004001d000000000031004b000000000300003900000020030020390000000000130435000000200130015f0000000002020433000000000021043500000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b0000000403000029000000030030006c0000000002030019000001bb0000413d000000010010006c000008510000c13d0000000201000029000000000010043f0000000401000039000003170000013d000002800020009c000004fe0000613d000002810020009c0000050b0000613d000002820020009c000000560000c13d000000240030008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000401100370000000000101043b000002720010009c000000560000213d000002b4020000410000000c0020043f000000000010043f0000000c0100003900000020020000390000049d0000013d0000027301000041000000000010041b00000bef010000390000000102000039000000000012041b000000000004004b000003810000c13d000002c001000041000000000010043f000002c101000041000009bb00010430000002b20020009c000005ad0000613d000002b30020009c000000560000c13d000000240030008c000000560000413d0000000001000416000000000001004b000000560000c13d09b909790000040f00000004010000390000000001100367000000000101043b0000000802000039000000000012041b0000000001000019000009ba0001042e000002970020009c000005c30000613d000002980020009c000000560000c13d000000240030008c000000560000413d0000000001000416000000000001004b000000560000c13d09b909790000040f00000004010000390000000001100367000000000101043b0000000502000039000000000012041b0000000001000019000009ba0001042e000002a50020009c000005c80000613d000002a60020009c000000560000c13d0000000001000416000000000001004b000000560000c13d0000000d01000039000006570000013d0000028a0020009c000005d00000613d0000028b0020009c000000560000c13d000000640030008c000000560000413d0000000402100370000000000202043b000500000002001d000002720020009c000000560000213d0000002402100370000000000202043b000002b60020009c000000560000213d0000002304200039000000000034004b000000560000813d0000000404200039000000000441034f000000000504043b000002b60050009c000006210000213d00000005045002100000003f06400039000002b706600197000002b80060009c000006210000213d0000008006600039000000400060043f000000800050043f00000024022000390000000004240019000000000034004b000000560000213d000000000005004b000002500000613d0000008003000039000000000521034f000000000505043b000000200330003900000000005304350000002002200039000000000042004b000002490000413d0000004401100370000000000101043b000200000001001d000002720010009c000000560000213d0000000e01000039000000000101041a0000027202100198000005bf0000613d000000400400043d000400000004001d0000002401400039000002c7030000410000000000310435000002c80100004100000000001404350000000401400039000000020300002900000000003104350000026f0040009c0000026f010000410000000001044019000000400110021000000000030004140000026f0030009c0000026f03008041000000c003300210000000000113019f000002c9011001c709b909b40000040f00000060031002700000026f03300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000040b00002900000004057000290000027e0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000027a0000c13d000000000006004b0000028b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000008100000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000002b60010009c000006210000213d0000000100200190000006210000c13d000000400010043f000000200030008c000000560000413d00000000010b0433000002720010009c000000560000213d0000000002000411000000000012004b000008000000c13d0000000901000039000000000101041a000400000001001d000002b901000041000000000010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002ba011001c70000800b0200003909b909b40000040f0000000100200190000007be0000613d000000000101043b0000000402000029000002bb02200197000000000012004b000007bf0000213d00000004020000290000002802200270000002bb02200197000000000012004b000007bf0000a13d000000000100041a0000000002000416000000000012004b000007e70000c13d0000000a01000039000000000101041a000002e00010009c000008380000613d0000000102000039000000000202041a000000000021004b000006050000813d0000000201000029000000000010043f0000000701000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000008470000c13d0000000801000039000000000101041a000100000001001d000000400100043d00000014020000390000000002210436000000020300002900000060033002100000000000320435000002bd0010009c000006210000213d0000004003100039000000400030043f0000026f0020009c0000026f02008041000000400220021000000000010104330000026f0010009c0000026f010080410000006001100210000000000121019f00000000020004140000026f0020009c0000026f02008041000000c002200210000000000112019f00000275011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000800300043d000000000003004b000003120000613d000000a0020000390000000503300210000300a00030003d0000000043020434000400000004001d000000000031004b000000000300003900000020030020390000000000130435000000200130015f0000000002020433000000000021043500000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b0000000403000029000000030030006c0000000002030019000002fb0000413d000000010010006c000008510000c13d0000000201000029000000000010043f0000000701000039000000200010043f0000004002000039000000000100001909b9099a0000040f000000000201041a000002e10220019700000001022001bf000000000021041b000000050100002909b908ea0000040f0000000001000019000009ba0001042e000002910020009c000006090000613d000002920020009c000000560000c13d0000000001000416000000000001004b000000560000c13d0000000801000039000005cc0000013d000002ac0020009c000006270000613d000002ad0020009c000000560000c13d000000c40030008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000402100370000000000402043b000002bb0040009c000000560000213d0000002402100370000000000202043b000002bb0020009c000000560000213d0000004403100370000000000503043b000002bb0050009c000000560000213d0000006403100370000000000303043b000002bb0030009c000000560000213d0000008406100370000000000606043b000002bb0060009c000000560000213d000000a401100370000000000101043b000002bb0010009c000000560000213d0000027407000041000000000707041a0000000008000411000000000078004b000004cf0000c13d000002bb07400197000002bb04200197000000000047004b0000081c0000213d000002bb05500197000002bb04300197000000000045004b0000081c0000213d000002bb04600197000002bb06100197000000000064004b0000081c0000213d0000000306000039000000000806041a00000277088001970000002802200210000002d402200197000000000282019f000000000272019f000000000026041b0000002802300210000002d4022001970000000603000039000000000603041a0000027706600197000000000262019f000000000252019f000000000023041b0000002801100210000002d4011001970000000902000039000000000302041a0000027703300197000000000131019f000000000141019f000000000012041b0000000001000019000009ba0001042e0000029f0020009c000006530000613d000002a00020009c000000560000c13d0000000001000416000000000001004b000000560000c13d0000027401000041000006570000013d000000000005004b0000065c0000c13d000002d201000041000000000010043f000002c101000041000009bb00010430000000240030008c000000560000413d0000000401100370000000000101043b000500000001001d000002720010009c000000560000213d0000027401000041000000000101041a0000000002000411000000000012004b000004cf0000c13d000002b4010000410000000c0010043f0000000501000029000000000010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002c2011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000300000001001d000000000101041a000400000001001d000002b901000041000000000010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002ba011001c70000800b0200003909b909b40000040f0000000100200190000007be0000613d000000000101043b000000040010006c000007e10000a13d000002c301000041000000000010043f000002bf01000041000009bb00010430000000240030008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000401100370000000000101043b000002720010009c000000560000213d0000027402000041000000000202041a0000000003000411000000000023004b000004cf0000c13d000000000001004b000001f40000613d0000000d02000039000004c90000013d000000240030008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000401100370000000000101043b000002720010009c000000560000213d000000000010043f0000000b010000390000049a0000013d0000000001000416000000000001004b000000560000c13d0000000601000039000004a30000013d0000000001000416000000000001004b000000560000c13d000000000100041a000000800010043f000002b501000041000009ba0001042e000000240030008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000401100370000000000101043b000002720010009c000000560000213d000000000010043f0000000401000039000004de0000013d000000440030008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000402100370000000000202043b000002b60020009c000000560000213d0000002304200039000000000034004b000000560000813d0000000404200039000000000441034f000000000504043b000002cc0050009c000006210000813d00000005045002100000003f06400039000002b706600197000002b80060009c000006210000213d0000008006600039000000400060043f000000800050043f00000024022000390000000004240019000000000034004b000000560000213d000000000005004b000004140000613d000000a005000039000000000621034f000000000606043b000002720060009c000000560000213d00000000056504360000002002200039000000000042004b0000040c0000413d0000002402100370000000000202043b000002b60020009c000000560000213d0000002304200039000000000034004b0000000005000019000002cd05004041000002cd04400197000000000004004b0000000006000019000002cd06002041000002cd0040009c000000000605c019000000000006004b000000560000613d0000000404200039000000000441034f000000000404043b000002b60040009c000006210000213d00000005054002100000003f06500039000002b706600197000000400700043d0000000006670019000300000007001d000000000076004b00000000070000390000000107004039000002b60060009c000006210000213d0000000100700190000006210000c13d000000400060043f00000003060000290000000006460436000200000006001d00000024022000390000000005250019000000000035004b000000560000213d000000000004004b000004470000613d0000000203000029000000000421034f000000000404043b00000000034304360000002002200039000000000052004b000004410000413d0000027401000041000000000101041a0000000002000411000000000012004b000004cf0000c13d00000003010000290000000002010433000000800100043d000000000021004b0000083e0000c13d000000000001004b000006510000613d000000000200001900000003010000290000000001010433000000000021004b0000084b0000a13d0000000501200210000500000002001d00000002021000290000000002020433000400000002001d000000a00110003900000000010104330000027201100197000000000010043f0000000201000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f00000001002001900000000502000029000000560000613d000000000101043b0000000403000029000000000031041b0000000102200039000000800100043d000000000012004b000004540000413d000006510000013d0000027401000041000000000101041a0000000005000411000000000015004b000004cf0000c13d00000000010004140000026f0010009c0000026f01008041000000c00110021000000275011001c70000800d0200003900000003030000390000027604000041000000000600001909b909af0000040f0000000100200190000000560000613d0000027401000041000000000001041b0000000001000019000009ba0001042e0000000001000416000000000001004b000000560000c13d0000000a01000039000005cc0000013d000000240030008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000401100370000000000101043b000002720010009c000000560000213d000000000010043f0000000201000039000000200010043f0000004002000039000000000100001909b9099a0000040f000005cc0000013d0000000001000416000000000001004b000000560000c13d0000000901000039000000000101041a0000002801100270000004fa0000013d000000240030008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000401100370000000000101043b000500000001001d000002720010009c000000560000213d09b909790000040f0000000e01000039000000000201041a0000027a0220019700000005022001af000000000021041b0000000001000019000009ba0001042e000000240030008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000401100370000000000101043b000002720010009c000000560000213d0000027402000041000000000202041a0000000003000411000000000023004b000004cf0000c13d000000000001004b000003830000613d0000000c02000039000000000302041a0000027a03300197000000000113019f000000000012041b0000000001000019000009ba0001042e000002d301000041000000000010043f000002bf01000041000009bb00010430000000240030008c000000560000413d0000000002000416000000000002004b000000560000c13d0000000401100370000000000101043b000002720010009c000000560000213d000000000010043f0000000701000039000000200010043f0000004002000039000000000100001909b9099a0000040f000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f000002b501000041000009ba0001042e000000240030008c000000560000413d0000000001000416000000000001004b000000560000c13d09b909790000040f00000004010000390000000001100367000000000101043b000000000010041b0000000001000019000009ba0001042e0000000001000416000000000001004b000000560000c13d0000000601000039000000000101041a000002bb01100197000000800010043f000002b501000041000009ba0001042e000000240030008c000000560000413d0000000001000416000000000001004b000000560000c13d09b909790000040f00000004010000390000000001100367000000000101043b0000000102000039000000000012041b0000000001000019000009ba0001042e000000440030008c000000560000413d0000000402100370000000000202043b000300000002001d000002720020009c000000560000213d0000002402100370000000000202043b000002b60020009c000000560000213d0000002305200039000000000035004b000000560000813d0000000405200039000000000551034f000000000605043b000002b60060009c000006210000213d00000005056002100000003f07500039000002b707700197000002b80070009c000006210000213d0000008007700039000000400070043f000000800060043f00000024022000390000000005250019000000000035004b000000560000213d000000000006004b000005330000613d000000000321034f000000000303043b000000200440003900000000003404350000002002200039000000000052004b0000052c0000413d0000000601000039000000000101041a000500000001001d000002b901000041000000000010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002ba011001c70000800b0200003909b909b40000040f0000000100200190000007be0000613d000000000101043b0000000502000029000002bb02200197000000000012004b000007bf0000213d00000005020000290000002802200270000002bb02200197000000000012004b000007bf0000a13d000000000100041a0000000002000416000000000012004b000007e70000c13d0000000a01000039000000000101041a000002e00010009c000008380000613d0000000102000039000000000202041a000000000021004b000006050000813d00000003010000290000027201100197000200000001001d000000000010043f0000000401000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000008470000c13d0000000501000039000000000101041a000100000001001d000000400100043d00000014020000390000000002210436000000030300002900000060033002100000000000320435000002bd0010009c000006210000213d0000004003100039000000400030043f0000026f0020009c0000026f02008041000000400220021000000000010104330000026f0010009c0000026f010080410000006001100210000000000121019f00000000020004140000026f0020009c0000026f02008041000000c002200210000000000112019f00000275011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000800300043d000000000003004b000005a70000613d000000a0020000390000000503300210000400a00030003d0000000043020434000500000004001d000000000031004b000000000300003900000020030020390000000000130435000000200130015f0000000002020433000000000021043500000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b0000000503000029000000040030006c0000000002030019000005900000413d000000010010006c000008510000c13d0000000201000029000000000010043f0000000401000039000007b20000013d000000640030008c000000560000413d0000000402100370000000000202043b000500000002001d000002720020009c000000560000213d0000002402100370000000000202043b000400000002001d0000004401100370000000000101043b000002720010009c000000560000213d0000000e02000039000000000202041a00000272022001980000069c0000c13d000002df01000041000000000010043f000002c101000041000009bb000104300000000001000416000000000001004b000000560000c13d0000000501000039000005cc0000013d0000000001000416000000000001004b000000560000c13d0000000101000039000000000101041a000000800010043f000002b501000041000009ba0001042e000000440030008c000000560000413d0000000402100370000000000202043b000500000002001d000002720020009c000000560000213d0000000302000039000000000202041a000400000002001d0000002401100370000000000101043b000300000001001d000002b901000041000000000010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002ba011001c70000800b0200003909b909b40000040f0000000100200190000007be0000613d000000000101043b0000000403000029000002bb02300197000000000012004b000007bf0000213d0000002802300270000002bb02200197000000000012004b000007bf0000a13d000000000200041a000000030300002900000000013200a9000000000002004b000005f90000613d00000000022100d9000000000032004b000008380000c13d0000000002000416000000000012004b000007e70000c13d0000000a01000039000000000101041a000000000031001a000008380000413d00000000013100190000000102000039000000000202041a000000000021004b000007eb0000a13d000002dd01000041000000000010043f000002c101000041000009bb00010430000000440030008c000000560000413d0000000402100370000000000202043b000300000002001d000002720020009c000000560000213d0000002402100370000000000202043b000002b60020009c000000560000213d0000002304200039000000000034004b000000560000813d0000000404200039000000000441034f000000000504043b000002b60050009c000006210000213d00000005045002100000003f06400039000002b706600197000002b80060009c000007280000a13d000002cf01000041000000000010043f0000004101000039000000040010043f000002d001000041000009bb00010430000002b4010000410000000c0010043f0000000001000411000000000010043f000002b901000041000000000010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002ba011001c70000800b0200003909b909b40000040f0000000100200190000007be0000613d000000000101043b000500000001001d00000000010004140000026f0010009c0000026f01008041000000c001100210000002c2011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b0000000502000029000002d60220009a000000000021041b00000000010004140000026f0010009c0000026f01008041000000c00110021000000275011001c70000800d020000390000000203000039000002d704000041000000000500041109b909af0000040f0000000100200190000000560000613d0000000001000019000009ba0001042e0000000001000416000000000001004b000000560000c13d0000000c01000039000000000101041a0000027201100197000000800010043f000002b501000041000009ba0001042e00000000060004110000027401000041000000000061041b00000000010004140000026f0010009c0000026f01008041000000c00110021000000275011001c70000800d020000390000000303000039000400000005001d000300000004001d0000027604000041000000000500001909b909af0000040f000000030400002900000004030000290000000100200190000000560000613d0000000302000039000000000102041a000002770110019700000278011001c7000000000012041b0000000601000039000000000201041a000002770220019700000278022001c7000000000021041b0000000901000039000000000201041a000002770220019700000279022001c7000000000021041b0000000c01000039000000000201041a0000027a02200197000000000232019f000000000021041b0000000d01000039000000000201041a0000027a02200197000000000242019f000000000021041b0000000e01000039000000000201041a0000027a0220019700000005022001af000000000021041b0000002001000039000001000010044300000120000004430000027b01000041000009ba0001042e00000275011001c70000800902000039000000000500001909b909af0000040f0000000100200190000006510000c13d000002c601000041000000000010043f000002bf01000041000009bb000104300000027203100197000002c801000041000000800010043f000300000003001d000000840030043f000002c701000041000000a40010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002d8011001c709b909b40000040f00000060031002700000026f03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000006b80000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000006b40000c13d000000000006004b000006c50000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000007c30000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c000000560000413d000000800100043d000002720010009c000000560000213d0000000002000411000000000012004b000008000000c13d0000000301000039000000000101041a000200000001001d000002b901000041000000000010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002ba011001c70000800b0200003909b909b40000040f0000000100200190000007be0000613d000000000101043b0000000202000029000002bb02200197000000000012004b000007bf0000213d00000002020000290000002802200270000002bb02200197000000000012004b000007bf0000a13d000000000200041a00000004012000b9000000000002004b000006f20000613d00000000022100d9000000040020006c000008380000c13d0000000002000416000000000012004b000007e70000c13d0000000a01000039000000000101041a000000040010002a000008380000413d00000004011000290000000102000039000000000202041a000000000021004b000006050000213d0000000301000029000000000010043f0000000201000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000000101041a000000040010006b000007fc0000213d000000040000006b000008220000613d0000000301000029000000000010043f0000000201000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000000201041a000000040220006c000008380000413d000000000021041b0000000501000029000000040200002909b908550000040f0000000001000019000009ba0001042e0000008006600039000000400060043f000000800050043f00000024022000390000000004240019000000000034004b000000560000213d000000000005004b000007390000613d0000008003000039000000000521034f000000000505043b000000200330003900000000005304350000002002200039000000000042004b000007320000413d0000000901000039000000000101041a000500000001001d000002b901000041000000000010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002ba011001c70000800b0200003909b909b40000040f0000000100200190000007be0000613d000000000101043b0000000502000029000002bb02200197000000000012004b000007bf0000213d00000005020000290000002802200270000002bb02200197000000000012004b000007bf0000a13d000000000100041a0000000002000416000000000012004b000007e70000c13d0000000a01000039000000000101041a000002e00010009c000008380000613d0000000102000039000000000202041a000000000021004b000006050000813d00000003010000290000027201100197000200000001001d000000000010043f0000000701000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000000101041a000000ff00100190000008470000c13d0000000801000039000000000101041a000100000001001d000000400100043d00000014020000390000000002210436000000030300002900000060033002100000000000320435000002bd0010009c000006210000213d0000004003100039000000400030043f0000026f0020009c0000026f02008041000000400220021000000000010104330000026f0010009c0000026f010080410000006001100210000000000121019f00000000020004140000026f0020009c0000026f02008041000000c002200210000000000112019f00000275011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000800300043d000000000003004b000007ad0000613d000000a0020000390000000503300210000400a00030003d0000000043020434000500000004001d000000000031004b000000000300003900000020030020390000000000130435000000200130015f0000000002020433000000000021043500000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b0000000503000029000000040030006c0000000002030019000007960000413d000000010010006c000008510000c13d0000000201000029000000000010043f0000000701000039000000200010043f0000004002000039000000000100001909b9099a0000040f000000000201041a000002e10220019700000001022001bf000000000021041b000000030100002909b908ea0000040f0000000001000019000009ba0001042e000000000001042f000002de01000041000000000010043f000002c101000041000009bb000104300000001f0530018f0000027106300198000000400200043d0000000004620019000007ce0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000007ca0000c13d000000000005004b000007db0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000026f0020009c0000026f020080410000004002200210000000000112019f000009bb000104300000000301000029000000000001041b000000050100002909b909830000040f0000000001000019000009ba0001042e000002da01000041000000000010043f000002c101000041000009bb000104300000000501000029000000000010043f0000000201000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000000101041a000000030010006b000008200000a13d000002dc01000041000000000010043f000002c101000041000009bb00010430000002d901000041000000000010043f000002c101000041000009bb000104300000001f0530018f0000027106300198000000400200043d0000000004620019000007ce0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000080b0000c13d000007ce0000013d0000001f0530018f0000027106300198000000400200043d0000000004620019000007ce0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008170000c13d000007ce0000013d000002d501000041000000000010043f000002c101000041000009bb00010430000000030000006b000008260000c13d000002db01000041000000000010043f000002c101000041000009bb000104300000000501000029000000000010043f0000000201000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000000560000613d000000000101043b000000000301041a0000000302000029000000000323004b000008420000813d000002cf01000041000000000010043f0000001101000039000000040010043f000002d001000041000009bb00010430000002ce01000041000000000010043f000002c101000041000009bb00010430000000000031041b000000050100002909b908550000040f0000000001000019000009ba0001042e000002ca01000041000000000010043f000002c101000041000009bb00010430000002cf01000041000000000010043f0000003201000039000000040010043f000002d001000041000009bb00010430000002cb01000041000000000010043f000002c101000041000009bb000104300005000000000002000500000002001d0000027201100197000400000001001d000000000010043f0000000b01000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f0000000100200190000008bb0000613d000000000101043b000000000201041a0000000504000029000000000042001a000008bd0000413d0000000002420019000000000021041b0000000a01000039000000000301041a0000000002430019000000000032004b00000000030000390000000103004039000000010030008c000008bd0000613d000000000021041b0000000c01000039000000000101041a000002e20200004100000000002004430000027201100197000300000001001d000000040010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002c5011001c7000080020200003909b909b40000040f0000000100200190000008c30000613d000000000101043b000000000001004b000008bb0000613d000000400300043d00000064013000390000008002000039000000000021043500000044013000390000000102000039000000000021043500000024013000390000000000210435000002e3010000410000000000130435000000040130003900000004020000290000000000210435000000840130003900000000000104350000026f0030009c000200000003001d0000026f010000410000000001034019000100400010021800000000010004140000026f0010009c0000026f01008041000000c00110021000000001011001af000002e4011001c7000000030200002909b909af0000040f0000000100200190000008c40000613d0000000202000029000002cc0020009c0000000501000029000008e40000813d000000400020043f000000000012043500000000010004140000026f0010009c0000026f01008041000000c00110021000000001011001af000002e5011001c70000800d020000390000000203000039000002e604000041000000040500002909b909af0000040f0000000100200190000008bb0000613d000000000001042d0000000001000019000009bb00010430000002cf01000041000000000010043f0000001101000039000000040010043f000002d001000041000009bb00010430000000000001042f00000060061002700000001f0460018f0000027105600198000000400200043d0000000003520019000008d00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000008cc0000c13d0000026f06600197000000000004004b000008de0000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000013043500000060016002100000026f0020009c0000026f020080410000004002200210000000000112019f000009bb00010430000002cf01000041000000000010043f0000004101000039000000040010043f000002d001000041000009bb0001043000040000000000020000027201100197000400000001001d000000000010043f0000000b01000039000000200010043f00000000010004140000026f0010009c0000026f01008041000000c001100210000002bc011001c7000080100200003909b909b40000040f00000001002001900000094a0000613d000000000101043b000000000201041a000000010220003a0000094c0000613d000000000021041b0000000a01000039000000000201041a000000010220003a0000094c0000613d000000000021041b0000000c01000039000000000101041a000002e20200004100000000002004430000027201100197000300000001001d000000040010044300000000010004140000026f0010009c0000026f01008041000000c001100210000002c5011001c7000080020200003909b909b40000040f0000000100200190000009520000613d000000000101043b000000000001004b0000094a0000613d000000400300043d000000640130003900000080020000390000000000210435000000440130003900000001020000390000000000210435000000240130003900000002020000390000000000210435000002e3010000410000000000130435000000040130003900000004020000290000000000210435000000840130003900000000000104350000026f0030009c000200000003001d0000026f010000410000000001034019000100400010021800000000010004140000026f0010009c0000026f01008041000000c00110021000000001011001af000002e4011001c7000000030200002909b909af0000040f0000000100200190000009530000613d0000000201000029000002cc0010009c000009730000813d000000400010043f0000000102000039000000000021043500000000010004140000026f0010009c0000026f01008041000000c00110021000000001011001af000002e5011001c70000800d020000390000000203000039000002e604000041000000040500002909b909af0000040f00000001002001900000094a0000613d000000000001042d0000000001000019000009bb00010430000002cf01000041000000000010043f0000001101000039000000040010043f000002d001000041000009bb00010430000000000001042f00000060061002700000001f0460018f0000027105600198000000400200043d00000000035200190000095f0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b0000095b0000c13d0000026f06600197000000000004004b0000096d0000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000013043500000060016002100000026f0020009c0000026f020080410000004002200210000000000112019f000009bb00010430000002cf01000041000000000010043f0000004101000039000000040010043f000002d001000041000009bb000104300000027401000041000000000101041a0000000002000411000000000012004b0000097f0000c13d000000000001042d000002d301000041000000000010043f000002bf01000041000009bb0001043000010000000000020000027402000041000000000502041a000000000200041400000272061001970000026f0020009c0000026f02008041000000c00120021000000275011001c70000800d0200003900000003030000390000027604000041000100000006001d09b909af0000040f0000000100200190000009970000613d00000274010000410000000102000029000000000021041b000000000001042d0000000001000019000009bb00010430000000000001042f0000026f0010009c0000026f0100804100000040011002100000026f0020009c0000026f020080410000006002200210000000000112019f00000000020004140000026f0020009c0000026f02008041000000c002200210000000000112019f00000275011001c7000080100200003909b909b40000040f0000000100200190000009ad0000613d000000000101043b000000000001042d0000000001000019000009bb00010430000009b2002104210000000102000039000000000001042d0000000002000019000000000001042d000009b7002104230000000102000039000000000001042d0000000002000019000000000001042d000009b900000432000009ba0001042e000009bb0001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000138a388a43c0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392702000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0ffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000067e478e00067e1d5e00000000000000000000000000000000000000000000000680d57600067e478e0ffffffffffffffffffffffff00000000000000000000000000000000000000000000000200000000000000000000000000000040000001000000000000000000000000000000000000000000000000000000000000000000000000009b69be9600000000000000000000000000000000000000000000000000000000cc542a2c00000000000000000000000000000000000000000000000000000000f04e283d00000000000000000000000000000000000000000000000000000000f740027800000000000000000000000000000000000000000000000000000000f740027900000000000000000000000000000000000000000000000000000000fe549d7300000000000000000000000000000000000000000000000000000000fee81cf400000000000000000000000000000000000000000000000000000000f04e283e00000000000000000000000000000000000000000000000000000000f0f4426000000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000d3bba3ed00000000000000000000000000000000000000000000000000000000d3bba3ee00000000000000000000000000000000000000000000000000000000dab543cf00000000000000000000000000000000000000000000000000000000e086e5ec00000000000000000000000000000000000000000000000000000000cc542a2d00000000000000000000000000000000000000000000000000000000cc5c53f900000000000000000000000000000000000000000000000000000000bbd77d8c00000000000000000000000000000000000000000000000000000000c39887f400000000000000000000000000000000000000000000000000000000c39887f500000000000000000000000000000000000000000000000000000000c571de5f00000000000000000000000000000000000000000000000000000000c989d07500000000000000000000000000000000000000000000000000000000bbd77d8d00000000000000000000000000000000000000000000000000000000bf6b6cf500000000000000000000000000000000000000000000000000000000a035b1fd00000000000000000000000000000000000000000000000000000000a035b1fe00000000000000000000000000000000000000000000000000000000a096595100000000000000000000000000000000000000000000000000000000b5b552ea000000000000000000000000000000000000000000000000000000009b69be97000000000000000000000000000000000000000000000000000000009bb93c4a0000000000000000000000000000000000000000000000000000000054d895e4000000000000000000000000000000000000000000000000000000008d6d49240000000000000000000000000000000000000000000000000000000091b7f5ec0000000000000000000000000000000000000000000000000000000091b7f5ed000000000000000000000000000000000000000000000000000000009218aaab0000000000000000000000000000000000000000000000000000000097b01d1d000000000000000000000000000000000000000000000000000000008d6d4925000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000006a5cab9f000000000000000000000000000000000000000000000000000000006a5caba000000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000007a8b39a10000000000000000000000000000000000000000000000000000000054d895e50000000000000000000000000000000000000000000000000000000061d027b300000000000000000000000000000000000000000000000000000000256929610000000000000000000000000000000000000000000000000000000047d212d90000000000000000000000000000000000000000000000000000000047d212da000000000000000000000000000000000000000000000000000000004e3cd2330000000000000000000000000000000000000000000000000000000054d1f13d0000000000000000000000000000000000000000000000000000000025692962000000000000000000000000000000000000000000000000000000002f99c77b00000000000000000000000000000000000000000000000000000000083a7ba900000000000000000000000000000000000000000000000000000000083a7baa000000000000000000000000000000000000000000000000000000000c795db4000000000000000000000000000000000000000000000000000000000ea307150000000000000000000000000000000000000000000000000000000001c372e70000000000000000000000000000000000000000000000000000000006f47a1300000000000000000000000000000000000000000000000000000000389a75e10000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffff7f796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffff0200000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf000000000000000000000000000000000000000000000000000000007448fbae00000000000000000000000000000000000000040000001c000000000000000014bcf5c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000002000000000000000000000000000000000000200000000c0000000000000000000000000000000000000000000000000000000000000000000000006f5e88189cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f39020000020000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000b12d13ebc10dcfe266c1f71ef476efbd3223555750dc271e4115626b00000000000000005989265700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000000000000000089644bf1000000000000000000000000000000000000000000000000000000000027b1550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000008000000000000000000000000000000000000000000000000000000000000000b89fe006000000000000000000000000000000000000000000000000000000004e487b71000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000fa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c923efb96ce000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082b4290000000000000000000000000000000000000000000000ffffffffff0000000000b7d0949700000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d00dbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d00000000000000000000000000000000000000440000008000000000000000009ccd6d760000000000000000000000000000000000000000000000000000000099b5cb1d000000000000000000000000000000000000000000000000000000002c5211c6000000000000000000000000000000000000000000000000000000003bce871c00000000000000000000000000000000000000000000000000000000a7dfdbd5000000000000000000000000000000000000000000000000000000000734f1ad0000000000000000000000000000000000000000000000000000000035a66b2c00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83731133e90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a40000000000000000000000000200000000000000000000000000000000000020000000000000000000000000d8b30ad5fe235bfcc526a3e3dd469192ec3ef9ee4fb0a31a626165efcc19e75c00000000000000000000000000000000000000000000000000000000000000009d02b947c0e46af5850ed6f908a1378efeb97866c40c744285b450ea7720e4d1
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000fae7a013ccf023525a0d2696806f7fd0fd8a6ecd0000000000000000000000009995d38fe4f87c806ebf1c45046af3a6c612fc090000000000000000000000000000000078cc4cc1c14e27c0fa35ed6e5e58825d
-----Decoded View---------------
Arg [0] : _badgeContract (address): 0xFaE7a013Ccf023525a0d2696806F7fd0fD8A6ecD
Arg [1] : _treasury (address): 0x9995d38fE4f87C806EBF1C45046af3A6C612Fc09
Arg [2] : _delegateResolver (address): 0x0000000078CC4Cc1C14E27c0fa35ED6E5E58825D
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000fae7a013ccf023525a0d2696806f7fd0fd8a6ecd
Arg [1] : 0000000000000000000000009995d38fe4f87c806ebf1c45046af3a6c612fc09
Arg [2] : 0000000000000000000000000000000078cc4cc1c14e27c0fa35ed6e5e58825d
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.