ETH Price: $2,232.63 (-2.49%)

Contract

0x08EAC676cA5448E55c9FAc8619BdA1e4a71c93F0
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
UsdPriceFeedManager

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 99999 runs

Other Settings:
london EvmVersion
File 1 of 10 : UsdPriceFeedManager.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;

import "@openzeppelin/token/ERC20/extensions/IERC20Metadata.sol";
import "../external/interfaces/chainlink/AggregatorV3Interface.sol";
import "../interfaces/IUsdPriceFeedManager.sol";
import "../access/Roles.sol";
import "../access/SpoolAccessControllable.sol";

contract UsdPriceFeedManager is IUsdPriceFeedManager, SpoolAccessControllable {
    /* ========== STATE VARIABLES ========== */

    /// @notice Number of decimals used by the asset.
    mapping(address => uint256) public assetDecimals;

    /// @notice Multiplier needed by the asset.
    mapping(address => uint256) public assetMultiplier;

    /// @notice Price aggregator for the asset.
    mapping(address => AggregatorV3Interface) public assetPriceAggregator;

    /// @notice Multiplier needed by the price aggregator for the asset.
    mapping(address => uint256) public assetPriceAggregatorMultiplier;

    /// @notice Whether the asset can be used.
    mapping(address => bool) public assetValidity;

    /// @notice max time in which asset price should be updated.
    mapping(address => uint256) public assetTimeLimit;

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

    /**
     * @param accessControl_ Access control for Spool ecosystem.
     */
    constructor(ISpoolAccessControl accessControl_) SpoolAccessControllable(accessControl_) {}

    /* ========== ADMIN FUNCTIONS ========== */

    function setAsset(address asset, AggregatorV3Interface priceAggregator, bool validity, uint256 timeLimit)
        external
        onlyRole(ROLE_SPOOL_ADMIN, msg.sender)
    {
        uint256 decimals = IERC20Metadata(asset).decimals();

        assetDecimals[asset] = decimals;
        assetMultiplier[asset] = 10 ** decimals;
        assetPriceAggregator[asset] = priceAggregator;
        assetPriceAggregatorMultiplier[asset] = 10 ** (USD_DECIMALS - priceAggregator.decimals());
        assetValidity[asset] = validity;
        assetTimeLimit[asset] = timeLimit;
    }

    function updateAssetTimeLimit(address asset, uint256 timeLimit) external onlyRole(ROLE_SPOOL_ADMIN, msg.sender) {
        assetTimeLimit[asset] = timeLimit;
    }

    /* ========== EXTERNAL FUNCTIONS ========== */

    function usdDecimals() external pure returns (uint256) {
        return USD_DECIMALS;
    }

    function assetToUsd(address asset, uint256 assetAmount) external view onlyValidAsset(asset) returns (uint256) {
        return assetAmount * _getAssetPriceInUsd(asset) * assetPriceAggregatorMultiplier[asset] / assetMultiplier[asset];
    }

    function usdToAsset(address asset, uint256 usdAmount) external view onlyValidAsset(asset) returns (uint256) {
        return usdAmount * assetMultiplier[asset] / assetPriceAggregatorMultiplier[asset] / _getAssetPriceInUsd(asset);
    }

    function assetToUsdCustomPrice(address asset, uint256 assetAmount, uint256 price)
        public
        view
        onlyValidAsset(asset)
        returns (uint256)
    {
        return assetAmount * price / assetMultiplier[asset];
    }

    function usdToAssetCustomPrice(address asset, uint256 usdAmount, uint256 price)
        external
        view
        onlyValidAsset(asset)
        returns (uint256)
    {
        return usdAmount * assetMultiplier[asset] / price;
    }

    function assetToUsdCustomPriceBulk(address[] calldata tokens, uint256[] calldata assets, uint256[] calldata prices)
        external
        view
        returns (uint256)
    {
        uint256 usdTotal = 0;
        for (uint256 i; i < tokens.length; ++i) {
            usdTotal += assetToUsdCustomPrice(tokens[i], assets[i], prices[i]);
        }

        return usdTotal;
    }

    /* ========== PRIVATE FUNCTIONS ========== */

    /**
     * @dev Gets latest asset price in USD from oracle.
     * @param asset Asset for price lookup.
     * @return assetPrice Latest asset price.
     */
    function _getAssetPriceInUsd(address asset) private view returns (uint256 assetPrice) {
        (
            /* uint80 roundId */
            ,
            int256 answer,
            /* uint256 startedAt */
            ,
            uint256 updatedAt,
            /* uint80 answeredInRound */
        ) = assetPriceAggregator[asset].latestRoundData();

        if (updatedAt == 0 || (updatedAt + assetTimeLimit[asset] < block.timestamp)) {
            revert StalePriceData();
        }

        if (answer < 1) {
            revert NonPositivePrice({price: answer});
        }

        return uint256(answer);
    }

    /**
     * @dev Ensures that the asset is valid.
     */
    function _onlyValidAsset(address asset) private view {
        if (!assetValidity[asset]) {
            revert InvalidAsset({asset: asset});
        }
    }

    /* ========== MODIFIERS ========== */

    /**
     * @notice Throws if the asset is not valid.
     */
    modifier onlyValidAsset(address asset) {
        _onlyValidAsset(asset);
        _;
    }
}

