ETH Price: $3,304.30 (+2.46%)
 

Overview

ETH Balance

5 wei

Eth Value

Less Than $0.01 (@ $3,304.30/ETH)

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw167315492023-03-01 4:59:23694 days ago1677646763IN
0x607F1a6D...8B014140d
0 ETH0.0228544218
Withdraw166535582023-02-18 5:50:23705 days ago1676699423IN
0x607F1a6D...8B014140d
0 ETH0.0247682922.37107708
Withdraw166002032023-02-10 18:39:47713 days ago1676054387IN
0x607F1a6D...8B014140d
0 ETH0.0302508327.03557799
Set Treasury Max...166001772023-02-10 18:34:35713 days ago1676054075IN
0x607F1a6D...8B014140d
0 ETH0.0005706523.91496003

Latest 24 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
167315492023-03-01 4:59:23694 days ago1677646763
0x607F1a6D...8B014140d
0.063 ETH
167315492023-03-01 4:59:23694 days ago1677646763
0x607F1a6D...8B014140d
0.0462 ETH
167315492023-03-01 4:59:23694 days ago1677646763
0x607F1a6D...8B014140d
0.0462 ETH
167315492023-03-01 4:59:23694 days ago1677646763
0x607F1a6D...8B014140d
0.0126 ETH
167315492023-03-01 4:59:23694 days ago1677646763
0x607F1a6D...8B014140d
0.0084 ETH
167315492023-03-01 4:59:23694 days ago1677646763
0x607F1a6D...8B014140d
0.084 ETH
167315492023-03-01 4:59:23694 days ago1677646763
0x607F1a6D...8B014140d
0.1596 ETH
167293462023-02-28 21:32:59695 days ago1677619979
0x607F1a6D...8B014140d
0.42 ETH
166535582023-02-18 5:50:23705 days ago1676699423
0x607F1a6D...8B014140d
0.063 ETH
166535582023-02-18 5:50:23705 days ago1676699423
0x607F1a6D...8B014140d
0.0462 ETH
166535582023-02-18 5:50:23705 days ago1676699423
0x607F1a6D...8B014140d
0.0462 ETH
166535582023-02-18 5:50:23705 days ago1676699423
0x607F1a6D...8B014140d
0.0126 ETH
166535582023-02-18 5:50:23705 days ago1676699423
0x607F1a6D...8B014140d
0.0084 ETH
166535582023-02-18 5:50:23705 days ago1676699423
0x607F1a6D...8B014140d
0.084 ETH
166535582023-02-18 5:50:23705 days ago1676699423
0x607F1a6D...8B014140d
0.1596 ETH
166374392023-02-15 23:32:59708 days ago1676503979
0x607F1a6D...8B014140d
0.42 ETH
166002032023-02-10 18:39:47713 days ago1676054387
0x607F1a6D...8B014140d
0.01619999 ETH
166002032023-02-10 18:39:47713 days ago1676054387
0x607F1a6D...8B014140d
0.01187999 ETH
166002032023-02-10 18:39:47713 days ago1676054387
0x607F1a6D...8B014140d
0.01187999 ETH
166002032023-02-10 18:39:47713 days ago1676054387
0x607F1a6D...8B014140d
0.00323999 ETH
166002032023-02-10 18:39:47713 days ago1676054387
0x607F1a6D...8B014140d
0.00215999 ETH
166002032023-02-10 18:39:47713 days ago1676054387
0x607F1a6D...8B014140d
0.02159999 ETH
166002032023-02-10 18:39:47713 days ago1676054387
0x607F1a6D...8B014140d
0.04103999 ETH
166001722023-02-10 18:33:35713 days ago1676054015
0x607F1a6D...8B014140d
0.10799999 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CryptaDaoVault

