ETH Price: $2,074.40 (+8.30%)
 

Overview

Max Total Supply

0 Custom Vault Registry Factory

Holders

0

Transfers

-
0

Market

Onchain Market Cap

-

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 0 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
RegistryFactory

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU AGPLv3 license
/**
 *Submitted for verification at Etherscan.io on 2023-06-30
*/

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.18;

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

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

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

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

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

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

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

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

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

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

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

/**
 * @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;
    }
}

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

contract Governance {
    event GovernanceTransferred(
        address indexed previousGovernance,
        address indexed newGovernance
    );

    modifier onlyGovernance() {
        _checkGovernance();
        _;
    }

    function _checkGovernance() internal view virtual {
        require(governance == msg.sender, "!governance");
    }

    // Address that can set the defualt base fee and provider
    address public governance;

    constructor(address _governance) {
        governance = _governance;
    }

    /**
     * @notice Sets a new address as the governance of the contract.
     * @dev Throws if the caller is not current governance.
     * @param _newGovernance The new governance address.
     */
    function transferGovernance(
        address _newGovernance
    ) external onlyGovernance {
        require(_newGovernance != address(0), "ZERO ADDRESS");
        address oldGovernance = governance;
        governance = _newGovernance;

        emit GovernanceTransferred(oldGovernance, _newGovernance);
    }
}

interface IFactory {
    function api_version() external view returns (string memory);

    function vault_blueprint() external view returns (address);

    function deploy_new_vault(
        ERC20 asset,
        string calldata name,
        string calldata symbol,
        address roleManager,
        uint256 profitMaxUnlockTime
    ) external returns (address);
}


contract ReleaseRegistry is Governance {
    event NewRelease(
        uint256 indexed releaseId,
        address indexed factory,
        string apiVersion
    );

    // The total number of releases that have been deployed
    uint256 public numReleases;

    // Mapping of release id starting at 0 to the address
    // of the corresponding factory for that release.
    mapping(uint256 => address) public factories;

    // Mapping of the API version for a specific release to the
    // place in the order it was released.
    mapping(string => uint256) public releaseTargets;

    constructor(address _governance) Governance(_governance) {}

    /**
     * @notice Returns the latest factory.
     * @dev Throws if no releases are registered yet.
     * @return The address of the factory for the latest release.
     */
    function latestFactory() external view returns (address) {
        return factories[numReleases - 1];
    }

    /**
     * @notice Returns the api version of the latest release.
     * @dev Throws if no releases are registered yet.
     * @return The api version of the latest release.
     */
    function latestRelease() external view returns (string memory) {
        return IFactory(factories[numReleases - 1]).api_version(); // dev: no release
    }

    /**
     * @notice Issue a new release using a deployed factory.
     * @dev Stores the factory address in `factories` and the release
     * target in `releaseTargests` with its associated API version.
     *
     *   Throws if caller isn't `governance`.
     *   Throws if the api version is the same as the previous release.
     *   Emits a `NewRelease` event.
     *
     * @param _factory The factory that will be used create new vaults.
     */
    function newRelease(address _factory) external onlyGovernance {
        // Check if the release is different from the current one
        uint256 releaseId = numReleases;

        string memory apiVersion = IFactory(_factory).api_version();

        if (releaseId > 0) {
            // Make sure this isnt the same as the last one
            require(
                keccak256(
                    bytes(IFactory(factories[releaseId - 1]).api_version())
                ) != keccak256(bytes(apiVersion)),
                "ReleaseRegistry: same api version"
            );
        }

        // Update latest release.
        factories[releaseId] = _factory;

        // Set the api to the target.
        releaseTargets[apiVersion] = releaseId;

        // Increase our number of releases.
        numReleases = releaseId + 1;

        // Log the release for external listeners
        emit NewRelease(releaseId, _factory, apiVersion);
    }
}

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

    function api_version() external view returns (string memory);
}

