false
false
100

Contract Address Details

0x84654e35E504452769757AAe5a8C7C6599cBf954

Contract Name
VaultRegistry
Creator
0xc6387eā€“2457ff at 0x7edbe2ā€“852a1e
Balance
0 KAVA ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
11603187
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
VaultRegistry




Optimization enabled
true
Compiler version
v0.8.15+commit.e14f2714




Optimization runs
200
Verified at
2023-04-27T00:32:18.446570Z

Constructor Arguments

000000000000000000000000697bc6bd64677be63240262869dd5f2a3eeaccd30000000000000000000000000000000000000000000000000000000000000000

Arg [0] (address) : 0x697bc6bd64677be63240262869dd5f2a3eeaccd3
Arg [1] (address) : 0x0000000000000000000000000000000000000000

              

contracts/VaultRegistry.sol

// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.15;

import "@openzeppelin/contracts/access/Ownable.sol";
import "./IVault.sol";

interface IReleaseRegistry {
    function numReleases() external view returns (uint256);

    function releases(uint256 _version) external view returns (address);

    function newVault(
        address _token,
        address _governance,
        address _guardian,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        uint256 _releaseDelta
    ) external returns (address);
}

contract VaultRegistry is Ownable {
    /* ========== STATE VARIABLES ========== */

    /// @notice Default vault type for this registry. Emitted on vault creation.
    uint256 public constant DEFAULT_VAULT_TYPE = 1;

    /// @notice Address of our pre-factory registry. Used to fetch older vaults.
    /// @dev Vaults read from the legacy registry are, by default, type 0.
    address public immutable LEGACY_REGISTRY;

    /// @notice Address of our release registry. Used to pull most recent vault release.
    address public releaseRegistry;

    /// @notice If one or more vault(s) exist for a token, they will be shown here.
    /// @dev Only vaults deployed from this registry will be shown.
    mapping(address => address[]) public vaults;

    /// @notice Tokens that this registry has deployed vaults for.
    address[] imported.tokens;

    /// @notice Check if an endorsed vault exists for a given underlying token.
    mapping(address => bool) public isRegistered;

    /// @notice Check the type of a given vault address.
    /// @dev Vault must have been endorsed by this registry.
    mapping(address => uint256) public vaultType;

    /// @notice Check if an address is allowed to own vaults from this registry.
    mapping(address => bool) public approvedVaultsOwner;

    /// @notice Check if a given vault was endorsed by this registry.
    mapping(address => bool) public isVaultEndorsed;

    /// @notice Check if an address can endorse vaults via this registry.
    mapping(address => bool) public vaultEndorsers;

    /* ========== EVENTS AND ERRORS ========== */

    event NewVault(
        address indexed token,
        uint256 indexed vaultId,
        uint256 vaultType,
        address vault,
        string apiVersion
    );

    event ApprovedVaultOwnerUpdated(address governance, bool approved);
    event ApprovedVaultEndorser(address account, bool canEndorse);
    event ReleaseRegistryUpdated(address newRegistry);

    error GovernanceMismatch(address vault);
    error NotAllowedToEndorse();
    error VersionMissmatch(string v1, string v2);
    error EndorseVaultWithSameVersion(address existingVault, address newVault);
    error VaultAlreadyEndorsed(address vault, uint256 vaultType);
    error InvalidVaultType();

    /* ========== CONSTRUCTOR ========== */

    constructor(address _releaseRegistry, address _legacyRegistry) {
        releaseRegistry = _releaseRegistry;
        LEGACY_REGISTRY = _legacyRegistry;
        emit ReleaseRegistryUpdated(_releaseRegistry);
    }

    /* ========== VIEWS ========== */

    /// @notice The number of tokens with vaults deployed by this registry.
    function numTokens() external view returns (uint256) {
        return tokens.length;
    }

    /// @notice The number of vaults deployed for a token by this registry.
    function numVaults(address _token) external view returns (uint256) {
        return _numVaults(_token);
    }

    function _numVaults(address _token) internal view returns (uint256) {
        return vaults[_token].length;
    }

    /**
     @notice Returns the latest deployed vault for the given token.
     @dev Return zero if no vault is associated with the token. Also
      checks our legacy registry as well.
     @param _token The token address to find the latest vault for.
     @return The address of the latest vault for the given token.
     */
    function latestVault(address _token) external view returns (address) {
        return _latestVault(_token);
    }

    /**
     @notice Returns the latest deployed vault for the given token and type.
     @dev Return zero if no vault exists for both token and type.
     @dev Currently defined types are 0: legacy, 1: default, 2: automated. More may be added later.
     @param _token The token address to find the latest vault for.
     @param _type The vault type to find the latest vault for.
     @return The address of the latest vault found matching both token and type.
     */
    function latestVaultOfType(
        address _token,
        uint256 _type
    ) external view returns (address) {
        return _latestVaultOfType(_token, _type);
    }

    // get the latest vault for a token, from this registry or our legacy registry.
    function _latestVault(address _token) internal view returns (address) {
        uint256 length = _numVaults(_token);
        if (length == 0) {
            return _fetchFromLegacy(_token);
        }
        return vaults[_token][length - 1];
    }

    // get the latest vault for a token and type. legacy is type 0.
    function _latestVaultOfType(
        address _token,
        uint256 _type
    ) internal view returns (address) {
        // type 0 are legacy, not from this registry
        if (_type == 0) {
            return _fetchFromLegacy(_token);
        }

        uint256 length = _numVaults(_token);
        if (length == 0) {
            return address(0);
        }

        uint256 i = length - 1;
        while (true) {
            address vault = vaults[_token][i];
            if (vaultType[vault] == _type) {
                return vault;
            }
            if (i == 0) {
                break;
            }
            unchecked {
                i--;
            }
        }
        return address(0);
    }

    // check our legacy registry for vaults for a given token
    function _fetchFromLegacy(address _token) internal view returns (address) {
        bytes memory data = abi.encodeWithSignature(
            "latestVault(address)",
            _token
        );
        (bool success, bytes memory returnBytes) = address(LEGACY_REGISTRY)
            .staticcall(data);
        if (success) {
            return abi.decode(returnBytes, (address));
        }
        return address(0);
    }

    /* ========== CORE FUNCTIONS ========== */

    /**
    @notice
        Create a new vault for the given token using the latest release in the registry,
        as a simple "forwarder-style" delegatecall proxy to the latest release.
    @dev
        governance is set in the new vault as governance, with no ability to override.
        Throws if caller isn't governance.
        Throws if no releases are registered yet.
        Throws if there already is a registered vault for the given token with the latest api version.
        Emits a NewVault event.
    @param _token The token that may be deposited into the new Vault.
    @param _guardian The address authorized for guardian interactions in the new Vault.
    @param _rewards The address to use for collecting rewards in the new Vault
    @param _name Specify a custom Vault name. Set to empty string for default choice.
    @param _symbol Specify a custom Vault symbol name. Set to empty string for default choice.
    @param _releaseDelta Specify the number of releases prior to the latest to use as a target. Default is latest.
    @param _type Vault type. Basic defined types are 1: default, 2: automated, but more can be added.
    @return The address of the newly-deployed vault
     */
    function newVault(
        address _token,
        address _governance,
        address _guardian,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        uint256 _releaseDelta,
        uint256 _type
    ) public returns (address) {
        require(vaultEndorsers[msg.sender], "unauthorized");
        require(approvedVaultsOwner[_governance], "not allowed vault owner");
        address vault = IReleaseRegistry(releaseRegistry).newVault(
            _token,
            _governance,
            _guardian,
            _rewards,
            _name,
            _symbol,
            _releaseDelta
        );
        _registerVault(_token, vault, _type);
        return vault;
    }

    /**
     @notice
         Adds an existing vault to the list of "endorsed" vaults for that token.
     @dev
         Throws if caller isn't an approved endorser.
         Throws if `_vault` governance isn't an approved vault owner.
         Throws if no releases are registered yet.
         Throws if `_vault` api version does not match latest release.
         Throws if there already is a deployment for the vault's token with the latest api version.
         Emits a NewVault event.
     @param _vault The vault that will be endorsed by this registry.
     @param _releaseDelta Specify the number of releases prior to the latest to use as a target. Default is latest.
     @param _type Vault type
    */
    function endorseVault(
        address _vault,
        uint256 _releaseDelta,
        uint256 _type
    ) public {
        if (vaultEndorsers[msg.sender] == false) {
            revert NotAllowedToEndorse();
        }

        if (approvedVaultsOwner[IVault(_vault).governance()] == false) {
            revert GovernanceMismatch(_vault);
        }

        // NOTE: Underflow if no releases created yet, or targeting prior to release history
        uint256 releaseTarget = IReleaseRegistry(releaseRegistry)
            .numReleases() -
            1 -
            _releaseDelta; // dev: no releases
        string memory apiVersion = IVault(
            IReleaseRegistry(releaseRegistry).releases(releaseTarget)
        ).apiVersion();
        if (
            keccak256(bytes((IVault(_vault).apiVersion()))) !=
            keccak256(bytes((apiVersion)))
        ) {
            revert VersionMissmatch(IVault(_vault).apiVersion(), apiVersion);
        }
        // Add to the end of the list of vaults for token
        _registerVault(IVault(_vault).token(), _vault, _type);
    }

    /**
    @notice Endorse a vault of the default vault type.
    @dev See main endorseVault() function for more details.
    @param _vault The vault that will be endorsed by this registry.
    @param _releaseDelta Specify the number of releases prior to the latest to use as a target. Default is latest.
     */
    function endorseVault(address _vault, uint256 _releaseDelta) external {
        endorseVault(_vault, _releaseDelta, DEFAULT_VAULT_TYPE);
    }

    /**
    @notice Endorse a vault of the default vault type and the current release.
    @dev See main endorseVault() function for more details.
    @param _vault The vault that will be endorsed by this registry.
     */
    function endorseVault(address _vault) external {
        endorseVault(_vault, 0, DEFAULT_VAULT_TYPE);
    }

    /**
    @notice Deploy a new vault with the default vault type.
    @dev See other newVault() function for more details.
     */
    function newVault(
        address _token,
        address _guardian,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        uint256 _releaseDelta
    ) external returns (address) {
        return
            newVault(
                _token,
                msg.sender,
                _guardian,
                _rewards,
                _name,
                _symbol,
                _releaseDelta,
                DEFAULT_VAULT_TYPE
            );
    }

    function _registerVault(
        address _token,
        address _vault,
        uint256 _type
    ) internal {
        // Check if there is an existing deployment for this token + type combination at the particular api version
        // NOTE: This doesn't check for strict semver-style linearly increasing release versions
        if (vaultType[_vault] != 0) {
            revert VaultAlreadyEndorsed(_vault, vaultType[_vault]);
        }

        if (_type == 0) {
            revert InvalidVaultType();
        }

        address latest = _latestVaultOfType(_token, _type);
        if (latest != address(0)) {
            if (
                keccak256(bytes(IVault(latest).apiVersion())) ==
                keccak256(bytes(IVault(_vault).apiVersion()))
            ) {
                revert EndorseVaultWithSameVersion(latest, _vault);
            }
        }
        uint256 id = _numVaults(_token);
        // Update the latest deployment
        vaults[_token].push(_vault);
        vaultType[_vault] = _type;

        // Register tokens for endorsed vaults
        if (isRegistered[_token] == false) {
            isRegistered[_token] = true;
            tokens.push(_token);
        }
        isVaultEndorsed[_vault] = true;
        emit NewVault(_token, id, _type, _vault, IVault(_vault).apiVersion());
    }

    /* ========== SETTERS ========== */

    /**
    @notice Set the ability of a particular tagger to tag current vaults.
    @dev Throws if caller is not owner.
    @param _addr The address to approve or deny access.
    @param _approved Allowed to endorse
     */
    function setVaultEndorsers(
        address _addr,
        bool _approved
    ) external onlyOwner {
        vaultEndorsers[_addr] = _approved;
        emit ApprovedVaultEndorser(_addr, _approved);
    }

    /**
    @notice Set the vaults owners
    @dev Throws if caller is not owner.
    @param _addr The address to approve or deny access.
    @param _approved Allowed to own vault
     */
    function setApprovedVaultsOwner(
        address _addr,
        bool _approved
    ) external onlyOwner {
        approvedVaultsOwner[_addr] = _approved;
        emit ApprovedVaultOwnerUpdated(_addr, _approved);
    }

    /**
    @notice Update the address of our release registry.
    @dev Contains information about latest and past vault releases. 
     Throws if caller is not owner.
    @param _newRegistry Address of our new release registry.
     */
    function updateReleaseRegistry(address _newRegistry) external onlyOwner {
        releaseRegistry = _newRegistry;
        emit ReleaseRegistryUpdated(_newRegistry);
    }
}
        

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