Compiler Version
v0.8.9+commit.e5eed63a

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion
File 1 of 12 : CryptaDaoVault.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeTransferLib} from "solady/src/utils/SafeTransferLib.sol";
import {ECDSA} from "solady/src/utils/ECDSA.sol";
import {IERC721A} from "erc721a/contracts/IERC721A.sol";
import {IERC721AQueryable} from "erc721a/contracts/extensions/IERC721AQueryable.sol";
//  Crypta Digital                                                 
//                        .        :kk:        .                                       
//                    .;oo'       cO00Oc       ,ol,.                                   
//                  .lKW0,      .cO0000Oc.      ,0WKl.                                 
//                 .xWMO'      .l00000000l.      'OMWd.                                
//                .xWMM0,      ;O00000000O;      ,0MMWx.                               
//               .kWMMMM0,     .l00000000l.     ,0MMMMWx.                              
//              .kWMMMMMMK;     .l00000Ol.     ;KMMMMMMWk.                             
//              ,KMMMMMMMMK;     .cO00Oc.     ;KMMMMMMMMK,                             
//               ;KMMMMMMMMK:      ckkc      :KMMMMMMMMK;                              
//                ,0MMMMMMMMX:      ..      :XMMMMMMMM0,                               
//                 ,0MMMMMMMMXc            cXMMMMMMMM0,                                
//                  'OWMMMMMMMXc          cXMMMMMMMMO'                                 
//                   .OWMMMMMMMNl        lNMMMMMMMWO.                                  
//                    .kWMMMMMMMNo.    .oNMMMMMMMWk.                                   
//                     .kWMMMMMMMNo.  .oNMMMMMMMWk.                                    
//                      .xWMMMMMMMWo''oWMMMMMMMWx.                                     
//                ..     .xWMMMMMMMWXXWMMMMMMMWx.     ..                               
//               'lc.     .dWMMMMMMMMMMMMMMMMWd.     .ox,                              
//              'looc.     .oNMMMMMMMMMMMMMMNo.     'dkkx;                             
//             ,odoodl.     .oNMMMMMMMMMMMMNo.     'dkkkkx;                            
//            ,oooooodl.     .lNMMMMMMMMMMNl.     ,dkkkkkkx;                           
//           ,ooooooooo;       lXMMMMMMMMXl       ckkkkkkkkx:                          
//          ;ooooooooo:.        cXMMMMMMXc        .ckkkkkkkkx:.                        
//         ;ooooooooo;.          :XMMMMX:          .ckkkkkkkkkc.                       
//        ;ooooooooo;             :XMMX:            .ckkkkkkkkkc.                      
//      .;ooooooooo;               :kk:              .:xkkkkkkkkc.                     
//     .:oooooooool,.                                .:xkkkkkkkkkl.                    
//     ,cccccccccccc:,.                           .':lddodddoododo;                    
//                                                 ................
/**
* Contrat for withdrawal of funds based on percentages of shares held
*/
contract CryptaDaoVault is Ownable, Pausable, ReentrancyGuard {
    // Admin address
    address public admin;

    // CryptaKeys Address
    address public keys;

    // Crypta Treasury Wallet
    address public treasury;

    // Crypta Treasury fixed amount
    uint public treasuryMaxAmount = 1.3 ether;

    // Timestamp of last withdrawal, one withdrawal in 30d
    uint public treasuryLastWithdrawal;

    // Interval for treasury withdrawal
    uint64 public treasuryInterval = 30 days;

    struct OwnerBalance {
        address wallet;
        uint shares;
    }
    
    event Received(address indexed sender, uint256 value);

    constructor() {
        treasury = address(0xed2Bcaa9D8808b80c0457605402A30C7038EF8cf);
        keys = address(0xfc09db1A2D09559F74191E160c597B061043Fa9C);
        admin = msg.sender;
    }

    receive() external payable {
        emit Received(msg.sender, msg.value);
    }

    modifier adminOrOwner() {
        require(msg.sender == admin || msg.sender == owner(), "403");
        _;
    }

    function setAdmin(address _admin) external onlyOwner {
        admin = _admin;
    }

    /**
    * @param _address treasury wallet address
    */
    function setTreasuryWallet(address _address) external adminOrOwner {
        treasury = _address;
    }

    function setTreasuryMaxAmount(uint _amount) external adminOrOwner {
        treasuryMaxAmount = _amount;
    }

    function setTreasuryInterval(uint64 _interval) external adminOrOwner {
        treasuryInterval = _interval;
    }

    function _indexOf(OwnerBalance[] memory arr, address searchFor) private pure returns (uint) {
        uint length = arr.length;
        for (uint i = 0; i < length;) {
            if (arr[i].wallet == searchFor) {
                return i;
            }
            unchecked { ++i; }
        }
        return 999;
    }

    function getOwnerBalance(address _owner) public view returns(uint) {
        IERC721A keyContract = IERC721A(keys);
        return keyContract.balanceOf(_owner);
    }

    function getOwnersSupply() public view returns(uint) {
        return IERC721A(keys).totalSupply();
    }

    function getOwnersTokens() public view returns(uint[] memory) {
        uint totalSupply = getOwnersSupply();
        uint[] memory tokenIds = new uint[](totalSupply);
        for (uint i = 0; i < totalSupply;) {
            tokenIds[i] = i + 1;
            unchecked { ++i; }
        }
        return tokenIds;
    }

    function getOwners() public view returns(OwnerBalance[] memory) {
        // Fetch keys ownership data
        IERC721AQueryable keysInstance = IERC721AQueryable(keys);
        IERC721A keyContract = IERC721A(keys);
        IERC721AQueryable.TokenOwnership[] memory explicitOwnership = keysInstance.explicitOwnershipsOf(getOwnersTokens());

        uint ownersLength = explicitOwnership.length;
        uint indexList = 0;
        // First create the array with max length (100)
        // fill the array with balances
        OwnerBalance[] memory ownersBalances = new OwnerBalance[](ownersLength);
        for (uint c = 0; c < ownersLength;) {
            if (explicitOwnership[c].addr != address(0) && !explicitOwnership[c].burned) {
                uint indexLocation = _indexOf(ownersBalances, explicitOwnership[c].addr);
                if (indexLocation == 999) {
                    uint balance = keyContract.balanceOf(explicitOwnership[c].addr);
                    if (balance != 0) {
                        ownersBalances[indexList] = OwnerBalance(explicitOwnership[c].addr, balance);
                        indexList++;
                    }   
                }
            }
            unchecked { ++c; }
        }
        // Filter empty slots out
        OwnerBalance[] memory ownersBalancesFiltered = new OwnerBalance[](indexList);
        for (uint c = 0; c < indexList;) {
            ownersBalancesFiltered[c] = ownersBalances[c];
            unchecked { ++c; }
        }
        return ownersBalancesFiltered;
    }

    function withdraw(address _token) external nonReentrant {
        OwnerBalance[] memory ownersList = getOwners();
        uint length = ownersList.length;
        require(length > 0, "NO_OWNERS");
        _withdrawTreasury();
        uint balanceLeft = address(this).balance;
        // Proceed with withdrawal if balance is > 0
        if (balanceLeft > 0) {
            for (uint c = 0; c < length;) {
                if (ownersList[c].shares > 0) {
                    uint256 payoutAmount = (balanceLeft * ownersList[c].shares) / 100;
                    SafeTransferLib.safeTransferETH(ownersList[c].wallet, payoutAmount);
                }
                unchecked { ++c; }
            }
        }
        if (_token != address(0)) {
            _withdrawERC20(_token, ownersList);
        }
    }

    function withdrawERC20(address _token) external nonReentrant {
        require(_token != address(0), "INVALID_TOKEN");
        OwnerBalance[] memory ownersList = getOwners();
        _withdrawERC20(_token, ownersList);
    }

    function _withdrawERC20(address _token, OwnerBalance[] memory ownersList) internal {
        IERC20 targetToken = IERC20(_token);
        uint256 balance = targetToken.balanceOf(address(this));

        if (balance > 0) {
            uint length = ownersList.length;
            if (length > 0) {
                for (uint c = 0; c < length;) {
                    if (ownersList[c].wallet != address(0) && ownersList[c].shares > 0) {
                        uint256 payoutAmount = (balance * ownersList[c].shares) / 100;
                        SafeTransferLib.safeTransfer(_token, ownersList[c].wallet, payoutAmount);
                    }
                    unchecked { ++c; }
                }
            } 
        } 
    }

    function calculateTreasuryWithdrawal() public view returns(uint) {
        uint balance = address(this).balance;
        if (treasuryMaxAmount > 0 && balance > 0){
            uint treasuryPayout = balance;
            if (balance > treasuryMaxAmount) {
                treasuryPayout = balance - treasuryMaxAmount;
            }
            return treasuryPayout;
        }
        return 0;
    }

    function _withdrawTreasury() internal {
        uint allowedTime = treasuryLastWithdrawal + treasuryInterval;
        if ((allowedTime < block.timestamp) && treasury != address(0)) {
            uint treasuryPayout = calculateTreasuryWithdrawal();
            if (treasuryPayout > 0) {
                (bool success,) = treasury.call{value: treasuryPayout}("");
                require(success, "FAILED_TREASURY");
                treasuryLastWithdrawal = block.timestamp;
            }
        }
    }

    function safetyTreasuryWithdraw() external nonReentrant onlyOwner {
        require(treasury != address(0), "INVALID_VAULT");
        SafeTransferLib.safeTransferETH(treasury, address(this).balance);
    }

    function safetyTreasuryWithdrawERC20(address _token) external nonReentrant onlyOwner {
        require(treasury != address(0), "INVALID_VAULT");
        IERC20 targetToken = IERC20(_token);
        uint256 balance = targetToken.balanceOf(address(this));
        require(balance != 0, "EMPTY_BALANCE");
        SafeTransferLib.safeTransfer(_token, treasury, balance);
    }
}

