ETH Price: $1,975.69 (+0.09%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Batch Withdraw243245932026-01-27 7:11:5926 days ago1769497919IN
0x3D0e3431...E4E088AC6
0 ETH0.000004040.03132095
Batch Withdraw242691122026-01-19 13:26:4733 days ago1768829207IN
0x3D0e3431...E4E088AC6
0 ETH0.000003540.03425982
Batch Withdraw242416962026-01-15 17:46:3537 days ago1768499195IN
0x3D0e3431...E4E088AC6
0 ETH0.000017830.13825915
Batch Withdraw241761252026-01-06 14:06:5946 days ago1767708419IN
0x3D0e3431...E4E088AC6
0 ETH0.000057240.44376049
Batch Withdraw241193372025-12-29 15:56:2354 days ago1767023783IN
0x3D0e3431...E4E088AC6
0 ETH0.000004820.04108828
Batch Withdraw240958562025-12-26 9:17:3558 days ago1766740655IN
0x3D0e3431...E4E088AC6
0 ETH0.000005530.049453
Batch Withdraw240957842025-12-26 9:03:1158 days ago1766739791IN
0x3D0e3431...E4E088AC6
0 ETH0.000005340.04547375
Batch Withdraw240957512025-12-26 8:56:3558 days ago1766739395IN
0x3D0e3431...E4E088AC6
0 ETH0.00000530.04115892
Batch Withdraw240957132025-12-26 8:48:5958 days ago1766738939IN
0x3D0e3431...E4E088AC6
0 ETH0.000003590.02788907
Batch Withdraw240956212025-12-26 8:30:3558 days ago1766737835IN
0x3D0e3431...E4E088AC6
0 ETH0.0000040.03103683
Batch Withdraw240480602025-12-19 17:13:1164 days ago1766164391IN
0x3D0e3431...E4E088AC6
0 ETH0.000018790.14571076

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x60806040240472692025-12-19 14:34:2364 days ago1766154863  Contract Creation0 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

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

Contract Source Code Verified (Exact Match)

Contract Name:
SuperVaultBatchOperator

Compiler Version
v0.8.30+commit.73712a01

Optimization Enabled:
Yes with 200 runs

Other Settings:
prague EvmVersion
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.30;

import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { ISuperVault } from "../interfaces/SuperVault/ISuperVault.sol";
import { ISuperVaultBatchOperator } from "../interfaces/SuperVault/ISuperVaultBatchOperator.sol";

/// @title SuperVaultBatchOperator
/// @author Superform Labs
/// @notice Batch operator for SuperVaults allowing batched withdrawals and redeems
/// @dev Users must approve this contract as an operator via vault.setOperator(address(this), true)
/// @dev Only addresses with OPERATOR_ROLE can call batch methods
contract SuperVaultBatchOperator is ISuperVaultBatchOperator, AccessControl {
    using SafeERC20 for IERC20;

    /*//////////////////////////////////////////////////////////////
                                CONSTANTS
    //////////////////////////////////////////////////////////////*/
    bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");

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

    /// @notice Initialize the batch operator with admin and operator
    /// @param admin The address that will have DEFAULT_ADMIN_ROLE
    /// @param operator The address that will have OPERATOR_ROLE
    constructor(address admin, address operator) {
        if (admin == address(0)) revert ZERO_ADMIN_ADDRESS();
        if (operator == address(0)) revert ZERO_OPERATOR_ADDRESS();

        _grantRole(DEFAULT_ADMIN_ROLE, admin);
        _grantRole(OPERATOR_ROLE, operator);
    }

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

    /// @notice Batch withdraw assets from multiple vaults for multiple owners
    /// @param requests The array of batch withdrawal requests
    /// @dev Requires this contract to be approved as operator for each controller on each vault
    /// @dev Individual request failures do not revert the batch - they are skipped
    function batchWithdraw(BatchRequest[] calldata requests) external override onlyRole(OPERATOR_ROLE) {
        uint256 len = requests.length;
        if (len == 0) revert EMPTY_REQUESTS();

        uint256 successCount;
        for (uint256 i; i < len; ++i) {
            BatchRequest calldata req = requests[i];

            // Skip invalid requests without reverting the batch
            if (!_isValidRequest(req)) {
                emit WithdrawRequestSkipped(i, req.vault, req.controller, req.amount);
                continue;
            }

            // receiver == controller is enforced on the vault side
            try ISuperVault(req.vault).withdraw(req.amount, req.controller, req.controller) {
                ++successCount;
            } catch {
                emit WithdrawFailed(i, req.vault, req.controller, req.amount);
            }
        }

        emit BatchWithdrawExecuted(msg.sender, successCount);
    }

    /// @notice Batch redeem shares from multiple vaults for multiple owners
    /// @param requests The array of batch redemption requests
    /// @dev Requires this contract to be approved as operator for each controller on each vault
    /// @dev Individual request failures do not revert the batch - they are skipped
    function batchRedeem(BatchRequest[] calldata requests) external override onlyRole(OPERATOR_ROLE) {
        uint256 len = requests.length;
        if (len == 0) revert EMPTY_REQUESTS();

        uint256 successCount;
        for (uint256 i; i < len; ++i) {
            BatchRequest calldata req = requests[i];

            // Skip invalid requests without reverting the batch
            if (!_isValidRequest(req)) {
                emit RedeemRequestSkipped(i, req.vault, req.controller, req.amount);
                continue;
            }

            // receiver == controller is enforced on the vault side
            try ISuperVault(req.vault).redeem(req.amount, req.controller, req.controller) {
                ++successCount;
            } catch {
                emit RedeemFailed(i, req.vault, req.controller, req.amount);
            }
        }

        emit BatchRedeemExecuted(msg.sender, successCount);
    }

    /// @notice Batch emergency withdraw tokens stuck in this contract
    /// @param tokens The array of token addresses to withdraw
    /// @param to The recipient address
    /// @dev Only callable by admin. Withdraws entire balance of each token.
    function batchEmergencyWithdraw(address[] calldata tokens, address to) external override onlyRole(DEFAULT_ADMIN_ROLE) {
        if (to == address(0)) revert ZERO_TO_ADDRESS();

        uint256[] memory amounts = new uint256[](tokens.length);

        for (uint256 i = 0; i < tokens.length; ++i) {
            address token = tokens[i];
            if (token == address(0)) revert ZERO_TOKEN_ADDRESS();
            uint256 balance = IERC20(token).balanceOf(address(this));
            amounts[i] = balance;
            if (balance > 0) {
                IERC20(token).safeTransfer(to, balance);
            }
        }

        emit BatchEmergencyWithdraw(tokens, to, amounts);
    }

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

    /// @notice Checks if a batch request is valid
    /// @param req The batch request to validate
    /// @return isValid True if the request has valid parameters
    function _isValidRequest(BatchRequest calldata req) internal pure returns (bool isValid) {
        return req.vault != address(0) && req.controller != address(0) && req.amount != 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {IERC165, ERC165} from "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual returns (bool) {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @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.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

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

    /**
     * @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 revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity >=0.4.16;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
     */
    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.30;

import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import { IERC7540Redeem, IERC7540CancelRedeem } from "../../vendor/standards/ERC7540/IERC7540Vault.sol";
import { IERC7741 } from "../../vendor/standards/ERC7741/IERC7741.sol";

/// @title ISuperVault
/// @notice Interface for SuperVault core contract that manages share minting
/// @author Superform Labs
interface ISuperVault is IERC4626, IERC7540Redeem, IERC7741, IERC7540CancelRedeem {
    /*//////////////////////////////////////////////////////////////
                                ERRORS
    //////////////////////////////////////////////////////////////*/
    error INVALID_ASSET();
    error ZERO_ADDRESS();
    error ZERO_AMOUNT();
    error INVALID_AMOUNT();
    error UNAUTHORIZED();
    error DEADLINE_PASSED();
    error INVALID_SIGNATURE();
    error NOT_IMPLEMENTED();
    error INVALID_NONCE();
    error INVALID_WITHDRAW_PRICE();
    error INVALID_CONTROLLER();
    error CONTROLLER_MUST_EQUAL_OWNER();
    error RECEIVER_MUST_EQUAL_CONTROLLER();
    error NOT_ENOUGH_ASSETS();
    error CANCELLATION_REDEEM_REQUEST_PENDING();

    /*//////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/

    event NonceInvalidated(address indexed sender, bytes32 indexed nonce);

    event SuperGovernorSet(address indexed superGovernor);

    event Initialized(address indexed asset, address indexed strategy, address indexed escrow);

    /*//////////////////////////////////////////////////////////////
                            EXTERNAL METHODS
    //////////////////////////////////////////////////////////////*/
    /// @notice Burn shares, only callable by strategy
    /// @param amount The amount of shares to burn
    function burnShares(uint256 amount) external;

    /// @notice Get the amount of assets escrowed
    function getEscrowedAssets() external view returns (uint256);

    /*//////////////////////////////////////////////////////////////
                            VIEW METHODS
    //////////////////////////////////////////////////////////////*/
    /// @notice Get the escrow address
    function escrow() external view returns (address);
}

// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.30;

/// @title ISuperVaultBatchOperator
/// @author Superform Labs
/// @notice Interface for SuperVaultBatchOperator - batch withdrawal/redeem operator for SuperVaults
interface ISuperVaultBatchOperator {
    /*//////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/

    /// @notice Emitted when a batch withdrawal is executed
    /// @param caller The address that executed the batch withdrawal
    /// @param requestCount The number of withdrawal requests processed
    event BatchWithdrawExecuted(address indexed caller, uint256 requestCount);

    /// @notice Emitted when a batch redemption is executed
    /// @param caller The address that executed the batch redemption
    /// @param requestCount The number of redemption requests processed
    event BatchRedeemExecuted(address indexed caller, uint256 requestCount);

    /// @notice Emitted when a withdrawal request is skipped due to invalid parameters
    /// @param index The index of the skipped request in the batch
    /// @param vault The vault address
    /// @param controller The controller address
    /// @param amount The requested amount
    event WithdrawRequestSkipped(uint256 indexed index, address indexed vault, address controller, uint256 amount);

    /// @notice Emitted when a withdrawal request fails during execution
    /// @param index The index of the failed request in the batch
    /// @param vault The vault address
    /// @param controller The controller address
    /// @param amount The requested amount
    event WithdrawFailed(uint256 indexed index, address indexed vault, address controller, uint256 amount);

    /// @notice Emitted when a redemption request is skipped due to invalid parameters
    /// @param index The index of the skipped request in the batch
    /// @param vault The vault address
    /// @param controller The controller address
    /// @param amount The requested amount
    event RedeemRequestSkipped(uint256 indexed index, address indexed vault, address controller, uint256 amount);

    /// @notice Emitted when a redemption request fails during execution
    /// @param index The index of the failed request in the batch
    /// @param vault The vault address
    /// @param controller The controller address
    /// @param amount The requested amount
    event RedeemFailed(uint256 indexed index, address indexed vault, address controller, uint256 amount);

    /// @notice Emitted when tokens are rescued via batch emergency withdraw
    /// @param tokens The token addresses that were withdrawn
    /// @param to The recipient address
    /// @param amounts The amounts of tokens withdrawn
    event BatchEmergencyWithdraw(address[] tokens, address indexed to, uint256[] amounts);

    /*//////////////////////////////////////////////////////////////
                                ERRORS
    //////////////////////////////////////////////////////////////*/

    error EMPTY_REQUESTS();
    error ZERO_ADMIN_ADDRESS();
    error ZERO_OPERATOR_ADDRESS();
    error ZERO_TOKEN_ADDRESS();
    error ZERO_TO_ADDRESS();

    /*//////////////////////////////////////////////////////////////
                                TYPES
    //////////////////////////////////////////////////////////////*/

    struct BatchRequest {
        address vault;
        address controller; // address that controls the shares and receives assets (must have approved this operator)
        uint256 amount; // assets for withdraw, shares for redeem
    }

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

    /// @notice Batch withdraw assets from multiple vaults for multiple owners
    /// @param requests The array of batch withdrawal requests
    /// @dev Requires this contract to be approved as operator for each controller on each vault
    /// @dev Individual request failures do not revert the batch - they are skipped
    function batchWithdraw(BatchRequest[] calldata requests) external;

    /// @notice Batch redeem shares from multiple vaults for multiple owners
    /// @param requests The array of batch redemption requests
    /// @dev Requires this contract to be approved as operator for each controller on each vault
    /// @dev Individual request failures do not revert the batch - they are skipped
    function batchRedeem(BatchRequest[] calldata requests) external;

    /// @notice Batch emergency withdraw tokens stuck in this contract
    /// @param tokens The array of token addresses to withdraw
    /// @param to The recipient address
    /// @dev Only callable by admin. Withdraws entire balance of each token.
    function batchEmergencyWithdraw(address[] calldata tokens, address to) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol)

pragma solidity >=0.8.4;

/**
 * @dev External interface of AccessControl declared to support ERC-165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @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 to signal this.
     */
    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. This account bears the admin role (for the granted role).
     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
     */
    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 `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity >=0.6.2;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol)

pragma solidity >=0.6.2;

import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";

/**
 * @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
 * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
 */
interface IERC4626 is IERC20, IERC20Metadata {
    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);

    event Withdraw(
        address indexed sender,
        address indexed receiver,
        address indexed owner,
        uint256 assets,
        uint256 shares
    );

    /**
     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
     *
     * - MUST be an ERC-20 token contract.
     * - MUST NOT revert.
     */
    function asset() external view returns (address assetTokenAddress);

    /**
     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
     *
     * - SHOULD include any compounding that occurs from yield.
     * - MUST be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT revert.
     */
    function totalAssets() external view returns (uint256 totalManagedAssets);

    /**
     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToShares(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
     * scenario where all the conditions are met.
     *
     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
     * - MUST NOT revert.
     *
     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
     * from.
     */
    function convertToAssets(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
     * through a deposit call.
     *
     * - MUST return a limited value if receiver is subject to some deposit limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
     * - MUST NOT revert.
     */
    function maxDeposit(address receiver) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
     *   in the same transaction.
     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewDeposit(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   deposit execution, and are accounted for during deposit.
     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function deposit(uint256 assets, address receiver) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
     * - MUST return a limited value if receiver is subject to some mint limit.
     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
     * - MUST NOT revert.
     */
    function maxMint(address receiver) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
     * current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
     *   same transaction.
     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
     *   would be accepted, regardless if the user has enough tokens approved, etc.
     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by minting.
     */
    function previewMint(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
     *
     * - MUST emit the Deposit event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
     *   execution, and are accounted for during mint.
     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
     *   approving enough underlying tokens to the Vault contract, etc).
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
     */
    function mint(uint256 shares, address receiver) external returns (uint256 assets);

    /**
     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
     * Vault, through a withdraw call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxWithdraw(address owner) external view returns (uint256 maxAssets);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
     *   called
     *   in the same transaction.
     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by depositing.
     */
    function previewWithdraw(uint256 assets) external view returns (uint256 shares);

    /**
     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   withdraw execution, and are accounted for during withdraw.
     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);

    /**
     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
     * through a redeem call.
     *
     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
     * - MUST NOT revert.
     */
    function maxRedeem(address owner) external view returns (uint256 maxShares);

    /**
     * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,
     * given current on-chain conditions.
     *
     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
     *   same transaction.
     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
     *   redemption would be accepted, regardless if the user has enough shares, etc.
     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
     * - MUST NOT revert.
     *
     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
     */
    function previewRedeem(uint256 shares) external view returns (uint256 assets);

    /**
     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
     *
     * - MUST emit the Withdraw event.
     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
     *   redeem execution, and are accounted for during redeem.
     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
     *   not having enough shares, etc).
     *
     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
     * Those methods should be performed separately.
     */
    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import { IERC7741 } from "../ERC7741/IERC7741.sol";

interface IERC7540Operator {
    /**
     * @dev The event emitted when an operator is set.
     *
     * @param controller The address of the controller.
     * @param operator The address of the operator.
     * @param approved The approval status.
     */
    event OperatorSet(address indexed controller, address indexed operator, bool approved);

    /**
     * @dev Sets or removes an operator for the caller.
     *
     * @param operator The address of the operator.
     * @param approved The approval status.
     * @return Whether the call was executed successfully or not
     */
    function setOperator(address operator, bool approved) external returns (bool);

    /**
     * @dev Returns `true` if the `operator` is approved as an operator for an `controller`.
     *
     * @param controller The address of the controller.
     * @param operator The address of the operator.
     * @return status The approval status
     */
    function isOperator(address controller, address operator) external view returns (bool status);
}

interface IERC7540Deposit is IERC7540Operator {
    event DepositRequest(
        address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
    );
    /**
     * @dev Transfers assets from sender into the Vault and submits a Request for asynchronous deposit.
     *
     * - MUST support ERC-20 approve / transferFrom on asset as a deposit Request flow.
     * - MUST revert if all of assets cannot be requested for deposit.
     * - owner MUST be msg.sender unless some unspecified explicit approval is given by the caller,
     *    approval of ERC-20 tokens from owner to sender is NOT enough.
     *
     * @param assets the amount of deposit assets to transfer from owner
     * @param controller the controller of the request who will be able to operate the request
     * @param owner the source of the deposit assets
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault's underlying asset token.
     */

    function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId);

    /**
     * @dev Returns the amount of requested assets in Pending state.
     *
     * - MUST NOT include any assets in Claimable state for deposit or mint.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
     */
    function pendingDepositRequest(uint256 requestId, address controller) external view returns (uint256 pendingAssets);

    /**
     * @dev Returns the amount of requested assets in Claimable state for the controller to deposit or mint.
     *
     * - MUST NOT include any assets in Pending state.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
     */
    function claimableDepositRequest(
        uint256 requestId,
        address controller
    )
        external
        view
        returns (uint256 claimableAssets);

    /**
     * @dev Mints shares Vault shares to receiver by claiming the Request of the controller.
     *
     * - MUST emit the Deposit event.
     * - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
     */
    function deposit(uint256 assets, address receiver, address controller) external returns (uint256 shares);

    /**
     * @dev Mints exactly shares Vault shares to receiver by claiming the Request of the controller.
     *
     * - MUST emit the Deposit event.
     * - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
     */
    function mint(uint256 shares, address receiver, address controller) external returns (uint256 assets);
}

interface IERC7540Redeem is IERC7540Operator {
    event RedeemRequest(
        address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
    );

    /**
     * @dev Assumes control of shares from sender into the Vault and submits a Request for asynchronous redeem.
     *
     * - MUST support a redeem Request flow where the control of shares is taken from sender directly
     *   where msg.sender has ERC-20 approval over the shares of owner.
     * - MUST revert if all of shares cannot be requested for redeem.
     *
     * @param shares the amount of shares to be redeemed to transfer from owner
     * @param controller the controller of the request who will be able to operate the request
     * @param owner the source of the shares to be redeemed
     *
     * NOTE: most implementations will require pre-approval of the Vault with the Vault's share token.
     */
    function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 requestId);

    /**
     * @dev Returns the amount of requested shares in Pending state.
     *
     * - MUST NOT include any shares in Claimable state for redeem or withdraw.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
     */
    function pendingRedeemRequest(uint256 requestId, address controller) external view returns (uint256 pendingShares);

    /**
     * @dev Returns the amount of requested shares in Claimable state for the controller to redeem or withdraw.
     *
     * - MUST NOT include any shares in Pending state for redeem or withdraw.
     * - MUST NOT show any variations depending on the caller.
     * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
     */
    function claimableRedeemRequest(
        uint256 requestId,
        address controller
    )
        external
        view
        returns (uint256 claimableShares);
}

interface IERC7540CancelDeposit {
    event CancelDepositRequest(address indexed controller, uint256 indexed requestId, address sender);
    event CancelDepositClaim(
        address indexed receiver, address indexed controller, uint256 indexed requestId, address sender, uint256 assets
    );

    /**
     * @dev Submits a Request for cancelling the pending deposit Request
     *
     * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
     *    approval of ERC-20 tokens from controller to sender is NOT enough.
     * - MUST set pendingCancelDepositRequest to `true` for the returned requestId after request
     * - MUST increase claimableCancelDepositRequest for the returned requestId after fulfillment
     * - SHOULD be claimable using `claimCancelDepositRequest`
     * Note: while `pendingCancelDepositRequest` is `true`, `requestDeposit` cannot be called
     */
    function cancelDepositRequest(uint256 requestId, address controller) external;

    /**
     * @dev Returns whether the deposit Request is pending cancelation
     *
     * - MUST NOT show any variations depending on the caller.
     */
    function pendingCancelDepositRequest(uint256 requestId, address controller) external view returns (bool isPending);

    /**
     * @dev Returns the amount of assets that were canceled from a deposit Request, and can now be claimed.
     *
     * - MUST NOT show any variations depending on the caller.
     */
    function claimableCancelDepositRequest(
        uint256 requestId,
        address controller
    )
        external
        view
        returns (uint256 claimableAssets);

    /**
     * @dev Claims the canceled deposit assets, and removes the pending cancelation Request
     *
     * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
     *    approval of ERC-20 tokens from controller to sender is NOT enough.
     * - MUST set pendingCancelDepositRequest to `false` for the returned requestId after request
     * - MUST set claimableCancelDepositRequest to 0 for the returned requestId after fulfillment
     */
    function claimCancelDepositRequest(
        uint256 requestId,
        address receiver,
        address controller
    )
        external
        returns (uint256 assets);
}

//IERC7887Redeem
interface IERC7540CancelRedeem {
    event CancelRedeemRequest(address indexed controller, uint256 indexed requestId, address sender);
    event CancelRedeemClaim(
        address indexed receiver, address indexed controller, uint256 indexed requestId, address sender, uint256 shares
    );

    /**
     * @dev Submits a Request for cancelling the pending redeem Request
     *
     * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
     *    approval of ERC-20 tokens from controller to sender is NOT enough.
     * - MUST set pendingCancelRedeemRequest to `true` for the returned requestId after request
     * - MUST increase claimableCancelRedeemRequest for the returned requestId after fulfillment
     * - SHOULD be claimable using `claimCancelRedeemRequest`
     * Note: while `pendingCancelRedeemRequest` is `true`, `requestRedeem` cannot be called
     */
    function cancelRedeemRequest(uint256 requestId, address controller) external;

    /**
     * @dev Returns whether the redeem Request is pending cancelation
     *
     * - MUST NOT show any variations depending on the caller.
     */
    function pendingCancelRedeemRequest(uint256 requestId, address controller) external view returns (bool isPending);

    /**
     * @dev Returns the amount of shares that were canceled from a redeem Request, and can now be claimed.
     *
     * - MUST NOT show any variations depending on the caller.
     */
    function claimableCancelRedeemRequest(
        uint256 requestId,
        address controller
    )
        external
        view
        returns (uint256 claimableShares);

    /**
     * @dev Claims the canceled redeem shares, and removes the pending cancelation Request
     *
     * - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
     *    approval of ERC-20 tokens from controller to sender is NOT enough.
     * - MUST set pendingCancelRedeemRequest to `false` for the returned requestId after request
     * - MUST set claimableCancelRedeemRequest to 0 for the returned requestId after fulfillment
     */
    function claimCancelRedeemRequest(
        uint256 requestId,
        address receiver,
        address controller
    )
        external
        returns (uint256 shares);
}

/**
 * @title  IERC7540
 * @dev    Fully async ERC7540 implementation according to the standard
 * @dev    Adapted from Centrifuge's IERC7540 implementation
 */
interface IERC7540 is IERC7540Deposit, IERC7540Redeem { }

/**
 * @title  IERC7540Vault
 * @dev    This is the specific set of interfaces used by the SuperVaults
 */
interface IERC7540Vault is IERC7540, IERC7741 {
    event DepositClaimable(address indexed controller, uint256 indexed requestId, uint256 assets, uint256 shares);
    event RedeemClaimable(address indexed controller, uint256 indexed requestId, uint256 assets, uint256 shares);
}

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

interface IERC7741 {
    /**
     * @dev Grants or revokes permissions for `operator` to manage Requests on behalf of the
     *      `msg.sender`, using an [EIP-712](./eip-712.md) signature.
     */
    function authorizeOperator(
        address controller,
        address operator,
        bool approved,
        bytes32 nonce,
        uint256 deadline,
        bytes memory signature
    )
        external
        returns (bool);

    /**
     * @dev Revokes the given `nonce` for `msg.sender` as the `owner`.
     */
    function invalidateNonce(bytes32 nonce) external;

    /**
     * @dev Returns whether the given `nonce` has been used for the `controller`.
     */
    function authorizations(address controller, bytes32 nonce) external view returns (bool used);

    /**
     * @dev Returns the `DOMAIN_SEPARATOR` as defined according to EIP-712. The `DOMAIN_SEPARATOR
     *      should be unique to the contract and chain to prevent replay attacks from other domains,
     *      and satisfy the requirements of EIP-712, but is otherwise unconstrained.
     */
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity >=0.4.16;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 15 of 17 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity >=0.4.16;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 16 of 17 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity >=0.4.16;

import {IERC165} from "../utils/introspection/IERC165.sol";

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity >=0.6.2;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
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);
}

Settings
{
  "remappings": [
    "@superform-v2-core/=lib/v2-core/",
    "@openzeppelin/contracts/=lib/v2-core/lib/openzeppelin-contracts/contracts/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@chimera/=lib/setup-helpers/lib/chimera/src/",
    "@recon/=lib/setup-helpers/src/",
    "excessivelySafeCall/=lib/v2-core/lib/ExcessivelySafeCall/src/",
    "modulekit/=lib/v2-core/lib/modulekit/src/",
    "@prb/math/=lib/v2-core/lib/modulekit/node_modules/@prb/math/src/",
    "@solady/=lib/v2-core/lib/solady/",
    "@account-abstraction/=lib/v2-core/lib/modulekit/node_modules/account-abstraction/contracts/",
    "@ERC4337/=lib/v2-core/lib/modulekit/node_modules/@ERC4337/",
    "@pigeon/=lib/v2-core/lib/pigeon/src/",
    "@surl/=lib/v2-core/lib/surl/src/",
    "@stringutils/=lib/v2-core/lib/solidity-stringutils/src/",
    "@pendle/=lib/v2-core/lib/pendle-core-v2-public/contracts/",
    "@safe/=lib/v2-core/lib/safe-smart-account/contracts/",
    "@safe7579/=lib/v2-core/lib/safe7579/src/",
    "@nexus/=lib/v2-core/lib/nexus/contracts/",
    "@properties-7540/=lib/erc7540-reusable-properties/src/",
    "sentinellist/=lib/v2-core/lib/nexus/node_modules/sentinellist/src/",
    "solady/=lib/v2-core/lib/solady/src/",
    "solarray/=lib/v2-core/lib/nexus/node_modules/solarray/src/",
    "account-abstraction/=lib/v2-core/lib/modulekit/node_modules/@ERC4337/account-abstraction/contracts/",
    "account-abstraction-v0.6/=lib/v2-core/lib/modulekit/node_modules/@ERC4337/account-abstraction-v0.6/contracts/",
    "excessively-safe-call/=lib/v2-core/lib/ExcessivelySafeCall/src/",
    "composability/=lib/v2-core/lib/nexus/node_modules/@biconomy/composability/contracts/",
    "erc7739Validator/=lib/v2-core/lib/nexus/node_modules/erc7739-validator-base/src/",
    "test/mock_fiattoken/=lib/v2-core/lib/evm-gateway-contracts/test/mock_fiattoken/",
    "@rhinestone/erc4337-validation/=lib/v2-core/lib/modulekit/node_modules/@rhinestone/erc4337-validation/",
    "erc4337-validation/=lib/v2-core/lib/modulekit/node_modules/@rhinestone/erc4337-validation/src/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
    "@layerzerolabs/oft-evm/=lib/devtools/packages/oft-evm/",
    "@layerzerolabs/oapp-evm/=lib/devtools/packages/oapp-evm/",
    "@layerzerolabs/lz-evm-protocol-v2/=lib/LayerZero-v2/packages/layerzero-v2/evm/protocol/",
    "@layerzerolabs/lz-evm-messagelib-v2/=lib/LayerZero-v2/packages/layerzero-v2/evm/messagelib/",
    "solidity-bytes-utils/=lib/solidity-bytes-utils/",
    "@biconomy/=lib/v2-core/lib/nexus/node_modules/@biconomy/",
    "@ensdomains/=lib/v2-core/lib/v4-core/node_modules/@ensdomains/",
    "@erc7579/=lib/v2-core/lib/nexus/node_modules/@erc7579/",
    "@gnosis.pm/=lib/v2-core/lib/modulekit/node_modules/@gnosis.pm/",
    "@memview-sol/=lib/v2-core/lib/evm-gateway-contracts/lib/memview-sol/contracts/",
    "@safe-global/=lib/v2-core/lib/nexus/node_modules/@safe-global/",
    "@zerodev/=lib/v2-core/lib/nexus/node_modules/@zerodev/",
    "ExcessivelySafeCall/=lib/v2-core/lib/ExcessivelySafeCall/src/",
    "LayerZero-v2/=lib/LayerZero-v2/",
    "chimera/=lib/chimera/src/",
    "devtools/=lib/devtools/packages/toolbox-foundry/src/",
    "ds-test/=lib/v2-core/lib/nexus/node_modules/ds-test/",
    "enumerableset4337/=lib/v2-core/lib/nexus/node_modules/erc7739-validator-base/node_modules/@erc7579/enumerablemap4337/src/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
    "erc7540-reusable-properties/=lib/erc7540-reusable-properties/src/",
    "erc7579/=lib/v2-core/lib/nexus/node_modules/erc7579/",
    "erc7739-validator-base/=lib/v2-core/lib/nexus/node_modules/erc7739-validator-base/",
    "eth-gas-reporter/=lib/v2-core/lib/nexus/node_modules/eth-gas-reporter/",
    "evm-gateway-contracts/=lib/v2-core/lib/evm-gateway-contracts/",
    "evm-gateway/=lib/v2-core/lib/evm-gateway-contracts/src/",
    "hardhat-deploy/=lib/v2-core/lib/modulekit/node_modules/hardhat-deploy/",
    "hardhat/=lib/v2-core/lib/modulekit/node_modules/hardhat/",
    "kernel/=lib/v2-core/lib/nexus/node_modules/erc7739-validator-base/node_modules/@zerodev/kernel/src/",
    "memview-sol/=lib/v2-core/lib/evm-gateway-contracts/lib/memview-sol/contracts/",
    "module-bases/=lib/v2-core/lib/safe7579/node_modules/@rhinestone/module-bases/src/",
    "nexus/=lib/v2-core/lib/nexus/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
    "pendle-core-v2-public/=lib/v2-core/lib/pendle-core-v2-public/contracts/",
    "pigeon/=lib/v2-core/lib/pigeon/src/",
    "prep/=lib/v2-core/lib/nexus/node_modules/prep/",
    "rhinestone/checknsignatures/=lib/v2-core/lib/safe7579/node_modules/@rhinestone/checknsignatures/",
    "safe-smart-account/=lib/v2-core/lib/safe-smart-account/",
    "safe7579/=lib/v2-core/lib/safe7579/",
    "setup-helpers/=lib/setup-helpers/src/",
    "solidity-stringutils/=lib/v2-core/lib/solidity-stringutils/",
    "solmate/=lib/v2-core/lib/v4-core/lib/solmate/",
    "surl/=lib/v2-core/lib/surl/",
    "v2-core/=lib/v2-core/",
    "v4-core/=lib/v2-core/lib/v4-core/src/",
    "lib/evm-gateway-contracts:src/=lib/v2-core/lib/evm-gateway-contracts/src/",
    "lib/evm-gateway-contracts:test/=lib/v2-core/lib/evm-gateway-contracts/test/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "prague",
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"EMPTY_REQUESTS","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"ZERO_ADMIN_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_OPERATOR_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_TOKEN_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_TO_ADDRESS","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"BatchEmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"requestCount","type":"uint256"}],"name":"BatchRedeemExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"requestCount","type":"uint256"}],"name":"BatchWithdrawExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"controller","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RedeemFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"controller","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RedeemRequestSkipped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"controller","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"controller","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawRequestSkipped","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address","name":"to","type":"address"}],"name":"batchEmergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"controller","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISuperVaultBatchOperator.BatchRequest[]","name":"requests","type":"tuple[]"}],"name":"batchRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"controller","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISuperVaultBatchOperator.BatchRequest[]","name":"requests","type":"tuple[]"}],"name":"batchWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