contracts/IVault.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;

interface IVault {
    function token() external view returns (address);

    function apiVersion() external view returns (string memory);

    function governance() external view returns (address);

    function initialize(
        address _token,
        address _governance,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        address _guardian
    ) external;
}
          

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

contracts/IVault.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;

interface IVault {
    function token() external view returns (address);

    function apiVersion() external view returns (string memory);

    function governance() external view returns (address);

    function initialize(
        address _token,
        address _governance,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        address _guardian
    ) external;
}
          

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

contracts/IVault.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;

interface IVault {
    function token() external view returns (address);

    function apiVersion() external view returns (string memory);

    function governance() external view returns (address);

    function initialize(
        address _token,
        address _governance,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        address _guardian
    ) external;
}
          

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

contracts/IVault.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;

interface IVault {
    function token() external view returns (address);

    function apiVersion() external view returns (string memory);

    function governance() external view returns (address);

    function initialize(
        address _token,
        address _governance,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        address _guardian
    ) external;
}
          

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

contracts/IVault.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;

interface IVault {
    function token() external view returns (address);

    function apiVersion() external view returns (string memory);

    function governance() external view returns (address);

    function initialize(
        address _token,
        address _governance,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        address _guardian
    ) external;
}
          

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

contracts/IVault.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;

interface IVault {
    function token() external view returns (address);