File 2 of 10 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

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

File 3 of 10 : AggregatorV3Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorV3Interface {
    function decimals() external view returns (uint8);

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

    function version() external view returns (uint256);

    function getRoundData(uint80 _roundId)
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);

    function latestRoundData()
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}

File 4 of 10 : IUsdPriceFeedManager.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;

/// @dev Number of decimals used for USD values.
uint256 constant USD_DECIMALS = 18;

/**
 * @notice Emitted when asset is invalid.
 * @param asset Invalid asset.
 */
error InvalidAsset(address asset);

/**
 * @notice Emitted when price returned by price aggregator is negative or zero.
 * @param price Actual price returned by price aggregator.
 */
error NonPositivePrice(int256 price);

/**
 * @notice Emitted when pricing data returned by price aggregator is not from the current
 * round or the round hasn't finished.
 */
error StalePriceData();

interface IUsdPriceFeedManager {
    /**
     * @notice Gets number of decimals for an asset.
     * @param asset Address of the asset.
     * @return assetDecimals Number of decimals for the asset.
     */
    function assetDecimals(address asset) external view returns (uint256 assetDecimals);

    /**
     * @notice Gets number of decimals for USD.
     * @return usdDecimals Number of decimals for USD.
     */
    function usdDecimals() external view returns (uint256 usdDecimals);

    /**
     * @notice Calculates asset value in USD using current price.
     * @param asset Address of asset.
     * @param assetAmount Amount of asset in asset decimals.
     * @return usdValue Value in USD in USD decimals.
     */
    function assetToUsd(address asset, uint256 assetAmount) external view returns (uint256 usdValue);

    /**
     * @notice Calculates USD value in asset using current price.
     * @param asset Address of asset.
     * @param usdAmount Amount of USD in USD decimals.
     * @return assetValue Value in asset in asset decimals.
     */
    function usdToAsset(address asset, uint256 usdAmount) external view returns (uint256 assetValue);

    /**
     * @notice Calculates asset value in USD using provided price.
     * @param asset Address of asset.
     * @param assetAmount Amount of asset in asset decimals.
     * @param price Price of asset in USD.
     * @return usdValue Value in USD in USD decimals.
     */
    function assetToUsdCustomPrice(address asset, uint256 assetAmount, uint256 price)
        external
        view
        returns (uint256 usdValue);

    /**
     * @notice Calculates assets value in USD using provided prices.
     * @param assets Addresses of assets.
     * @param assetAmounts Amounts of assets in asset decimals.
     * @param prices Prices of asset in USD.
     * @return usdValue Value in USD in USD decimals.
     */
    function assetToUsdCustomPriceBulk(
        address[] calldata assets,
        uint256[] calldata assetAmounts,
        uint256[] calldata prices
    ) external view returns (uint256 usdValue);

    /**
     * @notice Calculates USD value in asset using provided price.
     * @param asset Address of asset.
     * @param usdAmount Amount of USD in USD decimals.
     * @param price Price of asset in USD.
     * @return assetValue Value in asset in asset decimals.
     */
    function usdToAssetCustomPrice(address asset, uint256 usdAmount, uint256 price)
        external
        view
        returns (uint256 assetValue);
}

File 5 of 10 : Roles.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;

/**
 * @dev Grants permission to:
 * - acts as a default admin for other roles,
 * - can whitelist an action with action manager,
 * - can manage asset group registry.
 *
 * Is granted to the deployer of the SpoolAccessControl contract.
 *
 * Equals to the DEFAULT_ADMIN_ROLE of the OpenZeppelin AccessControl.
 */
bytes32 constant ROLE_SPOOL_ADMIN = 0x00;

/**
 * @dev Grants permission to integrate a new smart vault into the Spool ecosystem.
 *
 * Should be granted to smart vault factory contracts.
 */
bytes32 constant ROLE_SMART_VAULT_INTEGRATOR = keccak256("SMART_VAULT_INTEGRATOR");

/**
 * @dev Grants permission to
 * - manage rewards on smart vaults,
 * - manage roles on smart vaults,
 * - redeem for another user of a smart vault.
 */
bytes32 constant ROLE_SMART_VAULT_ADMIN = keccak256("SMART_VAULT_ADMIN");

/**
 * @dev Grants permission to manage allowlists with AllowlistGuard for a smart vault.
 *
 * Should be granted to whoever is in charge of maintaining allowlists with AllowlistGuard for a smart vault.
 */