608060405234801561000f575f5ffd5b50604051610fb3380380610fb383398101604081905261002e9161017d565b6001600160a01b0382166100555760405163b8a6675f60e01b815260040160405180910390fd5b6001600160a01b03811661007c5760405163eec3626f60e01b815260040160405180910390fd5b6100865f836100b9565b506100b17f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b929826100b9565b5050506101ae565b5f828152602081815260408083206001600160a01b038516845290915281205460ff16610159575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101113390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161015c565b505f5b92915050565b80516001600160a01b0381168114610178575f5ffd5b919050565b5f5f6040838503121561018e575f5ffd5b61019783610162565b91506101a560208401610162565b90509250929050565b610df8806101bb5f395ff3fe608060405234801561000f575f5ffd5b50600436106100a6575f3560e01c806336568abe1161006e57806336568abe1461013d57806344559b3c1461015057806391d1485414610163578063a217fddf14610176578063d547741f1461017d578063f5b541a614610190575f5ffd5b806301ffc9a7146100aa5780630513d63d146100d25780630baf3fae146100e7578063248a9ca3146100fa5780632f2ff15d1461012a575b5f5ffd5b6100bd6100b8366004610b6e565b6101b7565b60405190151581526020015b60405180910390f35b6100e56100e0366004610b9c565b6101ed565b005b6100e56100f5366004610b9c565b610454565b61011c610108366004610c0d565b5f9081526020819052604090206001015490565b6040519081526020016100c9565b6100e5610138366004610c3f565b6106b0565b6100e561014b366004610c3f565b6106da565b6100e561015e366004610c69565b610712565b6100bd610171366004610c3f565b6108ce565b61011c5f81565b6100e561018b366004610c3f565b6108f6565b61011c7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92981565b5f6001600160e01b03198216637965db0b60e01b14806101e757506301ffc9a760e01b6001600160e01b03198316145b92915050565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9296102178161091a565b815f819003610239576040516314990d3f60e31b815260040160405180910390fd5b5f5f5b82811015610416573686868381811061025757610257610ce8565b905060600201905061026881610927565b6102dd576102796020820182610cfc565b6001600160a01b0316827f4996fb0e0cff74859f415ac3f36fe452f5cb8d675b129e903ffa7ec96b01093a6102b46040850160208601610cfc565b604080516001600160a01b0390921682528086013560208301520160405180910390a35061040e565b6102ea6020820182610cfc565b6001600160a01b031663b460af946040830180359061030c9060208601610cfc565b61031c6040860160208701610cfc565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b0391821660248401521660448201526064016020604051808303815f875af192505050801561038b575060408051601f3d908101601f1916820190925261038891810190610d15565b60015b6103ff5761039c6020820182610cfc565b6001600160a01b0316827f0e0e09850922e2234c4cec8b1fb49c549130f1e25c268f710d41579eb4826a706103d76040850160208601610cfc565b604080516001600160a01b0390921682528086013560208301520160405180910390a361040c565b5061040983610d2c565b92505b505b60010161023c565b5060405181815233907f52cc3cbb9ba447be2acf8c157cfb0f7b133158f4c4ad10a43f43d77c18c37168906020015b60405180910390a25050505050565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92961047e8161091a565b815f8190036104a0576040516314990d3f60e31b815260040160405180910390fd5b5f5f5b8281101561067d57368686838181106104be576104be610ce8565b90506060020190506104cf81610927565b610544576104e06020820182610cfc565b6001600160a01b0316827fec45852a920fb023a1d176a20ac66c4de7a9188a6acffd83ffc66368b58299b061051b6040850160208601610cfc565b604080516001600160a01b0390921682528086013560208301520160405180910390a350610675565b6105516020820182610cfc565b6001600160a01b031663ba087652604083018035906105739060208601610cfc565b6105836040860160208701610cfc565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b0391821660248401521660448201526064016020604051808303815f875af19250505080156105f2575060408051601f3d908101601f191682019092526105ef91810190610d15565b60015b610666576106036020820182610cfc565b6001600160a01b0316827f53e10e5c1b2fec3b613c6b8c88e69cfc5672696d0092541411737693ff9e487661063e6040850160208601610cfc565b604080516001600160a01b0390921682528086013560208301520160405180910390a3610673565b5061067083610d2c565b92505b505b6001016104a3565b5060405181815233907f5ab7aa1e8bc519ae6e033dae855bc90b28f3ac4699e1ef2ab6fdee8d2a1c96cb90602001610445565b5f828152602081905260409020600101546106ca8161091a565b6106d48383610976565b50505050565b6001600160a01b03811633146107035760405163334bd91960e11b815260040160405180910390fd5b61070d8282610a05565b505050565b5f61071c8161091a565b6001600160a01b03821661074357604051638c75b9ff60e01b815260040160405180910390fd5b5f8367ffffffffffffffff81111561075d5761075d610d50565b604051908082528060200260200182016040528015610786578160200160208202803683370190505b5090505f5b84811015610890575f8686838181106107a6576107a6610ce8565b90506020020160208101906107bb9190610cfc565b90506001600160a01b0381166107e457604051631a3ec99560e11b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610828573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061084c9190610d15565b90508084848151811061086157610861610ce8565b60209081029190910101528015610886576108866001600160a01b0383168783610a6e565b505060010161078b565b50826001600160a01b03167ff51aa207463e9869b2dd9463eb5be4109216115d6580f7b59991a9e3d7cc9f1f86868460405161044593929190610d64565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f828152602081905260409020600101546109108161091a565b6106d48383610a05565b6109248133610ac0565b50565b5f806109366020840184610cfc565b6001600160a01b03161415801561096557505f6109596040840160208501610cfc565b6001600160a01b031614155b80156101e757505060400135151590565b5f61098183836108ce565b6109fe575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556109b63390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016101e7565b505f6101e7565b5f610a1083836108ce565b156109fe575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016101e7565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261070d908490610b02565b610aca82826108ce565b610afe5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044015b60405180910390fd5b5050565b5f5f60205f8451602086015f885af180610b21576040513d5f823e3d81fd5b50505f513d91508115610b38578060011415610b45565b6001600160a01b0384163b155b156106d457604051635274afe760e01b81526001600160a01b0385166004820152602401610af5565b5f60208284031215610b7e575f5ffd5b81356001600160e01b031981168114610b95575f5ffd5b9392505050565b5f5f60208385031215610bad575f5ffd5b823567ffffffffffffffff811115610bc3575f5ffd5b8301601f81018513610bd3575f5ffd5b803567ffffffffffffffff811115610be9575f5ffd5b856020606083028401011115610bfd575f5ffd5b6020919091019590945092505050565b5f60208284031215610c1d575f5ffd5b5035919050565b80356001600160a01b0381168114610c3a575f5ffd5b919050565b5f5f60408385031215610c50575f5ffd5b82359150610c6060208401610c24565b90509250929050565b5f5f5f60408486031215610c7b575f5ffd5b833567ffffffffffffffff811115610c91575f5ffd5b8401601f81018613610ca1575f5ffd5b803567ffffffffffffffff811115610cb7575f5ffd5b8660208260051b8401011115610ccb575f5ffd5b602091820194509250610cdf908501610c24565b90509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215610d0c575f5ffd5b610b9582610c24565b5f60208284031215610d25575f5ffd5b5051919050565b5f60018201610d4957634e487b7160e01b5f52601160045260245ffd5b5060010190565b634e487b7160e01b5f52604160045260245ffd5b604080825281018390525f8460608301825b86811015610da4576001600160a01b03610d8f84610c24565b16825260209283019290910190600101610d76565b50838103602080860191909152855180835291810192508501905f5b81811015610dde578251845260209384019390920191600101610dc0565b509197965050505050505056fea164736f6c634300081e000a00000000000000000000000089226a5fd572f380991bb17c20c96ba91f98ad2e00000000000000000000000002cbf3dac926743ec757b5a51310f46580e25a04

