OptimexConnector

Description:

Decentralized Finance (DeFi) protocol contract providing Factory functionality.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "@openzeppelin/contracts/interfaces/IERC1363.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.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);
}
"
    },
    "@openzeppelin/contracts/interfaces/IERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)

pragma solidity >=0.4.16;

import {IERC165} from "../utils/introspection/IERC165.sol";
"
    },
    "@openzeppelin/contracts/interfaces/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)

pragma solidity >=0.4.16;

import {IERC20} from "../token/ERC20/IERC20.sol";
"
    },
    "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.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);
}
"
    },
    "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
      "content": "// 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);
    }
}
"
    },
    "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.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);
}
"
    },
    "contracts/interfaces/IOptimexMessageHandler.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

/**
 * @title IOptimexMessageHandler
 * @notice Interface for handling messages from Optimex protocol components
 * @author Optimex Protocol
 */
interface IOptimexMessageHandler {
    /**
     * @notice Handles a message sent by the Optimex contracts
     *     @dev The caller may optionally attach native value (msg.value) for use by the callee
     *     @param message ABI-encoded calldata containing the operations to execute
     */
    function handleMessage(bytes calldata message) external payable;
}
"
    },
    "contracts/interfaces/IOptimexProtocol.sol": {
      "content": "// SPDX-License-Identifier: None
pragma solidity ^0.8.20;

import "./IProtocol.sol";

/**
 * @title IOptimexProtocol
 * @notice Extend the base IProtocol interface to provide role-based access control
 * @author Optimex Protocol
 */
interface IOptimexProtocol is IProtocol {
    /**
     * @notice Checks whether the specified `account` has been granted the given `role`.
     *     @param role The role to check, represented as a `bytes32` value.
     *     @param account The address of the account to check.
     *     @return isGranted granted = true, otherwise false.
     */
    function hasRole(bytes32 role, address account) external view returns (bool isGranted);
}
"
    },
    "contracts/interfaces/IProtocol.sol": {
      "content": "// SPDX-License-Identifier: None
pragma solidity ^0.8.20;

/**
 * @title IProtocol
 * @notice Provide the base interface for interacting with the Optimex Protocol contract
 * @author Optimex Protocol
 */
interface IProtocol {
    /**
     * @notice Returns the address of the current owner.
     *     @return currentOwner The current contract's owner.
     */
    function owner() external view returns (address currentOwner);

    /**
     * @notice Returns the current address of the Protocol Fee Receiver.
     *     @return pFeeReceiver The protocol fee receiver's address.
     */
    function pFeeAddr() external view returns (address pFeeReceiver);
}
"
    },
    "contracts/libraries/Bundle.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import "../libraries/Structs.sol";
import "../libraries/ErrorLib.sol";

/**
 * @title Bundle
 * @notice Library for executing multiple external calls in a single transaction
 * @dev This library provides functionality to execute multiple external calls
 *      as a bundle within a single transaction. It ensures atomic execution
 *      where all calls must succeed or the entire transaction reverts.
 * @author Optimex Protocol
 */
library Bundle {
    /**
     * @notice Executes multiple external calls atomically in a single transaction
     * @dev This function processes an array of Call structs and executes them sequentially.
     *      If any call fails, the entire transaction reverts, ensuring atomicity.
     *      Each call can include ETH value transfers and arbitrary calldata.
     */
    function multicall(Call[] memory bundle) internal {
        require(bundle.length > 0, ErrorLib.EmptyBundle());

        for (uint256 i; i < bundle.length; ++i) {
            address to = bundle[i].to;
            (bool success, bytes memory returnData) = to.call{value: bundle[i].value}(bundle[i].data);
            require(success, ErrorLib.MultiCallFailed(to, i, returnData));
        }
    }
}
"
    },
    "contracts/libraries/ErrorLib.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