File 2 of 12 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 3 of 12 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

File 4 of 12 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 5 of 12 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 6 of 12 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 7 of 12 : SafeTransferLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Caution! This library won't check that a token has code, responsibility is delegated to the caller.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH
    /// that disallows any storage writes.
    uint256 internal constant _GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    /// Multiply by a small constant (e.g. 2), if needed.
    uint256 internal constant _GAS_STIPEND_NO_GRIEF = 100000;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` (in wei) ETH to `to`.
    /// Reverts upon failure.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, amount, 0, 0, 0, 0)) {
                // Store the function selector of `ETHTransferFailed()`.
                mstore(0x00, 0xb12d13eb)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    /// The `gasStipend` can be set to a low enough value to prevent
    /// storage writes or gas griefing.
    ///
    /// If sending via the normal procedure fails, force sends the ETH by
    /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.
    ///
    /// Reverts if the current contract has insufficient balance.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // If insufficient balance, revert.
            if lt(selfbalance(), amount) {
                // Store the function selector of `ETHTransferFailed()`.
                mstore(0x00, 0xb12d13eb)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Transfer the ETH and check if it succeeded or not.
            if iszero(call(gasStipend, to, amount, 0, 0, 0, 0)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                // We can directly use `SELFDESTRUCT` in the contract creation.
                // We don't check and revert upon failure here, just in case
                // `SELFDESTRUCT`'s behavior is changed some day in the future.
                // (If that ever happens, we will riot, and port the code to use WETH).
                pop(create(amount, 0x0b, 0x16))
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a gas stipend
    /// equal to `_GAS_STIPEND_NO_GRIEF`. This gas stipend is a reasonable default
    /// for 99% of cases and can be overriden with the three-argument version of this
    /// function if necessary.
    ///
    /// If sending via the normal procedure fails, force sends the ETH by
    /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.
    ///
    /// Reverts if the current contract has insufficient balance.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        // Manually inlined because the compiler doesn't inline functions with branches.
        /// @solidity memory-safe-assembly
        assembly {
            // If insufficient balance, revert.
            if lt(selfbalance(), amount) {
                // Store the function selector of `ETHTransferFailed()`.
                mstore(0x00, 0xb12d13eb)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Transfer the ETH and check if it succeeded or not.
            if iszero(call(_GAS_STIPEND_NO_GRIEF, to, amount, 0, 0, 0, 0)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                // We can directly use `SELFDESTRUCT` in the contract creation.
                // We don't check and revert upon failure here, just in case
                // `SELFDESTRUCT`'s behavior is changed some day in the future.
                // (If that ever happens, we will riot, and port the code to use WETH).
                pop(create(amount, 0x0b, 0x16))
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    /// The `gasStipend` can be set to a low enough value to prevent
    /// storage writes or gas griefing.
    ///
    /// Simply use `gasleft()` for `gasStipend` if you don't need a gas stipend.
    ///
    /// Note: Does NOT revert upon failure.
    /// Returns whether the transfer of ETH is successful instead.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and check if it succeeded or not.
            success := call(gasStipend, to, amount, 0, 0, 0, 0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      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 {
            // We'll write our calldata to this slot below, but restore it later.
            let memPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(0x00, 0x23b872dd)
            mstore(0x20, from) // Append the "from" argument.
            mstore(0x40, to) // Append the "to" argument.
            mstore(0x60, amount) // Append the "amount" argument.

            if iszero(
                and(
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    // We use 0x64 because that's the total length of our calldata (0x04 + 0x20 * 3)
                    // Counterintuitively, this call() must be positioned after the or() in the
                    // surrounding and() because and() evaluates its arguments from right to left.
                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `TransferFromFailed()`.
                mstore(0x00, 0x7939f424)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, memPointer) // Restore the memPointer.
        }
    }

    /// @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 {
            // We'll write our calldata to this slot below, but restore it later.
            let memPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(0x00, 0xa9059cbb)
            mstore(0x20, to) // Append the "to" argument.
            mstore(0x40, amount) // Append the "amount" argument.

            if iszero(
                and(
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    // We use 0x44 because that's the total length of our calldata (0x04 + 0x20 * 2)
                    // Counterintuitively, this call() must be positioned after the or() in the
                    // surrounding and() because and() evaluates its arguments from right to left.
                    call(gas(), token, 0, 0x1c, 0x44, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `TransferFailed()`.
                mstore(0x00, 0x90b8ec18)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            mstore(0x40, memPointer) // Restore the memPointer.
        }
    }

    /// @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 {
            // We'll write our calldata to this slot below, but restore it later.
            let memPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(0x00, 0x095ea7b3)
            mstore(0x20, to) // Append the "to" argument.
            mstore(0x40, amount) // Append the "amount" argument.

            if iszero(
                and(
                    // Set success to whether the call reverted, if not we check it either
                    // returned exactly 1 (can't just be non-zero data), or had no return data.
                    or(eq(mload(0x00), 1), iszero(returndatasize())),
                    // We use 0x44 because that's the total length of our calldata (0x04 + 0x20 * 2)
                    // Counterintuitively, this call() must be positioned after the or() in the
                    // surrounding and() because and() evaluates its arguments from right to left.
                    call(gas(), token, 0, 0x1c, 0x44, 0x00, 0x20)
                )
            ) {
                // Store the function selector of `ApproveFailed()`.
                mstore(0x00, 0x3e3f8f73)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }

            mstore(0x40, memPointer) // Restore the memPointer.
        }
    }
}

File 8 of 12 : ECDSA.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
library ECDSA {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The signature is invalid.
    error InvalidSignature();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The number which `s` must not exceed in order for
    /// the signature to be non-malleable.
    bytes32 private constant _MALLEABILITY_THRESHOLD =
        0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    RECOVERY OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // Note: as of the Solady version v0.0.68, these functions will
    // revert upon recovery failure for more safety.

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    function recover(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            // Directly copy `r` and `s` from the calldata.
            calldatacopy(0x40, signature.offset, 0x40)
            // Store the `hash` in the scratch space.
            mstore(0x00, hash)
            // Compute `v` and store it in the scratch space.
            mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40))))
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    and(
                        // If the signature is exactly 65 bytes in length.
                        eq(signature.length, 65),
                        // If `s` in lower half order, such that the signature is not malleable.
                        lt(mload(0x60), add(_MALLEABILITY_THRESHOLD, 1))
                    ), // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x00, // Start of output.
                    0x20 // Size of output.
                )
            )
            result := mload(0x00)
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                // Store the function selector of `InvalidSignature()`.
                mstore(0x00, 0x8baa579f)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the zero slot.
            mstore(0x60, 0)
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    ///
    /// This function only accepts EIP-2098 short form signatures.
    /// See: https://eips.ethereum.org/EIPS/eip-2098
    ///
    /// To be honest, I do not recommend using EIP-2098 signatures
    /// for simplicity, performance, and security reasons. Most if not
    /// all clients support traditional non EIP-2098 signatures by default.
    /// As such, this method is intentionally not fully inlined.
    /// It is merely included for completeness.
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
        uint8 v;
        bytes32 s;
        /// @solidity memory-safe-assembly
        assembly {
            s := shr(1, shl(1, vs))
            v := add(shr(255, vs), 27)
        }
        result = recover(hash, v, r, s);
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    // If `s` in lower half order, such that the signature is not malleable.
                    lt(s, add(_MALLEABILITY_THRESHOLD, 1)), // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x00, // Start of output.
                    0x20 // Size of output.
                )
            )
            result := mload(0x00)
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                // Store the function selector of `InvalidSignature()`.
                mstore(0x00, 0x8baa579f)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the zero slot.
            mstore(0x60, 0)
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   TRY-RECOVER OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // WARNING!
    // These functions will NOT revert upon recovery failure.
    // Instead, they will return the zero address upon recovery failure.
    // It is critical that the returned address is NEVER compared against
    // a zero address (e.g. an uninitialized address variable).

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    function tryRecover(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(xor(signature.length, 65)) {
                // Copy the free memory pointer so that we can restore it later.
                let m := mload(0x40)
                // Directly copy `r` and `s` from the calldata.
                calldatacopy(0x40, signature.offset, 0x40)
                // If `s` in lower half order, such that the signature is not malleable.
                if iszero(gt(mload(0x60), _MALLEABILITY_THRESHOLD)) {
                    // Store the `hash` in the scratch space.
                    mstore(0x00, hash)
                    // Compute `v` and store it in the scratch space.
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40))))
                    pop(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            0x01, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x40, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                    // Restore the zero slot.
                    mstore(0x60, 0)
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    result := mload(xor(0x60, returndatasize()))
                }
                // Restore the free memory pointer.
                mstore(0x40, m)
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    ///
    /// This function only accepts EIP-2098 short form signatures.
    /// See: https://eips.ethereum.org/EIPS/eip-2098
    ///
    /// To be honest, I do not recommend using EIP-2098 signatures
    /// for simplicity, performance, and security reasons. Most if not
    /// all clients support traditional non EIP-2098 signatures by default.
    /// As such, this method is intentionally not fully inlined.
    /// It is merely included for completeness.
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (address result)
    {
        uint8 v;
        bytes32 s;
        /// @solidity memory-safe-assembly
        assembly {
            s := shr(1, shl(1, vs))
            v := add(shr(255, vs), 27)
        }
        result = tryRecover(hash, v, r, s);
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            // If `s` in lower half order, such that the signature is not malleable.
            if iszero(gt(s, _MALLEABILITY_THRESHOLD)) {
                // Store the `hash`, `v`, `r`, `s` in the scratch space.
                mstore(0x00, hash)
                mstore(0x20, and(v, 0xff))
                mstore(0x40, r)
                mstore(0x60, s)
                pop(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        0x01, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x40, // Start of output.
                        0x20 // Size of output.
                    )
                )
                // Restore the zero slot.
                mstore(0x60, 0)
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(xor(0x60, returndatasize()))
            }
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Store into scratch space for keccak256.
            mstore(0x20, hash)
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32")
            // 0x40 - 0x04 = 0x3c
            result := keccak256(0x04, 0x3c)
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        assembly {
            // The length of "\x19Ethereum Signed Message:\n" is 26 bytes (i.e. 0x1a).
            // If we reserve 2 words, we'll have 64 - 26 = 38 bytes to store the
            // ASCII decimal representation of the length of `s` up to about 2 ** 126.

            // Instead of allocating, we temporarily copy the 64 bytes before the
            // start of `s` data to some variables.
            let m1 := mload(sub(s, 0x20))
            // The length of `s` is in bytes.
            let sLength := mload(s)
            let ptr := add(s, 0x20)
            let w := not(0)
            // `end` marks the end of the memory which we will compute the keccak256 of.
            let end := add(ptr, sLength)
            // Convert the length of the bytes to ASCII decimal representation
            // and store it into the memory.
            for { let temp := sLength } 1 {} {
                ptr := add(ptr, w) // `sub(ptr, 1)`.
                mstore8(ptr, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            // Copy the header over to the memory.
            mstore(sub(ptr, 0x20), "\x00\x00\x00\x00\x00\x00\x19Ethereum Signed Message:\n")
            // Compute the keccak256 of the memory.
            result := keccak256(sub(ptr, 0x1a), sub(end, sub(ptr, 0x1a)))
            // Restore the previous memory.
            mstore(s, sLength)
            mstore(sub(s, 0x20), m1)
        }
    }
}

File 9 of 12 : IERC721A.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

/**
 * @dev Interface of ERC721A.
 */
interface IERC721A {
    /**
     * The caller must own the token or be an approved operator.
     */
    error ApprovalCallerNotOwnerNorApproved();

    /**
     * The token does not exist.
     */
    error ApprovalQueryForNonexistentToken();

    /**
     * Cannot query the balance for the zero address.
     */
    error BalanceQueryForZeroAddress();

    /**
     * Cannot mint to the zero address.
     */
    error MintToZeroAddress();

    /**
     * The quantity of tokens minted must be more than zero.
     */
    error MintZeroQuantity();

    /**
     * The token does not exist.
     */
    error OwnerQueryForNonexistentToken();

    /**
     * The caller must own the token or be an approved operator.
     */
    error TransferCallerNotOwnerNorApproved();

    /**
     * The token must be owned by `from`.
     */
    error TransferFromIncorrectOwner();

    /**
     * Cannot safely transfer to a contract that does not implement the
     * ERC721Receiver interface.
     */
    error TransferToNonERC721ReceiverImplementer();

    /**
     * Cannot transfer to the zero address.
     */
    error TransferToZeroAddress();

    /**
     * The token does not exist.
     */
    error URIQueryForNonexistentToken();

    /**
     * The `quantity` minted with ERC2309 exceeds the safety limit.
     */
    error MintERC2309QuantityExceedsLimit();

    /**
     * The `extraData` cannot be set on an unintialized ownership slot.
     */
    error OwnershipNotInitializedForExtraData();

    // =============================================================
    //                            STRUCTS
    // =============================================================

    struct TokenOwnership {
        // The address of the owner.
        address addr;
        // Stores the start time of ownership with minimal overhead for tokenomics.
        uint64 startTimestamp;
        // Whether the token has been burned.
        bool burned;
        // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
        uint24 extraData;
    }

    // =============================================================
    //                         TOKEN COUNTERS
    // =============================================================

    /**
     * @dev Returns the total number of tokens in existence.
     * Burned tokens will reduce the count.
     * To get the total number of tokens minted, please see {_totalMinted}.
     */
    function totalSupply() external view returns (uint256);

    // =============================================================
    //                            IERC165
    // =============================================================

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

    // =============================================================
    //                            IERC721
    // =============================================================

    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables
     * (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in `owner`'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`,
     * checking first that contract recipients are aware of the ERC721 protocol
     * to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move
     * this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement
     * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external payable;

    /**
     * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom}
     * whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token
     * by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external payable;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the
     * zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external payable;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom}
     * for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    // =============================================================
    //                        IERC721Metadata
    // =============================================================

    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);

    // =============================================================
    //                           IERC2309
    // =============================================================

    /**
     * @dev Emitted when tokens in `fromTokenId` to `toTokenId`
     * (inclusive) is transferred from `from` to `to`, as defined in the
     * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
     *
     * See {_mintERC2309} for more details.
     */
    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}