Deployed Bytecode

0x608060405234801561000f575f5ffd5b50600436106100a6575f3560e01c806336568abe1161006e57806336568abe1461013d57806344559b3c1461015057806391d1485414610163578063a217fddf14610176578063d547741f1461017d578063f5b541a614610190575f5ffd5b806301ffc9a7146100aa5780630513d63d146100d25780630baf3fae146100e7578063248a9ca3146100fa5780632f2ff15d1461012a575b5f5ffd5b6100bd6100b8366004610b6e565b6101b7565b60405190151581526020015b60405180910390f35b6100e56100e0366004610b9c565b6101ed565b005b6100e56100f5366004610b9c565b610454565b61011c610108366004610c0d565b5f9081526020819052604090206001015490565b6040519081526020016100c9565b6100e5610138366004610c3f565b6106b0565b6100e561014b366004610c3f565b6106da565b6100e561015e366004610c69565b610712565b6100bd610171366004610c3f565b6108ce565b61011c5f81565b6100e561018b366004610c3f565b6108f6565b61011c7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92981565b5f6001600160e01b03198216637965db0b60e01b14806101e757506301ffc9a760e01b6001600160e01b03198316145b92915050565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b9296102178161091a565b815f819003610239576040516314990d3f60e31b815260040160405180910390fd5b5f5f5b82811015610416573686868381811061025757610257610ce8565b905060600201905061026881610927565b6102dd576102796020820182610cfc565b6001600160a01b0316827f4996fb0e0cff74859f415ac3f36fe452f5cb8d675b129e903ffa7ec96b01093a6102b46040850160208601610cfc565b604080516001600160a01b0390921682528086013560208301520160405180910390a35061040e565b6102ea6020820182610cfc565b6001600160a01b031663b460af946040830180359061030c9060208601610cfc565b61031c6040860160208701610cfc565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b0391821660248401521660448201526064016020604051808303815f875af192505050801561038b575060408051601f3d908101601f1916820190925261038891810190610d15565b60015b6103ff5761039c6020820182610cfc565b6001600160a01b0316827f0e0e09850922e2234c4cec8b1fb49c549130f1e25c268f710d41579eb4826a706103d76040850160208601610cfc565b604080516001600160a01b0390921682528086013560208301520160405180910390a361040c565b5061040983610d2c565b92505b505b60010161023c565b5060405181815233907f52cc3cbb9ba447be2acf8c157cfb0f7b133158f4c4ad10a43f43d77c18c37168906020015b60405180910390a25050505050565b7f97667070c54ef182b0f5858b034beac1b6f3089aa2d3188bb1e8929f4fa9b92961047e8161091a565b815f8190036104a0576040516314990d3f60e31b815260040160405180910390fd5b5f5f5b8281101561067d57368686838181106104be576104be610ce8565b90506060020190506104cf81610927565b610544576104e06020820182610cfc565b6001600160a01b0316827fec45852a920fb023a1d176a20ac66c4de7a9188a6acffd83ffc66368b58299b061051b6040850160208601610cfc565b604080516001600160a01b0390921682528086013560208301520160405180910390a350610675565b6105516020820182610cfc565b6001600160a01b031663ba087652604083018035906105739060208601610cfc565b6105836040860160208701610cfc565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b0391821660248401521660448201526064016020604051808303815f875af19250505080156105f2575060408051601f3d908101601f191682019092526105ef91810190610d15565b60015b610666576106036020820182610cfc565b6001600160a01b0316827f53e10e5c1b2fec3b613c6b8c88e69cfc5672696d0092541411737693ff9e487661063e6040850160208601610cfc565b604080516001600160a01b0390921682528086013560208301520160405180910390a3610673565b5061067083610d2c565b92505b505b6001016104a3565b5060405181815233907f5ab7aa1e8bc519ae6e033dae855bc90b28f3ac4699e1ef2ab6fdee8d2a1c96cb90602001610445565b5f828152602081905260409020600101546106ca8161091a565b6106d48383610976565b50505050565b6001600160a01b03811633146107035760405163334bd91960e11b815260040160405180910390fd5b61070d8282610a05565b505050565b5f61071c8161091a565b6001600160a01b03821661074357604051638c75b9ff60e01b815260040160405180910390fd5b5f8367ffffffffffffffff81111561075d5761075d610d50565b604051908082528060200260200182016040528015610786578160200160208202803683370190505b5090505f5b84811015610890575f8686838181106107a6576107a6610ce8565b90506020020160208101906107bb9190610cfc565b90506001600160a01b0381166107e457604051631a3ec99560e11b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610828573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061084c9190610d15565b90508084848151811061086157610861610ce8565b60209081029190910101528015610886576108866001600160a01b0383168783610a6e565b505060010161078b565b50826001600160a01b03167ff51aa207463e9869b2dd9463eb5be4109216115d6580f7b59991a9e3d7cc9f1f86868460405161044593929190610d64565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f828152602081905260409020600101546109108161091a565b6106d48383610a05565b6109248133610ac0565b50565b5f806109366020840184610cfc565b6001600160a01b03161415801561096557505f6109596040840160208501610cfc565b6001600160a01b031614155b80156101e757505060400135151590565b5f61098183836108ce565b6109fe575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556109b63390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016101e7565b505f6101e7565b5f610a1083836108ce565b156109fe575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45060016101e7565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261070d908490610b02565b610aca82826108ce565b610afe5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044015b60405180910390fd5b5050565b5f5f60205f8451602086015f885af180610b21576040513d5f823e3d81fd5b50505f513d91508115610b38578060011415610b45565b6001600160a01b0384163b155b156106d457604051635274afe760e01b81526001600160a01b0385166004820152602401610af5565b5f60208284031215610b7e575f5ffd5b81356001600160e01b031981168114610b95575f5ffd5b9392505050565b5f5f60208385031215610bad575f5ffd5b823567ffffffffffffffff811115610bc3575f5ffd5b8301601f81018513610bd3575f5ffd5b803567ffffffffffffffff811115610be9575f5ffd5b856020606083028401011115610bfd575f5ffd5b6020919091019590945092505050565b5f60208284031215610c1d575f5ffd5b5035919050565b80356001600160a01b0381168114610c3a575f5ffd5b919050565b5f5f60408385031215610c50575f5ffd5b82359150610c6060208401610c24565b90509250929050565b5f5f5f60408486031215610c7b575f5ffd5b833567ffffffffffffffff811115610c91575f5ffd5b8401601f81018613610ca1575f5ffd5b803567ffffffffffffffff811115610cb7575f5ffd5b8660208260051b8401011115610ccb575f5ffd5b602091820194509250610cdf908501610c24565b90509250925092565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215610d0c575f5ffd5b610b9582610c24565b5f60208284031215610d25575f5ffd5b5051919050565b5f60018201610d4957634e487b7160e01b5f52601160045260245ffd5b5060010190565b634e487b7160e01b5f52604160045260245ffd5b604080825281018390525f8460608301825b86811015610da4576001600160a01b03610d8f84610c24565b16825260209283019290910190600101610d76565b50838103602080860191909152855180835291810192508501905f5b81811015610dde578251845260209384019390920191600101610dc0565b509197965050505050505056fea164736f6c634300081e000a

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

00000000000000000000000089226a5fd572f380991bb17c20c96ba91f98ad2e00000000000000000000000002cbf3dac926743ec757b5a51310f46580e25a04

-----Decoded View---------------
Arg [0] : admin (address): 0x89226a5Fd572f380991Bb17c20c96ba91F98aD2e
Arg [1] : operator (address): 0x02cbf3dac926743ec757b5A51310f46580e25A04

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000089226a5fd572f380991bb17c20c96ba91f98ad2e
Arg [1] : 00000000000000000000000002cbf3dac926743ec757b5a51310f46580e25a04


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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