Contract

0x324c5Dc1fC42c7a4D43d92df1eBA58a54d13Bf2d

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

-

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Parent Transaction Hash Block From To
4337052024-12-15 7:23:3720 days ago1734247417  Contract Creation0 S
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FluidVaultFactory

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 10000000 runs

Other Settings:
paris EvmVersion
File 1 of 6 : main.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

import { Owned } from "solmate/src/auth/Owned.sol";
import { ERC721 } from "./ERC721/ERC721.sol";
import { ErrorTypes } from "../errorTypes.sol";

import { StorageRead } from "../../../libraries/storageRead.sol";

abstract contract VaultFactoryVariables is Owned, ERC721, StorageRead {
    /// @dev ERC721 tokens name
    string internal constant ERC721_NAME = "Fluid Vault";
    /// @dev ERC721 tokens symbol
    string internal constant ERC721_SYMBOL = "fVLT";

    /*//////////////////////////////////////////////////////////////
                          STORAGE VARIABLES
    //////////////////////////////////////////////////////////////*/

    // ------------ storage variables from inherited contracts (Owned and ERC721) come before vars here --------

    // ----------------------- slot 0 ---------------------------
    // address public owner; // from Owned

    // 12 bytes empty

    // ----------------------- slot 1 ---------------------------
    // string public name;

    // ----------------------- slot 2 ---------------------------
    // string public symbol;

    // ----------------------- slot 3 ---------------------------
    // mapping(uint256 => uint256) internal _tokenConfig;

    // ----------------------- slot 4 ---------------------------
    // mapping(address => mapping(uint256 => uint256)) internal _ownerConfig;

    // ----------------------- slot 5 ---------------------------
    // uint256 public totalSupply;

    // ----------------------- slot 6 ---------------------------
    // mapping(uint256 => address) public getApproved;

    // ----------------------- slot 7  ---------------------------
    // mapping(address => mapping(address => bool)) public isApprovedForAll;

    // ----------------------- slot 8  ---------------------------
    /// @dev deployer can deploy new Vault contract
    /// owner can add/remove deployer.
    /// Owner is deployer by default.
    mapping(address => bool) internal _deployers;

    // ----------------------- slot 9  ---------------------------
    /// @dev global auths can update any vault config.
    /// owner can add/remove global auths.
    /// Owner is global auth by default.
    mapping(address => bool) internal _globalAuths;

    // ----------------------- slot 10  ---------------------------
    /// @dev vault auths can update specific vault config.
    /// owner can add/remove vault auths.
    /// Owner is vault auth by default.
    /// vault => auth => add/remove
    mapping(address => mapping(address => bool)) internal _vaultAuths;

    // ----------------------- slot 11 ---------------------------
    /// @dev total no of vaults deployed by the factory
    /// only addresses that have deployer role or owner can deploy new vault.
    uint256 internal _totalVaults;

    // ----------------------- slot 12 ---------------------------
    /// @dev vault deployment logics for deploying vault
    /// These logic contracts hold the deployment logics of specific vaults and are called via .delegatecall inside deployVault().
    /// only addresses that have owner can add/remove new vault deployment logic.
    mapping(address => bool) internal _vaultDeploymentLogics;

    /*//////////////////////////////////////////////////////////////
                          CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/
    constructor(address owner_) Owned(owner_) ERC721(ERC721_NAME, ERC721_SYMBOL) {}
}

abstract contract VaultFactoryEvents {
    /// @dev Emitted when a new vault is deployed.
    /// @param vault The address of the newly deployed vault.
    /// @param vaultId The id of the newly deployed vault.
    event VaultDeployed(address indexed vault, uint256 indexed vaultId);

    /// @dev Emitted when a new token/position is minted by a vault.
    /// @param vault The address of the vault that minted the token.
    /// @param user The address of the user who received the minted token.
    /// @param tokenId The ID of the newly minted token.
    event NewPositionMinted(address indexed vault, address indexed user, uint256 indexed tokenId);

    /// @dev Emitted when the deployer is modified by owner.
    /// @param deployer Address whose deployer status is updated.
    /// @param allowed Indicates whether the address is authorized as a deployer or not.
    event LogSetDeployer(address indexed deployer, bool indexed allowed);

    /// @dev Emitted when the globalAuth is modified by owner.
    /// @param globalAuth Address whose globalAuth status is updated.
    /// @param allowed Indicates whether the address is authorized as a deployer or not.
    event LogSetGlobalAuth(address indexed globalAuth, bool indexed allowed);

    /// @dev Emitted when the vaultAuth is modified by owner.
    /// @param vaultAuth Address whose vaultAuth status is updated.
    /// @param allowed Indicates whether the address is authorized as a deployer or not.
    /// @param vault Address of the specific vault related to the authorization change.
    event LogSetVaultAuth(address indexed vaultAuth, bool indexed allowed, address indexed vault);

    /// @dev Emitted when the vault deployment logic is modified by owner.
    /// @param vaultDeploymentLogic The address of the vault deployment logic contract.
    /// @param allowed  Indicates whether the address is authorized as a deployer or not.
    event LogSetVaultDeploymentLogic(address indexed vaultDeploymentLogic, bool indexed allowed);
}

abstract contract VaultFactoryCore is VaultFactoryVariables, VaultFactoryEvents {
    constructor(address owner_) validAddress(owner_) VaultFactoryVariables(owner_) {}

    /// @dev validates that an address is not the zero address
    modifier validAddress(address value_) {
        if (value_ == address(0)) {
            revert FluidVaultError(ErrorTypes.VaultFactory__InvalidParams);
        }
        _;
    }
}

/// @dev Implements Vault Factory auth-only callable methods. Owner / auths can set various config values and
/// can define the allow-listed deployers.
abstract contract VaultFactoryAuth is VaultFactoryCore {
    /// @notice                         Sets an address (`deployer_`) as allowed deployer or not.
    ///                                 This function can only be called by the owner.
    /// @param deployer_                The address to be set as deployer.
    /// @param allowed_                 A boolean indicating whether the specified address is allowed to deploy vaults.
    function setDeployer(address deployer_, bool allowed_) external onlyOwner validAddress(deployer_) {
        _deployers[deployer_] = allowed_;

        emit LogSetDeployer(deployer_, allowed_);
    }

    /// @notice                         Sets an address (`globalAuth_`) as a global authorization or not.
    ///                                 This function can only be called by the owner.
    /// @param globalAuth_              The address to be set as global authorization.
    /// @param allowed_                 A boolean indicating whether the specified address is allowed to update any vault config.
    function setGlobalAuth(address globalAuth_, bool allowed_) external onlyOwner validAddress(globalAuth_) {
        _globalAuths[globalAuth_] = allowed_;

        emit LogSetGlobalAuth(globalAuth_, allowed_);
    }

    /// @notice                         Sets an address (`vaultAuth_`) as allowed vault authorization or not for a specific vault (`vault_`).
    ///                                 This function can only be called by the owner.
    /// @param vault_                   The address of the vault for which the authorization is being set.
    /// @param vaultAuth_               The address to be set as vault authorization.
    /// @param allowed_                 A boolean indicating whether the specified address is allowed to update the specific vault config.
    function setVaultAuth(
        address vault_,
        address vaultAuth_,
        bool allowed_
    ) external onlyOwner validAddress(vaultAuth_) {
        _vaultAuths[vault_][vaultAuth_] = allowed_;

        emit LogSetVaultAuth(vaultAuth_, allowed_, vault_);
    }

    /// @notice                         Sets an address as allowed vault deployment logic (`deploymentLogic_`) contract or not.
    ///                                 This function can only be called by the owner.
    /// @param deploymentLogic_         The address of the vault deployment logic contract to be set.
    /// @param allowed_                 A boolean indicating whether the specified address is allowed to deploy new type of vault.
    function setVaultDeploymentLogic(
        address deploymentLogic_,
        bool allowed_
    ) public onlyOwner validAddress(deploymentLogic_) {
        _vaultDeploymentLogics[deploymentLogic_] = allowed_;

        emit LogSetVaultDeploymentLogic(deploymentLogic_, allowed_);
    }

    /// @notice                         Spell allows owner aka governance to do any arbitrary call on factory
    /// @param target_                  Address to which the call needs to be delegated
    /// @param data_                    Data to execute at the delegated address
    function spell(address target_, bytes memory data_) external onlyOwner returns (bytes memory response_) {
        assembly {
            let succeeded := delegatecall(gas(), target_, add(data_, 0x20), mload(data_), 0, 0)
            let size := returndatasize()

            response_ := mload(0x40)
            mstore(0x40, add(response_, and(add(add(size, 0x20), 0x1f), not(0x1f))))
            mstore(response_, size)
            returndatacopy(add(response_, 0x20), 0, size)

            switch iszero(succeeded)
            case 1 {
                // throw if delegatecall failed
                returndatacopy(0x00, 0x00, size)
                revert(0x00, size)
            }
        }
    }

    /// @notice                         Checks if the provided address (`deployer_`) is authorized as a deployer.
    /// @param deployer_                The address to be checked for deployer authorization.
    /// @return                         Returns `true` if the address is a deployer, otherwise `false`.
    function isDeployer(address deployer_) public view returns (bool) {
        return _deployers[deployer_] || owner == deployer_;
    }

    /// @notice                         Checks if the provided address (`globalAuth_`) has global vault authorization privileges.
    /// @param globalAuth_              The address to be checked for global authorization privileges.
    /// @return                         Returns `true` if the given address has global authorization privileges, otherwise `false`.
    function isGlobalAuth(address globalAuth_) public view returns (bool) {
        return _globalAuths[globalAuth_] || owner == globalAuth_;
    }

    /// @notice                         Checks if the provided address (`vaultAuth_`) has vault authorization privileges for the specified vault (`vault_`).
    /// @param vault_                   The address of the vault to check.
    /// @param vaultAuth_               The address to be checked for vault authorization privileges.
    /// @return                         Returns `true` if the given address has vault authorization privileges for the specified vault, otherwise `false`.
    function isVaultAuth(address vault_, address vaultAuth_) public view returns (bool) {
        return _vaultAuths[vault_][vaultAuth_] || owner == vaultAuth_;
    }

    /// @notice                         Checks if the provided (`vaultDeploymentLogic_`) address has authorization for vault deployment.
    /// @param vaultDeploymentLogic_    The address of the vault deploy logic to check for authorization privileges.
    /// @return                         Returns `true` if the given address has authorization privileges for vault deployment, otherwise `false`.
    function isVaultDeploymentLogic(address vaultDeploymentLogic_) public view returns (bool) {
        return _vaultDeploymentLogics[vaultDeploymentLogic_];
    }
}

/// @dev implements VaultFactory deploy vault related methods.
abstract contract VaultFactoryDeployment is VaultFactoryCore, VaultFactoryAuth {
    /// @dev                            Deploys a contract using the CREATE opcode with the provided bytecode (`bytecode_`).
    ///                                 This is an internal function, meant to be used within the contract to facilitate the deployment of other contracts.
    /// @param bytecode_                The bytecode of the contract to be deployed.
    /// @return address_                Returns the address of the deployed contract.
    function _deploy(bytes memory bytecode_) internal returns (address address_) {
        if (bytecode_.length == 0) {
            revert FluidVaultError(ErrorTypes.VaultFactory__InvalidOperation);
        }
        /// @solidity memory-safe-assembly
        assembly {
            address_ := create(0, add(bytecode_, 0x20), mload(bytecode_))
        }
        if (address_ == address(0)) {
            revert FluidVaultError(ErrorTypes.VaultFactory__InvalidOperation);
        }
    }

    /// @notice                         Deploys a new vault using the specified deployment logic `vaultDeploymentLogic_` and data `vaultDeploymentData_`.
    ///                                 Only accounts with deployer access or the owner can deploy a new vault.
    /// @param vaultDeploymentLogic_    The address of the vault deployment logic contract.
    /// @param vaultDeploymentData_     The data to be used for vault deployment.
    /// @return vault_                  Returns the address of the newly deployed vault.
    function deployVault(
        address vaultDeploymentLogic_,
        bytes calldata vaultDeploymentData_
    ) external returns (address vault_) {
        // Revert if msg.sender doesn't have deployer access or is an owner.
        if (!isDeployer(msg.sender)) revert FluidVaultError(ErrorTypes.VaultFactory__Unauthorized);
        // Revert if vaultDeploymentLogic_ is not whitelisted.
        if (!isVaultDeploymentLogic(vaultDeploymentLogic_))
            revert FluidVaultError(ErrorTypes.VaultFactory__Unauthorized);

        // Vault ID for the new vault and also acts as `nonce` for CREATE
        uint256 vaultId_ = ++_totalVaults;

        // compute vault address for vault id.
        vault_ = getVaultAddress(vaultId_);

        // deploy the vault using vault deployment logic by making .delegatecall
        (bool success_, bytes memory data_) = vaultDeploymentLogic_.delegatecall(vaultDeploymentData_);

        if (!(success_ && vault_ == _deploy(abi.decode(data_, (bytes))) && isVault(vault_))) {
            revert FluidVaultError(ErrorTypes.VaultFactory__InvalidVaultAddress);
        }

        emit VaultDeployed(vault_, vaultId_);
    }

    /// @notice                         Computes the address of a vault based on its given ID (`vaultId_`).
    /// @param vaultId_                 The ID of the vault.
    /// @return vault_                  Returns the computed address of the vault.
    function getVaultAddress(uint256 vaultId_) public view returns (address vault_) {
        // @dev based on https://ethereum.stackexchange.com/a/61413

        // nonce of smart contract always starts with 1. so, with nonce 0 there won't be any deployment
        // hence, nonce of vault deployment starts with 1.
        bytes memory data;
        if (vaultId_ == 0x00) {
            return address(0);
        } else if (vaultId_ <= 0x7f) {
            data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), address(this), uint8(vaultId_));
        } else if (vaultId_ <= 0xff) {
            data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), address(this), bytes1(0x81), uint8(vaultId_));
        } else if (vaultId_ <= 0xffff) {
            data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), address(this), bytes1(0x82), uint16(vaultId_));
        } else if (vaultId_ <= 0xffffff) {
            data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), address(this), bytes1(0x83), uint24(vaultId_));
        } else {
            data = abi.encodePacked(bytes1(0xda), bytes1(0x94), address(this), bytes1(0x84), uint32(vaultId_));
        }

        return address(uint160(uint256(keccak256(data))));
    }

    /// @notice                         Checks if a given address (`vault_`) corresponds to a valid vault.
    /// @param vault_                   The vault address to check.
    /// @return                         Returns `true` if the given address corresponds to a valid vault, otherwise `false`.
    function isVault(address vault_) public view returns (bool) {
        if (vault_.code.length == 0) {
            return false;
        } else {
            // VAULT_ID() function signature is 0x540acabc
            (bool success_, bytes memory data_) = vault_.staticcall(hex"540acabc");
            return success_ && vault_ == getVaultAddress(abi.decode(data_, (uint256)));
        }
    }

    /// @notice                   Returns the total number of vaults deployed by the factory.
    /// @return                   Returns the total number of vaults.
    function totalVaults() external view returns (uint256) {
        return _totalVaults;
    }
}

abstract contract VaultFactoryERC721 is VaultFactoryCore, VaultFactoryDeployment {
    /// @notice                   Mints a new ERC721 token for a specific vault (`vaultId_`) to a specified user (`user_`).
    ///                           Only the corresponding vault is authorized to mint a token.
    /// @param vaultId_           The ID of the vault that's minting the token.
    /// @param user_              The address receiving the minted token.
    /// @return tokenId_          The ID of the newly minted token.
    function mint(uint256 vaultId_, address user_) external returns (uint256 tokenId_) {
        if (msg.sender != getVaultAddress(vaultId_)) revert FluidVaultError(ErrorTypes.VaultFactory__InvalidVault);

        // Using _mint() instead of _safeMint() to allow any msg.sender to receive ERC721 without onERC721Received holder.
        tokenId_ = _mint(user_, vaultId_);

        emit NewPositionMinted(msg.sender, user_, tokenId_);
    }

    /// @notice                   Returns the URI of the specified token ID (`id_`).
    ///                           In this implementation, an empty string is returned as no specific URI is defined.
    /// @param id_                The ID of the token to query.
    /// @return                   An empty string since no specific URI is defined in this implementation.
    function tokenURI(uint256 id_) public view virtual override returns (string memory) {
        return "";
    }
}

/// @title Fluid VaultFactory
/// @notice creates Fluid vault protocol vaults, which are interacting with Fluid Liquidity to deposit / borrow funds.
/// Vaults are created at a deterministic address, given an incrementing `vaultId` (see `getVaultAddress()`).
/// Vaults can only be deployed by allow-listed deployer addresses.
/// This factory also implements ERC721-Enumerable, the NFTs are used to represent created user positions. Only vaults
/// can mint new NFTs.
/// @dev Note the deployed vaults start out with no config at Liquidity contract.
/// This must be done by Liquidity auths in a separate step, otherwise no deposits will be possible.
/// This contract is not upgradeable. It supports adding new vault deployment logic contracts for new, future vaults.
contract FluidVaultFactory is VaultFactoryCore, VaultFactoryAuth, VaultFactoryDeployment, VaultFactoryERC721 {
    constructor(address owner_) VaultFactoryCore(owner_) {}
}

File 2 of 6 : storageRead.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

/// @notice implements a method to read uint256 data from storage at a bytes32 storage slot key.
contract StorageRead {
    function readFromStorage(bytes32 slot_) public view returns (uint256 result_) {
        assembly {
            result_ := sload(slot_) // read value from the storage slot
        }
    }
}

File 3 of 6 : error.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

contract Error {
    error FluidVaultError(uint256 errorId_);

    /// @notice used to simulate liquidation to find the maximum liquidatable amounts
    error FluidLiquidateResult(uint256 colLiquidated, uint256 debtLiquidated);
}

File 4 of 6 : errorTypes.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

library ErrorTypes {
    /***********************************|
    |           Vault Factory           | 
    |__________________________________*/

    uint256 internal constant VaultFactory__InvalidOperation = 30001;
    uint256 internal constant VaultFactory__Unauthorized = 30002;
    uint256 internal constant VaultFactory__SameTokenNotAllowed = 30003;
    uint256 internal constant VaultFactory__InvalidParams = 30004;
    uint256 internal constant VaultFactory__InvalidVault = 30005;
    uint256 internal constant VaultFactory__InvalidVaultAddress = 30006;
    uint256 internal constant VaultFactory__OnlyDelegateCallAllowed = 30007;

    /***********************************|
    |            VaultT1                | 
    |__________________________________*/

    /// @notice thrown at reentrancy
    uint256 internal constant VaultT1__AlreadyEntered = 31001;

    /// @notice thrown when user sends deposit & borrow amount as 0
    uint256 internal constant VaultT1__InvalidOperateAmount = 31002;

    /// @notice thrown when msg.value is not in sync with native token deposit or payback
    uint256 internal constant VaultT1__InvalidMsgValueOperate = 31003;

    /// @notice thrown when msg.sender is not the owner of the vault
    uint256 internal constant VaultT1__NotAnOwner = 31004;

    /// @notice thrown when user's position does not exist. Sending the wrong index from the frontend
    uint256 internal constant VaultT1__TickIsEmpty = 31005;

    /// @notice thrown when the user's position is above CF and the user tries to make it more risky by trying to withdraw or borrow
    uint256 internal constant VaultT1__PositionAboveCF = 31006;

    /// @notice thrown when the top tick is not initialized. Happens if the vault is totally new or all the user's left
    uint256 internal constant VaultT1__TopTickDoesNotExist = 31007;

    /// @notice thrown when msg.value in liquidate is not in sync payback
    uint256 internal constant VaultT1__InvalidMsgValueLiquidate = 31008;

    /// @notice thrown when slippage is more on liquidation than what the liquidator sent
    uint256 internal constant VaultT1__ExcessSlippageLiquidation = 31009;

    /// @notice thrown when msg.sender is not the rebalancer/reserve contract
    uint256 internal constant VaultT1__NotRebalancer = 31010;

    /// @notice thrown when NFT of one vault interacts with the NFT of other vault
    uint256 internal constant VaultT1__NftNotOfThisVault = 31011;

    /// @notice thrown when the token is not initialized on the liquidity contract
    uint256 internal constant VaultT1__TokenNotInitialized = 31012;

    /// @notice thrown when admin updates fallback if a non-auth calls vault
    uint256 internal constant VaultT1__NotAnAuth = 31013;

    /// @notice thrown in operate when user tries to witdhraw more collateral than deposited
    uint256 internal constant VaultT1__ExcessCollateralWithdrawal = 31014;

    /// @notice thrown in operate when user tries to payback more debt than borrowed
    uint256 internal constant VaultT1__ExcessDebtPayback = 31015;

    /// @notice thrown when user try to withdrawal more than operate's withdrawal limit
    uint256 internal constant VaultT1__WithdrawMoreThanOperateLimit = 31016;

    /// @notice thrown when caller of liquidityCallback is not Liquidity
    uint256 internal constant VaultT1__InvalidLiquidityCallbackAddress = 31017;

    /// @notice thrown when reentrancy is not already on
    uint256 internal constant VaultT1__NotEntered = 31018;

    /// @notice thrown when someone directly calls secondary implementation contract
    uint256 internal constant VaultT1__OnlyDelegateCallAllowed = 31019;

    /// @notice thrown when the safeTransferFrom for a token amount failed
    uint256 internal constant VaultT1__TransferFromFailed = 31020;

    /// @notice thrown when exchange price overflows while updating on storage
    uint256 internal constant VaultT1__ExchangePriceOverFlow = 31021;

    /// @notice thrown when debt to liquidate amt is sent wrong
    uint256 internal constant VaultT1__InvalidLiquidationAmt = 31022;

    /// @notice thrown when user debt or collateral goes above 2**128 or below -2**128
    uint256 internal constant VaultT1__UserCollateralDebtExceed = 31023;

    /// @notice thrown if on liquidation branch debt becomes lower than 100
    uint256 internal constant VaultT1__BranchDebtTooLow = 31024;

    /// @notice thrown when tick's debt is less than 10000
    uint256 internal constant VaultT1__TickDebtTooLow = 31025;

    /// @notice thrown when the received new liquidity exchange price is of unexpected value (< than the old one)
    uint256 internal constant VaultT1__LiquidityExchangePriceUnexpected = 31026;

    /// @notice thrown when user's debt is less than 10000
    uint256 internal constant VaultT1__UserDebtTooLow = 31027;

    /// @notice thrown when on only payback and only deposit the ratio of position increases
    uint256 internal constant VaultT1__InvalidPaybackOrDeposit = 31028;

    /// @notice thrown when liquidation just happens of a single partial
    uint256 internal constant VaultT1__InvalidLiquidation = 31029;

    /// @notice thrown when msg.value is sent wrong in rebalance
    uint256 internal constant VaultT1__InvalidMsgValueInRebalance = 31030;

    /// @notice thrown when nothing rebalanced
    uint256 internal constant VaultT1__NothingToRebalance = 31031;

    /***********************************|
    |              ERC721               | 
    |__________________________________*/

    uint256 internal constant ERC721__InvalidParams = 32001;
    uint256 internal constant ERC721__Unauthorized = 32002;
    uint256 internal constant ERC721__InvalidOperation = 32003;
    uint256 internal constant ERC721__UnsafeRecipient = 32004;
    uint256 internal constant ERC721__OutOfBoundsIndex = 32005;

    /***********************************|
    |            Vault Admin            | 
    |__________________________________*/

    /// @notice thrown when admin tries to setup invalid value which are crossing limits
    uint256 internal constant VaultT1Admin__ValueAboveLimit = 33001;

    /// @notice when someone directly calls admin implementation contract
    uint256 internal constant VaultT1Admin__OnlyDelegateCallAllowed = 33002;

    /// @notice thrown when auth sends NFT ID as 0 while collecting dust debt
    uint256 internal constant VaultT1Admin__NftIdShouldBeNonZero = 33003;

    /// @notice thrown when trying to collect dust debt of NFT which is not of this vault
    uint256 internal constant VaultT1Admin__NftNotOfThisVault = 33004;

    /// @notice thrown when dust debt of NFT is 0, meaning nothing to collect
    uint256 internal constant VaultT1Admin__DustDebtIsZero = 33005;

    /// @notice thrown when final debt after liquidation is not 0, meaning position 100% liquidated
    uint256 internal constant VaultT1Admin__FinalDebtShouldBeZero = 33006;

    /// @notice thrown when NFT is not liquidated state
    uint256 internal constant VaultT1Admin__NftNotLiquidated = 33007;

    /// @notice thrown when total absorbed dust debt is 0
    uint256 internal constant VaultT1Admin__AbsorbedDustDebtIsZero = 33008;

    /// @notice thrown when address is set as 0
    uint256 internal constant VaultT1Admin__AddressZeroNotAllowed = 33009;

    /***********************************|
    |            Vault Rewards          | 
    |__________________________________*/

    uint256 internal constant VaultRewards__Unauthorized = 34001;
    uint256 internal constant VaultRewards__AddressZero = 34002;
    uint256 internal constant VaultRewards__InvalidParams = 34003;
    uint256 internal constant VaultRewards__NewMagnifierSameAsOldMagnifier = 34004;
    uint256 internal constant VaultRewards__NotTheInitiator = 34005;
    uint256 internal constant VaultRewards__AlreadyStarted = 34006;
    uint256 internal constant VaultRewards__RewardsNotStartedOrEnded = 34007;
}