/**
 * @title ErrorLib
 * @notice Provides common error messages for the Optimex Lending Protocol
 * @dev Designed as a library to be used by other Optimex Lending Protocol contracts
 * @author Optimex Protocol
 */
library ErrorLib {
    error AccessDenied(bytes32 positionId);
    error AttachedValueMismatch(uint256 expected, uint256 actual);
    error AuthorizerNotGranted();
    error DeadlineExpired();
    error EmptyBundle();
    error ExceedMaxAcceptanceFee(uint256 maxAcceptedFee, uint256 fee);
    error InvalidAmount();
    error InvalidAuthorizerSig();
    error InvalidBorrowShares();
    error InvalidMarketId();
    error InvalidOwner(address account);
    error InvalidPosition(bytes32 positionId);
    error InvalidValidator(address validator);
    error MultiCallFailed(address to, uint256 index, bytes returnedData);
    error PositionAlreadyExists();
    error RecipientNotPermitted(address recipient);
    error StateAlreadySet();
    error TokenMismatch(address expected, address actual);
    error Unauthorized(address sender);
    error Uncollateralized(bytes32 positionId);
    error ZeroAddress();
    error ZeroAmount();
}
"
    },
    "contracts/libraries/Structs.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

/// @notice Enum that defines the access permission of an Optimex position
/// @param FULL_ACCESS For this state, the position can perform all position-related operations
/// @param EXIT_ONLY For this state, only following operations are allowed:
///   - Repaying assets
///   - Withdrawing collateral
///   - Claiming credits
/// @param REPAY_WITHDRAW For this state, only the following operations are allowed:
///   - Repaying assets
///   - Withdrawing collateral
enum Permission {
    FULL_ACCESS,
    EXIT_ONLY,
    REPAY_WITHDRAW
}

/// @notice Struct to store the result of a payment operation: liquidation or repayment
/// @param seizedCollateral The amount of collateral being seized from the position
/// @param remainCollateral The portion of collateral that remains after seizure
/// @param repaidDebt The amount of debt repaid to Morpho
/// @param surplus The left-over amount being returned to the AccountPositionManager
/// @param profit The amount being taken as profit
///
/// @dev
/// - On liquidation, the `seizedCollateral` is calculated by Morpho based on the `borrowShares`
/// - On repayment, the `seizedCollateral` is set to `0`
///
/// @dev
/// - On liquidation, the `remainCollateral` is the portion of collateral that remains after seizure
/// - On repayment, the `remainCollateral` is set to `totalCollateral`.
///   The AccountPositionManager can then withdraw the full amount of collateral
///   and transfer it back to the ERC-20 contract for removal from circulation
struct PaymentResult {
    uint256 seizedCollateral;
    uint256 remainCollateral;
    uint256 repaidDebt;
    uint256 surplus;
    uint256 profit;
}

/// @notice Contains access control information for an Optimex position.
/// @param marketId The identifier of the market
/// @param positionAccount The dedicated account that represents a position in Morpho
/// @param owner The address of the position owner authorized to perform actions.
/// @param validator The address of the validator allowed to perform special actions.
struct MarketAccess {
    bytes32 marketId;
    address positionAccount;
    address owner;
    address validator;
}

/// @notice Struct containing the data needed to borrow assets from a position
/// @param borrowAmount The amount of assets to borrow
/// @param fee The fee charged for this request
/// @param recipient The address to receive the borrowed assets
/// @param deadline The timestamp after which the signature is no longer valid
struct BorrowRequest {
    uint256 borrowAmount;
    uint256 fee;
    address recipient;
    uint64 deadline;
}

/// Authored: https://github.com/morpho-org/bundler3/blob/main/src/interfaces/IBundler3.sol
/// @notice Struct containing all the data needed to make a call.
/// @notice The call target is `to`, the calldata is `data` with value `value`.
/// @notice If `skipRevert` is true, other planned calls will continue executing even if this call reverts. `skipRevert`
/// will ignore all reverts. Use with caution.
/// @notice If the call will trigger a reenter, the callbackHash should be set to the hash of the reenter bundle data.
struct Call {
    address to;
    bytes data;
    uint256 value;
    bool skipRevert;
    bytes32 callbackHash;
}
"
    },
    "contracts/protocol/OptimexAdminGuard.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