bytes32 constant ROLE_GUARD_ALLOWLIST_MANAGER = keccak256("GUARD_ALLOWLIST_MANAGER");

/**
 * @dev Grants permission to manage assets on master wallet.
 *
 * Should be granted to:
 * - the SmartVaultManager contract,
 * - the StrategyRegistry contract,
 * - the DepositManager contract,
 * - the WithdrawalManager contract.
 */
bytes32 constant ROLE_MASTER_WALLET_MANAGER = keccak256("MASTER_WALLET_MANAGER");

/**
 * @dev Marks a contract as a smart vault manager.
 *
 * Should be granted to:
 * - the SmartVaultManager contract,
 * - the DepositManager contract.
 */
bytes32 constant ROLE_SMART_VAULT_MANAGER = keccak256("SMART_VAULT_MANAGER");

/**
 * @dev Marks a contract as a strategy registry.
 *
 * Should be granted to the StrategyRegistry contract.
 */
bytes32 constant ROLE_STRATEGY_REGISTRY = keccak256("STRATEGY_REGISTRY");

/**
 * @dev Grants permission to act as a risk provider.
 *
 * Should be granted to whoever is allowed to provide risk scores.
 */
bytes32 constant ROLE_RISK_PROVIDER = keccak256("RISK_PROVIDER");

/**
 * @dev Grants permission to act as an allocation provider.
 *
 * Should be granted to contracts that are allowed to calculate allocations.
 */
bytes32 constant ROLE_ALLOCATION_PROVIDER = keccak256("ALLOCATION_PROVIDER");

/**
 * @dev Grants permission to pause the system.
 */
bytes32 constant ROLE_PAUSER = keccak256("SYSTEM_PAUSER");

/**
 * @dev Grants permission to unpause the system.
 */
bytes32 constant ROLE_UNPAUSER = keccak256("SYSTEM_UNPAUSER");

/**
 * @dev Grants permission to manage rewards payment pool.
 */
bytes32 constant ROLE_REWARD_POOL_ADMIN = keccak256("REWARD_POOL_ADMIN");

/**
 * @dev Grants permission to reallocate smart vaults.
 */
bytes32 constant ROLE_REALLOCATOR = keccak256("REALLOCATOR");

/**
 * @dev Grants permission to be used as a strategy.
 */
bytes32 constant ROLE_STRATEGY = keccak256("STRATEGY");

/**
 * @dev Grants permission to manually set strategy apy.
 */
bytes32 constant ROLE_STRATEGY_APY_SETTER = keccak256("STRATEGY_APY_SETTER");

/**
 * @dev Grants permission to manage role ROLE_STRATEGY.
 */
bytes32 constant ADMIN_ROLE_STRATEGY = keccak256("ADMIN_STRATEGY");

/**
 * @dev Grants permission vault admins to allow redeem on behalf of other users.
 */
bytes32 constant ROLE_SMART_VAULT_ALLOW_REDEEM = keccak256("SMART_VAULT_ALLOW_REDEEM");

/**
 * @dev Grants permission to manage role ROLE_SMART_VAULT_ALLOW_REDEEM.
 */
bytes32 constant ADMIN_ROLE_SMART_VAULT_ALLOW_REDEEM = keccak256("ADMIN_SMART_VAULT_ALLOW_REDEEM");

/**
 * @dev Grants permission to run do hard work.
 */
bytes32 constant ROLE_DO_HARD_WORKER = keccak256("DO_HARD_WORKER");

/**
 * @dev Grants permission to immediately withdraw assets in case of emergency.
 */
bytes32 constant ROLE_EMERGENCY_WITHDRAWAL_EXECUTOR = keccak256("EMERGENCY_WITHDRAWAL_EXECUTOR");

/**
 * @dev Grants permission to swap with swapper.
 *
 * Should be granted to the DepositSwap contract.
 */
bytes32 constant ROLE_SWAPPER = keccak256("SWAPPER");

File 6 of 10 : SpoolAccessControllable.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;

import "../interfaces/ISpoolAccessControl.sol";
import "../interfaces/CommonErrors.sol";
import "./Roles.sol";

/**
 * @notice Account access role verification middleware
 */
