ETH Price: $3,361.18 (-0.62%)
Gas: 13 Gwei

Token

Fluid Vault (fVLT)
 

Overview

Max Total Supply

59 fVLT

Holders

15

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
2 fVLT
0x9cbf099ff424979439dfba03f00b5961784c06ce
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
FluidVaultFactory

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 10000000 runs

Other Settings:
paris EvmVersion
File 1 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 2 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 3 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;

    /***********************************|
    |              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 4 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 5 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                         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 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":"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"}]

60806040523480156200001157600080fd5b5060405162002cce38038062002cce83398101604081905262000034916200011d565b604080518082018252600b81526a119b1d5a590815985d5b1d60aa1b6020808301919091528251808401845260048152631995931560e21b91810191909152600080546001600160a01b0319166001600160a01b0386169081178255935185948594939285927f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001620000ce8382620001f4565b506002620000dd8282620001f4565b50839250506001600160a01b038216905062000114576040516330090e6560e11b8152617534600482015260240160405180910390fd5b505050620002c0565b6000602082840312156200013057600080fd5b81516001600160a01b03811681146200014857600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200017a57607f821691505b6020821081036200019b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001ef57600081815260208120601f850160051c81016020861015620001ca5750805b601f850160051c820191505b81811015620001eb57828155600101620001d6565b5050505b505050565b81516001600160401b038111156200021057620002106200014f565b620002288162000221845462000165565b84620001a1565b602080601f831160018114620002605760008415620002475750858301515b600019600386901b1c1916600185901b178555620001eb565b600085815260208120601f198616915b82811015620002915788860151825594840194600190910190840162000270565b5085821015620002b05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6129fe80620002d06000396000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80637faa1d211161010f578063a34b5ee8116100a2578063e04c8e5d11610071578063e04c8e5d14610498578063e6bd26a2146104ab578063e985e9c5146104be578063f2fde38b146104ec57600080fd5b8063a34b5ee81461043f578063b5c736e414610452578063b88d4fde14610464578063c87b56dd1461047757600080fd5b806394bf804d116100de57806394bf804d146103fe57806395d89b4114610411578063968cbade14610419578063a22cb4651461042c57600080fd5b80637faa1d21146103b05780638d654023146103c35780638da5cb5b146103cb5780638f2db95d146103eb57600080fd5b80632f745c591161018757806350c358a41161015657806350c358a4146103645780636352211e14610377578063652b9b411461038a57806370a082311461039d57600080fd5b80632f745c591461031857806342842e0e1461032b5780634502d0631461033e5780634f6ccce71461035157600080fd5b8063095ea7b3116101c3578063095ea7b3146102a257806317e7681c146102b557806318160ddd146102ee57806323b872dd1461030557600080fd5b806301ffc9a7146101f557806306fdde031461021d578063081812fc1461023257806308a892d91461028d575b600080fd5b61020861020336600461238d565b6104ff565b60405190151581526020015b60405180910390f35b610225610630565b60405161021491906123ce565b61026861024036600461241f565b60066020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b6102a061029b36600461246c565b6106be565b005b6102a06102b036600461249f565b610816565b6102086102c33660046124c9565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b6102f760055481565b604051908152602001610214565b6102a06103133660046124e4565b610934565b6102f761032636600461249f565b610ae9565b6102a06103393660046124e4565b610ba3565b61020861034c3660046124c9565b610ce1565b6102f761035f36600461241f565b610d32565b6102086103723660046124c9565b610d7e565b61026861038536600461241f565b610dcf565b6102086103983660046124c9565b610e34565b6102f76103ab3660046124c9565b610f42565b6102a06103be366004612520565b610fcf565b600b546102f7565b6000546102689073ffffffffffffffffffffffffffffffffffffffff1681565b6102a06103f936600461246c565b611136565b6102f761040c366004612563565b611289565b610225611354565b6102686104273660046125cf565b611361565b6102a061043a36600461246c565b611584565b6102a061044d36600461246c565b61161b565b6102f761046036600461241f565b5490565b6102a0610472366004612622565b61176e565b61022561048536600461241f565b5060408051602081019091526000815290565b6102086104a6366004612691565b61189c565b6102686104b936600461241f565b611900565b6102086104cc366004612691565b600760209081526000928352604080842090915290825290205460ff1681565b6102a06104fa3660046124c9565b611d63565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061059257507f80ac58cd000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b806105de57507f5b5e139f000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b8061062a57507f780e9d63000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6001805461063d906126bb565b80601f0160208091040260200160405190810160405280929190818152602001828054610669906126bb565b80156106b65780601f1061068b576101008083540402835291602001916106b6565b820191906000526020600020905b81548152906001019060200180831161069957829003601f168201915b505050505081565b60005473ffffffffffffffffffffffffffffffffffffffff163314610744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff8116610796576040517f60121cca000000000000000000000000000000000000000000000000000000008152617534600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f6e71f281df08e5962589123c1ca39a8c9df25c6c9cfa7b6d1525effed3dafd2191a3505050565b6000818152600360205260409020543373ffffffffffffffffffffffffffffffffffffffff82161480610879575073ffffffffffffffffffffffffffffffffffffffff8116600090815260076020908152604080832033845290915290205460ff165b6108b3576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d02600482015260240161073b565b60008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff87811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff84811690821614610999576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d01600482015260240161073b565b3373ffffffffffffffffffffffffffffffffffffffff851614806109ed575073ffffffffffffffffffffffffffffffffffffffff8416600090815260076020908152604080832033845290915290205460ff165b80610a1b575060008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff1633145b610a55576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d02600482015260240161073b565b610a6b84848460c085901c63ffffffff16611e54565b60008281526006602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905551839173ffffffffffffffffffffffffffffffffffffffff86811692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b6000610af483610f42565b8210610b30576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d05600482015260240161073b565b610b3b82600161273d565b915063ffffffff610b4d60088461277f565b610b58906020612793565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260046020526040812090610b896008876127aa565b815260200190815260200160002054901c16905092915050565b610bae838383610934565b73ffffffffffffffffffffffffffffffffffffffff82163b1580610ca257506040517f150b7a020000000000000000000000000000000000000000000000000000000080825233600483015273ffffffffffffffffffffffffffffffffffffffff858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610c5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7e91906127be565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b610cdc576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d04600482015260240161073b565b505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526009602052604081205460ff168061062a57505060005473ffffffffffffffffffffffffffffffffffffffff91821691161490565b60006005548210610d73576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d05600482015260240161073b565b61062a82600161273d565b73ffffffffffffffffffffffffffffffffffffffff811660009081526008602052604081205460ff168061062a57505060005473ffffffffffffffffffffffffffffffffffffffff91821691161490565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff8116610e2f576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d01600482015260240161073b565b919050565b60008173ffffffffffffffffffffffffffffffffffffffff163b600003610e5d57506000919050565b6000808373ffffffffffffffffffffffffffffffffffffffff16604051610ea7907f540acabc00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610ee2576040519150601f19603f3d011682016040523d82523d6000602084013e610ee7565b606091505b5091509150818015610f3a5750610f0b818060200190518101906104b991906127db565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8216610f95576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d01600482015260240161073b565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260046020908152604080832083805290915290205463ffffffff1690565b60005473ffffffffffffffffffffffffffffffffffffffff163314611050576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161073b565b8173ffffffffffffffffffffffffffffffffffffffff81166110a2576040517f60121cca000000000000000000000000000000000000000000000000000000008152617534600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff8481166000818152600a602090815260408083209488168084529490915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001687151590811790915590519293909290917f7aee16d2c366535c2577e873699b458af55a0b0bd4c4fab5e930a780f05669d791a450505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161073b565b8173ffffffffffffffffffffffffffffffffffffffff8116611209576040517f60121cca000000000000000000000000000000000000000000000000000000008152617534600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff831660008181526009602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f0a1c6cd77aa2e405e482adf6ee6cf190a27682b6dd1234403f7602e5203c83bb91a3505050565b600061129483611900565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146112fc576040517f60121cca000000000000000000000000000000000000000000000000000000008152617535600482015260240161073b565b611306828461203d565b604051909150819073ffffffffffffffffffffffffffffffffffffffff84169033907ffcc2278353c4cc5d54b742d7eee2d4a7abc22e4dc6213340088293860d502b5190600090a492915050565b6002805461063d906126bb565b600061136c33610d7e565b6113a6576040517f60121cca000000000000000000000000000000000000000000000000000000008152617532600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604090205460ff16611409576040517f60121cca000000000000000000000000000000000000000000000000000000008152617532600482015260240161073b565b6000600b6000815461141a906127f4565b9182905550905061142a81611900565b91506000808673ffffffffffffffffffffffffffffffffffffffff16868660405161145692919061282c565b600060405180830381855af49150503d8060008114611491576040519150601f19603f3d011682016040523d82523d6000602084013e611496565b606091505b50915091508180156114ee57506114bf818060200190518101906114ba919061286b565b6120fb565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b80156114fe57506114fe84610e34565b611538576040517f60121cca000000000000000000000000000000000000000000000000000000008152617536600482015260240161073b565b604051839073ffffffffffffffffffffffffffffffffffffffff8616907efa89a51ae01c150bfde909191818194382d30b43b645428ed6a71f1955107390600090a35050509392505050565b33600081815260076020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461169c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161073b565b8173ffffffffffffffffffffffffffffffffffffffff81166116ee576040517f60121cca000000000000000000000000000000000000000000000000000000008152617534600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff831660008181526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f48cc5b4660fae22eabe5e803ee595e63572773d114bcd54ecc118c1efa8d75af91a3505050565b611779858585610934565b73ffffffffffffffffffffffffffffffffffffffff84163b158061185b57506040517f150b7a02000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff86169063150b7a02906117f49033908a90899089908990600401612936565b6020604051808303816000875af1158015611813573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183791906127be565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b611895576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d04600482015260240161073b565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600a6020908152604080832093851683529290529081205460ff16806118f9575060005473ffffffffffffffffffffffffffffffffffffffff8381169116145b9392505050565b60006060826000036119155750600092915050565b607f83116119dd576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b6040516020818303038152906040529050611d55565b60ff8311611ab9576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660378201526038016119c7565b61ffff8311611b96576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b1660378201526039016119c7565b62ffffff8311611c74576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a016119c7565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b805160209091012092915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611de4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161073b565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b73ffffffffffffffffffffffffffffffffffffffff8316611ea5576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d03600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff8416611f5f5773ffffffffffffffffffffffffffffffffffffffff83166000818152600460209081526040808320838052808352818420805488865260038552838620600163ffffffff83160160a081901b90981760c08a901b1790557fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000168617905560088504845282529091208054600790931690910284901b9091179055612037565b8373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461203757611f9c8483612198565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600460209081526040808320838052808352818420805488865260038552838620600163ffffffff83160160a081901b90981760c08a901b1790557fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000168617905560088504845282529091208054600790931690910284901b90911790555b50505050565b600580546001019081905563ffffffff81101580612068575060008181526003602052604090205415155b156120a3576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d01600482015260240161073b565b6120b06000848385611e54565b604051819073ffffffffffffffffffffffffffffffffffffffff8516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a492915050565b6000815160000361213c576040517f60121cca000000000000000000000000000000000000000000000000000000008152617531600482015260240161073b565b8151602083016000f0905073ffffffffffffffffffffffffffffffffffffffff8116610e2f576040517f60121cca000000000000000000000000000000000000000000000000000000008152617531600482015260240161073b565b600081815260036020908152604080832080549084905573ffffffffffffffffffffffffffffffffffffffff8616845260048352818420848052909252909120549060a01c63ffffffff9081169082166121f36001826129b5565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260046020908152604080832083805282528083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000009790971693909317909555600883048082529190205493600783160283831461231757600884046020600786160286831c63ffffffff168483036122985763ffffffff821b199790971687821b17966122da565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526004602090815260408083208684529091529020805463ffffffff841b191682841b1790555b600090815260036020526040902080547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff1660a088901b17905550505b73ffffffffffffffffffffffffffffffffffffffff90961660009081526004602090815260408083209383529290522063ffffffff90951b1992909216909355505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461238a57600080fd5b50565b60006020828403121561239f57600080fd5b81356118f98161235c565b60005b838110156123c55781810151838201526020016123ad565b50506000910152565b60208152600082518060208401526123ed8160408501602087016123aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561243157600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e2f57600080fd5b80358015158114610e2f57600080fd5b6000806040838503121561247f57600080fd5b61248883612438565b91506124966020840161245c565b90509250929050565b600080604083850312156124b257600080fd5b6124bb83612438565b946020939093013593505050565b6000602082840312156124db57600080fd5b6118f982612438565b6000806000606084860312156124f957600080fd5b61250284612438565b925061251060208501612438565b9150604084013590509250925092565b60008060006060848603121561253557600080fd5b61253e84612438565b925061254c60208501612438565b915061255a6040850161245c565b90509250925092565b6000806040838503121561257657600080fd5b8235915061249660208401612438565b60008083601f84011261259857600080fd5b50813567ffffffffffffffff8111156125b057600080fd5b6020830191508360208285010111156125c857600080fd5b9250929050565b6000806000604084860312156125e457600080fd5b6125ed84612438565b9250602084013567ffffffffffffffff81111561260957600080fd5b61261586828701612586565b9497909650939450505050565b60008060008060006080868803121561263a57600080fd5b61264386612438565b945061265160208701612438565b935060408601359250606086013567ffffffffffffffff81111561267457600080fd5b61268088828901612586565b969995985093965092949392505050565b600080604083850312156126a457600080fd5b6126ad83612438565b915061249660208401612438565b600181811c908216806126cf57607f821691505b602082108103612708577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561062a5761062a61270e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261278e5761278e612750565b500690565b808202811582820484141761062a5761062a61270e565b6000826127b9576127b9612750565b500490565b6000602082840312156127d057600080fd5b81516118f98161235c565b6000602082840312156127ed57600080fd5b5051919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036128255761282561270e565b5060010190565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561287d57600080fd5b815167ffffffffffffffff8082111561289557600080fd5b818401915084601f8301126128a957600080fd5b8151818111156128bb576128bb61283c565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156129015761290161283c565b8160405282815287602084870101111561291a57600080fd5b61292b8360208301602088016123aa565b979650505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011683010190509695505050505050565b8181038181111561062a5761062a61270e56fea26469706673582212200d4cdcde81be0a68e93227413d1bbcf7c556db4d4ab4fba51544ff36fbb590c964736f6c634300081500330000000000000000000000004f6f977acdd1177dcd81ab83074855ecb9c2d49e

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101f05760003560e01c80637faa1d211161010f578063a34b5ee8116100a2578063e04c8e5d11610071578063e04c8e5d14610498578063e6bd26a2146104ab578063e985e9c5146104be578063f2fde38b146104ec57600080fd5b8063a34b5ee81461043f578063b5c736e414610452578063b88d4fde14610464578063c87b56dd1461047757600080fd5b806394bf804d116100de57806394bf804d146103fe57806395d89b4114610411578063968cbade14610419578063a22cb4651461042c57600080fd5b80637faa1d21146103b05780638d654023146103c35780638da5cb5b146103cb5780638f2db95d146103eb57600080fd5b80632f745c591161018757806350c358a41161015657806350c358a4146103645780636352211e14610377578063652b9b411461038a57806370a082311461039d57600080fd5b80632f745c591461031857806342842e0e1461032b5780634502d0631461033e5780634f6ccce71461035157600080fd5b8063095ea7b3116101c3578063095ea7b3146102a257806317e7681c146102b557806318160ddd146102ee57806323b872dd1461030557600080fd5b806301ffc9a7146101f557806306fdde031461021d578063081812fc1461023257806308a892d91461028d575b600080fd5b61020861020336600461238d565b6104ff565b60405190151581526020015b60405180910390f35b610225610630565b60405161021491906123ce565b61026861024036600461241f565b60066020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b6102a061029b36600461246c565b6106be565b005b6102a06102b036600461249f565b610816565b6102086102c33660046124c9565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b6102f760055481565b604051908152602001610214565b6102a06103133660046124e4565b610934565b6102f761032636600461249f565b610ae9565b6102a06103393660046124e4565b610ba3565b61020861034c3660046124c9565b610ce1565b6102f761035f36600461241f565b610d32565b6102086103723660046124c9565b610d7e565b61026861038536600461241f565b610dcf565b6102086103983660046124c9565b610e34565b6102f76103ab3660046124c9565b610f42565b6102a06103be366004612520565b610fcf565b600b546102f7565b6000546102689073ffffffffffffffffffffffffffffffffffffffff1681565b6102a06103f936600461246c565b611136565b6102f761040c366004612563565b611289565b610225611354565b6102686104273660046125cf565b611361565b6102a061043a36600461246c565b611584565b6102a061044d36600461246c565b61161b565b6102f761046036600461241f565b5490565b6102a0610472366004612622565b61176e565b61022561048536600461241f565b5060408051602081019091526000815290565b6102086104a6366004612691565b61189c565b6102686104b936600461241f565b611900565b6102086104cc366004612691565b600760209081526000928352604080842090915290825290205460ff1681565b6102a06104fa3660046124c9565b611d63565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061059257507f80ac58cd000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b806105de57507f5b5e139f000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b8061062a57507f780e9d63000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6001805461063d906126bb565b80601f0160208091040260200160405190810160405280929190818152602001828054610669906126bb565b80156106b65780601f1061068b576101008083540402835291602001916106b6565b820191906000526020600020905b81548152906001019060200180831161069957829003601f168201915b505050505081565b60005473ffffffffffffffffffffffffffffffffffffffff163314610744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff8116610796576040517f60121cca000000000000000000000000000000000000000000000000000000008152617534600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f6e71f281df08e5962589123c1ca39a8c9df25c6c9cfa7b6d1525effed3dafd2191a3505050565b6000818152600360205260409020543373ffffffffffffffffffffffffffffffffffffffff82161480610879575073ffffffffffffffffffffffffffffffffffffffff8116600090815260076020908152604080832033845290915290205460ff165b6108b3576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d02600482015260240161073b565b60008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff87811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff84811690821614610999576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d01600482015260240161073b565b3373ffffffffffffffffffffffffffffffffffffffff851614806109ed575073ffffffffffffffffffffffffffffffffffffffff8416600090815260076020908152604080832033845290915290205460ff165b80610a1b575060008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff1633145b610a55576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d02600482015260240161073b565b610a6b84848460c085901c63ffffffff16611e54565b60008281526006602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905551839173ffffffffffffffffffffffffffffffffffffffff86811692908816917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a450505050565b6000610af483610f42565b8210610b30576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d05600482015260240161073b565b610b3b82600161273d565b915063ffffffff610b4d60088461277f565b610b58906020612793565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260046020526040812090610b896008876127aa565b815260200190815260200160002054901c16905092915050565b610bae838383610934565b73ffffffffffffffffffffffffffffffffffffffff82163b1580610ca257506040517f150b7a020000000000000000000000000000000000000000000000000000000080825233600483015273ffffffffffffffffffffffffffffffffffffffff858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610c5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7e91906127be565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b610cdc576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d04600482015260240161073b565b505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526009602052604081205460ff168061062a57505060005473ffffffffffffffffffffffffffffffffffffffff91821691161490565b60006005548210610d73576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d05600482015260240161073b565b61062a82600161273d565b73ffffffffffffffffffffffffffffffffffffffff811660009081526008602052604081205460ff168061062a57505060005473ffffffffffffffffffffffffffffffffffffffff91821691161490565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff8116610e2f576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d01600482015260240161073b565b919050565b60008173ffffffffffffffffffffffffffffffffffffffff163b600003610e5d57506000919050565b6000808373ffffffffffffffffffffffffffffffffffffffff16604051610ea7907f540acabc00000000000000000000000000000000000000000000000000000000815260040190565b600060405180830381855afa9150503d8060008114610ee2576040519150601f19603f3d011682016040523d82523d6000602084013e610ee7565b606091505b5091509150818015610f3a5750610f0b818060200190518101906104b991906127db565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8216610f95576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d01600482015260240161073b565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260046020908152604080832083805290915290205463ffffffff1690565b60005473ffffffffffffffffffffffffffffffffffffffff163314611050576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161073b565b8173ffffffffffffffffffffffffffffffffffffffff81166110a2576040517f60121cca000000000000000000000000000000000000000000000000000000008152617534600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff8481166000818152600a602090815260408083209488168084529490915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001687151590811790915590519293909290917f7aee16d2c366535c2577e873699b458af55a0b0bd4c4fab5e930a780f05669d791a450505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161073b565b8173ffffffffffffffffffffffffffffffffffffffff8116611209576040517f60121cca000000000000000000000000000000000000000000000000000000008152617534600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff831660008181526009602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f0a1c6cd77aa2e405e482adf6ee6cf190a27682b6dd1234403f7602e5203c83bb91a3505050565b600061129483611900565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146112fc576040517f60121cca000000000000000000000000000000000000000000000000000000008152617535600482015260240161073b565b611306828461203d565b604051909150819073ffffffffffffffffffffffffffffffffffffffff84169033907ffcc2278353c4cc5d54b742d7eee2d4a7abc22e4dc6213340088293860d502b5190600090a492915050565b6002805461063d906126bb565b600061136c33610d7e565b6113a6576040517f60121cca000000000000000000000000000000000000000000000000000000008152617532600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604090205460ff16611409576040517f60121cca000000000000000000000000000000000000000000000000000000008152617532600482015260240161073b565b6000600b6000815461141a906127f4565b9182905550905061142a81611900565b91506000808673ffffffffffffffffffffffffffffffffffffffff16868660405161145692919061282c565b600060405180830381855af49150503d8060008114611491576040519150601f19603f3d011682016040523d82523d6000602084013e611496565b606091505b50915091508180156114ee57506114bf818060200190518101906114ba919061286b565b6120fb565b73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b80156114fe57506114fe84610e34565b611538576040517f60121cca000000000000000000000000000000000000000000000000000000008152617536600482015260240161073b565b604051839073ffffffffffffffffffffffffffffffffffffffff8616907efa89a51ae01c150bfde909191818194382d30b43b645428ed6a71f1955107390600090a35050509392505050565b33600081815260076020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461169c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161073b565b8173ffffffffffffffffffffffffffffffffffffffff81166116ee576040517f60121cca000000000000000000000000000000000000000000000000000000008152617534600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff831660008181526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519092917f48cc5b4660fae22eabe5e803ee595e63572773d114bcd54ecc118c1efa8d75af91a3505050565b611779858585610934565b73ffffffffffffffffffffffffffffffffffffffff84163b158061185b57506040517f150b7a02000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff86169063150b7a02906117f49033908a90899089908990600401612936565b6020604051808303816000875af1158015611813573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183791906127be565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b611895576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d04600482015260240161073b565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600a6020908152604080832093851683529290529081205460ff16806118f9575060005473ffffffffffffffffffffffffffffffffffffffff8381169116145b9392505050565b60006060826000036119155750600092915050565b607f83116119dd576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b16602282015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660368201526037015b6040516020818303038152906040529050611d55565b60ff8311611ab9576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f8100000000000000000000000000000000000000000000000000000000000000603682015260f884901b7fff000000000000000000000000000000000000000000000000000000000000001660378201526038016119c7565b61ffff8311611b96576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f085901b1660378201526039016119c7565b62ffffff8311611c74576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e885901b166037820152603a016119c7565b6040517fda0000000000000000000000000000000000000000000000000000000000000060208201527f940000000000000000000000000000000000000000000000000000000000000060218201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e085901b166037820152603b0160405160208183030381529060405290505b805160209091012092915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611de4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a45440000000000000000000000000000000000000000604482015260640161073b565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b73ffffffffffffffffffffffffffffffffffffffff8316611ea5576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d03600482015260240161073b565b73ffffffffffffffffffffffffffffffffffffffff8416611f5f5773ffffffffffffffffffffffffffffffffffffffff83166000818152600460209081526040808320838052808352818420805488865260038552838620600163ffffffff83160160a081901b90981760c08a901b1790557fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000168617905560088504845282529091208054600790931690910284901b9091179055612037565b8373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461203757611f9c8483612198565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600460209081526040808320838052808352818420805488865260038552838620600163ffffffff83160160a081901b90981760c08a901b1790557fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000168617905560088504845282529091208054600790931690910284901b90911790555b50505050565b600580546001019081905563ffffffff81101580612068575060008181526003602052604090205415155b156120a3576040517f60121cca000000000000000000000000000000000000000000000000000000008152617d01600482015260240161073b565b6120b06000848385611e54565b604051819073ffffffffffffffffffffffffffffffffffffffff8516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a492915050565b6000815160000361213c576040517f60121cca000000000000000000000000000000000000000000000000000000008152617531600482015260240161073b565b8151602083016000f0905073ffffffffffffffffffffffffffffffffffffffff8116610e2f576040517f60121cca000000000000000000000000000000000000000000000000000000008152617531600482015260240161073b565b600081815260036020908152604080832080549084905573ffffffffffffffffffffffffffffffffffffffff8616845260048352818420848052909252909120549060a01c63ffffffff9081169082166121f36001826129b5565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260046020908152604080832083805282528083207fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000009790971693909317909555600883048082529190205493600783160283831461231757600884046020600786160286831c63ffffffff168483036122985763ffffffff821b199790971687821b17966122da565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526004602090815260408083208684529091529020805463ffffffff841b191682841b1790555b600090815260036020526040902080547fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff1660a088901b17905550505b73ffffffffffffffffffffffffffffffffffffffff90961660009081526004602090815260408083209383529290522063ffffffff90951b1992909216909355505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461238a57600080fd5b50565b60006020828403121561239f57600080fd5b81356118f98161235c565b60005b838110156123c55781810151838201526020016123ad565b50506000910152565b60208152600082518060208401526123ed8160408501602087016123aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561243157600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e2f57600080fd5b80358015158114610e2f57600080fd5b6000806040838503121561247f57600080fd5b61248883612438565b91506124966020840161245c565b90509250929050565b600080604083850312156124b257600080fd5b6124bb83612438565b946020939093013593505050565b6000602082840312156124db57600080fd5b6118f982612438565b6000806000606084860312156124f957600080fd5b61250284612438565b925061251060208501612438565b9150604084013590509250925092565b60008060006060848603121561253557600080fd5b61253e84612438565b925061254c60208501612438565b915061255a6040850161245c565b90509250925092565b6000806040838503121561257657600080fd5b8235915061249660208401612438565b60008083601f84011261259857600080fd5b50813567ffffffffffffffff8111156125b057600080fd5b6020830191508360208285010111156125c857600080fd5b9250929050565b6000806000604084860312156125e457600080fd5b6125ed84612438565b9250602084013567ffffffffffffffff81111561260957600080fd5b61261586828701612586565b9497909650939450505050565b60008060008060006080868803121561263a57600080fd5b61264386612438565b945061265160208701612438565b935060408601359250606086013567ffffffffffffffff81111561267457600080fd5b61268088828901612586565b969995985093965092949392505050565b600080604083850312156126a457600080fd5b6126ad83612438565b915061249660208401612438565b600181811c908216806126cf57607f821691505b602082108103612708577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561062a5761062a61270e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261278e5761278e612750565b500690565b808202811582820484141761062a5761062a61270e565b6000826127b9576127b9612750565b500490565b6000602082840312156127d057600080fd5b81516118f98161235c565b6000602082840312156127ed57600080fd5b5051919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036128255761282561270e565b5060010190565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561287d57600080fd5b815167ffffffffffffffff8082111561289557600080fd5b818401915084601f8301126128a957600080fd5b8151818111156128bb576128bb61283c565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156129015761290161283c565b8160405282815287602084870101111561291a57600080fd5b61292b8360208301602088016123aa565b979650505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011683010190509695505050505050565b8181038181111561062a5761062a61270e56fea26469706673582212200d4cdcde81be0a68e93227413d1bbcf7c556db4d4ab4fba51544ff36fbb590c964736f6c63430008150033

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


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.