File 5 of 6 : ERC721.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;

import { ErrorTypes } from "../../errorTypes.sol";
import { Error } from "../../error.sol";

/// @notice Fluid Vault Factory ERC721 base contract. Implements the ERC721 standard, based on Solmate.
/// In addition, implements ERC721 Enumerable.
/// Modern, minimalist, and gas efficient ERC-721 with Enumerable implementation.
///
/// @author Instadapp
/// @author Modified Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 is Error {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    // token id => token config
    // uint160 0 - 159: address:: owner
    // uint32 160 - 191: uint32:: index
    // uint32 192 - 223: uint32:: vaultId
    // uint32 224 - 255: uint32:: null
    mapping(uint256 => uint256) internal _tokenConfig;

    // owner => slot => index
    /*
    // slot 0: 
    // uint32 0 - 31: uint32:: balanceOf
    // uint224 32 - 255: 7 tokenIds each of uint32 packed
    // slot N (N >= 1)
    // uint32 * 8 each tokenId
    */
    mapping(address => mapping(uint256 => uint256)) internal _ownerConfig;

    /// @notice returns `owner_` of NFT with `id_`
    function ownerOf(uint256 id_) public view virtual returns (address owner_) {
        if ((owner_ = address(uint160(_tokenConfig[id_]))) == address(0))
            revert FluidVaultError(ErrorTypes.ERC721__InvalidParams);
    }

    /// @notice returns total count of NFTs owned by `owner_`
    function balanceOf(address owner_) public view virtual returns (uint256) {
        if (owner_ == address(0)) revert FluidVaultError(ErrorTypes.ERC721__InvalidParams);

        return _ownerConfig[owner_][0] & type(uint32).max;
    }

    /*//////////////////////////////////////////////////////////////
                    ERC721Enumerable STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @notice total amount of tokens stored by the contract.
    uint256 public totalSupply;

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @notice trackes if a NFT id is approved for a certain address.
    mapping(uint256 => address) public getApproved;

    /// @notice trackes if all the NFTs of an owner are approved for a certain other address.
    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice approves an NFT with `id_` to be spent (transferred) by `spender_`
    function approve(address spender_, uint256 id_) public virtual {
        address owner_ = address(uint160(_tokenConfig[id_]));
        if (!(msg.sender == owner_ || isApprovedForAll[owner_][msg.sender]))
            revert FluidVaultError(ErrorTypes.ERC721__Unauthorized);

        getApproved[id_] = spender_;

        emit Approval(owner_, spender_, id_);
    }

    /// @notice approves all NFTs owned by msg.sender to be spent (transferred) by `operator_`
    function setApprovalForAll(address operator_, bool approved_) public virtual {
        isApprovedForAll[msg.sender][operator_] = approved_;

        emit ApprovalForAll(msg.sender, operator_, approved_);
    }

    /// @notice transfers an NFT with `id_` `from_` address `to_` address without safe check
    function transferFrom(address from_, address to_, uint256 id_) public virtual {
        uint256 tokenConfig_ = _tokenConfig[id_];
        if (from_ != address(uint160(tokenConfig_))) revert FluidVaultError(ErrorTypes.ERC721__InvalidParams);

        if (!(msg.sender == from_ || isApprovedForAll[from_][msg.sender] || msg.sender == getApproved[id_]))
            revert FluidVaultError(ErrorTypes.ERC721__Unauthorized);

        // call _transfer with vaultId extracted from tokenConfig_
        _transfer(from_, to_, id_, (tokenConfig_ >> 192) & type(uint32).max);

        delete getApproved[id_];

        emit Transfer(from_, to_, id_);
    }

    /// @notice transfers an NFT with `id_` `from_` address `to_` address
    function safeTransferFrom(address from_, address to_, uint256 id_) public virtual {
        transferFrom(from_, to_, id_);

        if (
            !(to_.code.length == 0 ||
                ERC721TokenReceiver(to_).onERC721Received(msg.sender, from_, id_, "") ==
                ERC721TokenReceiver.onERC721Received.selector)
        ) revert FluidVaultError(ErrorTypes.ERC721__UnsafeRecipient);
    }

    /// @notice transfers an NFT with `id_` `from_` address `to_` address, passing `data_` to `onERC721Received` callback
    function safeTransferFrom(address from_, address to_, uint256 id_, bytes calldata data_) public virtual {
        transferFrom(from_, to_, id_);

        if (
            !((to_.code.length == 0) ||
                ERC721TokenReceiver(to_).onERC721Received(msg.sender, from_, id_, data_) ==
                ERC721TokenReceiver.onERC721Received.selector)
        ) revert FluidVaultError(ErrorTypes.ERC721__UnsafeRecipient);
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721Enumerable LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Returns a token ID at a given `index_` of all the tokens stored by the contract.
    /// Use along with {totalSupply} to enumerate all tokens.
    function tokenByIndex(uint256 index_) external view returns (uint256) {
        if (index_ >= totalSupply) {
            revert FluidVaultError(ErrorTypes.ERC721__OutOfBoundsIndex);
        }
        return index_ + 1;
    }

    /// @notice Returns a token ID owned by `owner_` at a given `index_` of its token list.
    /// Use along with {balanceOf} to enumerate all of `owner_`'s tokens.
    function tokenOfOwnerByIndex(address owner_, uint256 index_) external view returns (uint256) {
        if (index_ >= balanceOf(owner_)) {
            revert FluidVaultError(ErrorTypes.ERC721__OutOfBoundsIndex);
        }

        index_ = index_ + 1;
        return (_ownerConfig[owner_][index_ / 8] >> ((index_ % 8) * 32)) & type(uint32).max;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId_) public view virtual returns (bool) {
        return
            interfaceId_ == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId_ == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId_ == 0x5b5e139f || // ERC165 Interface ID for ERC721Metadata
            interfaceId_ == 0x780e9d63; // ERC165 Interface ID for ERC721Enumberable
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL TRANSFER LOGIC
    //////////////////////////////////////////////////////////////*/

    function _transfer(address from_, address to_, uint256 id_, uint256 vaultId_) internal {
        if (to_ == address(0)) {
            revert FluidVaultError(ErrorTypes.ERC721__InvalidOperation);
        } else if (from_ == address(0)) {
            _add(to_, id_, vaultId_);
        } else if (to_ != from_) {
            _remove(from_, id_);
            _add(to_, id_, vaultId_);
        }
    }

    function _add(address user_, uint256 id_, uint256 vaultId_) private {
        uint256 ownerConfig_ = _ownerConfig[user_][0];
        unchecked {
            // index starts from `1`
            uint256 balanceOf_ = (ownerConfig_ & type(uint32).max) + 1;

            _tokenConfig[id_] = (uint160(user_) | (balanceOf_ << 160) | (vaultId_ << 192));

            _ownerConfig[user_][0] = (ownerConfig_ & ~uint256(type(uint32).max)) | (balanceOf_);

            uint256 wordIndex_ = (balanceOf_ / 8);
            _ownerConfig[user_][wordIndex_] = _ownerConfig[user_][wordIndex_] | (id_ << ((balanceOf_ % 8) * 32));
        }
    }

    function _remove(address user_, uint256 id_) private {
        uint256 temp_ = _tokenConfig[id_];

        // fetching `id_` details and deleting it.
        uint256 tokenIndex_ = (temp_ >> 160) & type(uint32).max;
        _tokenConfig[id_] = 0;

        // fetching & updating balance
        temp_ = _ownerConfig[user_][0];
        uint256 lastTokenIndex_ = (temp_ & type(uint32).max); // (lastTokenIndex_ = balanceOf)
        _ownerConfig[user_][0] = (temp_ & ~uint256(type(uint32).max)) | (lastTokenIndex_ - 1);

        {
            unchecked {
                uint256 lastTokenWordIndex_ = (lastTokenIndex_ / 8);
                uint256 lastTokenBitShift_ = (lastTokenIndex_ % 8) * 32;
                temp_ = _ownerConfig[user_][lastTokenWordIndex_];

                // replace `id_` tokenId with `last` tokenId.
                if (lastTokenIndex_ != tokenIndex_) {
                    uint256 wordIndex_ = (tokenIndex_ / 8);
                    uint256 bitShift_ = (tokenIndex_ % 8) * 32;

                    // temp_ here is _ownerConfig[user_][lastTokenWordIndex_];
                    uint256 lastTokenId_ = uint256((temp_ >> lastTokenBitShift_) & type(uint32).max);
                    if (wordIndex_ == lastTokenWordIndex_) {
                        // this case, when lastToken and currentToken are in same slot.
                        // updating temp_ as we will remove the lastToken from this slot itself
                        temp_ = (temp_ & ~(uint256(type(uint32).max) << bitShift_)) | (lastTokenId_ << bitShift_);
                    } else {
                        _ownerConfig[user_][wordIndex_] =
                            (_ownerConfig[user_][wordIndex_] & ~(uint256(type(uint32).max) << bitShift_)) |
                            (lastTokenId_ << bitShift_);
                    }
                    _tokenConfig[lastTokenId_] =
                        (_tokenConfig[lastTokenId_] & ~(uint256(type(uint32).max) << 160)) |
                        (tokenIndex_ << 160);
                }

                // temp_ here is _ownerConfig[user_][lastTokenWordIndex_];
                _ownerConfig[user_][lastTokenWordIndex_] = temp_ & ~(uint256(type(uint32).max) << lastTokenBitShift_);
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to_, uint256 vaultId_) internal virtual returns (uint256 id_) {

        unchecked {
            ++totalSupply;
        }

        id_ = totalSupply;
        if (id_ >= type(uint32).max || _tokenConfig[id_] != 0) revert FluidVaultError(ErrorTypes.ERC721__InvalidParams);

        _transfer(address(0), to_, id_, vaultId_);

        emit Transfer(address(0), to_, id_);
    }
}

abstract contract ERC721TokenReceiver {
    function onERC721Received(address, address, uint256, bytes calldata) external virtual returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }
}