    function apiVersion() external view returns (string memory);

    function governance() external view returns (address);

    function initialize(
        address _token,
        address _governance,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        address _guardian
    ) external;
}
          

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

contracts/IVault.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;

interface IVault {
    function token() external view returns (address);

    function apiVersion() external view returns (string memory);

    function governance() external view returns (address);

    function initialize(
        address _token,
        address _governance,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        address _guardian
    ) external;
}
          

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

contracts/IVault.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;

interface IVault {
    function token() external view returns (address);

    function apiVersion() external view returns (string memory);

    function governance() external view returns (address);

    function initialize(
        address _token,
        address _governance,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        address _guardian
    ) external;
}
          

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

contracts/IVault.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;

interface IVault {
    function token() external view returns (address);

    function apiVersion() external view returns (string memory);

    function governance() external view returns (address);

    function initialize(
        address _token,
        address _governance,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        address _guardian
    ) external;
}
          

@openzeppelin/contracts/access/Ownable.sol

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

@openzeppelin/contracts/utils/Context.sol

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

pragma solidity ^0.8.0;

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

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

contracts/IVault.sol

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.15;

interface IVault {
    function token() external view returns (address);

    function apiVersion() external view returns (string memory);

    function governance() external view returns (address);

    function initialize(
        address _token,
        address _governance,
        address _rewards,
        string calldata _name,
        string calldata _symbol,
        address _guardian
    ) external;
}
          

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_releaseRegistry","internalType":"address"},{"type":"address","name":"_legacyRegistry","internalType":"address"}]},{"type":"error","name":"EndorseVaultWithSameVersion","inputs":[{"type":"address","name":"existingVault","internalType":"address"},{"type":"address","name":"newVault","internalType":"address"}]},{"type":"error","name":"GovernanceMismatch","inputs":[{"type":"address","name":"vault","internalType":"address"}]},{"type":"error","name":"InvalidVaultType","inputs":[]},{"type":"error","name":"NotAllowedToEndorse","inputs":[]},{"type":"error","name":"VaultAlreadyEndorsed","inputs":[{"type":"address","name":"vault","internalType":"address"},{"type":"uint256","name":"vaultType","internalType":"uint256"}]},{"type":"error","name":"VersionMissmatch","inputs":[{"type":"string","name":"v1","internalType":"string"},{"type":"string","name":"v2","internalType":"string"}]},{"type":"event","name":"ApprovedVaultEndorser","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false},{"type":"bool","name":"canEndorse","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"ApprovedVaultOwnerUpdated","inputs":[{"type":"address","name":"governance","internalType":"address","indexed":false},{"type":"bool","name":"approved","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"NewVault","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"uint256","name":"vaultId","internalType":"uint256","indexed":true},{"type":"uint256","name":"vaultType","internalType":"uint256","indexed":false},{"type":"address","name":"vault","internalType":"address","indexed":false},{"type":"string","name":"apiVersion","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ReleaseRegistryUpdated","inputs":[{"type":"address","name":"newRegistry","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"DEFAULT_VAULT_TYPE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"LEGACY_REGISTRY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approvedVaultsOwner","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"endorseVault","inputs":[{"type":"address","name":"_vault","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"endorseVault","inputs":[{"type":"address","name":"_vault","internalType":"address"},{"type":"uint256","name":"_releaseDelta","internalType":"uint256"},{"type":"uint256","name":"_type","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"endorseVault","inputs":[{"type":"address","name":"_vault","internalType":"address"},{"type":"uint256","name":"_releaseDelta","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isRegistered","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isVaultEndorsed","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"latestVault","inputs":[{"type":"address","name":"_token","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"latestVaultOfType","inputs":[{"type":"address","name":"_token","internalType":"address"},{"type":"uint256","name":"_type","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"newVault","inputs":[{"type":"address","name":"_token","internalType":"address"},{"type":"address","name":"_governance","internalType":"address"},{"type":"address","name":"_guardian","internalType":"address"},{"type":"address","name":"_rewards","internalType":"address"},{"type":"string","name":"_name","internalType":"string"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"uint256","name":"_releaseDelta","internalType":"uint256"},{"type":"uint256","name":"_type","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"newVault","inputs":[{"type":"address","name":"_token","internalType":"address"},{"type":"address","name":"_guardian","internalType":"address"},{"type":"address","name":"_rewards","internalType":"address"},{"type":"string","name":"_name","internalType":"string"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"uint256","name":"_releaseDelta","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"numTokens","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"numVaults","inputs":[{"type":"address","name":"_token","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"releaseRegistry","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setApprovedVaultsOwner","inputs":[{"type":"address","name":"_addr","internalType":"address"},{"type":"bool","name":"_approved","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setVaultEndorsers","inputs":[{"type":"address","name":"_addr","internalType":"address"},{"type":"bool","name":"_approved","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"tokens","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateReleaseRegistry","inputs":[{"type":"address","name":"_newRegistry","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"vaultEndorsers","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"vaultType","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"vaults","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]}]
              

Contract Creation Code

0x60a06040523480156200001157600080fd5b50604051620018793803806200187983398101604081905262000034916200010c565b6200003f336200009f565b600180546001600160a01b0319166001600160a01b038481169182179092559082166080526040519081527f65104c4699f20a240a0ce199d616669f9518c0469b60b2a8c904f7cd4eb471fd9060200160405180910390a1505062000144565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200010757600080fd5b919050565b600080604083850312156200012057600080fd5b6200012b83620000ef565b91506200013b60208401620000ef565b90509250929050565b60805161171262000167600039600081816101ad015261110e01526117126000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80638e499bcf116100de578063c3c5a54711610097578063e177dc7011610071578063e177dc7014610389578063f2cb777f1461039c578063f2fde38b146103a4578063f9c7bba5146103b757600080fd5b8063c3c5a54714610333578063c9b8f05514610356578063dbf424611461037657600080fd5b80638e499bcf146102b2578063931074ba146102c45780639de312f0146102d7578063a0dd0bcf146102ea578063b0b40fce1461030d578063b366a35c1461032057600080fd5b806351f69a6e1161013057806351f69a6e1461023d5780636fc74f9e14610250578063715018a6146102735780637bbfc69e1461027b5780638cd473c21461028e5780638da5cb5b146102a157600080fd5b8063125d43361461017857806315065519146101a857806319ee073e146101cf57806329b2e0c6146101e25780632b017c8b146101f75780634f64b2be1461022a575b600080fd5b61018b610186366004611200565b6103ca565b6040516001600160a01b0390911681526020015b60405180910390f35b61018b7f000000000000000000000000000000000000000000000000000000000000000081565b60015461018b906001600160a01b031681565b6101f56101f03660046112cd565b610525565b005b61021a6102053660046112cd565b60066020526000908152604090205460ff1681565b604051901515815260200161019f565b61018b6102383660046112ea565b610535565b6101f561024b366004611303565b61055f565b61021a61025e3660046112cd565b60086020526000908152604090205460ff1681565b6101f56105cb565b61018b610289366004611341565b6105df565b6101f561029c3660046112cd565b610617565b6000546001600160a01b031661018b565b6003545b60405190815260200161019f565b6101f56102d236600461136d565b610673565b61018b6102e5366004611341565b610a30565b61021a6102f83660046112cd565b60076020526000908152604090205460ff1681565b61018b61031b3660046113a2565b610a45565b6101f561032e366004611341565b610a67565b61021a6103413660046112cd565b60046020526000908152604090205460ff1681565b6102b66103643660046112cd565b60056020526000908152604090205481565b6101f5610384366004611303565b610a77565b61018b6103973660046112cd565b610adb565b6102b6600181565b6101f56103b23660046112cd565b610ae6565b6102b66103c53660046112cd565b610b5c565b3360009081526008602052604081205460ff1661041d5760405162461bcd60e51b815260206004820152600c60248201526b1d5b985d5d1a1bdc9a5e995960a21b60448201526064015b60405180910390fd5b6001600160a01b038a1660009081526006602052604090205460ff166104855760405162461bcd60e51b815260206004820152601760248201527f6e6f7420616c6c6f776564207661756c74206f776e65720000000000000000006044820152606401610414565b60015460405163e1c6ba5d60e01b81526000916001600160a01b03169063e1c6ba5d906104c6908f908f908f908f908f908f908f908f908f9060040161147a565b6020604051808303816000875af11580156104e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050991906114e1565b90506105168c8285610b7a565b9b9a5050505050505050505050565b6105328160006001610673565b50565b6003818154811061054557600080fd5b6000918252602090912001546001600160a01b0316905081565b610567610eb2565b6001600160a01b038216600081815260066020908152604091829020805460ff19168515159081179091558251938452908301527fc9219e6871f1efb578009a697784e88c6375187771bda2c8899b8ead4bbea82291015b60405180910390a15050565b6105d3610eb2565b6105dd6000610f0c565b565b600260205281600052604060002081815481106105fb57600080fd5b6000918252602090912001546001600160a01b03169150829050565b61061f610eb2565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f65104c4699f20a240a0ce199d616669f9518c0469b60b2a8c904f7cd4eb471fd9060200160405180910390a150565b3360009081526008602052604081205460ff16151590036106a757604051632e1027db60e11b815260040160405180910390fd5b60066000846001600160a01b0316635aa6e6756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070d91906114e1565b6001600160a01b03168152602081019190915260400160009081205460ff16151590036107585760405163d0c41e7960e01b81526001600160a01b0384166004820152602401610414565b60008260018060009054906101000a90046001600160a01b03166001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d391906114fe565b6107dd9190611517565b6107e79190611517565b60015460405163b6a9f40f60e01b8152600481018390529192506000916001600160a01b039091169063b6a9f40f90602401602060405180830381865afa158015610836573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085a91906114e1565b6001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610897573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108bf9190810190611582565b90508080519060200120856001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610907573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261092f9190810190611582565b80519060200120146109bd57846001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610979573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109a19190810190611582565b81604051639102966160e01b815260040161041492919061165b565b610a29856001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2291906114e1565b8685610b7a565b5050505050565b6000610a3c8383610f5c565b90505b92915050565b6000610a5a89338a8a8a8a8a8a8a60016103ca565b9998505050505050505050565b610a7382826001610673565b5050565b610a7f610eb2565b6001600160a01b038216600081815260086020908152604091829020805460ff19168515159081179091558251938452908301527f0432d20aa3457fdf75aad100b0473a9a5a3f29275b066abbeb243dc7e0db4a4891016105bf565b6000610a3f82611037565b610aee610eb2565b6001600160a01b038116610b535760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610414565b61053281610f0c565b6001600160a01b038116600090815260026020526040812054610a3f565b6001600160a01b03821660009081526005602052604090205415610bd4576001600160a01b038216600081815260056020526040908190205490516314e3ee7560e01b815260048101929092526024820152604401610414565b80600003610bf55760405163031366db60e01b815260040160405180910390fd5b6000610c018483610f5c565b90506001600160a01b03811615610d1d57826001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c50573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c789190810190611582565b80519060200120816001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610cbd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ce59190810190611582565b8051906020012003610d1d576040516318aec0af60e01b81526001600160a01b03808316600483015284166024820152604401610414565b6001600160a01b0384811660008181526002602090815260408083208054600181018255908452828420810180546001600160a01b031916968a16968717905594835260058252808320879055928252600490529081205460ff1615159003610de6576001600160a01b0385166000818152600460205260408120805460ff191660019081179091556003805491820181559091527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b03191690911790555b6001600160a01b03808516600081815260076020526040808220805460ff191660011790558051630258294160e41b8152905185948a16937f665814fc0711cd098dc48648ad2f63460a3cb758a6aca058c168d7a9067d9f389389938b936325829410926004808401939192918290030181865afa158015610e6c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e949190810190611582565b604051610ea393929190611680565b60405180910390a35050505050565b6000546001600160a01b031633146105dd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610414565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600081600003610f7657610f6f836110b7565b9050610a3f565b6001600160a01b03831660009081526002602052604081205490819003610fa1576000915050610a3f565b6000610fae600183611517565b90505b6001600160a01b0385166000908152600260205260408120805483908110610fdb57610fdb6116aa565b60009182526020808320909101546001600160a01b03168083526005909152604090912054909150859003611014579250610a3f915050565b81600003611022575061102c565b5060001901610fb1565b506000949350505050565b6001600160a01b0381166000908152600260205260408120548060000361106857611061836110b7565b9392505050565b6001600160a01b038316600090815260026020526040902061108b600183611517565b8154811061109b5761109b6116aa565b6000918252602090912001546001600160a01b03169392505050565b6040516001600160a01b0382166024820152600090819060440160408051601f198184030181529181526020820180516001600160e01b0316630e177dc760e41b1790525190915060009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169061113a9085906116c0565b600060405180830381855afa9150503d8060008114611175576040519150601f19603f3d011682016040523d82523d6000602084013e61117a565b606091505b5091509150811561102c578080602001905181019061119991906114e1565b95945050505050565b6001600160a01b038116811461053257600080fd5b60008083601f8401126111c957600080fd5b50813567ffffffffffffffff8111156111e157600080fd5b6020830191508360208285010111156111f957600080fd5b9250929050565b6000806000806000806000806000806101008b8d03121561122057600080fd5b8a3561122b816111a2565b995060208b013561123b816111a2565b985060408b013561124b816111a2565b975060608b013561125b816111a2565b965060808b013567ffffffffffffffff8082111561127857600080fd5b6112848e838f016111b7565b909850965060a08d013591508082111561129d57600080fd5b506112aa8d828e016111b7565b9b9e9a9d50989b979a969995989760c08101359660e09091013595509350505050565b6000602082840312156112df57600080fd5b8135611061816111a2565b6000602082840312156112fc57600080fd5b5035919050565b6000806040838503121561131657600080fd5b8235611321816111a2565b91506020830135801515811461133657600080fd5b809150509250929050565b6000806040838503121561135457600080fd5b823561135f816111a2565b946020939093013593505050565b60008060006060848603121561138257600080fd5b833561138d816111a2565b95602085013595506040909401359392505050565b60008060008060008060008060c0898b0312156113be57600080fd5b88356113c9816111a2565b975060208901356113d9816111a2565b965060408901356113e9816111a2565b9550606089013567ffffffffffffffff8082111561140657600080fd5b6114128c838d016111b7565b909750955060808b013591508082111561142b57600080fd5b506114388b828c016111b7565b999c989b50969995989497949560a00135949350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038a81168252898116602083015288811660408301528716606082015260e0608082018190526000906114b79083018789611451565b82810360a08401526114ca818688611451565b9150508260c08301529a9950505050505050505050565b6000602082840312156114f357600080fd5b8151611061816111a2565b60006020828403121561151057600080fd5b5051919050565b60008282101561153757634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561156d578181015183820152602001611555565b8381111561157c576000848401525b50505050565b60006020828403121561159457600080fd5b815167ffffffffffffffff808211156115ac57600080fd5b818401915084601f8301126115c057600080fd5b8151818111156115d2576115d261153c565b604051601f8201601f19908116603f011681019083821181831017156115fa576115fa61153c565b8160405282815287602084870101111561161357600080fd5b611624836020830160208801611552565b979650505050505050565b60008151808452611647816020860160208601611552565b601f01601f19169290920160200192915050565b60408152600061166e604083018561162f565b8281036020840152611199818561162f565b8381526001600160a01b03831660208201526060604082018190526000906111999083018461162f565b634e487b7160e01b600052603260045260246000fd5b600082516116d2818460208701611552565b919091019291505056fea2646970667358221220f879bf438dfafc7b952580342c996d34c4730539025a7036fc2fda8876d24a8764736f6c634300080f0033000000000000000000000000697bc6bd64677be63240262869dd5f2a3eeaccd30000000000000000000000000000000000000000000000000000000000000000

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101735760003560e01c80638e499bcf116100de578063c3c5a54711610097578063e177dc7011610071578063e177dc7014610389578063f2cb777f1461039c578063f2fde38b146103a4578063f9c7bba5146103b757600080fd5b8063c3c5a54714610333578063c9b8f05514610356578063dbf424611461037657600080fd5b80638e499bcf146102b2578063931074ba146102c45780639de312f0146102d7578063a0dd0bcf146102ea578063b0b40fce1461030d578063b366a35c1461032057600080fd5b806351f69a6e1161013057806351f69a6e1461023d5780636fc74f9e14610250578063715018a6146102735780637bbfc69e1461027b5780638cd473c21461028e5780638da5cb5b146102a157600080fd5b8063125d43361461017857806315065519146101a857806319ee073e146101cf57806329b2e0c6146101e25780632b017c8b146101f75780634f64b2be1461022a575b600080fd5b61018b610186366004611200565b6103ca565b6040516001600160a01b0390911681526020015b60405180910390f35b61018b7f000000000000000000000000000000000000000000000000000000000000000081565b60015461018b906001600160a01b031681565b6101f56101f03660046112cd565b610525565b005b61021a6102053660046112cd565b60066020526000908152604090205460ff1681565b604051901515815260200161019f565b61018b6102383660046112ea565b610535565b6101f561024b366004611303565b61055f565b61021a61025e3660046112cd565b60086020526000908152604090205460ff1681565b6101f56105cb565b61018b610289366004611341565b6105df565b6101f561029c3660046112cd565b610617565b6000546001600160a01b031661018b565b6003545b60405190815260200161019f565b6101f56102d236600461136d565b610673565b61018b6102e5366004611341565b610a30565b61021a6102f83660046112cd565b60076020526000908152604090205460ff1681565b61018b61031b3660046113a2565b610a45565b6101f561032e366004611341565b610a67565b61021a6103413660046112cd565b60046020526000908152604090205460ff1681565b6102b66103643660046112cd565b60056020526000908152604090205481565b6101f5610384366004611303565b610a77565b61018b6103973660046112cd565b610adb565b6102b6600181565b6101f56103b23660046112cd565b610ae6565b6102b66103c53660046112cd565b610b5c565b3360009081526008602052604081205460ff1661041d5760405162461bcd60e51b815260206004820152600c60248201526b1d5b985d5d1a1bdc9a5e995960a21b60448201526064015b60405180910390fd5b6001600160a01b038a1660009081526006602052604090205460ff166104855760405162461bcd60e51b815260206004820152601760248201527f6e6f7420616c6c6f776564207661756c74206f776e65720000000000000000006044820152606401610414565b60015460405163e1c6ba5d60e01b81526000916001600160a01b03169063e1c6ba5d906104c6908f908f908f908f908f908f908f908f908f9060040161147a565b6020604051808303816000875af11580156104e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050991906114e1565b90506105168c8285610b7a565b9b9a5050505050505050505050565b6105328160006001610673565b50565b6003818154811061054557600080fd5b6000918252602090912001546001600160a01b0316905081565b610567610eb2565b6001600160a01b038216600081815260066020908152604091829020805460ff19168515159081179091558251938452908301527fc9219e6871f1efb578009a697784e88c6375187771bda2c8899b8ead4bbea82291015b60405180910390a15050565b6105d3610eb2565b6105dd6000610f0c565b565b600260205281600052604060002081815481106105fb57600080fd5b6000918252602090912001546001600160a01b03169150829050565b61061f610eb2565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f65104c4699f20a240a0ce199d616669f9518c0469b60b2a8c904f7cd4eb471fd9060200160405180910390a150565b3360009081526008602052604081205460ff16151590036106a757604051632e1027db60e11b815260040160405180910390fd5b60066000846001600160a01b0316635aa6e6756040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070d91906114e1565b6001600160a01b03168152602081019190915260400160009081205460ff16151590036107585760405163d0c41e7960e01b81526001600160a01b0384166004820152602401610414565b60008260018060009054906101000a90046001600160a01b03166001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d391906114fe565b6107dd9190611517565b6107e79190611517565b60015460405163b6a9f40f60e01b8152600481018390529192506000916001600160a01b039091169063b6a9f40f90602401602060405180830381865afa158015610836573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085a91906114e1565b6001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610897573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108bf9190810190611582565b90508080519060200120856001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610907573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261092f9190810190611582565b80519060200120146109bd57846001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610979573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109a19190810190611582565b81604051639102966160e01b815260040161041492919061165b565b610a29856001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2291906114e1565b8685610b7a565b5050505050565b6000610a3c8383610f5c565b90505b92915050565b6000610a5a89338a8a8a8a8a8a8a60016103ca565b9998505050505050505050565b610a7382826001610673565b5050565b610a7f610eb2565b6001600160a01b038216600081815260086020908152604091829020805460ff19168515159081179091558251938452908301527f0432d20aa3457fdf75aad100b0473a9a5a3f29275b066abbeb243dc7e0db4a4891016105bf565b6000610a3f82611037565b610aee610eb2565b6001600160a01b038116610b535760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610414565b61053281610f0c565b6001600160a01b038116600090815260026020526040812054610a3f565b6001600160a01b03821660009081526005602052604090205415610bd4576001600160a01b038216600081815260056020526040908190205490516314e3ee7560e01b815260048101929092526024820152604401610414565b80600003610bf55760405163031366db60e01b815260040160405180910390fd5b6000610c018483610f5c565b90506001600160a01b03811615610d1d57826001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c50573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c789190810190611582565b80519060200120816001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa158015610cbd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ce59190810190611582565b8051906020012003610d1d576040516318aec0af60e01b81526001600160a01b03808316600483015284166024820152604401610414565b6001600160a01b0384811660008181526002602090815260408083208054600181018255908452828420810180546001600160a01b031916968a16968717905594835260058252808320879055928252600490529081205460ff1615159003610de6576001600160a01b0385166000818152600460205260408120805460ff191660019081179091556003805491820181559091527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b03191690911790555b6001600160a01b03808516600081815260076020526040808220805460ff191660011790558051630258294160e41b8152905185948a16937f665814fc0711cd098dc48648ad2f63460a3cb758a6aca058c168d7a9067d9f389389938b936325829410926004808401939192918290030181865afa158015610e6c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e949190810190611582565b604051610ea393929190611680565b60405180910390a35050505050565b6000546001600160a01b031633146105dd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610414565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600081600003610f7657610f6f836110b7565b9050610a3f565b6001600160a01b03831660009081526002602052604081205490819003610fa1576000915050610a3f565b6000610fae600183611517565b90505b6001600160a01b0385166000908152600260205260408120805483908110610fdb57610fdb6116aa565b60009182526020808320909101546001600160a01b03168083526005909152604090912054909150859003611014579250610a3f915050565b81600003611022575061102c565b5060001901610fb1565b506000949350505050565b6001600160a01b0381166000908152600260205260408120548060000361106857611061836110b7565b9392505050565b6001600160a01b038316600090815260026020526040902061108b600183611517565b8154811061109b5761109b6116aa565b6000918252602090912001546001600160a01b03169392505050565b6040516001600160a01b0382166024820152600090819060440160408051601f198184030181529181526020820180516001600160e01b0316630e177dc760e41b1790525190915060009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169061113a9085906116c0565b600060405180830381855afa9150503d8060008114611175576040519150601f19603f3d011682016040523d82523d6000602084013e61117a565b606091505b5091509150811561102c578080602001905181019061119991906114e1565b95945050505050565b6001600160a01b038116811461053257600080fd5b60008083601f8401126111c957600080fd5b50813567ffffffffffffffff8111156111e157600080fd5b6020830191508360208285010111156111f957600080fd5b9250929050565b6000806000806000806000806000806101008b8d03121561122057600080fd5b8a3561122b816111a2565b995060208b013561123b816111a2565b985060408b013561124b816111a2565b975060608b013561125b816111a2565b965060808b013567ffffffffffffffff8082111561127857600080fd5b6112848e838f016111b7565b909850965060a08d013591508082111561129d57600080fd5b506112aa8d828e016111b7565b9b9e9a9d50989b979a969995989760c08101359660e09091013595509350505050565b6000602082840312156112df57600080fd5b8135611061816111a2565b6000602082840312156112fc57600080fd5b5035919050565b6000806040838503121561131657600080fd5b8235611321816111a2565b91506020830135801515811461133657600080fd5b809150509250929050565b6000806040838503121561135457600080fd5b823561135f816111a2565b946020939093013593505050565b60008060006060848603121561138257600080fd5b833561138d816111a2565b95602085013595506040909401359392505050565b60008060008060008060008060c0898b0312156113be57600080fd5b88356113c9816111a2565b975060208901356113d9816111a2565b965060408901356113e9816111a2565b9550606089013567ffffffffffffffff8082111561140657600080fd5b6114128c838d016111b7565b909750955060808b013591508082111561142b57600080fd5b506114388b828c016111b7565b999c989b50969995989497949560a00135949350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038a81168252898116602083015288811660408301528716606082015260e0608082018190526000906114b79083018789611451565b82810360a08401526114ca818688611451565b9150508260c08301529a9950505050505050505050565b6000602082840312156114f357600080fd5b8151611061816111a2565b60006020828403121561151057600080fd5b5051919050565b60008282101561153757634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561156d578181015183820152602001611555565b8381111561157c576000848401525b50505050565b60006020828403121561159457600080fd5b815167ffffffffffffffff808211156115ac57600080fd5b818401915084601f8301126115c057600080fd5b8151818111156115d2576115d261153c565b604051601f8201601f19908116603f011681019083821181831017156115fa576115fa61153c565b8160405282815287602084870101111561161357600080fd5b611624836020830160208801611552565b979650505050505050565b60008151808452611647816020860160208601611552565b601f01601f19169290920160200192915050565b60408152600061166e604083018561162f565b8281036020840152611199818561162f565b8381526001600160a01b03831660208201526060604082018190526000906111999083018461162f565b634e487b7160e01b600052603260045260246000fd5b600082516116d2818460208701611552565b919091019291505056fea2646970667358221220f879bf438dfafc7b952580342c996d34c4730539025a7036fc2fda8876d24a8764736f6c634300080f0033