File 10 of 12 : IERC721AQueryable.sol
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

import '../IERC721A.sol';

/**
 * @dev Interface of ERC721AQueryable.
 */
interface IERC721AQueryable is IERC721A {
    /**
     * Invalid query range (`start` >= `stop`).
     */
    error InvalidQueryRange();

    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *
     * - `addr = address(0)`
     * - `startTimestamp = 0`
     * - `burned = false`
     * - `extraData = 0`
     *
     * If the `tokenId` is burned:
     *
     * - `addr = <Address of owner before token was burned>`
     * - `startTimestamp = <Timestamp when token was burned>`
     * - `burned = true`
     * - `extraData = <Extra data when token was burned>`
     *
     * Otherwise:
     *
     * - `addr = <Address of owner>`
     * - `startTimestamp = <Timestamp of start of ownership>`
     * - `burned = false`
     * - `extraData = <Extra data at start of ownership>`
     */
    function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory);

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory);

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start < stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view returns (uint256[] memory);

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K collections should be fine).
     */
    function tokensOfOwner(address owner) external view returns (uint256[] memory);
}

File 11 of 12 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 12 of 12 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculateTreasuryWithdrawal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getOwnerBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwners","outputs":[{"components":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"}],"internalType":"struct CryptaDaoVault.OwnerBalance[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwnersSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwnersTokens","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keys","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"safetyTreasuryWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"safetyTreasuryWithdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_interval","type":"uint64"}],"name":"setTreasuryInterval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setTreasuryMaxAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setTreasuryWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryInterval","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryLastWithdrawal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryMaxAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405267120a871cc0020000600555600780546001600160401b03191662278d0017905534801561003157600080fd5b5061003b336100a3565b6000805460ff60a01b1916905560018055600480546001600160a01b031990811673ed2bcaa9d8808b80c0457605402a30c7038ef8cf1790915560038054821673fc09db1a2d09559f74191e160c597b061043fa9c17905560028054909116331790556100f3565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6118bf806101026000396000f3fe6080604052600436106101845760003560e01c80637fcf440a116100d6578063a8602fea1161007f578063f2fde38b11610059578063f2fde38b14610469578063f4f3b20014610489578063f851a440146104a957600080fd5b8063a8602fea146103ed578063b140a7081461040d578063beb705741461044757600080fd5b80639ea68750116100b05780639ea68750146103a0578063a0e67e2b146103b5578063a7be5ad0146103d757600080fd5b80637fcf440a1461034c57806381d047ad1461036c5780638da5cb5b1461038257600080fd5b806351cff8d911610138578063704b6c0211610112578063704b6c02146102f7578063715018a6146103175780637ba549b21461032c57600080fd5b806351cff8d91461027c5780635c975abb1461029c57806361d027b3146102d757600080fd5b8063131b413a11610169578063131b413a1461020f578063307540f6146102245780634dca69b11461025c57600080fd5b80630c4cc953146101c5578063129041eb146101e757600080fd5b366101c05760405134815233907f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f885258749060200160405180910390a2005b600080fd5b3480156101d157600080fd5b506101e56101e036600461152f565b6104c9565b005b3480156101f357600080fd5b506101fc610662565b6040519081526020015b60405180910390f35b34801561021b57600080fd5b506101e56106a7565b34801561023057600080fd5b50600354610244906001600160a01b031681565b6040516001600160a01b039091168152602001610206565b34801561026857600080fd5b506101e5610277366004611562565b61076b565b34801561028857600080fd5b506101e561029736600461152f565b6107e4565b3480156102a857600080fd5b5060005474010000000000000000000000000000000000000000900460ff166040519015158152602001610206565b3480156102e357600080fd5b50600454610244906001600160a01b031681565b34801561030357600080fd5b506101e561031236600461152f565b610967565b34801561032357600080fd5b506101e561099e565b34801561033857600080fd5b506101e561034736600461157f565b6109b2565b34801561035857600080fd5b506101fc61036736600461152f565b610a0c565b34801561037857600080fd5b506101fc60055481565b34801561038e57600080fd5b506000546001600160a01b0316610244565b3480156103ac57600080fd5b506101fc610a93565b3480156103c157600080fd5b506103ca610b2e565b6040516102069190611598565b3480156103e357600080fd5b506101fc60065481565b3480156103f957600080fd5b506101e561040836600461152f565b610eba565b34801561041957600080fd5b5060075461042e9067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610206565b34801561045357600080fd5b5061045c610f3e565b60405161020691906115f0565b34801561047557600080fd5b506101e561048436600461152f565b610fd5565b34801561049557600080fd5b506101e56104a436600461152f565b611065565b3480156104b557600080fd5b50600254610244906001600160a01b031681565b600260015414156105215760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b600260015561052e611131565b6004546001600160a01b03166105765760405162461bcd60e51b815260206004820152600d60248201526c1253959053125117d590555315609a1b6044820152606401610518565b6040516370a0823160e01b815230600482015281906000906001600160a01b038316906370a082319060240160206040518083038186803b1580156105ba57600080fd5b505afa1580156105ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f29190611634565b9050806106415760405162461bcd60e51b815260206004820152600d60248201527f454d5054595f42414c414e4345000000000000000000000000000000000000006044820152606401610518565b6004546106599084906001600160a01b03168361118b565b50506001805550565b6005546000904790158015906106785750600081115b1561069f576005548190811115610699576005546106969083611663565b90505b92915050565b600091505090565b600260015414156106fa5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610518565b6002600155610707611131565b6004546001600160a01b031661074f5760405162461bcd60e51b815260206004820152600d60248201526c1253959053125117d590555315609a1b6044820152606401610518565b600454610765906001600160a01b0316476111cf565b60018055565b6002546001600160a01b031633148061078e57506000546001600160a01b031633145b6107c05760405162461bcd60e51b815260206004820152600360248201526234303360e81b6044820152606401610518565b6007805467ffffffffffffffff191667ffffffffffffffff92909216919091179055565b600260015414156108375760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610518565b60026001556000610846610b2e565b8051909150806108985760405162461bcd60e51b815260206004820152600960248201527f4e4f5f4f574e45525300000000000000000000000000000000000000000000006044820152606401610518565b6108a06111ef565b4780156109445760005b828110156109425760008482815181106108c6576108c661167a565b602002602001015160200151111561093a57600060648583815181106108ee576108ee61167a565b602002602001015160200151846109059190611690565b61090f91906116af565b90506109388583815181106109265761092661167a565b602002602001015160000151826111cf565b505b6001016108aa565b505b6001600160a01b0384161561095d5761095d84846112ec565b5050600180555050565b61096f611131565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6109a6611131565b6109b0600061145a565b565b6002546001600160a01b03163314806109d557506000546001600160a01b031633145b610a075760405162461bcd60e51b815260206004820152600360248201526234303360e81b6044820152606401610518565b600555565b6003546040516370a0823160e01b81526001600160a01b038381166004830152600092169081906370a082319060240160206040518083038186803b158015610a5457600080fd5b505afa158015610a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8c9190611634565b9392505050565b600354604080517f18160ddd00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015610af157600080fd5b505afa158015610b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b299190611634565b905090565b6003546060906001600160a01b031680600081635bbb2177610b4e610f3e565b6040518263ffffffff1660e01b8152600401610b6a91906115f0565b60006040518083038186803b158015610b8257600080fd5b505afa158015610b96573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bbe9190810190611741565b80519091506000808267ffffffffffffffff811115610bdf57610bdf6116d1565b604051908082528060200260200182016040528015610c2457816020015b6040805180820190915260008082526020820152815260200190600190039081610bfd5790505b50905060005b83811015610e005760006001600160a01b0316858281518110610c4f57610c4f61167a565b6020026020010151600001516001600160a01b031614158015610c8d5750848181518110610c7f57610c7f61167a565b602002602001015160400151155b15610df8576000610cbb83878481518110610caa57610caa61167a565b6020026020010151600001516114b7565b9050806103e71415610df6576000876001600160a01b03166370a08231888581518110610cea57610cea61167a565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015610d4d57600080fd5b505afa158015610d61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d859190611634565b90508015610df4576040518060400160405280888581518110610daa57610daa61167a565b6020026020010151600001516001600160a01b0316815260200182815250848681518110610dda57610dda61167a565b60200260200101819052508480610df090611856565b9550505b505b505b600101610c2a565b5060008267ffffffffffffffff811115610e1c57610e1c6116d1565b604051908082528060200260200182016040528015610e6157816020015b6040805180820190915260008082526020820152815260200190600190039081610e3a5790505b50905060005b83811015610eae57828181518110610e8157610e8161167a565b6020026020010151828281518110610e9b57610e9b61167a565b6020908102919091010152600101610e67565b50979650505050505050565b6002546001600160a01b0316331480610edd57506000546001600160a01b031633145b610f0f5760405162461bcd60e51b815260206004820152600360248201526234303360e81b6044820152606401610518565b6004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60606000610f4a610a93565b905060008167ffffffffffffffff811115610f6757610f676116d1565b604051908082528060200260200182016040528015610f90578160200160208202803683370190505b50905060005b82811015610fce57610fa9816001611871565b828281518110610fbb57610fbb61167a565b6020908102919091010152600101610f96565b5092915050565b610fdd611131565b6001600160a01b0381166110595760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610518565b6110628161145a565b50565b600260015414156110b85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610518565b60026001556001600160a01b0381166111135760405162461bcd60e51b815260206004820152600d60248201527f494e56414c49445f544f4b454e000000000000000000000000000000000000006044820152606401610518565b600061111d610b2e565b905061112982826112ec565b505060018055565b6000546001600160a01b031633146109b05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610518565b60405163a9059cbb6000528260205281604052602060006044601c6000885af13d1560016000511417166111c7576390b8ec186000526004601cfd5b604052505050565b60008060008084865af16111eb5763b12d13eb6000526004601cfd5b5050565b60075460065460009161120e9167ffffffffffffffff90911690611871565b9050428110801561122957506004546001600160a01b031615155b15611062576000611238610662565b905080156111eb576004546040516000916001600160a01b03169083908381818185875af1925050503d806000811461128d576040519150601f19603f3d011682016040523d82523d6000602084013e611292565b606091505b50509050806112e35760405162461bcd60e51b815260206004820152600f60248201527f4641494c45445f545245415355525900000000000000000000000000000000006044820152606401610518565b50426006555050565b6040516370a0823160e01b815230600482015282906000906001600160a01b038316906370a082319060240160206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113689190611634565b9050801561145457825180156114525760005b818110156114505760006001600160a01b03168582815181106113a0576113a061167a565b6020026020010151600001516001600160a01b0316141580156113e0575060008582815181106113d2576113d261167a565b602002602001015160200151115b1561144857600060648683815181106113fb576113fb61167a565b602002602001015160200151856114129190611690565b61141c91906116af565b9050611446878784815181106114345761143461167a565b6020026020010151600001518361118b565b505b60010161137b565b505b505b50505050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8151600090815b8181101561150e57836001600160a01b03168582815181106114e2576114e261167a565b6020026020010151600001516001600160a01b031614156115065791506106999050565b6001016114be565b506103e7949350505050565b6001600160a01b038116811461106257600080fd5b60006020828403121561154157600080fd5b8135610a8c8161151a565b67ffffffffffffffff8116811461106257600080fd5b60006020828403121561157457600080fd5b8135610a8c8161154c565b60006020828403121561159157600080fd5b5035919050565b602080825282518282018190526000919060409081850190868401855b828110156115e357815180516001600160a01b031685528601518685015292840192908501906001016115b5565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156116285783518352928401929184019160010161160c565b50909695505050505050565b60006020828403121561164657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156116755761167561164d565b500390565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156116aa576116aa61164d565b500290565b6000826116cc57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561170a5761170a6116d1565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611739576117396116d1565b604052919050565b6000602080838503121561175457600080fd5b825167ffffffffffffffff8082111561176c57600080fd5b818501915085601f83011261178057600080fd5b815181811115611792576117926116d1565b6117a0848260051b01611710565b818152848101925060079190911b8301840190878211156117c057600080fd5b928401925b8184101561184b57608084890312156117de5760008081fd5b6117e66116e7565b84516117f18161151a565b8152848601516118008161154c565b8187015260408581015180151581146118195760008081fd5b9082015260608581015162ffffff811681146118355760008081fd5b90820152835260809390930192918401916117c5565b979650505050505050565b600060001982141561186a5761186a61164d565b5060010190565b600082198211156118845761188461164d565b50019056fea26469706673582212200a246cd18fe50162ee557d0f0c59b8567351a120f71b72e0c4b7b18673ed7af564736f6c63430008090033