import "../libraries/ErrorLib.sol";
import "../interfaces/IOptimexProtocol.sol";

/**
 * @title OptimexAdminGuard
 * @notice Access control contract that provides admin-only functionality.
 * @dev This contract serves as a base contract for other Optimex contracts that need admin access control.
 * @author Optimex Protocol
 */
contract OptimexAdminGuard {
    /// @dev Address of the OptimexProtocol contract
    IOptimexProtocol internal _protocol;

    /**
     * @notice Emitted when the OptimexProtocol address is updated.
     *     @param operator The address of the caller (owner) who performed the update.
     *     @param newProtocol The new OptimexProtocol contract address.
     *     @dev Related function: { setProtocol }
     */
    event ProtocolUpdated(address indexed operator, address indexed newProtocol);

    modifier onlyAdmin() {
        address sender = msg.sender;
        if (sender != _getProtocol().owner()) {
            revert ErrorLib.Unauthorized(sender);
        }
        _;
    }

    constructor(IOptimexProtocol protocol) {
        _protocol = protocol;
    }

    /**
     * @notice Returns the current address of the OptimexProtocol contract.
     *     @dev Can be called by anyone.
     *     @return protocol The OptimexProtocol address.
     */
    function getProtocol() external view returns (address protocol) {
        protocol = address(_getProtocol());
    }

    /**
     * @notice Updates the OptimexProtocol contract to a new address.
     *     @dev Caller must be the current Admin of the OptimexProtocol contract.
     *     @param newProtocol The new OptimexProtocol contract address.
     */
    function setProtocol(address newProtocol) external onlyAdmin {
        if (newProtocol == address(0)) revert ErrorLib.ZeroAddress();

        _protocol = IOptimexProtocol(newProtocol);

        emit ProtocolUpdated(msg.sender, newProtocol);
    }

    function _isAuthorized(bytes32 role, address account) internal view virtual returns (bool) {
        return _getProtocol().hasRole(role, account);
    }

    function _getProtocol() internal view virtual returns (IOptimexProtocol) {
        return _protocol;
    }
}
"
    },
    "contracts/protocol/OptimexDomain.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

/**
 * @title Optimex Domain Information
 * @notice Provides a standardized way to expose the contract's name and version.
 * @dev Designed as an abstract base contract to be inherited by other Optimex contracts.
 * @author Optimex Protocol
 */
abstract contract OptimexDomain {
    /// @notice The name identifier for the Optimex contract domain.
    string internal _name;

    /// @notice The version identifier for the Optimex contract domain.
    string internal _version;

    constructor(string memory name, string memory version) {
        _name = name;
        _version = version;
    }

    /**
     * @notice Returns the domain information of the Optimex contract.
     *     @dev Can be called by anyone
     *     @return name The name of the contract.
     *     @return version The current version of the contract.
     */
    function optimexDomain() external view virtual returns (string memory name, string memory version) {
        name = _name;
        version = _version;
    }
}
"
    },
    "contracts/protocol/Rescuable.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import "../protocol/OptimexAdminGuard.sol";
import "../libraries/ErrorLib.sol";

/**
 * @title Rescuable
 * @notice Emergency rescue functionality for ERC-20 tokens mistakenly sent to the contract
 * @dev This contract allows the protocol admin to rescue ERC-20 tokens that may have been
 *      accidentally sent to the contract. Rescued tokens are automatically transferred to
 *      the protocol's fee address.
 * @author Optimex Protocol
 */