File 6 of 6 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

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

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"colLiquidated","type":"uint256"},{"internalType":"uint256","name":"debtLiquidated","type":"uint256"}],"name":"FluidLiquidateResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorId_","type":"uint256"}],"name":"FluidVaultError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"deployer","type":"address"},{"indexed":true,"internalType":"bool","name":"allowed","type":"bool"}],"name":"LogSetDeployer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"globalAuth","type":"address"},{"indexed":true,"internalType":"bool","name":"allowed","type":"bool"}],"name":"LogSetGlobalAuth","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vaultAuth","type":"address"},{"indexed":true,"internalType":"bool","name":"allowed","type":"bool"},{"indexed":true,"internalType":"address","name":"vault","type":"address"}],"name":"LogSetVaultAuth","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vaultDeploymentLogic","type":"address"},{"indexed":true,"internalType":"bool","name":"allowed","type":"bool"}],"name":"LogSetVaultDeploymentLogic","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NewPositionMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"VaultDeployed","type":"event"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vaultDeploymentLogic_","type":"address"},{"internalType":"bytes","name":"vaultDeploymentData_","type":"bytes"}],"name":"deployVault","outputs":[{"internalType":"address","name":"vault_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultId_","type":"uint256"}],"name":"getVaultAddress","outputs":[{"internalType":"address","name":"vault_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"deployer_","type":"address"}],"name":"isDeployer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"globalAuth_","type":"address"}],"name":"isGlobalAuth","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault_","type":"address"}],"name":"isVault","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault_","type":"address"},{"internalType":"address","name":"vaultAuth_","type":"address"}],"name":"isVaultAuth","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vaultDeploymentLogic_","type":"address"}],"name":"isVaultDeploymentLogic","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vaultId_","type":"uint256"},{"internalType":"address","name":"user_","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"slot_","type":"bytes32"}],"name":"readFromStorage","outputs":[{"internalType":"uint256","name":"result_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator_","type":"address"},{"internalType":"bool","name":"approved_","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"deployer_","type":"address"},{"internalType":"bool","name":"allowed_","type":"bool"}],"name":"setDeployer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"globalAuth_","type":"address"},{"internalType":"bool","name":"allowed_","type":"bool"}],"name":"setGlobalAuth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault_","type":"address"},{"internalType":"address","name":"vaultAuth_","type":"address"},{"internalType":"bool","name":"allowed_","type":"bool"}],"name":"setVaultAuth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"deploymentLogic_","type":"address"},{"internalType":"bool","name":"allowed_","type":"bool"}],"name":"setVaultDeploymentLogic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target_","type":"address"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"spell","outputs":[{"internalType":"bytes","name":"response_","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId_","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"uint256","name":"index_","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalVaults","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162002ea838038062002ea883398101604081905262000034916200011d565b604080518082018252600b81526a119b1d5a590815985d5b1d60aa1b6020808301919091528251808401845260048152631995931560e21b91810191909152600080546001600160a01b0319166001600160a01b0386169081178255935185948594939285927f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001620000ce8382620001f4565b506002620000dd8282620001f4565b50839250506001600160a01b038216905062000114576040516330090e6560e11b8152617534600482015260240160405180910390fd5b505050620002c0565b6000602082840312156200013057600080fd5b81516001600160a01b03811681146200014857600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200017a57607f821691505b6020821081036200019b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001ef57600081815260208120601f850160051c81016020861015620001ca5750805b601f850160051c820191505b81811015620001eb57828155600101620001d6565b5050505b505050565b81516001600160401b038111156200021057620002106200014f565b620002288162000221845462000165565b84620001a1565b602080601f831160018114620002605760008415620002475750858301515b600019600386901b1c1916600185901b178555620001eb565b600085815260208120601f198616915b82811015620002915788860151825594840194600190910190840162000270565b5085821015620002b05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b612bd880620002d06000396000f3fe608060405234801561001057600080fd5b506004361061020b5760003560e01c80637faa1d211161012a578063a34b5ee8116100bd578063c87b56dd1161008c578063e6bd26a211610071578063e6bd26a2146104d9578063e985e9c5146104ec578063f2fde38b1461051a57600080fd5b8063c87b56dd146104a5578063e04c8e5d146104c657600080fd5b8063a34b5ee81461045a578063b5c736e41461046d578063b88d4fde1461047f578063c7acb01f1461049257600080fd5b806394bf804d116100f957806394bf804d1461041957806395d89b411461042c578063968cbade14610434578063a22cb4651461044757600080fd5b80637faa1d21146103cb5780638d654023146103de5780638da5cb5b146103e65780638f2db95d1461040657600080fd5b80632f745c59116101a257806350c358a41161017157806350c358a41461037f5780636352211e14610392578063652b9b41146103a557806370a08231146103b857600080fd5b80632f745c591461033357806342842e0e146103465780634502d063146103595780634f6ccce71461036c57600080fd5b8063095ea7b3116101de578063095ea7b3146102bd57806317e7681c146102d057806318160ddd1461030957806323b872dd1461032057600080fd5b806301ffc9a71461021057806306fdde0314610238578063081812fc1461024d57806308a892d9146102a8575b600080fd5b61022361021e366004612489565b61052d565b60405190151581526020015b60405180910390f35b61024061065e565b60405161022f9190612514565b61028361025b366004612527565b60066020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022f565b6102bb6102b6366004612574565b6106ec565b005b6102bb6102cb3660046125a7565b610844565b6102236102de3660046125d1565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b61031260055481565b60405190815260200161022f565b6102bb61032e3660046125ec565b610962565b6103126103413660046125a7565b610b17565b6102bb6103543660046125ec565b610bd1565b6102236103673660046125d1565b610d0f565b61031261037a366004612527565b610d60565b61022361038d3660046125d1565b610dac565b6102836103a0366004612527565b610dfd565b6102236103b33660046125d1565b610e62565b6103126103c63660046125d1565b610f70565b6102bb6103d9366004612628565b610ffd565b600b54610312565b6000546102839073ffffffffffffffffffffffffffffffffffffffff1681565b6102bb610414366004612574565b611164565b61031261042736600461266b565b6112b7565b610240611382565b6102836104423660046126d7565b61138f565b6102bb610455366004612574565b6115b2565b6102bb610468366004612574565b611649565b61031261047b366004612527565b5490565b6102bb61048d36600461272a565b61179c565b6102406104a036600461285d565b6118ca565b6102406104b3366004612527565b5060408051602081019091526000815290565b6102236104d43660046128ee565b611998565b6102836104e7366004612527565b6119fc565b6102236104fa3660046128ee565b600760209081526000928352604080842090915290825290205460ff1681565b6102bb6105283660046125d1565b611e5f565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614806105c057507f80ac58cd000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b8061060c57507f5b5e139f000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b8061065857507f780e9d63000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6001805461066b90612918565b80601f016020809104026020016040519081016040528092919081815260200182805461069790612918565b80156106e45780601f106106b9576101008083540402835291602001916106e4565b820191906000526020600020905b8154815290600101906020018083116106c757829003601f168201915b505050505081565b60005473ffffffffffffffffffffffffffffffffffffffff163314610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff81166107c4576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175346004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f6e71f281df08e5962589123c1ca39a8c9df25c6c9cfa7b6d1525effed3dafd2191a3505050565b6000818152600360205260409020543373ffffffffffffffffffffffffffffffffffffffff821614806108a7575073ffffffffffffffffffffffffffffffffffffffff8116600090815260076020908152604080832033845290915290205460ff165b6108e1576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d026004820152602401610769565b60008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff87811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff848116908216146109c7576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d016004820152602401610769565b3373ffffffffffffffffffffffffffffffffffffffff85161480610a1b575073ffffffffffffffffffffffffffffffffffffffff8416600090815260076020908152604080832033845290915290205460ff165b80610a49575060008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff1633145b610a83576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d026004820152602401610769565b610a9984848460c085901c63ffffffff16611f50565b60008281526006602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905551839173ffffffffffffffffffffffffffffffffffffffff86811692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b6000610b2283610f70565b8210610b5e576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d056004820152602401610769565b610b6982600161299a565b915063ffffffff610b7b6008846129dc565b610b869060206129f0565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260046020526040812090610bb7600887612a07565b815260200190815260200160002054901c16905092915050565b610bdc838383610962565b73ffffffffffffffffffffffffffffffffffffffff82163b1580610cd057506040517f150b7a020000000000000000000000000000000000000000000000000000000080825233600483015273ffffffffffffffffffffffffffffffffffffffff858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610c88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cac9190612a1b565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b610d0a576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d046004820152602401610769565b505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526009602052604081205460ff168061065857505060005473ffffffffffffffffffffffffffffffffffffffff91821691161490565b60006005548210610da1576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d056004820152602401610769565b61065882600161299a565b73ffffffffffffffffffffffffffffffffffffffff811660009081526008602052604081205460ff168061065857505060005473ffffffffffffffffffffffffffffffffffffffff91821691161490565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff8116610e5d576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d016004820152602401610769565b919050565b60008173ffffffffffffffffffffffffffffffffffffffff163b600003610e8b57506000919050565b6000808373ffffffffffffffffffffffffffffffffffffffff16604051610ed5907f540acabc00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610f10576040519150601f19603f3d011682016040523d82523d6000602084013e610f15565b606091505b5091509150818015610f685750610f39818060200190518101906104e79190612a38565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8216610fc3576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d016004820152602401610769565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260046020908152604080832083805290915290205463ffffffff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461107e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610769565b8173ffffffffffffffffffffffffffffffffffffffff81166110d0576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175346004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff8481166000818152600a602090815260408083209488168084529490915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001687151590811790915590519293909290917f7aee16d2c366535c2577e873699b458af55a0b0bd4c4fab5e930a780f05669d791a450505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146111e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610769565b8173ffffffffffffffffffffffffffffffffffffffff8116611237576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175346004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff831660008181526009602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f0a1c6cd77aa2e405e482adf6ee6cf190a27682b6dd1234403f7602e5203c83bb91a3505050565b60006112c2836119fc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461132a576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175356004820152602401610769565b6113348284612139565b604051909150819073ffffffffffffffffffffffffffffffffffffffff84169033907ffcc2278353c4cc5d54b742d7eee2d4a7abc22e4dc6213340088293860d502b5190600090a492915050565b6002805461066b90612918565b600061139a33610dac565b6113d4576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175326004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604090205460ff16611437576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175326004820152602401610769565b6000600b6000815461144890612a51565b91829055509050611458816119fc565b91506000808673ffffffffffffffffffffffffffffffffffffffff168686604051611484929190612a89565b600060405180830381855af49150503d80600081146114bf576040519150601f19603f3d011682016040523d82523d6000602084013e6114c4565b606091505b509150915081801561151c57506114ed818060200190518101906114e89190612a99565b6121f7565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b801561152c575061152c84610e62565b611566576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175366004820152602401610769565b604051839073ffffffffffffffffffffffffffffffffffffffff8616907efa89a51ae01c150bfde909191818194382d30b43b645428ed6a71f1955107390600090a35050509392505050565b33600081815260076020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146116ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610769565b8173ffffffffffffffffffffffffffffffffffffffff811661171c576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175346004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff831660008181526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f48cc5b4660fae22eabe5e803ee595e63572773d114bcd54ecc118c1efa8d75af91a3505050565b6117a7858585610962565b73ffffffffffffffffffffffffffffffffffffffff84163b158061188957506040517f150b7a02000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff86169063150b7a02906118229033908a90899089908990600401612b10565b6020604051808303816000875af1158015611841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118659190612a1b565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b6118c3576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d046004820152602401610769565b5050505050565b60005460609073ffffffffffffffffffffffffffffffffffffffff16331461194e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610769565b600080835160208501865af43d6040519250601f19601f6020830101168301604052808352806000602085013e81156001810361198f57816000803e816000fd5b50505092915050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600a6020908152604080832093851683529290529081205460ff16806119f5575060005473ffffffffffffffffffffffffffffffffffffffff8381169116145b9392505050565b6000606082600003611a115750600092915050565b607f8311611ad9576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b6040516020818303038152906040529050611e51565b60ff8311611bb5576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff00000000000000000000000000000000000000000000000000000000000000166037820152603801611ac3565b61ffff8311611c92576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b166037820152603901611ac3565b62ffffff8311611d70576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a01611ac3565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b805160209091012092915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611ee0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610769565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b73ffffffffffffffffffffffffffffffffffffffff8316611fa1576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d036004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff841661205b5773ffffffffffffffffffffffffffffffffffffffff83166000818152600460209081526040808320838052808352818420805488865260038552838620600163ffffffff83160160a081901b90981760c08a901b1790557fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000168617905560088504845282529091208054600790931690910284901b9091179055612133565b8373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612133576120988483612294565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600460209081526040808320838052808352818420805488865260038552838620600163ffffffff83160160a081901b90981760c08a901b1790557fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000168617905560088504845282529091208054600790931690910284901b90911790555b50505050565b600580546001019081905563ffffffff81101580612164575060008181526003602052604090205415155b1561219f576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d016004820152602401610769565b6121ac6000848385611f50565b604051819073ffffffffffffffffffffffffffffffffffffffff8516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a492915050565b60008151600003612238576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175316004820152602401610769565b8151602083016000f0905073ffffffffffffffffffffffffffffffffffffffff8116610e5d576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175316004820152602401610769565b600081815260036020908152604080832080549084905573ffffffffffffffffffffffffffffffffffffffff8616845260048352818420848052909252909120549060a01c63ffffffff9081169082166122ef600182612b8f565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260046020908152604080832083805282528083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000009790971693909317909555600883048082529190205493600783160283831461241357600884046020600786160286831c63ffffffff168483036123945763ffffffff821b199790971687821b17966123d6565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526004602090815260408083208684529091529020805463ffffffff841b191682841b1790555b600090815260036020526040902080547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff1660a088901b17905550505b73ffffffffffffffffffffffffffffffffffffffff90961660009081526004602090815260408083209383529290522063ffffffff90951b1992909216909355505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461248657600080fd5b50565b60006020828403121561249b57600080fd5b81356119f581612458565b60005b838110156124c15781810151838201526020016124a9565b50506000910152565b600081518084526124e28160208601602086016124a6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006119f560208301846124ca565b60006020828403121561253957600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e5d57600080fd5b80358015158114610e5d57600080fd5b6000806040838503121561258757600080fd5b61259083612540565b915061259e60208401612564565b90509250929050565b600080604083850312156125ba57600080fd5b6125c383612540565b946020939093013593505050565b6000602082840312156125e357600080fd5b6119f582612540565b60008060006060848603121561260157600080fd5b61260a84612540565b925061261860208501612540565b9150604084013590509250925092565b60008060006060848603121561263d57600080fd5b61264684612540565b925061265460208501612540565b915061266260408501612564565b90509250925092565b6000806040838503121561267e57600080fd5b8235915061259e60208401612540565b60008083601f8401126126a057600080fd5b50813567ffffffffffffffff8111156126b857600080fd5b6020830191508360208285010111156126d057600080fd5b9250929050565b6000806000604084860312156126ec57600080fd5b6126f584612540565b9250602084013567ffffffffffffffff81111561271157600080fd5b61271d8682870161268e565b9497909650939450505050565b60008060008060006080868803121561274257600080fd5b61274b86612540565b945061275960208701612540565b935060408601359250606086013567ffffffffffffffff81111561277c57600080fd5b6127888882890161268e565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561280f5761280f612799565b604052919050565b600067ffffffffffffffff82111561283157612831612799565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b6000806040838503121561287057600080fd5b61287983612540565b9150602083013567ffffffffffffffff81111561289557600080fd5b8301601f810185136128a657600080fd5b80356128b96128b482612817565b6127c8565b8181528660208385010111156128ce57600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000806040838503121561290157600080fd5b61290a83612540565b915061259e60208401612540565b600181811c9082168061292c57607f821691505b602082108103612965577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156106585761065861296b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826129eb576129eb6129ad565b500690565b80820281158282048414176106585761065861296b565b600082612a1657612a166129ad565b500490565b600060208284031215612a2d57600080fd5b81516119f581612458565b600060208284031215612a4a57600080fd5b5051919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a8257612a8261296b565b5060010190565b8183823760009101908152919050565b600060208284031215612aab57600080fd5b815167ffffffffffffffff811115612ac257600080fd5b8201601f81018413612ad357600080fd5b8051612ae16128b482612817565b818152856020838501011115612af657600080fd5b612b078260208301602086016124a6565b95945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011683010190509695505050505050565b818103818111156106585761065861296b56fea2646970667358221220e8bb1399bdae8c2e8b5a12c38f6d4d678260ca807614968cd3519512187a96a064736f6c634300081500330000000000000000000000004f6f977acdd1177dcd81ab83074855ecb9c2d49e

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061020b5760003560e01c80637faa1d211161012a578063a34b5ee8116100bd578063c87b56dd1161008c578063e6bd26a211610071578063e6bd26a2146104d9578063e985e9c5146104ec578063f2fde38b1461051a57600080fd5b8063c87b56dd146104a5578063e04c8e5d146104c657600080fd5b8063a34b5ee81461045a578063b5c736e41461046d578063b88d4fde1461047f578063c7acb01f1461049257600080fd5b806394bf804d116100f957806394bf804d1461041957806395d89b411461042c578063968cbade14610434578063a22cb4651461044757600080fd5b80637faa1d21146103cb5780638d654023146103de5780638da5cb5b146103e65780638f2db95d1461040657600080fd5b80632f745c59116101a257806350c358a41161017157806350c358a41461037f5780636352211e14610392578063652b9b41146103a557806370a08231146103b857600080fd5b80632f745c591461033357806342842e0e146103465780634502d063146103595780634f6ccce71461036c57600080fd5b8063095ea7b3116101de578063095ea7b3146102bd57806317e7681c146102d057806318160ddd1461030957806323b872dd1461032057600080fd5b806301ffc9a71461021057806306fdde0314610238578063081812fc1461024d57806308a892d9146102a8575b600080fd5b61022361021e366004612489565b61052d565b60405190151581526020015b60405180910390f35b61024061065e565b60405161022f9190612514565b61028361025b366004612527565b60066020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022f565b6102bb6102b6366004612574565b6106ec565b005b6102bb6102cb3660046125a7565b610844565b6102236102de3660046125d1565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b61031260055481565b60405190815260200161022f565b6102bb61032e3660046125ec565b610962565b6103126103413660046125a7565b610b17565b6102bb6103543660046125ec565b610bd1565b6102236103673660046125d1565b610d0f565b61031261037a366004612527565b610d60565b61022361038d3660046125d1565b610dac565b6102836103a0366004612527565b610dfd565b6102236103b33660046125d1565b610e62565b6103126103c63660046125d1565b610f70565b6102bb6103d9366004612628565b610ffd565b600b54610312565b6000546102839073ffffffffffffffffffffffffffffffffffffffff1681565b6102bb610414366004612574565b611164565b61031261042736600461266b565b6112b7565b610240611382565b6102836104423660046126d7565b61138f565b6102bb610455366004612574565b6115b2565b6102bb610468366004612574565b611649565b61031261047b366004612527565b5490565b6102bb61048d36600461272a565b61179c565b6102406104a036600461285d565b6118ca565b6102406104b3366004612527565b5060408051602081019091526000815290565b6102236104d43660046128ee565b611998565b6102836104e7366004612527565b6119fc565b6102236104fa3660046128ee565b600760209081526000928352604080842090915290825290205460ff1681565b6102bb6105283660046125d1565b611e5f565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614806105c057507f80ac58cd000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b8061060c57507f5b5e139f000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b8061065857507f780e9d63000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6001805461066b90612918565b80601f016020809104026020016040519081016040528092919081815260200182805461069790612918565b80156106e45780601f106106b9576101008083540402835291602001916106e4565b820191906000526020600020905b8154815290600101906020018083116106c757829003601f168201915b505050505081565b60005473ffffffffffffffffffffffffffffffffffffffff163314610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff81166107c4576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175346004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f6e71f281df08e5962589123c1ca39a8c9df25c6c9cfa7b6d1525effed3dafd2191a3505050565b6000818152600360205260409020543373ffffffffffffffffffffffffffffffffffffffff821614806108a7575073ffffffffffffffffffffffffffffffffffffffff8116600090815260076020908152604080832033845290915290205460ff165b6108e1576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d026004820152602401610769565b60008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff87811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff848116908216146109c7576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d016004820152602401610769565b3373ffffffffffffffffffffffffffffffffffffffff85161480610a1b575073ffffffffffffffffffffffffffffffffffffffff8416600090815260076020908152604080832033845290915290205460ff165b80610a49575060008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff1633145b610a83576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d026004820152602401610769565b610a9984848460c085901c63ffffffff16611f50565b60008281526006602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905551839173ffffffffffffffffffffffffffffffffffffffff86811692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b6000610b2283610f70565b8210610b5e576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d056004820152602401610769565b610b6982600161299a565b915063ffffffff610b7b6008846129dc565b610b869060206129f0565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260046020526040812090610bb7600887612a07565b815260200190815260200160002054901c16905092915050565b610bdc838383610962565b73ffffffffffffffffffffffffffffffffffffffff82163b1580610cd057506040517f150b7a020000000000000000000000000000000000000000000000000000000080825233600483015273ffffffffffffffffffffffffffffffffffffffff858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610c88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cac9190612a1b565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b610d0a576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d046004820152602401610769565b505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526009602052604081205460ff168061065857505060005473ffffffffffffffffffffffffffffffffffffffff91821691161490565b60006005548210610da1576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d056004820152602401610769565b61065882600161299a565b73ffffffffffffffffffffffffffffffffffffffff811660009081526008602052604081205460ff168061065857505060005473ffffffffffffffffffffffffffffffffffffffff91821691161490565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff8116610e5d576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d016004820152602401610769565b919050565b60008173ffffffffffffffffffffffffffffffffffffffff163b600003610e8b57506000919050565b6000808373ffffffffffffffffffffffffffffffffffffffff16604051610ed5907f540acabc00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610f10576040519150601f19603f3d011682016040523d82523d6000602084013e610f15565b606091505b5091509150818015610f685750610f39818060200190518101906104e79190612a38565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8216610fc3576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d016004820152602401610769565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260046020908152604080832083805290915290205463ffffffff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461107e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610769565b8173ffffffffffffffffffffffffffffffffffffffff81166110d0576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175346004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff8481166000818152600a602090815260408083209488168084529490915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001687151590811790915590519293909290917f7aee16d2c366535c2577e873699b458af55a0b0bd4c4fab5e930a780f05669d791a450505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146111e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610769565b8173ffffffffffffffffffffffffffffffffffffffff8116611237576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175346004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff831660008181526009602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f0a1c6cd77aa2e405e482adf6ee6cf190a27682b6dd1234403f7602e5203c83bb91a3505050565b60006112c2836119fc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461132a576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175356004820152602401610769565b6113348284612139565b604051909150819073ffffffffffffffffffffffffffffffffffffffff84169033907ffcc2278353c4cc5d54b742d7eee2d4a7abc22e4dc6213340088293860d502b5190600090a492915050565b6002805461066b90612918565b600061139a33610dac565b6113d4576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175326004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604090205460ff16611437576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175326004820152602401610769565b6000600b6000815461144890612a51565b91829055509050611458816119fc565b91506000808673ffffffffffffffffffffffffffffffffffffffff168686604051611484929190612a89565b600060405180830381855af49150503d80600081146114bf576040519150601f19603f3d011682016040523d82523d6000602084013e6114c4565b606091505b509150915081801561151c57506114ed818060200190518101906114e89190612a99565b6121f7565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b801561152c575061152c84610e62565b611566576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175366004820152602401610769565b604051839073ffffffffffffffffffffffffffffffffffffffff8616907efa89a51ae01c150bfde909191818194382d30b43b645428ed6a71f1955107390600090a35050509392505050565b33600081815260076020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146116ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610769565b8173ffffffffffffffffffffffffffffffffffffffff811661171c576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175346004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff831660008181526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f48cc5b4660fae22eabe5e803ee595e63572773d114bcd54ecc118c1efa8d75af91a3505050565b6117a7858585610962565b73ffffffffffffffffffffffffffffffffffffffff84163b158061188957506040517f150b7a02000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff86169063150b7a02906118229033908a90899089908990600401612b10565b6020604051808303816000875af1158015611841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118659190612a1b565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b6118c3576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d046004820152602401610769565b5050505050565b60005460609073ffffffffffffffffffffffffffffffffffffffff16331461194e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610769565b600080835160208501865af43d6040519250601f19601f6020830101168301604052808352806000602085013e81156001810361198f57816000803e816000fd5b50505092915050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600a6020908152604080832093851683529290529081205460ff16806119f5575060005473ffffffffffffffffffffffffffffffffffffffff8381169116145b9392505050565b6000606082600003611a115750600092915050565b607f8311611ad9576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b6040516020818303038152906040529050611e51565b60ff8311611bb5576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff00000000000000000000000000000000000000000000000000000000000000166037820152603801611ac3565b61ffff8311611c92576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b166037820152603901611ac3565b62ffffff8311611d70576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a01611ac3565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b805160209091012092915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611ee0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610769565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b73ffffffffffffffffffffffffffffffffffffffff8316611fa1576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d036004820152602401610769565b73ffffffffffffffffffffffffffffffffffffffff841661205b5773ffffffffffffffffffffffffffffffffffffffff83166000818152600460209081526040808320838052808352818420805488865260038552838620600163ffffffff83160160a081901b90981760c08a901b1790557fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000168617905560088504845282529091208054600790931690910284901b9091179055612133565b8373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612133576120988483612294565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600460209081526040808320838052808352818420805488865260038552838620600163ffffffff83160160a081901b90981760c08a901b1790557fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000168617905560088504845282529091208054600790931690910284901b90911790555b50505050565b600580546001019081905563ffffffff81101580612164575060008181526003602052604090205415155b1561219f576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d016004820152602401610769565b6121ac6000848385611f50565b604051819073ffffffffffffffffffffffffffffffffffffffff8516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a492915050565b60008151600003612238576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175316004820152602401610769565b8151602083016000f0905073ffffffffffffffffffffffffffffffffffffffff8116610e5d576040517f60121cca0000000000000000000000000000000000000000000000000000000081526175316004820152602401610769565b600081815260036020908152604080832080549084905573ffffffffffffffffffffffffffffffffffffffff8616845260048352818420848052909252909120549060a01c63ffffffff9081169082166122ef600182612b8f565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260046020908152604080832083805282528083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000009790971693909317909555600883048082529190205493600783160283831461241357600884046020600786160286831c63ffffffff168483036123945763ffffffff821b199790971687821b17966123d6565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526004602090815260408083208684529091529020805463ffffffff841b191682841b1790555b600090815260036020526040902080547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff1660a088901b17905550505b73ffffffffffffffffffffffffffffffffffffffff90961660009081526004602090815260408083209383529290522063ffffffff90951b1992909216909355505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461248657600080fd5b50565b60006020828403121561249b57600080fd5b81356119f581612458565b60005b838110156124c15781810151838201526020016124a9565b50506000910152565b600081518084526124e28160208601602086016124a6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006119f560208301846124ca565b60006020828403121561253957600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e5d57600080fd5b80358015158114610e5d57600080fd5b6000806040838503121561258757600080fd5b61259083612540565b915061259e60208401612564565b90509250929050565b600080604083850312156125ba57600080fd5b6125c383612540565b946020939093013593505050565b6000602082840312156125e357600080fd5b6119f582612540565b60008060006060848603121561260157600080fd5b61260a84612540565b925061261860208501612540565b9150604084013590509250925092565b60008060006060848603121561263d57600080fd5b61264684612540565b925061265460208501612540565b915061266260408501612564565b90509250925092565b6000806040838503121561267e57600080fd5b8235915061259e60208401612540565b60008083601f8401126126a057600080fd5b50813567ffffffffffffffff8111156126b857600080fd5b6020830191508360208285010111156126d057600080fd5b9250929050565b6000806000604084860312156126ec57600080fd5b6126f584612540565b9250602084013567ffffffffffffffff81111561271157600080fd5b61271d8682870161268e565b9497909650939450505050565b60008060008060006080868803121561274257600080fd5b61274b86612540565b945061275960208701612540565b935060408601359250606086013567ffffffffffffffff81111561277c57600080fd5b6127888882890161268e565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561280f5761280f612799565b604052919050565b600067ffffffffffffffff82111561283157612831612799565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b6000806040838503121561287057600080fd5b61287983612540565b9150602083013567ffffffffffffffff81111561289557600080fd5b8301601f810185136128a657600080fd5b80356128b96128b482612817565b6127c8565b8181528660208385010111156128ce57600080fd5b816020840160208301376000602083830101528093505050509250929050565b6000806040838503121561290157600080fd5b61290a83612540565b915061259e60208401612540565b600181811c9082168061292c57607f821691505b602082108103612965577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156106585761065861296b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826129eb576129eb6129ad565b500690565b80820281158282048414176106585761065861296b565b600082612a1657612a166129ad565b500490565b600060208284031215612a2d57600080fd5b81516119f581612458565b600060208284031215612a4a57600080fd5b5051919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a8257612a8261296b565b5060010190565b8183823760009101908152919050565b600060208284031215612aab57600080fd5b815167ffffffffffffffff811115612ac257600080fd5b8201601f81018413612ad357600080fd5b8051612ae16128b482612817565b818152856020838501011115612af657600080fd5b612b078260208301602086016124a6565b95945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011683010190509695505050505050565b818103818111156106585761065861296b56fea2646970667358221220e8bb1399bdae8c2e8b5a12c38f6d4d678260ca807614968cd3519512187a96a064736f6c63430008150033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000004f6f977acdd1177dcd81ab83074855ecb9c2d49e

-----Decoded View---------------
Arg [0] : owner_ (address): 0x4F6F977aCDD1177DCD81aB83074855EcB9C2D49e

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000004f6f977acdd1177dcd81ab83074855ecb9c2d49e


Block Transaction 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
[ 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.