abstract contract SpoolAccessControllable {
    /* ========== CONSTANTS ========== */

    /**
     * @dev Spool access control manager.
     */
    ISpoolAccessControl internal immutable _accessControl;

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

    /**
     * @param accessControl_ Spool access control manager.
     */
    constructor(ISpoolAccessControl accessControl_) {
        if (address(accessControl_) == address(0)) revert ConfigurationAddressZero();

        _accessControl = accessControl_;
    }

    /* ========== INTERNAL FUNCTIONS ========== */

    /**
     * @dev Reverts if an account is missing a role.\
     * @param role Role to check for.
     * @param account Account to check.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!_accessControl.hasRole(role, account)) {
            revert MissingRole(role, account);
        }
    }

    /**
     * @dev Revert if an account is missing a role for a smartVault.
     * @param smartVault Address of the smart vault.
     * @param role Role to check for.
     * @param account Account to check.
     */
    function _checkSmartVaultRole(address smartVault, bytes32 role, address account) internal view {
        if (!_accessControl.hasSmartVaultRole(smartVault, role, account)) {
            revert MissingRole(role, account);
        }
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        if (_accessControl.paused()) {
            revert SystemPaused();
        }
    }

    function _checkNonReentrant() internal view {
        _accessControl.checkNonReentrant();
    }

    function _nonReentrantBefore() internal {
        _accessControl.nonReentrantBefore();
    }

    function _nonReentrantAfter() internal {
        _accessControl.nonReentrantAfter();
    }

    /* ========== MODIFIERS ========== */

    /**
     * @notice Only allows accounts with granted role.
     * @dev Reverts when the account fails check.
     * @param role Role to check for.
     * @param account Account to check.
     */
    modifier onlyRole(bytes32 role, address account) {
        _checkRole(role, account);
        _;
    }

    /**
     * @notice Only allows accounts with granted role for a smart vault.
     * @dev Reverts when the account fails check.
     * @param smartVault Address of the smart vault.
     * @param role Role to check for.
     * @param account Account to check.
     */
    modifier onlySmartVaultRole(address smartVault, bytes32 role, address account) {
        _checkSmartVaultRole(smartVault, role, account);
        _;
    }

    /**
     * @notice Only allows accounts that are Spool admins or admins of a smart vault.
     * @dev Reverts when the account fails check.
     * @param smartVault Address of the smart vault.
     * @param account Account to check.
     */
    modifier onlyAdminOrVaultAdmin(address smartVault, address account) {
        _accessControl.checkIsAdminOrVaultAdmin(smartVault, account);
        _;
    }

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

    /**
     * @dev Prevents a contract from calling itself, or other contracts using this modifier.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    /**
     * @dev Check if a system has already entered in the non-reentrant state.
     */
    modifier checkNonReentrant() {
        _checkNonReentrant();
        _;
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

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

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

File 8 of 10 : ISpoolAccessControl.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;

import "@openzeppelin-upgradeable/access/IAccessControlUpgradeable.sol";

/**
 * @notice Used when an account is missing a required role.
 * @param role Required role.
 * @param account Account missing the required role.
 */
error MissingRole(bytes32 role, address account);

/**
 * @notice Used when interacting with Spool when the system is paused.
 */
error SystemPaused();

/**
 * @notice Used when setting smart vault owner
 */
error SmartVaultOwnerAlreadySet(address smartVault);

/**
 * @notice Used when a contract tries to enter in a non-reentrant state.
 */
error ReentrantCall();

/**
 * @notice Used when a contract tries to call in a non-reentrant function and doesn't have the correct role.
 */
error NoReentrantRole();

interface ISpoolAccessControl is IAccessControlUpgradeable {
    /* ========== VIEW FUNCTIONS ========== */

    /**
     * @notice Gets owner of a smart vault.
     * @param smartVault Smart vault.
     * @return owner Owner of the smart vault.
     */
    function smartVaultOwner(address smartVault) external view returns (address owner);

    /**
     * @notice Looks if an account has a role for a smart vault.
     * @param smartVault Address of the smart vault.
     * @param role Role to look for.
     * @param account Account to check.
     * @return hasRole True if account has the role for the smart vault, false otherwise.
     */
    function hasSmartVaultRole(address smartVault, bytes32 role, address account)
        external
        view
        returns (bool hasRole);

    /**
     * @notice Checks if an account is either Spool admin or admin for a smart vault.
     * @dev The function reverts if account is neither.
     * @param smartVault Address of the smart vault.
     * @param account to check.
     */
    function checkIsAdminOrVaultAdmin(address smartVault, address account) external view;

    /**
     * @notice Checks if system is paused or not.
     * @return isPaused True if system is paused, false otherwise.
     */
    function paused() external view returns (bool isPaused);

    /* ========== MUTATIVE FUNCTIONS ========== */

    /**
     * @notice Pauses the whole system.
     * @dev Requirements:
     * - caller must have role ROLE_PAUSER
     */
    function pause() external;

    /**
     * @notice Unpauses the whole system.
     * @dev Requirements:
     * - caller must have role ROLE_UNPAUSER
     */
    function unpause() external;

    /**
     * @notice Grants role to an account for a smart vault.
     * @dev Requirements:
     * - caller must have either role ROLE_SPOOL_ADMIN or role ROLE_SMART_VAULT_ADMIN for the smart vault
     * @param smartVault Address of the smart vault.
     * @param role Role to grant.
     * @param account Account to grant the role to.
     */
    function grantSmartVaultRole(address smartVault, bytes32 role, address account) external;

    /**
     * @notice Revokes role from an account for a smart vault.
     * @dev Requirements:
     * - caller must have either role ROLE_SPOOL_ADMIN or role ROLE_SMART_VAULT_ADMIN for the smart vault
     * @param smartVault Address of the smart vault.
     * @param role Role to revoke.
     * @param account Account to revoke the role from.
     */
    function revokeSmartVaultRole(address smartVault, bytes32 role, address account) external;

    /**
     * @notice Renounce role for a smart vault.
     * @param smartVault Address of the smart vault.
     * @param role Role to renounce.
     */
    function renounceSmartVaultRole(address smartVault, bytes32 role) external;

    /**
     * @notice Grant ownership to smart vault and assigns admin role.
     * @dev Ownership can only be granted once and it should be done at vault creation time.
     * @param smartVault Address of the smart vault.
     * @param owner address to which grant ownership to
     */
    function grantSmartVaultOwnership(address smartVault, address owner) external;

    /**
     * @notice Checks and reverts if a system has already entered in the non-reentrant state.
     */
    function checkNonReentrant() external view;

    /**
     * @notice Sets the entered flag to true when entering for the first time.
     * @dev Reverts if a system has already entered before.
     */
    function nonReentrantBefore() external;

    /**
     * @notice Resets the entered flag after the call is finished.
     */
    function nonReentrantAfter() external;

    /**
     * @notice Emitted when ownership of a smart vault is granted to an address
     * @param smartVault Smart vault address
     * @param address_ Address of the new smart vault owner
     */
    event SmartVaultOwnershipGranted(address indexed smartVault, address indexed address_);

    /**
     * @notice Smart vault specific role was granted
     * @param smartVault Smart vault address
     * @param role Role ID
     * @param account Account to which the role was granted
     */
    event SmartVaultRoleGranted(address indexed smartVault, bytes32 indexed role, address indexed account);

    /**
     * @notice Smart vault specific role was revoked
     * @param smartVault Smart vault address
     * @param role Role ID
     * @param account Account for which the role was revoked
     */
    event SmartVaultRoleRevoked(address indexed smartVault, bytes32 indexed role, address indexed account);

    /**
     * @notice Smart vault specific role was renounced
     * @param smartVault Smart vault address
     * @param role Role ID
     * @param account Account that renounced the role
     */
    event SmartVaultRoleRenounced(address indexed smartVault, bytes32 indexed role, address indexed account);
}

File 9 of 10 : CommonErrors.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.17;

/**
 * @notice Used when an array has invalid length.
 */
error InvalidArrayLength();

/**
 * @notice Used when group of smart vaults or strategies do not have same asset group.
 */
error NotSameAssetGroup();

/**
 * @notice Used when configuring an address with a zero address.
 */
error ConfigurationAddressZero();

/**
 * @notice Used when constructor or intializer parameters are invalid.
 */
error InvalidConfiguration();

/**
 * @notice Used when fetched exchange rate is out of slippage range.
 */
error ExchangeRateOutOfSlippages();

/**
 * @notice Used when an invalid strategy is provided.
 * @param address_ Address of the invalid strategy.
 */
error InvalidStrategy(address address_);

/**
 * @notice Used when doing low-level call on an address that is not a contract.
 * @param address_ Address of the contract
 */
error AddressNotContract(address address_);

/**
 * @notice Used when invoking an only view execution and tx.origin is not address zero.
 * @param address_ Address of the tx.origin
 */
error OnlyViewExecution(address address_);

File 10 of 10 : IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControlUpgradeable {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "@openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@solmate/=lib/solmate/src/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
    "create3/=lib/create3/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solmate/=lib/solmate/src/",
    "sstore2/=lib/sstore2/contracts/",
    "swap-router-contracts/=lib/swap-router-contracts/contracts/",
    "v3-core/=lib/v3-core/contracts/",
    "v3-periphery/=lib/v3-periphery/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 99999
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {
    "script/helper/ArraysHelper.sol": {
      "ArraysHelper": "0x7fba0ee43670df6c179d3da2d711a8c7511dc0d5"
    },
    "src/libraries/ArrayMapping.sol": {
      "ArrayMappingUint256": "0xa41237f822c466e673c8228346ffad39ab598c53"
    },
    "src/libraries/ReallocationLib.sol": {
      "ReallocationLib": "0xc444b8636a1ad1c27b257a67824ea66c7817ab6b"
    },
    "src/libraries/SpoolUtils.sol": {
      "SpoolUtils": "0xaf1a11f4987204cd710f55064d07df24a508fbdc"
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract ISpoolAccessControl","name":"accessControl_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ConfigurationAddressZero","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"InvalidAsset","type":"error"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"MissingRole","type":"error"},{"inputs":[{"internalType":"int256","name":"price","type":"int256"}],"name":"NonPositivePrice","type":"error"},{"inputs":[],"name":"StalePriceData","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assetDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assetMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assetPriceAggregator","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assetPriceAggregatorMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assetTimeLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"assetAmount","type":"uint256"}],"name":"assetToUsd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"assetAmount","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"assetToUsdCustomPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"assets","type":"uint256[]"},{"internalType":"uint256[]","name":"prices","type":"uint256[]"}],"name":"assetToUsdCustomPriceBulk","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assetValidity","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"contract AggregatorV3Interface","name":"priceAggregator","type":"address"},{"internalType":"bool","name":"validity","type":"bool"},{"internalType":"uint256","name":"timeLimit","type":"uint256"}],"name":"setAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"timeLimit","type":"uint256"}],"name":"updateAssetTimeLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"usdAmount","type":"uint256"}],"name":"usdToAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"usdAmount","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"usdToAssetCustomPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60a060405234801561001057600080fd5b50604051610f9a380380610f9a83398101604081905261002f91610069565b806001600160a01b0381166100575760405163bb0e4c3560e01b815260040160405180910390fd5b6001600160a01b031660805250610099565b60006020828403121561007b57600080fd5b81516001600160a01b038116811461009257600080fd5b9392505050565b608051610ee66100b460003960006109110152610ee66000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806387fc7c6c1161008c578063ca7ce04611610066578063ca7ce046146101f0578063e366da2c1461024b578063f2918c761461026b578063f6db781e1461027e57600080fd5b806387fc7c6c146101aa5780639115900c146101ca578063a2d2657f146101dd57600080fd5b80632edd3fe2116100c85780632edd3fe21461014a57806338f744331461015d5780634557e95c1461017057806366a4b6c0146101a357600080fd5b806310e55698146100ef57806324049ca8146101155780632d8b4b2b1461012a575b600080fd5b6101026100fd3660046109f7565b61029e565b6040519081526020015b60405180910390f35b610128610123366004610a31565b61030b565b005b610102610138366004610a82565b60346020526000908152604090205481565b6101286101583660046109f7565b610527565b61010261016b366004610aa6565b61055f565b61019361017e366004610a82565b60356020526000908152604090205460ff1681565b604051901515815260200161010c565b6012610102565b6101026101b8366004610a82565b60366020526000908152604090205481565b6101026101d8366004610aa6565b6105b0565b6101026101eb366004610b27565b6105ec565b6102266101fe366004610a82565b60336020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010c565b610102610259366004610a82565b60316020526000908152604090205481565b6101026102793660046109f7565b610682565b61010261028c366004610a82565b60326020526000908152604090205481565b6000826102aa816106dd565b73ffffffffffffffffffffffffffffffffffffffff84166000908152603260209081526040808320546034909252909120546102e58661075c565b6102ef9086610bf0565b6102f99190610bf0565b6103039190610c0d565b949350505050565b60003361031882826108c5565b60008673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103899190610c48565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260316020526040902060ff919091169081905590506103c581600a610d8b565b73ffffffffffffffffffffffffffffffffffffffff888116600090815260326020908152604080832094909455603381529083902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016928a16928317905582517f313ce5670000000000000000000000000000000000000000000000000000000081529251919263313ce56792600480830193928290030181865afa158015610475573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104999190610c48565b6104a79060ff166012610d97565b6104b290600a610d8b565b73ffffffffffffffffffffffffffffffffffffffff979097166000908152603460209081526040808320999099556035815288822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169715159790971790965560369095525050509290209190915550565b60003361053482826108c5565b505073ffffffffffffffffffffffffffffffffffffffff909116600090815260366020526040902055565b60008361056b816106dd565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260326020526040902054839061059d9086610bf0565b6105a79190610c0d565b95945050505050565b6000836105bc816106dd565b73ffffffffffffffffffffffffffffffffffffffff851660009081526032602052604090205461059d8486610bf0565b600080805b878110156106765761065a89898381811061060e5761060e610daa565b90506020020160208101906106239190610a82565b88888481811061063557610635610daa565b9050602002013587878581811061064e5761064e610daa565b905060200201356105b0565b6106649083610dd9565b915061066f81610dec565b90506105f1565b50979650505050505050565b60008261068e816106dd565b6106978461075c565b73ffffffffffffffffffffffffffffffffffffffff85166000908152603460209081526040808320546032909252909120546106d39086610bf0565b6102f99190610c0d565b73ffffffffffffffffffffffffffffffffffffffff811660009081526035602052604090205460ff16610759576040517f6f79c78a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024015b60405180910390fd5b50565b73ffffffffffffffffffffffffffffffffffffffff8082166000908152603360205260408082205481517ffeaf968c0000000000000000000000000000000000000000000000000000000081529151929384938493929091169163feaf968c9160048083019260a09291908290030181865afa1580156107e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108049190610e43565b509350509250508060001480610849575073ffffffffffffffffffffffffffffffffffffffff841660009081526036602052604090205442906108479083610dd9565b105b15610880576040517f355e186c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018212156108be576040517f936f629800000000000000000000000000000000000000000000000000000000815260048101839052602401610750565b5092915050565b6040517f91d148540000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff82811660248301527f000000000000000000000000000000000000000000000000000000000000000016906391d1485490604401602060405180830381865afa158015610958573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097c9190610e93565b6109d1576040517f75000dc00000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff82166024820152604401610750565b5050565b73ffffffffffffffffffffffffffffffffffffffff8116811461075957600080fd5b60008060408385031215610a0a57600080fd5b8235610a15816109d5565b946020939093013593505050565b801515811461075957600080fd5b60008060008060808587031215610a4757600080fd5b8435610a52816109d5565b93506020850135610a62816109d5565b92506040850135610a7281610a23565b9396929550929360600135925050565b600060208284031215610a9457600080fd5b8135610a9f816109d5565b9392505050565b600080600060608486031215610abb57600080fd5b8335610ac6816109d5565b95602085013595506040909401359392505050565b60008083601f840112610aed57600080fd5b50813567ffffffffffffffff811115610b0557600080fd5b6020830191508360208260051b8501011115610b2057600080fd5b9250929050565b60008060008060008060608789031215610b4057600080fd5b863567ffffffffffffffff80821115610b5857600080fd5b610b648a838b01610adb565b90985096506020890135915080821115610b7d57600080fd5b610b898a838b01610adb565b90965094506040890135915080821115610ba257600080fd5b50610baf89828a01610adb565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610c0757610c07610bc1565b92915050565b600082610c43577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215610c5a57600080fd5b815160ff81168114610a9f57600080fd5b600181815b80851115610cc457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610caa57610caa610bc1565b80851615610cb757918102915b93841c9390800290610c70565b509250929050565b600082610cdb57506001610c07565b81610ce857506000610c07565b8160018114610cfe5760028114610d0857610d24565b6001915050610c07565b60ff841115610d1957610d19610bc1565b50506001821b610c07565b5060208310610133831016604e8410600b8410161715610d47575081810a610c07565b610d518383610c6b565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610d8357610d83610bc1565b029392505050565b6000610a9f8383610ccc565b81810381811115610c0757610c07610bc1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80820180821115610c0757610c07610bc1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610e1d57610e1d610bc1565b5060010190565b805169ffffffffffffffffffff81168114610e3e57600080fd5b919050565b600080600080600060a08688031215610e5b57600080fd5b610e6486610e24565b9450602086015193506040860151925060608601519150610e8760808701610e24565b90509295509295909350565b600060208284031215610ea557600080fd5b8151610a9f81610a2356fea264697066735822122063ca8245fc293655e377170a643bc00c97842d8e4cfcac4ce7ace317aa0abd7a64736f6c634300081100330000000000000000000000007b533e72e0cdc63aacd8cdb926ac402b846fbd13

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c806387fc7c6c1161008c578063ca7ce04611610066578063ca7ce046146101f0578063e366da2c1461024b578063f2918c761461026b578063f6db781e1461027e57600080fd5b806387fc7c6c146101aa5780639115900c146101ca578063a2d2657f146101dd57600080fd5b80632edd3fe2116100c85780632edd3fe21461014a57806338f744331461015d5780634557e95c1461017057806366a4b6c0146101a357600080fd5b806310e55698146100ef57806324049ca8146101155780632d8b4b2b1461012a575b600080fd5b6101026100fd3660046109f7565b61029e565b6040519081526020015b60405180910390f35b610128610123366004610a31565b61030b565b005b610102610138366004610a82565b60346020526000908152604090205481565b6101286101583660046109f7565b610527565b61010261016b366004610aa6565b61055f565b61019361017e366004610a82565b60356020526000908152604090205460ff1681565b604051901515815260200161010c565b6012610102565b6101026101b8366004610a82565b60366020526000908152604090205481565b6101026101d8366004610aa6565b6105b0565b6101026101eb366004610b27565b6105ec565b6102266101fe366004610a82565b60336020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010c565b610102610259366004610a82565b60316020526000908152604090205481565b6101026102793660046109f7565b610682565b61010261028c366004610a82565b60326020526000908152604090205481565b6000826102aa816106dd565b73ffffffffffffffffffffffffffffffffffffffff84166000908152603260209081526040808320546034909252909120546102e58661075c565b6102ef9086610bf0565b6102f99190610bf0565b6103039190610c0d565b949350505050565b60003361031882826108c5565b60008673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610365573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103899190610c48565b73ffffffffffffffffffffffffffffffffffffffff8816600090815260316020526040902060ff919091169081905590506103c581600a610d8b565b73ffffffffffffffffffffffffffffffffffffffff888116600090815260326020908152604080832094909455603381529083902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016928a16928317905582517f313ce5670000000000000000000000000000000000000000000000000000000081529251919263313ce56792600480830193928290030181865afa158015610475573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104999190610c48565b6104a79060ff166012610d97565b6104b290600a610d8b565b73ffffffffffffffffffffffffffffffffffffffff979097166000908152603460209081526040808320999099556035815288822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169715159790971790965560369095525050509290209190915550565b60003361053482826108c5565b505073ffffffffffffffffffffffffffffffffffffffff909116600090815260366020526040902055565b60008361056b816106dd565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260326020526040902054839061059d9086610bf0565b6105a79190610c0d565b95945050505050565b6000836105bc816106dd565b73ffffffffffffffffffffffffffffffffffffffff851660009081526032602052604090205461059d8486610bf0565b600080805b878110156106765761065a89898381811061060e5761060e610daa565b90506020020160208101906106239190610a82565b88888481811061063557610635610daa565b9050602002013587878581811061064e5761064e610daa565b905060200201356105b0565b6106649083610dd9565b915061066f81610dec565b90506105f1565b50979650505050505050565b60008261068e816106dd565b6106978461075c565b73ffffffffffffffffffffffffffffffffffffffff85166000908152603460209081526040808320546032909252909120546106d39086610bf0565b6102f99190610c0d565b73ffffffffffffffffffffffffffffffffffffffff811660009081526035602052604090205460ff16610759576040517f6f79c78a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024015b60405180910390fd5b50565b73ffffffffffffffffffffffffffffffffffffffff8082166000908152603360205260408082205481517ffeaf968c0000000000000000000000000000000000000000000000000000000081529151929384938493929091169163feaf968c9160048083019260a09291908290030181865afa1580156107e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108049190610e43565b509350509250508060001480610849575073ffffffffffffffffffffffffffffffffffffffff841660009081526036602052604090205442906108479083610dd9565b105b15610880576040517f355e186c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018212156108be576040517f936f629800000000000000000000000000000000000000000000000000000000815260048101839052602401610750565b5092915050565b6040517f91d148540000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff82811660248301527f0000000000000000000000007b533e72e0cdc63aacd8cdb926ac402b846fbd1316906391d1485490604401602060405180830381865afa158015610958573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097c9190610e93565b6109d1576040517f75000dc00000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff82166024820152604401610750565b5050565b73ffffffffffffffffffffffffffffffffffffffff8116811461075957600080fd5b60008060408385031215610a0a57600080fd5b8235610a15816109d5565b946020939093013593505050565b801515811461075957600080fd5b60008060008060808587031215610a4757600080fd5b8435610a52816109d5565b93506020850135610a62816109d5565b92506040850135610a7281610a23565b9396929550929360600135925050565b600060208284031215610a9457600080fd5b8135610a9f816109d5565b9392505050565b600080600060608486031215610abb57600080fd5b8335610ac6816109d5565b95602085013595506040909401359392505050565b60008083601f840112610aed57600080fd5b50813567ffffffffffffffff811115610b0557600080fd5b6020830191508360208260051b8501011115610b2057600080fd5b9250929050565b60008060008060008060608789031215610b4057600080fd5b863567ffffffffffffffff80821115610b5857600080fd5b610b648a838b01610adb565b90985096506020890135915080821115610b7d57600080fd5b610b898a838b01610adb565b90965094506040890135915080821115610ba257600080fd5b50610baf89828a01610adb565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610c0757610c07610bc1565b92915050565b600082610c43577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600060208284031215610c5a57600080fd5b815160ff81168114610a9f57600080fd5b600181815b80851115610cc457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610caa57610caa610bc1565b80851615610cb757918102915b93841c9390800290610c70565b509250929050565b600082610cdb57506001610c07565b81610ce857506000610c07565b8160018114610cfe5760028114610d0857610d24565b6001915050610c07565b60ff841115610d1957610d19610bc1565b50506001821b610c07565b5060208310610133831016604e8410600b8410161715610d47575081810a610c07565b610d518383610c6b565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610d8357610d83610bc1565b029392505050565b6000610a9f8383610ccc565b81810381811115610c0757610c07610bc1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80820180821115610c0757610c07610bc1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610e1d57610e1d610bc1565b5060010190565b805169ffffffffffffffffffff81168114610e3e57600080fd5b919050565b600080600080600060a08688031215610e5b57600080fd5b610e6486610e24565b9450602086015193506040860151925060608601519150610e8760808701610e24565b90509295509295909350565b600060208284031215610ea557600080fd5b8151610a9f81610a2356fea264697066735822122063ca8245fc293655e377170a643bc00c97842d8e4cfcac4ce7ace317aa0abd7a64736f6c63430008110033

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

0000000000000000000000007b533e72e0cdc63aacd8cdb926ac402b846fbd13

-----Decoded View---------------
Arg [0] : accessControl_ (address): 0x7b533e72E0cDC63AacD8cDB926AC402b846Fbd13

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000007b533e72e0cdc63aacd8cdb926ac402b846fbd13


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.