Deployed Bytecode

0x6080604052600436106101845760003560e01c80637fcf440a116100d6578063a8602fea1161007f578063f2fde38b11610059578063f2fde38b14610469578063f4f3b20014610489578063f851a440146104a957600080fd5b8063a8602fea146103ed578063b140a7081461040d578063beb705741461044757600080fd5b80639ea68750116100b05780639ea68750146103a0578063a0e67e2b146103b5578063a7be5ad0146103d757600080fd5b80637fcf440a1461034c57806381d047ad1461036c5780638da5cb5b1461038257600080fd5b806351cff8d911610138578063704b6c0211610112578063704b6c02146102f7578063715018a6146103175780637ba549b21461032c57600080fd5b806351cff8d91461027c5780635c975abb1461029c57806361d027b3146102d757600080fd5b8063131b413a11610169578063131b413a1461020f578063307540f6146102245780634dca69b11461025c57600080fd5b80630c4cc953146101c5578063129041eb146101e757600080fd5b366101c05760405134815233907f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f885258749060200160405180910390a2005b600080fd5b3480156101d157600080fd5b506101e56101e036600461152f565b6104c9565b005b3480156101f357600080fd5b506101fc610662565b6040519081526020015b60405180910390f35b34801561021b57600080fd5b506101e56106a7565b34801561023057600080fd5b50600354610244906001600160a01b031681565b6040516001600160a01b039091168152602001610206565b34801561026857600080fd5b506101e5610277366004611562565b61076b565b34801561028857600080fd5b506101e561029736600461152f565b6107e4565b3480156102a857600080fd5b5060005474010000000000000000000000000000000000000000900460ff166040519015158152602001610206565b3480156102e357600080fd5b50600454610244906001600160a01b031681565b34801561030357600080fd5b506101e561031236600461152f565b610967565b34801561032357600080fd5b506101e561099e565b34801561033857600080fd5b506101e561034736600461157f565b6109b2565b34801561035857600080fd5b506101fc61036736600461152f565b610a0c565b34801561037857600080fd5b506101fc60055481565b34801561038e57600080fd5b506000546001600160a01b0316610244565b3480156103ac57600080fd5b506101fc610a93565b3480156103c157600080fd5b506103ca610b2e565b6040516102069190611598565b3480156103e357600080fd5b506101fc60065481565b3480156103f957600080fd5b506101e561040836600461152f565b610eba565b34801561041957600080fd5b5060075461042e9067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610206565b34801561045357600080fd5b5061045c610f3e565b60405161020691906115f0565b34801561047557600080fd5b506101e561048436600461152f565b610fd5565b34801561049557600080fd5b506101e56104a436600461152f565b611065565b3480156104b557600080fd5b50600254610244906001600160a01b031681565b600260015414156105215760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b600260015561052e611131565b6004546001600160a01b03166105765760405162461bcd60e51b815260206004820152600d60248201526c1253959053125117d590555315609a1b6044820152606401610518565b6040516370a0823160e01b815230600482015281906000906001600160a01b038316906370a082319060240160206040518083038186803b1580156105ba57600080fd5b505afa1580156105ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f29190611634565b9050806106415760405162461bcd60e51b815260206004820152600d60248201527f454d5054595f42414c414e4345000000000000000000000000000000000000006044820152606401610518565b6004546106599084906001600160a01b03168361118b565b50506001805550565b6005546000904790158015906106785750600081115b1561069f576005548190811115610699576005546106969083611663565b90505b92915050565b600091505090565b600260015414156106fa5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610518565b6002600155610707611131565b6004546001600160a01b031661074f5760405162461bcd60e51b815260206004820152600d60248201526c1253959053125117d590555315609a1b6044820152606401610518565b600454610765906001600160a01b0316476111cf565b60018055565b6002546001600160a01b031633148061078e57506000546001600160a01b031633145b6107c05760405162461bcd60e51b815260206004820152600360248201526234303360e81b6044820152606401610518565b6007805467ffffffffffffffff191667ffffffffffffffff92909216919091179055565b600260015414156108375760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610518565b60026001556000610846610b2e565b8051909150806108985760405162461bcd60e51b815260206004820152600960248201527f4e4f5f4f574e45525300000000000000000000000000000000000000000000006044820152606401610518565b6108a06111ef565b4780156109445760005b828110156109425760008482815181106108c6576108c661167a565b602002602001015160200151111561093a57600060648583815181106108ee576108ee61167a565b602002602001015160200151846109059190611690565b61090f91906116af565b90506109388583815181106109265761092661167a565b602002602001015160000151826111cf565b505b6001016108aa565b505b6001600160a01b0384161561095d5761095d84846112ec565b5050600180555050565b61096f611131565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6109a6611131565b6109b0600061145a565b565b6002546001600160a01b03163314806109d557506000546001600160a01b031633145b610a075760405162461bcd60e51b815260206004820152600360248201526234303360e81b6044820152606401610518565b600555565b6003546040516370a0823160e01b81526001600160a01b038381166004830152600092169081906370a082319060240160206040518083038186803b158015610a5457600080fd5b505afa158015610a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8c9190611634565b9392505050565b600354604080517f18160ddd00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015610af157600080fd5b505afa158015610b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b299190611634565b905090565b6003546060906001600160a01b031680600081635bbb2177610b4e610f3e565b6040518263ffffffff1660e01b8152600401610b6a91906115f0565b60006040518083038186803b158015610b8257600080fd5b505afa158015610b96573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bbe9190810190611741565b80519091506000808267ffffffffffffffff811115610bdf57610bdf6116d1565b604051908082528060200260200182016040528015610c2457816020015b6040805180820190915260008082526020820152815260200190600190039081610bfd5790505b50905060005b83811015610e005760006001600160a01b0316858281518110610c4f57610c4f61167a565b6020026020010151600001516001600160a01b031614158015610c8d5750848181518110610c7f57610c7f61167a565b602002602001015160400151155b15610df8576000610cbb83878481518110610caa57610caa61167a565b6020026020010151600001516114b7565b9050806103e71415610df6576000876001600160a01b03166370a08231888581518110610cea57610cea61167a565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015610d4d57600080fd5b505afa158015610d61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d859190611634565b90508015610df4576040518060400160405280888581518110610daa57610daa61167a565b6020026020010151600001516001600160a01b0316815260200182815250848681518110610dda57610dda61167a565b60200260200101819052508480610df090611856565b9550505b505b505b600101610c2a565b5060008267ffffffffffffffff811115610e1c57610e1c6116d1565b604051908082528060200260200182016040528015610e6157816020015b6040805180820190915260008082526020820152815260200190600190039081610e3a5790505b50905060005b83811015610eae57828181518110610e8157610e8161167a565b6020026020010151828281518110610e9b57610e9b61167a565b6020908102919091010152600101610e67565b50979650505050505050565b6002546001600160a01b0316331480610edd57506000546001600160a01b031633145b610f0f5760405162461bcd60e51b815260206004820152600360248201526234303360e81b6044820152606401610518565b6004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60606000610f4a610a93565b905060008167ffffffffffffffff811115610f6757610f676116d1565b604051908082528060200260200182016040528015610f90578160200160208202803683370190505b50905060005b82811015610fce57610fa9816001611871565b828281518110610fbb57610fbb61167a565b6020908102919091010152600101610f96565b5092915050565b610fdd611131565b6001600160a01b0381166110595760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610518565b6110628161145a565b50565b600260015414156110b85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610518565b60026001556001600160a01b0381166111135760405162461bcd60e51b815260206004820152600d60248201527f494e56414c49445f544f4b454e000000000000000000000000000000000000006044820152606401610518565b600061111d610b2e565b905061112982826112ec565b505060018055565b6000546001600160a01b031633146109b05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610518565b60405163a9059cbb6000528260205281604052602060006044601c6000885af13d1560016000511417166111c7576390b8ec186000526004601cfd5b604052505050565b60008060008084865af16111eb5763b12d13eb6000526004601cfd5b5050565b60075460065460009161120e9167ffffffffffffffff90911690611871565b9050428110801561122957506004546001600160a01b031615155b15611062576000611238610662565b905080156111eb576004546040516000916001600160a01b03169083908381818185875af1925050503d806000811461128d576040519150601f19603f3d011682016040523d82523d6000602084013e611292565b606091505b50509050806112e35760405162461bcd60e51b815260206004820152600f60248201527f4641494c45445f545245415355525900000000000000000000000000000000006044820152606401610518565b50426006555050565b6040516370a0823160e01b815230600482015282906000906001600160a01b038316906370a082319060240160206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113689190611634565b9050801561145457825180156114525760005b818110156114505760006001600160a01b03168582815181106113a0576113a061167a565b6020026020010151600001516001600160a01b0316141580156113e0575060008582815181106113d2576113d261167a565b602002602001015160200151115b1561144857600060648683815181106113fb576113fb61167a565b602002602001015160200151856114129190611690565b61141c91906116af565b9050611446878784815181106114345761143461167a565b6020026020010151600001518361118b565b505b60010161137b565b505b505b50505050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8151600090815b8181101561150e57836001600160a01b03168582815181106114e2576114e261167a565b6020026020010151600001516001600160a01b031614156115065791506106999050565b6001016114be565b506103e7949350505050565b6001600160a01b038116811461106257600080fd5b60006020828403121561154157600080fd5b8135610a8c8161151a565b67ffffffffffffffff8116811461106257600080fd5b60006020828403121561157457600080fd5b8135610a8c8161154c565b60006020828403121561159157600080fd5b5035919050565b602080825282518282018190526000919060409081850190868401855b828110156115e357815180516001600160a01b031685528601518685015292840192908501906001016115b5565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156116285783518352928401929184019160010161160c565b50909695505050505050565b60006020828403121561164657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156116755761167561164d565b500390565b634e487b7160e01b600052603260045260246000fd5b60008160001904831182151516156116aa576116aa61164d565b500290565b6000826116cc57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561170a5761170a6116d1565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611739576117396116d1565b604052919050565b6000602080838503121561175457600080fd5b825167ffffffffffffffff8082111561176c57600080fd5b818501915085601f83011261178057600080fd5b815181811115611792576117926116d1565b6117a0848260051b01611710565b818152848101925060079190911b8301840190878211156117c057600080fd5b928401925b8184101561184b57608084890312156117de5760008081fd5b6117e66116e7565b84516117f18161151a565b8152848601516118008161154c565b8187015260408581015180151581146118195760008081fd5b9082015260608581015162ffffff811681146118355760008081fd5b90820152835260809390930192918401916117c5565b979650505050505050565b600060001982141561186a5761186a61164d565b5060010190565b600082198211156118845761188461164d565b50019056fea26469706673582212200a246cd18fe50162ee557d0f0c59b8567351a120f71b72e0c4b7b18673ed7af564736f6c63430008090033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.