interface IStrategy {
    function asset() external view returns (address);

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

contract Registry is Governance {
    event NewEndorsedVault(
        address indexed vault,
        address indexed asset,
        uint256 releaseVersion
    );

    event NewEndorsedStrategy(
        address indexed strategy,
        address indexed asset,
        uint256 releaseVersion
    );

    // Struct stored for every endorsed vault or strategy for
    // off chain use to easily retreive info.
    struct Info {
        // The token thats being used.
        address asset;
        // The release number corresponding to the release registries version.
        uint256 releaseVersion;
        // Time when the vault was deployed for easier indexing.
        uint256 deploymentTimeStamp;
        // String so that mangement to tag a vault with any info for FE's.
        string tag;
    }

    // Custom name for this Registry.
    string public name;

    // Address used to get the specific versions from.
    address public immutable releaseRegistry;

    // Array of all tokens used as the underlying.
    address[] public assets;

    // Mapping to check if a specific `asset` has a vault.
    mapping(address => bool) public assetIsUsed;

    // asset => array of all endorsed vaults.
    mapping(address => address[]) internal _endorsedVaults;

    // asset => array of all endorsed strategies.
    mapping(address => address[]) internal _endorsedStrategies;

    // asset => release number => array of endorsed vaults
    mapping(address => mapping(uint256 => address[]))
        internal _endorsedVaultsByVersion;

    // asset => release number => array of endorsed strategies
    mapping(address => mapping(uint256 => address[]))
        internal _endorsedStrategiesByVersion;

    // vault/strategy address => Info stuct.
    mapping(address => Info) public info;

    /**
     * @param _governance Address to set as owner of the Registry.
     * @param _name The custom string for this custom registry to be called.
     * @param _releaseRegistry The Permisionless releaseRegistry to deploy vaults through.
     */
    constructor(
        address _governance,
        string memory _name,
        address _releaseRegistry
    ) Governance(_governance) {
        // Set name.
        name = _name;
        // Set releaseRegistry.
        releaseRegistry = _releaseRegistry;
    }

    /**
     * @notice Returns the total numer of assets being used as the underlying.
     * @return The amount of assets.
     */
    function numAssets() external view returns (uint256) {
        return assets.length;
    }

    /**
     * @notice Get the full array of tokens being used.
     * @return The full array of underlying tokens being used/.
     */
    function getAssets() external view returns (address[] memory) {
        return assets;
    }

    /**
     * @notice The amount of endorsed vaults for a specific token.
     * @return The amount of endorsed vaults.
     */
    function numEndorsedVaults(address _asset) public view returns (uint256) {
        return _endorsedVaults[_asset].length;
    }

    /**
     * @notice The amount of endorsed strategies for a specific token.
     * @return The amount of endorsed strategies.
     */
    function numEndorsedStrategies(
        address _asset
    ) public view returns (uint256) {
        return _endorsedStrategies[_asset].length;
    }

    /**
     * @notice Get the array of vaults endorsed for an `_asset`.
     * @param _asset The underlying token used by the vaults.
     * @return The endorsed vaults.
     */
    function getEndorsedVaults(
        address _asset
    ) external view returns (address[] memory) {
        return _endorsedVaults[_asset];
    }

    /**
     * @notice Get the array of strategies endorsed for an `_asset`.
     * @param _asset The underlying token used by the strategies.
     * @return The endorsed strategies.
     */
    function getEndorsedStrategies(
        address _asset
    ) external view returns (address[] memory) {
        return _endorsedStrategies[_asset];
    }

    /**
     * @notice Get the number of endorsed vaults for an asset of a specific API version.
     * @return The amount of endorsed vaults.
     */
    function numEndorsedVaultsByVersion(
        address _asset,
        uint256 _versionDelta
    ) public view returns (uint256) {
        uint256 version = ReleaseRegistry(releaseRegistry).numReleases() -
            1 -
            _versionDelta;
        return _endorsedVaultsByVersion[_asset][version].length;
    }

    /**
     * @notice Get the number of endorsed strategies for an asset of a specific API version.
     * @return The amount of endorsed strategies.
     */
    function numEndorsedStrategiesByVersion(
        address _asset,
        uint256 _versionDelta
    ) public view returns (uint256) {
        uint256 version = ReleaseRegistry(releaseRegistry).numReleases() -
            1 -
            _versionDelta;
        return _endorsedStrategiesByVersion[_asset][version].length;
    }

    /**
     * @notice Get the array of vaults endorsed for an `_asset` of a specific API.
     * @param _asset The underlying token used by the vaults.
     * @param _versionDelta The difference from the most recent API version.
     * @return The endorsed vaults.
     */
    function getEndorsedVaultsByVersion(
        address _asset,
        uint256 _versionDelta
    ) public view returns (address[] memory) {
        uint256 version = ReleaseRegistry(releaseRegistry).numReleases() -
            1 -
            _versionDelta;
        return _endorsedVaultsByVersion[_asset][version];
    }

    /**
     * @notice Get the array of strategies endorsed for an `_asset` of a specific API.
     * @param _asset The underlying token used by the strategies.
     * @param _versionDelta The difference from the most recent API version.
     * @return The endorsed strategies.
     */
    function getEndorsedStrategiesByVersion(
        address _asset,
        uint256 _versionDelta
    ) public view returns (address[] memory) {
        uint256 version = ReleaseRegistry(releaseRegistry).numReleases() -
            1 -
            _versionDelta;
        return _endorsedStrategiesByVersion[_asset][version];
    }

    /**
     * @notice Get all endorsed vaults deployed using the Registry.
     * @dev This will return a nested array of all vaults deployed
     * seperated by their underlying asset.
     *
     * This is only meant for off chain viewing and should not be used during any
     * on chain tx's.
     *
     * @return allEndorsedVaults A nested array containing all vaults.
     */
    function getAllEndorsedVaults()
        external
        view
        returns (address[][] memory allEndorsedVaults)
    {
        address[] memory allAssets = assets;
        uint256 length = assets.length;

        allEndorsedVaults = new address[][](length);
        for (uint256 i; i < length; ++i) {
            allEndorsedVaults[i] = _endorsedVaults[allAssets[i]];
        }
    }

    /**
     * @notice Get all strategies endorsed through this registry.
     * @dev This will return a nested array of all endorsed strategies
     * seperated by their underlying asset.
     *
     * This is only meant for off chain viewing and should not be used during any
     * on chain tx's.
     *
     * @return allEndorsedStrategies A nested array containing all strategies.
     */
    function getAllEndorsedStrategies()
        external
        view
        returns (address[][] memory allEndorsedStrategies)
    {
        address[] memory allAssets = assets;
        uint256 length = assets.length;

        allEndorsedStrategies = new address[][](length);
        for (uint256 i; i < length; ++i) {
            allEndorsedStrategies[i] = _endorsedStrategies[allAssets[i]];
        }
    }

    /**
     * @notice
     *    Create a new vault for the given asset using a given release in the
     *     release registry.
     * @dev
     *   Throws if caller isn't `owner`.
     *   Throws if no releases are registered yet.
     *   Emits a `NewEndorsedVault` event.
     * @param _asset The asset that may be deposited into the new Vault.
     * @param _name Specify a custom Vault name. .
     * @param _symbol Specify a custom Vault symbol name.
     * @param _roleManager The address authorized for guardian interactions in the new Vault.
     * @param _profitMaxUnlockTime The time strategy profits will unlock over.
     * @param _releaseDelta The number of releases prior to the latest to use as a target. NOTE: Set to 0 for latest.
     * @return _vault address of the newly-deployed vault
     */
    function newEndorsedVault(
        address _asset,
        string memory _name,
        string memory _symbol,
        address _roleManager,
        uint256 _profitMaxUnlockTime,
        uint256 _releaseDelta
    ) public onlyGovernance returns (address _vault) {
        // Get the target release based on the delta given.
        uint256 _releaseTarget = ReleaseRegistry(releaseRegistry)
            .numReleases() -
            1 -
            _releaseDelta;

        // Get the factory address for that specific Api version.
        address factory = ReleaseRegistry(releaseRegistry).factories(
            _releaseTarget
        );

        // Make sure we got an actual factory
        require(factory != address(0), "Registry: unknown release");

        // Deploy New vault.
        _vault = IFactory(factory).deploy_new_vault(
            ERC20(_asset),
            _name,
            _symbol,
            _roleManager,
            _profitMaxUnlockTime
        );

        // Register the vault with this Registry
        _registerVault(_vault, _asset, _releaseTarget, block.timestamp);
    }

    /**
     * @notice
     *    Adds an existing vault to the list of "endorsed" vaults for that asset.
     * @dev
     *    Throws if caller isn't `owner`.
     *    Throws if no releases are registered yet.
     *    Throws if `vault`'s api version does not match the release specified.
     *    Emits a `NewEndorsedVault` event.
     * @param _vault The vault that will be endorsed by the Registry.
     * @param _releaseDelta Specify the number of releases prior to the latest to use as a target.
     * @param _deploymentTimestamp The timestamp of when the vault was deployed for FE use.
     */
    function endorseVault(
        address _vault,
        uint256 _releaseDelta,
        uint256 _deploymentTimestamp
    ) public onlyGovernance {
        // Will underflow if no releases created yet, or targeting prior to release history
        uint256 releaseTarget = ReleaseRegistry(releaseRegistry).numReleases() -
            1 -
            _releaseDelta; // dev: no releases

        // Get the API version for the target specified
        string memory apiVersion = IFactory(
            ReleaseRegistry(releaseRegistry).factories(releaseTarget)
        ).api_version();

        require(
            keccak256(bytes(IVault(_vault).api_version())) ==
                keccak256(bytes((apiVersion))),
            "Wrong API Version"
        );

        // Add to the end of the list of vaults for asset
        _registerVault(
            _vault,
            IVault(_vault).asset(),
            releaseTarget,
            _deploymentTimestamp
        );
    }

    /**
     * @notice Endorse an already deployed vault.
     * @dev To be used with default values for `_releaseDelta` and
     * `_deploymentTimestamp`.
     *
     * @param _vault Address of the vault to endorse.
     */
    function endorseVault(address _vault) external {
        endorseVault(_vault, 0, 0);
    }

    function _registerVault(
        address _vault,
        address _asset,
        uint256 _releaseTarget,
        uint256 _deploymentTimestamp
    ) internal {
        // Add to the endorsed vaults arrays.
        _endorsedVaults[_asset].push(_vault);
        _endorsedVaultsByVersion[_asset][_releaseTarget].push(_vault);

        // Set the Info struct for this vault
        info[_vault] = Info({
            asset: _asset,
            releaseVersion: _releaseTarget,
            deploymentTimeStamp: _deploymentTimestamp,
            tag: ""
        });

        if (!assetIsUsed[_asset]) {
            // We have a new asset to add
            assets.push(_asset);
            assetIsUsed[_asset] = true;
        }

        emit NewEndorsedVault(_vault, _asset, _releaseTarget);
    }

    /**
     * @notice
     *    Adds an existing strategy to the list of "endorsed" strategies for that asset.
     * @dev
     *    Throws if caller isn't `owner`.
     *    Throws if no releases are registered yet.
     *    Throws if `strategies`'s api version does not match the release specified.
     *    Emits a `NewEndorsedStrategy` event.
     * @param _strategy The strategy that will be endorsed by the Registry.
     * @param _releaseDelta Specify the number of releases prior to the latest to use as a target.
     * @param _deploymentTimestamp The timestamp of when the strategy was deployed for FE use.
     */
    function endorseStrategy(
        address _strategy,
        uint256 _releaseDelta,
        uint256 _deploymentTimestamp
    ) public onlyGovernance {
        // Will underflow if no releases created yet, or targeting prior to release history
        uint256 _releaseTarget = ReleaseRegistry(releaseRegistry)
            .numReleases() -
            1 -
            _releaseDelta; // dev: no releases

        // Get the API version for this release
        string memory apiVersion = IFactory(
            ReleaseRegistry(releaseRegistry).factories(_releaseTarget)
        ).api_version();

        // Make sure the API versions match
        require(
            keccak256(bytes((IStrategy(_strategy).apiVersion()))) ==
                keccak256(bytes((apiVersion))),
            "Wrong API Version"
        );

        address _asset = IStrategy(_strategy).asset();

        _endorsedStrategies[_asset].push(_strategy);
        _endorsedStrategiesByVersion[_asset][_releaseTarget].push(_strategy);

        info[_strategy] = Info({
            asset: _asset,
            releaseVersion: _releaseTarget,
            deploymentTimeStamp: _deploymentTimestamp,
            tag: ""
        });

        if (!assetIsUsed[_asset]) {
            // We have a new asset to add
            assets.push(_asset);
            assetIsUsed[_asset] = true;
        }

        emit NewEndorsedStrategy(_strategy, _asset, _releaseTarget);
    }

    /**
     * @notice Endorse an already deployed strategy.
     * @dev To be used with default values for `_releaseDelta` and
     * `_deploymentTimestamp`.
     *
     * @param _strategy Address of the strategy to endorse.
     */
    function endorseStrategy(address _strategy) external {
        endorseStrategy(_strategy, 0, 0);
    }

    /**
     * @notice Tag a vault with a specific string.
     * @dev This is available to governance to tag any vault or strategy
     * on chain if desired to arbitrarily classify any vaults.
     *   i.e. Certain credit ratings ("AAA") / Vault status ("Shutdown") etc.
     *
     * @param _vault Address of the vault or strategy to tag.
     * @param _tag The string to tag the vault or strategy with.
     */
    function tagVault(
        address _vault,
        string memory _tag
    ) external onlyGovernance {
        require(info[_vault].asset != address(0), "!Endorsed");
        info[_vault].tag = _tag;
    }
}


contract RegistryFactory {
    event NewRegistry(
        address indexed newRegistry,
        address indexed governance,
        string name
    );

    address public immutable releaseRegistry;

    constructor(address _releaseRegistry) {
        releaseRegistry = _releaseRegistry;
    }

    function name() external pure returns (string memory) {
        return "Custom Vault Registry Factory";
    }

    function createNewRegistry(string memory _name) external returns (address) {
        return createNewRegistry(msg.sender, _name);
    }

    function createNewRegistry(
        address _governance,
        string memory _name
    ) public returns (address) {
        Registry newRegistry = new Registry(
            _governance,
            _name,
            releaseRegistry
        );

        emit NewRegistry(address(newRegistry), _governance, _name);
        return address(newRegistry);
    }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_releaseRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newRegistry","type":"address"},{"indexed":true,"internalType":"address","name":"governance","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NewRegistry","type":"event"},{"inputs":[{"internalType":"address","name":"_governance","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"name":"createNewRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"}],"name":"createNewRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"releaseRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60a060405234801561001057600080fd5b5060405161286038038061286083398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b6080516127cf61009160003960008181609e015261010501526127cf6000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806306fdde031461005157806319ee073e14610099578063aef72f9c146100d8578063e2eb36ee146100eb575b600080fd5b604080518082018252601d81527f437573746f6d205661756c7420526567697374727920466163746f7279000000602082015290516100909190610212565b60405180910390f35b6100c07f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610090565b6100c06100e63660046102cf565b6100fe565b6100c06100f936600461032b565b6101ad565b60008083837f0000000000000000000000000000000000000000000000000000000000000000604051610130906101bf565b61013c93929190610368565b604051809103906000f080158015610158573d6000803e3d6000fd5b509050836001600160a01b0316816001600160a01b03167f9ae0c36b9499b323d42aa4b4f00f0fb81394b12086a416e9fdf8e9889e40a2f88560405161019e9190610212565b60405180910390a39392505050565b60006101b933836100fe565b92915050565b6123fc8061039e83390190565b6000815180845260005b818110156101f2576020818501810151868301820152016101d6565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061022560208301846101cc565b9392505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261025357600080fd5b813567ffffffffffffffff8082111561026e5761026e61022c565b604051601f8301601f19908116603f011681019082821181831017156102965761029661022c565b816040528381528660208588010111156102af57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156102e257600080fd5b82356001600160a01b03811681146102f957600080fd5b9150602083013567ffffffffffffffff81111561031557600080fd5b61032185828601610242565b9150509250929050565b60006020828403121561033d57600080fd5b813567ffffffffffffffff81111561035457600080fd5b61036084828501610242565b949350505050565b600060018060a01b0380861683526060602084015261038a60608401866101cc565b915080841660408401525094935050505056fe60a06040523480156200001157600080fd5b50604051620023fc380380620023fc8339810160408190526200003491620000a6565b600080546001600160a01b0319166001600160a01b03851617905560016200005d838262000230565b506001600160a01b031660805250620002fc9050565b80516001600160a01b03811681146200008b57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600060608486031215620000bc57600080fd5b620000c78462000073565b602085810151919450906001600160401b0380821115620000e757600080fd5b818701915087601f830112620000fc57600080fd5b81518181111562000111576200011162000090565b604051601f8201601f19908116603f011681019083821181831017156200013c576200013c62000090565b816040528281528a868487010111156200015557600080fd5b600093505b828410156200017957848401860151818501870152928501926200015a565b6000868483010152809750505050505050620001986040850162000073565b90509250925092565b600181811c90821680620001b657607f821691505b602082108103620001d757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200022b57600081815260208120601f850160051c81016020861015620002065750805b601f850160051c820191505b81811015620002275782815560010162000212565b5050505b505050565b81516001600160401b038111156200024c576200024c62000090565b62000264816200025d8454620001a1565b84620001dd565b602080601f8311600181146200029c5760008415620002835750858301515b600019600386901b1c1916600185901b17855562000227565b600085815260208120601f198616915b82811015620002cd57888601518255948401946001909101908401620002ac565b5085821015620002ec5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805161209e6200035e6000396000818161022e0152818161060c015281816106c401528181610bab01528181610d4a015281816110870152818161113f015281816112a20152818161135a0152818161155f015261167b015261209e6000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80635de4a556116100de578063a241861211610097578063ac01762a11610071578063ac01762a14610362578063b2c6161c14610395578063cf35bdd0146103be578063d38bfff4146103d157600080fd5b8063a241861214610334578063a46fe83b14610347578063ab47098a1461034f57600080fd5b80635de4a556146102d857806360bd68f8146102eb57806367e4ac2c146102fe57806370df8ba7146103065780637be7b20b1461030e578063931074ba1461032157600080fd5b80631895cd51116101305780631895cd511461021657806319ee073e1461022957806329b2e0c6146102685780633e3c7b601461027b57806353d2e949146102b25780635aa6e675146102c557600080fd5b806306a70f3d1461017857806306fdde03146101965780630724b07b146101ab5780630a225ecf146101c05780630aae7a6b146101d3578063153a5b16146101f6575b600080fd5b6101806103e4565b60405161018d91906119f4565b60405180910390f35b61019e61056f565b60405161018d9190611ad7565b6101be6101b9366004611b06565b6105fd565b005b6101be6101ce366004611b3b565b610a60565b6101e66101e1366004611b3b565b610a6f565b60405161018d9493929190611b58565b610209610204366004611b3b565b610b2c565b60405161018d9190611b8f565b610209610224366004611bdc565b610ba2565b6102507f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161018d565b6101be610276366004611b3b565b610cc2565b6102a4610289366004611b3b565b6001600160a01b031660009081526005602052604090205490565b60405190815260200161018d565b6102096102c0366004611b3b565b610cce565b600054610250906001600160a01b031681565b6102a46102e6366004611bdc565b610d42565b6101be6102f9366004611ccd565b610e0a565b610209610e8f565b610180610ef1565b61025061031c366004611d1d565b611076565b6101be61032f366004611b06565b611293565b610209610342366004611bdc565b611556565b6002546102a4565b6102a461035d366004611bdc565b611673565b610385610370366004611b3b565b60036020526000908152604090205460ff1681565b604051901515815260200161018d565b6102a46103a3366004611b3b565b6001600160a01b031660009081526004602052604090205490565b6102506103cc366004611db8565b61173b565b6101be6103df366004611b3b565b611765565b60606000600280548060200260200160405190810160405280929190818152602001828054801561043e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610420575b5050600254939450839250505067ffffffffffffffff81111561046357610463611c08565b60405190808252806020026020018201604052801561049657816020015b60608152602001906001900390816104815790505b50925060005b8181101561056957600560008483815181106104ba576104ba611dd1565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561053657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610518575b505050505084828151811061054d5761054d611dd1565b60200260200101819052508061056290611dfd565b905061049c565b50505090565b6001805461057c90611e16565b80601f01602080910402602001604051908101604052809291908181526020018280546105a890611e16565b80156105f55780601f106105ca576101008083540402835291602001916105f5565b820191906000526020600020905b8154815290600101906020018083116105d857829003601f168201915b505050505081565b610605611802565b60008260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610668573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068c9190611e50565b6106969190611e69565b6106a09190611e69565b6040516319c8e0f160e21b8152600481018290529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063672383c490602401602060405180830381865afa15801561070b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072f9190611e7c565b6001600160a01b031663eec400236040518163ffffffff1660e01b8152600401600060405180830381865afa15801561076c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107949190810190611e99565b90508080519060200120856001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa1580156107dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108049190810190611e99565b80519060200120146108515760405162461bcd60e51b81526020600482015260116024820152702bb937b7339020a824902b32b939b4b7b760791b60448201526064015b60405180910390fd5b6000856001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610891573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b59190611e7c565b6001600160a01b0380821660008181526005602090815260408083208054600181810183559185528385200180548e88166001600160a01b03199182168117909255868652600785528386208c875285528386208054808501825590875285872001805482168317905583516080810185529687528685018c81528785018e81528551808801875288815260608a019081529388526008909652939095208651815498169790951696909617845590519083015551600282015591519293509160038201906109849082611f5e565b5050506001600160a01b03811660009081526003602052604090205460ff16610a0b576002805460018082019092557f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b0384169081179091556000908152600360205260409020805460ff191690911790555b806001600160a01b0316866001600160a01b03167f2ab8c6c9129a30daa2d2add32ab462e1b35dd8fc42a473ea04380a25b5cc9d3a85604051610a5091815260200190565b60405180910390a3505050505050565b610a6c816000806105fd565b50565b60086020526000908152604090208054600182015460028301546003840180546001600160a01b03909416949293919291610aa990611e16565b80601f0160208091040260200160405190810160405280929190818152602001828054610ad590611e16565b8015610b225780601f10610af757610100808354040283529160200191610b22565b820191906000526020600020905b815481529060010190602001808311610b0557829003601f168201915b5050505050905084565b6001600160a01b038116600090815260056020908152604091829020805483518184028101840190945280845260609392830182828015610b9657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b78575b50505050509050919050565b606060008260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2b9190611e50565b610c359190611e69565b610c3f9190611e69565b6001600160a01b03851660009081526006602090815260408083208484528252918290208054835181840281018401909452808452939450919290830182828015610cb357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c95575b50505050509150505b92915050565b610a6c81600080611293565b6001600160a01b038116600090815260046020908152604091829020805483518184028101840190945280845260609392830182828015610b96576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610b785750505050509050919050565b6000808260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dca9190611e50565b610dd49190611e69565b610dde9190611e69565b6001600160a01b0385166000908152600660209081526040808320938352929052205491505092915050565b610e12611802565b6001600160a01b0382811660009081526008602052604090205416610e655760405162461bcd60e51b815260206004820152600960248201526808515b991bdc9cd95960ba1b6044820152606401610848565b6001600160a01b0382166000908152600860205260409020600301610e8a8282611f5e565b505050565b60606002805480602002602001604051908101604052809291908181526020018280548015610ee757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ec9575b5050505050905090565b606060006002805480602002602001604051908101604052809291908181526020018280548015610f4b57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f2d575b5050600254939450839250505067ffffffffffffffff811115610f7057610f70611c08565b604051908082528060200260200182016040528015610fa357816020015b6060815260200190600190039081610f8e5790505b50925060005b818110156105695760046000848381518110610fc757610fc7611dd1565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561104357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611025575b505050505084828151811061105a5761105a611dd1565b60200260200101819052508061106f90611dfd565b9050610fa9565b6000611080611802565b60008260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111079190611e50565b6111119190611e69565b61111b9190611e69565b6040516319c8e0f160e21b8152600481018290529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063672383c490602401602060405180830381865afa158015611186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111aa9190611e7c565b90506001600160a01b0381166112025760405162461bcd60e51b815260206004820152601960248201527f52656769737472793a20756e6b6e6f776e2072656c65617365000000000000006044820152606401610848565b60405163b4aeee7760e01b81526001600160a01b0382169063b4aeee7790611236908c908c908c908c908c9060040161201e565b6020604051808303816000875af1158015611255573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112799190611e7c565b9250611287838a844261184c565b50509695505050505050565b61129b611802565b60008260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113229190611e50565b61132c9190611e69565b6113369190611e69565b6040516319c8e0f160e21b8152600481018290529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063672383c490602401602060405180830381865afa1580156113a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c59190611e7c565b6001600160a01b031663eec400236040518163ffffffff1660e01b8152600401600060405180830381865afa158015611402573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261142a9190810190611e99565b90508080519060200120856001600160a01b031663eec400236040518163ffffffff1660e01b8152600401600060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261149a9190810190611e99565b80519060200120146114e25760405162461bcd60e51b81526020600482015260116024820152702bb937b7339020a824902b32b939b4b7b760791b6044820152606401610848565b61154f85866001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611524573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115489190611e7c565b848661184c565b5050505050565b606060008260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115df9190611e50565b6115e99190611e69565b6115f39190611e69565b6001600160a01b03851660009081526007602090815260408083208484528252918290208054835181840281018401909452808452939450919290830182828015610cb3576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610c9557505050505091505092915050565b6000808260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116fb9190611e50565b6117059190611e69565b61170f9190611e69565b6001600160a01b0385166000908152600760209081526040808320938352929052205491505092915050565b6002818154811061174b57600080fd5b6000918252602090912001546001600160a01b0316905081565b61176d611802565b6001600160a01b0381166117b25760405162461bcd60e51b815260206004820152600c60248201526b5a45524f204144445245535360a01b6044820152606401610848565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce809190a35050565b6000546001600160a01b0316331461184a5760405162461bcd60e51b815260206004820152600b60248201526a21676f7665726e616e636560a81b6044820152606401610848565b565b6001600160a01b0380841660008181526004602090815260408083208054600181810183559185528385200180548b88166001600160a01b03199182168117909255868652600685528386208a875285528386208054808501825590875285872001805482168317905583516080810185529687528685018a81528785018a81528551808801875288815260608a01908152938852600890965293909520865181549816979095169690961784559051908301555160028201559151909190600382019061191a9082611f5e565b5050506001600160a01b03831660009081526003602052604090205460ff166119a1576002805460018082019092557f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b0386169081179091556000908152600360205260409020805460ff191690911790555b826001600160a01b0316846001600160a01b03167f5bf19cf6c9f6c9210bc8cfecb4fda8057ebe0c41e300b60c5efa3de7f98f2f35846040516119e691815260200190565b60405180910390a350505050565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b83811015611a7957888603603f19018552825180518088529088019088880190845b81811015611a635783516001600160a01b03168352928a0192918a0191600101611a3e565b5090975050509386019391860191600101611a1c565b509398975050505050505050565b60005b83811015611aa2578181015183820152602001611a8a565b50506000910152565b60008151808452611ac3816020860160208601611a87565b601f01601f19169290920160200192915050565b602081526000611aea6020830184611aab565b9392505050565b6001600160a01b0381168114610a6c57600080fd5b600080600060608486031215611b1b57600080fd5b8335611b2681611af1565b95602085013595506040909401359392505050565b600060208284031215611b4d57600080fd5b8135611aea81611af1565b60018060a01b0385168152836020820152826040820152608060608201526000611b856080830184611aab565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611bd05783516001600160a01b031683529284019291840191600101611bab565b50909695505050505050565b60008060408385031215611bef57600080fd5b8235611bfa81611af1565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611c4757611c47611c08565b604052919050565b600067ffffffffffffffff821115611c6957611c69611c08565b50601f01601f191660200190565b600082601f830112611c8857600080fd5b8135611c9b611c9682611c4f565b611c1e565b818152846020838601011115611cb057600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215611ce057600080fd5b8235611ceb81611af1565b9150602083013567ffffffffffffffff811115611d0757600080fd5b611d1385828601611c77565b9150509250929050565b60008060008060008060c08789031215611d3657600080fd5b8635611d4181611af1565b9550602087013567ffffffffffffffff80821115611d5e57600080fd5b611d6a8a838b01611c77565b96506040890135915080821115611d8057600080fd5b50611d8d89828a01611c77565b9450506060870135611d9e81611af1565b9598949750929560808101359460a0909101359350915050565b600060208284031215611dca57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611e0f57611e0f611de7565b5060010190565b600181811c90821680611e2a57607f821691505b602082108103611e4a57634e487b7160e01b600052602260045260246000fd5b50919050565b600060208284031215611e6257600080fd5b5051919050565b81810381811115610cbc57610cbc611de7565b600060208284031215611e8e57600080fd5b8151611aea81611af1565b600060208284031215611eab57600080fd5b815167ffffffffffffffff811115611ec257600080fd5b8201601f81018413611ed357600080fd5b8051611ee1611c9682611c4f565b818152856020838501011115611ef657600080fd5b611f07826020830160208601611a87565b95945050505050565b601f821115610e8a57600081815260208120601f850160051c81016020861015611f375750805b601f850160051c820191505b81811015611f5657828155600101611f43565b505050505050565b815167ffffffffffffffff811115611f7857611f78611c08565b611f8c81611f868454611e16565b84611f10565b602080601f831160018114611fc15760008415611fa95750858301515b600019600386901b1c1916600185901b178555611f56565b600085815260208120601f198616915b82811015611ff057888601518255948401946001909101908401611fd1565b508582101561200e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060018060a01b03808816835260a0602084015261204060a0840188611aab565b83810360408501526120528188611aab565b959091166060840152505060800152939250505056fea2646970667358221220e5282f2e3494da6a357e7858fe978c235347eac50644203cafed74de11d94b6664736f6c63430008120033a2646970667358221220c86c2a47263cce3f4a2cee6fcef97ff1d3e68e9d1545680d19a988ea5e5147ce64736f6c634300081200330000000000000000000000005a6e1ecc767d949d6da74e76b05dbb4870488ef6

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806306fdde031461005157806319ee073e14610099578063aef72f9c146100d8578063e2eb36ee146100eb575b600080fd5b604080518082018252601d81527f437573746f6d205661756c7420526567697374727920466163746f7279000000602082015290516100909190610212565b60405180910390f35b6100c07f0000000000000000000000005a6e1ecc767d949d6da74e76b05dbb4870488ef681565b6040516001600160a01b039091168152602001610090565b6100c06100e63660046102cf565b6100fe565b6100c06100f936600461032b565b6101ad565b60008083837f0000000000000000000000005a6e1ecc767d949d6da74e76b05dbb4870488ef6604051610130906101bf565b61013c93929190610368565b604051809103906000f080158015610158573d6000803e3d6000fd5b509050836001600160a01b0316816001600160a01b03167f9ae0c36b9499b323d42aa4b4f00f0fb81394b12086a416e9fdf8e9889e40a2f88560405161019e9190610212565b60405180910390a39392505050565b60006101b933836100fe565b92915050565b6123fc8061039e83390190565b6000815180845260005b818110156101f2576020818501810151868301820152016101d6565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061022560208301846101cc565b9392505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261025357600080fd5b813567ffffffffffffffff8082111561026e5761026e61022c565b604051601f8301601f19908116603f011681019082821181831017156102965761029661022c565b816040528381528660208588010111156102af57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080604083850312156102e257600080fd5b82356001600160a01b03811681146102f957600080fd5b9150602083013567ffffffffffffffff81111561031557600080fd5b61032185828601610242565b9150509250929050565b60006020828403121561033d57600080fd5b813567ffffffffffffffff81111561035457600080fd5b61036084828501610242565b949350505050565b600060018060a01b0380861683526060602084015261038a60608401866101cc565b915080841660408401525094935050505056fe60a06040523480156200001157600080fd5b50604051620023fc380380620023fc8339810160408190526200003491620000a6565b600080546001600160a01b0319166001600160a01b03851617905560016200005d838262000230565b506001600160a01b031660805250620002fc9050565b80516001600160a01b03811681146200008b57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600060608486031215620000bc57600080fd5b620000c78462000073565b602085810151919450906001600160401b0380821115620000e757600080fd5b818701915087601f830112620000fc57600080fd5b81518181111562000111576200011162000090565b604051601f8201601f19908116603f011681019083821181831017156200013c576200013c62000090565b816040528281528a868487010111156200015557600080fd5b600093505b828410156200017957848401860151818501870152928501926200015a565b6000868483010152809750505050505050620001986040850162000073565b90509250925092565b600181811c90821680620001b657607f821691505b602082108103620001d757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200022b57600081815260208120601f850160051c81016020861015620002065750805b601f850160051c820191505b81811015620002275782815560010162000212565b5050505b505050565b81516001600160401b038111156200024c576200024c62000090565b62000264816200025d8454620001a1565b84620001dd565b602080601f8311600181146200029c5760008415620002835750858301515b600019600386901b1c1916600185901b17855562000227565b600085815260208120601f198616915b82811015620002cd57888601518255948401946001909101908401620002ac565b5085821015620002ec5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805161209e6200035e6000396000818161022e0152818161060c015281816106c401528181610bab01528181610d4a015281816110870152818161113f015281816112a20152818161135a0152818161155f015261167b015261209e6000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80635de4a556116100de578063a241861211610097578063ac01762a11610071578063ac01762a14610362578063b2c6161c14610395578063cf35bdd0146103be578063d38bfff4146103d157600080fd5b8063a241861214610334578063a46fe83b14610347578063ab47098a1461034f57600080fd5b80635de4a556146102d857806360bd68f8146102eb57806367e4ac2c146102fe57806370df8ba7146103065780637be7b20b1461030e578063931074ba1461032157600080fd5b80631895cd51116101305780631895cd511461021657806319ee073e1461022957806329b2e0c6146102685780633e3c7b601461027b57806353d2e949146102b25780635aa6e675146102c557600080fd5b806306a70f3d1461017857806306fdde03146101965780630724b07b146101ab5780630a225ecf146101c05780630aae7a6b146101d3578063153a5b16146101f6575b600080fd5b6101806103e4565b60405161018d91906119f4565b60405180910390f35b61019e61056f565b60405161018d9190611ad7565b6101be6101b9366004611b06565b6105fd565b005b6101be6101ce366004611b3b565b610a60565b6101e66101e1366004611b3b565b610a6f565b60405161018d9493929190611b58565b610209610204366004611b3b565b610b2c565b60405161018d9190611b8f565b610209610224366004611bdc565b610ba2565b6102507f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161018d565b6101be610276366004611b3b565b610cc2565b6102a4610289366004611b3b565b6001600160a01b031660009081526005602052604090205490565b60405190815260200161018d565b6102096102c0366004611b3b565b610cce565b600054610250906001600160a01b031681565b6102a46102e6366004611bdc565b610d42565b6101be6102f9366004611ccd565b610e0a565b610209610e8f565b610180610ef1565b61025061031c366004611d1d565b611076565b6101be61032f366004611b06565b611293565b610209610342366004611bdc565b611556565b6002546102a4565b6102a461035d366004611bdc565b611673565b610385610370366004611b3b565b60036020526000908152604090205460ff1681565b604051901515815260200161018d565b6102a46103a3366004611b3b565b6001600160a01b031660009081526004602052604090205490565b6102506103cc366004611db8565b61173b565b6101be6103df366004611b3b565b611765565b60606000600280548060200260200160405190810160405280929190818152602001828054801561043e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610420575b5050600254939450839250505067ffffffffffffffff81111561046357610463611c08565b60405190808252806020026020018201604052801561049657816020015b60608152602001906001900390816104815790505b50925060005b8181101561056957600560008483815181106104ba576104ba611dd1565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561053657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610518575b505050505084828151811061054d5761054d611dd1565b60200260200101819052508061056290611dfd565b905061049c565b50505090565b6001805461057c90611e16565b80601f01602080910402602001604051908101604052809291908181526020018280546105a890611e16565b80156105f55780601f106105ca576101008083540402835291602001916105f5565b820191906000526020600020905b8154815290600101906020018083116105d857829003601f168201915b505050505081565b610605611802565b60008260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610668573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068c9190611e50565b6106969190611e69565b6106a09190611e69565b6040516319c8e0f160e21b8152600481018290529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063672383c490602401602060405180830381865afa15801561070b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072f9190611e7c565b6001600160a01b031663eec400236040518163ffffffff1660e01b8152600401600060405180830381865afa15801561076c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107949190810190611e99565b90508080519060200120856001600160a01b031663258294106040518163ffffffff1660e01b8152600401600060405180830381865afa1580156107dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108049190810190611e99565b80519060200120146108515760405162461bcd60e51b81526020600482015260116024820152702bb937b7339020a824902b32b939b4b7b760791b60448201526064015b60405180910390fd5b6000856001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610891573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b59190611e7c565b6001600160a01b0380821660008181526005602090815260408083208054600181810183559185528385200180548e88166001600160a01b03199182168117909255868652600785528386208c875285528386208054808501825590875285872001805482168317905583516080810185529687528685018c81528785018e81528551808801875288815260608a019081529388526008909652939095208651815498169790951696909617845590519083015551600282015591519293509160038201906109849082611f5e565b5050506001600160a01b03811660009081526003602052604090205460ff16610a0b576002805460018082019092557f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b0384169081179091556000908152600360205260409020805460ff191690911790555b806001600160a01b0316866001600160a01b03167f2ab8c6c9129a30daa2d2add32ab462e1b35dd8fc42a473ea04380a25b5cc9d3a85604051610a5091815260200190565b60405180910390a3505050505050565b610a6c816000806105fd565b50565b60086020526000908152604090208054600182015460028301546003840180546001600160a01b03909416949293919291610aa990611e16565b80601f0160208091040260200160405190810160405280929190818152602001828054610ad590611e16565b8015610b225780601f10610af757610100808354040283529160200191610b22565b820191906000526020600020905b815481529060010190602001808311610b0557829003601f168201915b5050505050905084565b6001600160a01b038116600090815260056020908152604091829020805483518184028101840190945280845260609392830182828015610b9657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b78575b50505050509050919050565b606060008260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2b9190611e50565b610c359190611e69565b610c3f9190611e69565b6001600160a01b03851660009081526006602090815260408083208484528252918290208054835181840281018401909452808452939450919290830182828015610cb357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c95575b50505050509150505b92915050565b610a6c81600080611293565b6001600160a01b038116600090815260046020908152604091829020805483518184028101840190945280845260609392830182828015610b96576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610b785750505050509050919050565b6000808260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dca9190611e50565b610dd49190611e69565b610dde9190611e69565b6001600160a01b0385166000908152600660209081526040808320938352929052205491505092915050565b610e12611802565b6001600160a01b0382811660009081526008602052604090205416610e655760405162461bcd60e51b815260206004820152600960248201526808515b991bdc9cd95960ba1b6044820152606401610848565b6001600160a01b0382166000908152600860205260409020600301610e8a8282611f5e565b505050565b60606002805480602002602001604051908101604052809291908181526020018280548015610ee757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610ec9575b5050505050905090565b606060006002805480602002602001604051908101604052809291908181526020018280548015610f4b57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f2d575b5050600254939450839250505067ffffffffffffffff811115610f7057610f70611c08565b604051908082528060200260200182016040528015610fa357816020015b6060815260200190600190039081610f8e5790505b50925060005b818110156105695760046000848381518110610fc757610fc7611dd1565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561104357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611025575b505050505084828151811061105a5761105a611dd1565b60200260200101819052508061106f90611dfd565b9050610fa9565b6000611080611802565b60008260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111079190611e50565b6111119190611e69565b61111b9190611e69565b6040516319c8e0f160e21b8152600481018290529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063672383c490602401602060405180830381865afa158015611186573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111aa9190611e7c565b90506001600160a01b0381166112025760405162461bcd60e51b815260206004820152601960248201527f52656769737472793a20756e6b6e6f776e2072656c65617365000000000000006044820152606401610848565b60405163b4aeee7760e01b81526001600160a01b0382169063b4aeee7790611236908c908c908c908c908c9060040161201e565b6020604051808303816000875af1158015611255573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112799190611e7c565b9250611287838a844261184c565b50509695505050505050565b61129b611802565b60008260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113229190611e50565b61132c9190611e69565b6113369190611e69565b6040516319c8e0f160e21b8152600481018290529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063672383c490602401602060405180830381865afa1580156113a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c59190611e7c565b6001600160a01b031663eec400236040518163ffffffff1660e01b8152600401600060405180830381865afa158015611402573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261142a9190810190611e99565b90508080519060200120856001600160a01b031663eec400236040518163ffffffff1660e01b8152600401600060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261149a9190810190611e99565b80519060200120146114e25760405162461bcd60e51b81526020600482015260116024820152702bb937b7339020a824902b32b939b4b7b760791b6044820152606401610848565b61154f85866001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611524573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115489190611e7c565b848661184c565b5050505050565b606060008260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115df9190611e50565b6115e99190611e69565b6115f39190611e69565b6001600160a01b03851660009081526007602090815260408083208484528252918290208054835181840281018401909452808452939450919290830182828015610cb3576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610c9557505050505091505092915050565b6000808260017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356e0a94b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116fb9190611e50565b6117059190611e69565b61170f9190611e69565b6001600160a01b0385166000908152600760209081526040808320938352929052205491505092915050565b6002818154811061174b57600080fd5b6000918252602090912001546001600160a01b0316905081565b61176d611802565b6001600160a01b0381166117b25760405162461bcd60e51b815260206004820152600c60248201526b5a45524f204144445245535360a01b6044820152606401610848565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce809190a35050565b6000546001600160a01b0316331461184a5760405162461bcd60e51b815260206004820152600b60248201526a21676f7665726e616e636560a81b6044820152606401610848565b565b6001600160a01b0380841660008181526004602090815260408083208054600181810183559185528385200180548b88166001600160a01b03199182168117909255868652600685528386208a875285528386208054808501825590875285872001805482168317905583516080810185529687528685018a81528785018a81528551808801875288815260608a01908152938852600890965293909520865181549816979095169690961784559051908301555160028201559151909190600382019061191a9082611f5e565b5050506001600160a01b03831660009081526003602052604090205460ff166119a1576002805460018082019092557f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b0386169081179091556000908152600360205260409020805460ff191690911790555b826001600160a01b0316846001600160a01b03167f5bf19cf6c9f6c9210bc8cfecb4fda8057ebe0c41e300b60c5efa3de7f98f2f35846040516119e691815260200190565b60405180910390a350505050565b6000602080830181845280855180835260408601915060408160051b87010192508387016000805b83811015611a7957888603603f19018552825180518088529088019088880190845b81811015611a635783516001600160a01b03168352928a0192918a0191600101611a3e565b5090975050509386019391860191600101611a1c565b509398975050505050505050565b60005b83811015611aa2578181015183820152602001611a8a565b50506000910152565b60008151808452611ac3816020860160208601611a87565b601f01601f19169290920160200192915050565b602081526000611aea6020830184611aab565b9392505050565b6001600160a01b0381168114610a6c57600080fd5b600080600060608486031215611b1b57600080fd5b8335611b2681611af1565b95602085013595506040909401359392505050565b600060208284031215611b4d57600080fd5b8135611aea81611af1565b60018060a01b0385168152836020820152826040820152608060608201526000611b856080830184611aab565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611bd05783516001600160a01b031683529284019291840191600101611bab565b50909695505050505050565b60008060408385031215611bef57600080fd5b8235611bfa81611af1565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611c4757611c47611c08565b604052919050565b600067ffffffffffffffff821115611c6957611c69611c08565b50601f01601f191660200190565b600082601f830112611c8857600080fd5b8135611c9b611c9682611c4f565b611c1e565b818152846020838601011115611cb057600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215611ce057600080fd5b8235611ceb81611af1565b9150602083013567ffffffffffffffff811115611d0757600080fd5b611d1385828601611c77565b9150509250929050565b60008060008060008060c08789031215611d3657600080fd5b8635611d4181611af1565b9550602087013567ffffffffffffffff80821115611d5e57600080fd5b611d6a8a838b01611c77565b96506040890135915080821115611d8057600080fd5b50611d8d89828a01611c77565b9450506060870135611d9e81611af1565b9598949750929560808101359460a0909101359350915050565b600060208284031215611dca57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611e0f57611e0f611de7565b5060010190565b600181811c90821680611e2a57607f821691505b602082108103611e4a57634e487b7160e01b600052602260045260246000fd5b50919050565b600060208284031215611e6257600080fd5b5051919050565b81810381811115610cbc57610cbc611de7565b600060208284031215611e8e57600080fd5b8151611aea81611af1565b600060208284031215611eab57600080fd5b815167ffffffffffffffff811115611ec257600080fd5b8201601f81018413611ed357600080fd5b8051611ee1611c9682611c4f565b818152856020838501011115611ef657600080fd5b611f07826020830160208601611a87565b95945050505050565b601f821115610e8a57600081815260208120601f850160051c81016020861015611f375750805b601f850160051c820191505b81811015611f5657828155600101611f43565b505050505050565b815167ffffffffffffffff811115611f7857611f78611c08565b611f8c81611f868454611e16565b84611f10565b602080601f831160018114611fc15760008415611fa95750858301515b600019600386901b1c1916600185901b178555611f56565b600085815260208120601f198616915b82811015611ff057888601518255948401946001909101908401611fd1565b508582101561200e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600060018060a01b03808816835260a0602084015261204060a0840188611aab565b83810360408501526120528188611aab565b959091166060840152505060800152939250505056fea2646970667358221220e5282f2e3494da6a357e7858fe978c235347eac50644203cafed74de11d94b6664736f6c63430008120033a2646970667358221220c86c2a47263cce3f4a2cee6fcef97ff1d3e68e9d1545680d19a988ea5e5147ce64736f6c63430008120033

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