contract Rescuable is OptimexAdminGuard {
    using SafeERC20 for IERC20;

    /**
     * @notice Emitted when tokens are manually rescued by the Admin.
     *     @param operator The Admin's address that performed the rescue operation.
     *     @param token The token that is being rescued.
     *     @param recipient The address receiving the rescued tokens (typically the protocol fee receiver).
     *     @param amount The amount of tokens rescued.
     *     @dev Related function: { rescue }
     */
    event Rescued(address indexed operator, address indexed token, address indexed recipient, uint256 amount);

    constructor(IOptimexProtocol protocol) OptimexAdminGuard(protocol) {}

    /**
     * @notice Rescue ERC-20 tokens that are mistakenly sent or locked in the contract.
     *     @dev Caller must be the current Admin of the OptimexProtocol contract.
     *     @param token The address of the ERC-20 token to be rescued.
     *     @param amount The amount of tokens to transfer.
     */
    function rescue(address token, uint256 amount) external onlyAdmin {
        address recipient = _getProtocol().pFeeAddr();
        if (recipient == address(0)) revert ErrorLib.ZeroAddress();

        IERC20(token).safeTransfer(recipient, amount);

        emit Rescued(msg.sender, token, recipient, amount);
    }
}
"
    },
    "contracts/utils/OptimexConnector.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import "../protocol/OptimexDomain.sol";
import "../protocol/Rescuable.sol";
import "../libraries/Structs.sol";
import "../libraries/Bundle.sol";
import "../libraries/ErrorLib.sol";
import "../interfaces/IOptimexMessageHandler.sol";

/**
 * @title OptimexConnector
 * @notice Secure message handler and multicall executor for the Optimex protocol
 * @dev This contract serves as a critical infrastructure component that enables authorized
 *      Optimex components to execute multiple operations atomically through a single transaction.
 *      It implements strict role-based access control and ensures all operations either succeed
 *      completely or fail completely, maintaining protocol consistency.
 * @dev Only addresses with the OPTIMEX_CALLER_ROLE can trigger message execution, preventing
 *      unauthorized access while enabling complex multi-step operations.
 * @author Optimex Protocol
 */
contract OptimexConnector is OptimexDomain, Rescuable, IOptimexMessageHandler {
    using SafeERC20 for IERC20;

    /// @dev Role identifier for authorized Optimex components that can trigger message execution
    /// @dev keccak256("OPTIMEX_CALLER")
    bytes32 internal constant _OPTIMEX_CALLER_ROLE = 0xe8248995e23255e87f8275766433c1d93780aeebe6d808ddc2d4cd7148738329;

    constructor(address protocol, string memory name, string memory version)
        OptimexDomain(name, version)
        Rescuable(IOptimexProtocol(protocol))
    {}

    /**
     * @notice Handles a message containing multiple operations sent by authorized Optimex components
     * @dev The function implements strict access control, ensuring only addresses with the
     *      OPTIMEX_CALLER_ROLE can trigger message execution. This prevents unauthorized
     *      access to the multicall functionality.
     * @dev All calls are executed atomically - if any call fails, the entire transaction reverts.
     *      This ensures data consistency and prevents partial execution states.
     * @param message ABI-encoded array of Call structs containing the operations to execute
     */
    function handleMessage(bytes calldata message) external payable {
        address sender = msg.sender;
        require(_isAuthorized(_OPTIMEX_CALLER_ROLE, sender), ErrorLib.Unauthorized(sender));

        Call[] memory calls = abi.decode(message, (Call[]));
        Bundle.multicall(calls);
    }
}
"
    }
  },
  "settings": {
    "viaIR": true,
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "evmVersion": "cancun",
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    }
  }
}}

Tags:
ERC20, ERC165, DeFi, Factory|addr:0xd0cecd22e6f3cf24350ea51b858e0d97cbe5c3c4|verified:true|block:23516394|tx:0x15ea7a3327eccdc702aa066dbe4f5372a9e18c3fdd37fc92f8b9ce0100f8560f|first_check:1759744345

Submitted on: 2025-10-06 11:52:27

Comments

Log in to comment.

No comments yet.