0000000000000000000000005a6e1ecc767d949d6da74e76b05dbb4870488ef6

-----Decoded View---------------
Arg [0] : _releaseRegistry (address): 0x5a6E1eCC767d949D6da74e76b05DBB4870488ef6

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000005a6e1ecc767d949d6da74e76b05dbb4870488ef6


Deployed Bytecode Sourcemap

37639:946:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37949:111;38014:38;;;;;;;;;;;;;;;;37949:111;;;;38014:38;37949:111;:::i;:::-;;;;;;;;37801:40;;;;;;;;-1:-1:-1;;;;;831:32:1;;;813:51;;801:2;786:18;37801:40:0;667:203:1;38213:369:0;;;;;;:::i;:::-;;:::i;38068:137::-;;;;;;:::i;:::-;;:::i;38213:369::-;38323:7;38343:20;38393:11;38419:5;38439:15;38366:99;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;38343:122;;38517:11;-1:-1:-1;;;;;38483:53:0;38503:11;-1:-1:-1;;;;;38483:53:0;;38530:5;38483:53;;;;;;:::i;:::-;;;;;;;;38562:11;38213:369;-1:-1:-1;;;38213:369:0:o;38068:137::-;38134:7;38161:36;38179:10;38191:5;38161:17;:36::i;:::-;38154:43;38068:137;-1:-1:-1;;38068:137:0:o;-1:-1:-1:-;;;;;;;;:::o;14:423:1:-;56:3;94:5;88:12;121:6;116:3;109:19;146:1;156:162;170:6;167:1;164:13;156:162;;;232:4;288:13;;;284:22;;278:29;260:11;;;256:20;;249:59;185:12;156:162;;;160:3;363:1;356:4;347:6;342:3;338:16;334:27;327:38;426:4;419:2;415:7;410:2;402:6;398:15;394:29;389:3;385:39;381:50;374:57;;;14:423;;;;:::o;442:220::-;591:2;580:9;573:21;554:4;611:45;652:2;641:9;637:18;629:6;611:45;:::i;:::-;603:53;442:220;-1:-1:-1;;;442:220:1:o;875:127::-;936:10;931:3;927:20;924:1;917:31;967:4;964:1;957:15;991:4;988:1;981:15;1007:719;1050:5;1103:3;1096:4;1088:6;1084:17;1080:27;1070:55;;1121:1;1118;1111:12;1070:55;1157:6;1144:20;1183:18;1220:2;1216;1213:10;1210:36;;;1226:18;;:::i;:::-;1301:2;1295:9;1269:2;1355:13;;-1:-1:-1;;1351:22:1;;;1375:2;1347:31;1343:40;1331:53;;;1399:18;;;1419:22;;;1396:46;1393:72;;;1445:18;;:::i;:::-;1485:10;1481:2;1474:22;1520:2;1512:6;1505:18;1566:3;1559:4;1554:2;1546:6;1542:15;1538:26;1535:35;1532:55;;;1583:1;1580;1573:12;1532:55;1647:2;1640:4;1632:6;1628:17;1621:4;1613:6;1609:17;1596:54;1694:1;1687:4;1682:2;1674:6;1670:15;1666:26;1659:37;1714:6;1705:15;;;;;;1007:719;;;;:::o;1731:496::-;1809:6;1817;1870:2;1858:9;1849:7;1845:23;1841:32;1838:52;;;1886:1;1883;1876:12;1838:52;1912:23;;-1:-1:-1;;;;;1964:31:1;;1954:42;;1944:70;;2010:1;2007;2000:12;1944:70;2033:5;-1:-1:-1;2089:2:1;2074:18;;2061:32;2116:18;2105:30;;2102:50;;;2148:1;2145;2138:12;2102:50;2171;2213:7;2204:6;2193:9;2189:22;2171:50;:::i;:::-;2161:60;;;1731:496;;;;;:::o;2232:322::-;2301:6;2354:2;2342:9;2333:7;2329:23;2325:32;2322:52;;;2370:1;2367;2360:12;2322:52;2410:9;2397:23;2443:18;2435:6;2432:30;2429:50;;;2475:1;2472;2465:12;2429:50;2498;2540:7;2531:6;2520:9;2516:22;2498:50;:::i;:::-;2488:60;2232:322;-1:-1:-1;;;;2232:322:1:o;2559:418::-;2727:4;2773:1;2769;2764:3;2760:11;2756:19;2814:2;2806:6;2802:15;2791:9;2784:34;2854:2;2849;2838:9;2834:18;2827:30;2874:45;2915:2;2904:9;2900:18;2892:6;2874:45;:::i;:::-;2866:53;;2967:2;2959:6;2955:15;2950:2;2939:9;2935:18;2928:43;;2559:418;;;;;;:::o

Swarm Source

ipfs://c86c2a47263cce3f4a2cee6fcef97ff1d3e68e9d1545680d19a988ea5e5147ce
Loading...
Loading
Loading...
Loading
[ 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.