SyrupClaimFuse

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "lib/ipor-fusion/contracts/rewards_fuses/syrup/SyrupClaimFuse.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {PlasmaVaultLib} from "../../libraries/PlasmaVaultLib.sol";
import {ISyrup} from "./ext/ISyrup.sol";

/**
 * @title SyrupClaimFuse
 * @notice A fuse contract responsible for claiming rewards from Syrup contract
 * @dev This contract acts as an intermediary to claim rewards and forward them to the RewardsClaimManager
 */
contract SyrupClaimFuse {
    using SafeERC20 for IERC20;

    /**
     * @notice Emitted when rewards are successfully claimed from the Syrup contract
     * @param id Unique identifier of the token allocation that was claimed
     * @param asset Address of the reward token
     * @param amount Amount of rewards tokens claimed
     * @param rewardsClaimManager Address of the RewardsClaimManager receiving the claimed rewards
     */
    event SyrupClaimFuseRewardsClaimed(uint256 id, address asset, uint256 amount, address rewardsClaimManager);

    /**
     * @notice Thrown when the Syrup contract address is zero
     */
    error SyrupClaimFuseSyrupZeroAddress();

    /**
     * @notice Thrown when the RewardsClaimManager address is zero
     */
    error SyrupClaimFuseRewardsClaimManagerZeroAddress();
    /**
     * @notice Thrown when the claim amount is zero
     */
    error SyrupClaimFuseClaimAmountZero();

    /// @notice The address of this contract instance, used for version tracking
    address public immutable VERSION;

    address public immutable REWARD_DISTRIBUTOR;

    /**
     * @notice Constructs a new SyrupClaimFuse instance
     * @param rewardDistributor_ The address of the Reward Distributor contract
     */
    constructor(address rewardDistributor_) {
        if (rewardDistributor_ == address(0)) {
            revert SyrupClaimFuseSyrupZeroAddress();
        }

        VERSION = address(this);
        REWARD_DISTRIBUTOR = rewardDistributor_;
    }

    /**
     * @notice Claims rewards from Syrup contract and forwards them to the RewardsClaimManager
     * @dev Claims rewards to address(this) (PlasmaVault) first, then transfers to RewardsClaimManager
     *      The account parameter is always set to address(this) (PlasmaVault) when calling the Syrup contract
     * @param id_ Unique identifier of the token allocation
     * @param claimAmount_ Amount of tokens to claim
     * @param proof_ Proof that the recipient is part of the Merkle tree of token allocations
     */
    function claim(uint256 id_, uint256 claimAmount_, bytes32[] calldata proof_) external {
        address rewardsClaimManager = PlasmaVaultLib.getRewardsClaimManagerAddress();
        if (rewardsClaimManager == address(0)) {
            revert SyrupClaimFuseRewardsClaimManagerZeroAddress();
        }
        if (claimAmount_ == 0) {
            revert SyrupClaimFuseClaimAmountZero();
        }

        address plasmaVault = address(this);
        address asset = ISyrup(REWARD_DISTRIBUTOR).asset();

        uint256 balanceBefore = IERC20(asset).balanceOf(plasmaVault);

        ISyrup(REWARD_DISTRIBUTOR).claim(id_, plasmaVault, claimAmount_, proof_);

        uint256 claimedAmount = IERC20(asset).balanceOf(plasmaVault) - balanceBefore;

        if (claimedAmount > 0) {
            IERC20(asset).safeTransfer(rewardsClaimManager, claimedAmount);

            emit SyrupClaimFuseRewardsClaimed(id_, asset, claimedAmount, rewardsClaimManager);
        }
    }
}
"
    },
    "lib/ipor-fusion/node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

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

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

    /**
     * @dev Returns the 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);
}
"
    },
    "lib/ipor-fusion/node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 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 {
    using Address for address;

    /**
     * @dev An operation with an ERC20 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 Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    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.
     */
    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.
     */
    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 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).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            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 silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
    }
}
"
    },
    "lib/ipor-fusion/contracts/libraries/PlasmaVaultLib.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {Errors} from "./errors/Errors.sol";
import {PlasmaVaultStorageLib} from "./PlasmaVaultStorageLib.sol";
import {FusesLib} from "./FusesLib.sol";

/// @title InstantWithdrawalFusesParamsStruct
/// @notice A technical struct used to configure instant withdrawal fuses and their parameters in the Plasma Vault system
/// @dev This struct is used primarily in configureInstantWithdrawalFuses function to set up withdrawal paths
struct InstantWithdrawalFusesParamsStruct {
    /// @notice The address of the fuse contract that handles a specific withdrawal path
    /// @dev Must be a valid and supported fuse contract address that implements instant withdrawal logic
    address fuse;
    /// @notice Array of parameters specific to the fuse's withdrawal logic
    /// @dev Parameter structure:
    /// - params[0]: Always represents the withdrawal amount in underlying token decimals (set during withdrawal, not during configuration)
    /// - params[1+]: Additional fuse-specific parameters such as:
    ///   - Asset addresses
    ///   - Market IDs
    ///   - Slippage tolerances
    ///   - Protocol-specific parameters
    /// @dev The same fuse can appear multiple times with different params for different withdrawal paths
    bytes32[] params;
}

/// @title Plasma Vault Library
/// @notice Core library responsible for managing the Plasma Vault's state and operations
/// @dev Provides centralized management of vault operations, fees, configuration and state updates
///
/// Key responsibilities:
/// - Asset management and accounting
/// - Fee configuration and calculations
/// - Market balance tracking and updates
/// - Withdrawal system configuration
/// - Access control and execution state
/// - Price oracle integration
/// - Rewards claim management
library PlasmaVaultLib {
    using SafeCast for uint256;
    using SafeCast for int256;

    /// @dev Hard CAP for the performance fee in percentage - 50%
    uint256 public constant PERFORMANCE_MAX_FEE_IN_PERCENTAGE = 5000;

    /// @dev Hard CAP for the management fee in percentage - 5%
    uint256 public constant MANAGEMENT_MAX_FEE_IN_PERCENTAGE = 500;

    /// @dev The offset for the underlying asset decimals in the Plasma Vault
    uint8 public constant DECIMALS_OFFSET = 2;

    error InvalidPerformanceFee(uint256 feeInPercentage);
    error InvalidManagementFee(uint256 feeInPercentage);

    event InstantWithdrawalFusesConfigured(InstantWithdrawalFusesParamsStruct[] fuses);
    event PriceOracleMiddlewareChanged(address newPriceOracleMiddleware);
    event PerformanceFeeDataConfigured(address feeAccount, uint256 feeInPercentage);
    event ManagementFeeDataConfigured(address feeAccount, uint256 feeInPercentage);
    event RewardsClaimManagerAddressChanged(address newRewardsClaimManagerAddress);
    event DependencyBalanceGraphChanged(uint256 marketId, uint256[] newDependenceGraph);
    event WithdrawManagerChanged(address newWithdrawManager);
    event TotalSupplyCapChanged(uint256 newTotalSupplyCap);

    /// @notice Gets the total assets in the vault for all markets
    /// @dev Retrieves the total value of assets across all integrated markets and protocols
    /// @return uint256 The total assets in the vault, represented in decimals of the underlying asset
    ///
    /// This function:
    /// - Returns the raw total of assets without considering:
    ///   - Unrealized management fees
    ///   - Unrealized performance fees
    ///   - Pending rewards
    ///   - Current vault balance
    ///
    /// Used by:
    /// - PlasmaVault.totalAssets() for share price calculations
    /// - Fee calculations and accrual
    /// - Asset distribution checks
    /// - Market limit validations
    ///
    /// @dev Important: This value represents only the tracked assets in markets,
    /// for full vault assets see PlasmaVault._getGrossTotalAssets()
    function getTotalAssetsInAllMarkets() internal view returns (uint256) {
        return PlasmaVaultStorageLib.getTotalAssets().value;
    }

    /// @notice Gets the total assets in the vault for a specific market
    /// @param marketId_ The ID of the market to query
    /// @return uint256 The total assets in the vault for the market, represented in decimals of the underlying asset
    ///
    /// @dev This function provides market-specific asset tracking and is used for:
    /// - Market balance validation
    /// - Asset distribution checks
    /// - Market limit enforcement
    /// - Balance dependency resolution
    ///
    /// Important considerations:
    /// - Returns raw balance without considering fees
    /// - Value is updated by balance fuses during market interactions
    /// - Used in conjunction with market dependency graphs
    /// - Critical for maintaining proper asset distribution across markets
    ///
    /// Integration points:
    /// - Balance Fuses: Update market balances
    /// - Asset Distribution Protection: Check market limits
    /// - Withdrawal System: Verify available assets
    /// - Market Dependencies: Track related market updates
    function getTotalAssetsInMarket(uint256 marketId_) internal view returns (uint256) {
        return PlasmaVaultStorageLib.getMarketTotalAssets().value[marketId_];
    }

    /// @notice Gets the dependency balance graph for a specific market
    /// @param marketId_ The ID of the market to query
    /// @return uint256[] Array of market IDs that depend on the queried market
    ///
    /// @dev The dependency balance graph is critical for maintaining consistent state across related markets:
    /// - Ensures atomic balance updates across dependent markets
    /// - Prevents inconsistent states in interconnected protocols
    /// - Manages complex market relationships
    ///
    /// Use cases:
    /// - Market balance updates
    /// - Withdrawal validations
    /// - Asset rebalancing
    /// - Protocol integrations
    ///
    /// Example dependencies:
    /// - Lending markets depending on underlying asset markets
    /// - LP token markets depending on constituent token markets
    /// - Derivative markets depending on base asset markets
    ///
    /// Important considerations:
    /// - Dependencies are unidirectional (A->B doesn't imply B->A)
    /// - Empty array means no dependencies
    /// - Order of dependencies may matter for some operations
    /// - Used by _checkBalanceFusesDependencies() during balance updates
    function getDependencyBalanceGraph(uint256 marketId_) internal view returns (uint256[] memory) {
        return PlasmaVaultStorageLib.getDependencyBalanceGraph().dependencyGraph[marketId_];
    }

    /// @notice Updates the dependency balance graph for a specific market
    /// @param marketId_ The ID of the market to update
    /// @param newDependenceGraph_ Array of market IDs that should depend on this market
    /// @dev Updates the market dependency relationships and emits an event
    ///
    /// This function:
    /// - Overwrites existing dependencies for the market
    /// - Establishes new dependency relationships
    /// - Triggers event for dependency tracking
    ///
    /// Security considerations:
    /// - Only callable by authorized governance functions
    /// - Critical for maintaining market balance consistency
    /// - Must prevent circular dependencies
    /// - Should validate market existence
    ///
    /// Common update scenarios:
    /// - Adding new market dependencies
    /// - Removing obsolete dependencies
    /// - Modifying existing dependency chains
    /// - Protocol integration changes
    ///
    /// @dev Important: Changes to dependency graph affect:
    /// - Balance update order
    /// - Withdrawal validations
    /// - Market rebalancing operations
    /// - Protocol interaction flows
    function updateDependencyBalanceGraph(uint256 marketId_, uint256[] memory newDependenceGraph_) internal {
        PlasmaVaultStorageLib.getDependencyBalanceGraph().dependencyGraph[marketId_] = newDependenceGraph_;
        emit DependencyBalanceGraphChanged(marketId_, newDependenceGraph_);
    }

    /// @notice Adds or subtracts an amount from the total assets in the Plasma Vault
    /// @param amount_ The signed amount to adjust total assets by, represented in decimals of the underlying asset
    /// @dev Updates the global total assets tracker based on market operations
    ///
    /// Function behavior:
    /// - Positive amount: Increases total assets
    /// - Negative amount: Decreases total assets
    /// - Zero amount: No effect
    ///
    /// Used during:
    /// - Market balance updates
    /// - Fee realizations
    /// - Asset rebalancing
    /// - Withdrawal processing
    ///
    /// Security considerations:
    /// - Handles signed integers safely using SafeCast
    /// - Only called during validated operations
    /// - Must maintain accounting consistency
    /// - Critical for share price calculations
    ///
    /// @dev Important: This function affects:
    /// - Total vault valuation
    /// - Share price calculations
    /// - Fee calculations
    /// - Asset distribution checks
    function addToTotalAssetsInAllMarkets(int256 amount_) internal {
        if (amount_ < 0) {
            PlasmaVaultStorageLib.getTotalAssets().value -= (-amount_).toUint256();
        } else {
            PlasmaVaultStorageLib.getTotalAssets().value += amount_.toUint256();
        }
    }

    /// @notice Updates the total assets in the Plasma Vault for a specific market
    /// @param marketId_ The ID of the market to update
    /// @param newTotalAssetsInUnderlying_ The new total assets value for the market
    /// @return deltaInUnderlying The net change in assets (positive or negative), represented in underlying decimals
    /// @dev Updates market-specific asset tracking and calculates the change in total assets
    ///
    /// Function behavior:
    /// - Stores new total assets for the market
    /// - Calculates delta between old and new values
    /// - Returns signed delta for total asset updates
    ///
    /// Used during:
    /// - Balance fuse updates
    /// - Market rebalancing
    /// - Protocol interactions
    /// - Asset redistribution
    ///
    /// Security considerations:
    /// - Handles asset value transitions safely
    /// - Uses SafeCast for integer conversions
    /// - Must be called within proper market context
    /// - Critical for maintaining accurate balances
    ///
    /// Integration points:
    /// - Called by balance fuses after market operations
    /// - Used in _updateMarketsBalances for batch updates
    /// - Triggers market limit validations
    /// - Affects total asset calculations
    ///
    /// @dev Important: The returned delta is used by:
    /// - addToTotalAssetsInAllMarkets
    /// - Asset distribution protection checks
    /// - Market balance event emissions
    function updateTotalAssetsInMarket(
        uint256 marketId_,
        uint256 newTotalAssetsInUnderlying_
    ) internal returns (int256 deltaInUnderlying) {
        uint256 oldTotalAssetsInUnderlying = PlasmaVaultStorageLib.getMarketTotalAssets().value[marketId_];
        PlasmaVaultStorageLib.getMarketTotalAssets().value[marketId_] = newTotalAssetsInUnderlying_;
        deltaInUnderlying = newTotalAssetsInUnderlying_.toInt256() - oldTotalAssetsInUnderlying.toInt256();
    }

    /// @notice Gets the management fee configuration data
    /// @return managementFeeData The current management fee configuration containing:
    ///         - feeAccount: Address receiving management fees
    ///         - feeInPercentage: Current fee rate (basis points, 1/10000)
    ///         - lastUpdateTimestamp: Last time fees were realized
    /// @dev Retrieves the current management fee settings from storage
    ///
    /// Fee structure:
    /// - Continuous time-based fee on assets under management (AUM)
    /// - Fee percentage limited by MANAGEMENT_MAX_FEE_IN_PERCENTAGE (5%)
    /// - Fees accrue linearly over time
    /// - Realized during vault operations
    ///
    /// Used for:
    /// - Fee calculations in totalAssets()
    /// - Fee realization during operations
    /// - Management fee distribution
    /// - Governance fee adjustments
    ///
    /// Integration points:
    /// - PlasmaVault._realizeManagementFee()
    /// - PlasmaVault.totalAssets()
    /// - FeeManager contract
    /// - Governance configuration
    ///
    /// @dev Important: Management fees:
    /// - Are calculated based on total vault assets
    /// - Affect share price calculations
    /// - Must be realized before major vault operations
    /// - Are distributed to configured fee recipients
    function getManagementFeeData()
        internal
        view
        returns (PlasmaVaultStorageLib.ManagementFeeData memory managementFeeData)
    {
        return PlasmaVaultStorageLib.getManagementFeeData();
    }

    /// @notice Configures the management fee settings for the vault
    /// @param feeAccount_ The address that will receive management fees
    /// @param feeInPercentage_ The management fee rate in basis points (100 = 1%)
    /// @dev Updates fee configuration and emits event
    ///
    /// Parameter requirements:
    /// - feeAccount_: Must be non-zero address. The address of the technical Management Fee Account that will receive the management fee collected by the Plasma Vault and later on distributed to IPOR DAO and recipients by FeeManager
    /// - feeInPercentage_: Must not exceed MANAGEMENT_MAX_FEE_IN_PERCENTAGE (5%)
    ///
    /// Fee account types:
    /// - FeeManager contract: Distributes fees to IPOR DAO and other recipients
    /// - EOA/MultiSig: Receives fees directly without distribution
    /// - Technical account: Temporary fee collection before distribution
    ///
    /// Fee percentage format:
    /// - Uses 2 decimal places (basis points)
    /// - Examples:
    ///   - 10000 = 100%
    ///   - 100 = 1%
    ///   - 1 = 0.01%
    ///
    /// Security considerations:
    /// - Only callable by authorized governance functions
    /// - Validates fee percentage against maximum limit
    /// - Emits event for tracking changes
    /// - Critical for vault economics
    ///
    /// @dev Important: Changes affect:
    /// - Future fee calculations
    /// - Share price computations
    /// - Vault revenue distribution
    /// - Total asset calculations
    function configureManagementFee(address feeAccount_, uint256 feeInPercentage_) internal {
        if (feeAccount_ == address(0)) {
            revert Errors.WrongAddress();
        }
        if (feeInPercentage_ > MANAGEMENT_MAX_FEE_IN_PERCENTAGE) {
            revert InvalidManagementFee(feeInPercentage_);
        }

        PlasmaVaultStorageLib.ManagementFeeData storage managementFeeData = PlasmaVaultStorageLib
            .getManagementFeeData();

        managementFeeData.feeAccount = feeAccount_;
        managementFeeData.feeInPercentage = feeInPercentage_.toUint16();

        emit ManagementFeeDataConfigured(feeAccount_, feeInPercentage_);
    }

    /// @notice Gets the performance fee configuration data
    /// @return performanceFeeData The current performance fee configuration containing:
    ///         - feeAccount: The address of the technical Performance Fee Account that will receive the performance fee collected by the Plasma Vault and later on distributed to IPOR DAO and recipients by FeeManager
    ///         - feeInPercentage: Current fee rate (basis points, 1/10000)
    /// @dev Retrieves the current performance fee settings from storage
    ///
    /// Fee structure:
    /// - Charged on positive vault performance
    /// - Fee percentage limited by PERFORMANCE_MAX_FEE_IN_PERCENTAGE (50%)
    /// - Calculated on realized gains only
    /// - Applied during execute() operations
    ///
    /// Used for:
    /// - Performance fee calculations
    /// - Fee realization during profitable operations
    /// - Performance fee distribution
    /// - Governance fee adjustments
    ///
    /// Integration points:
    /// - PlasmaVault._addPerformanceFee()
    /// - PlasmaVault.execute()
    /// - FeeManager contract
    /// - Governance configuration
    ///
    /// @dev Important: Performance fees:
    /// - Only charged on positive performance
    /// - Calculated based on profit since last fee realization
    /// - Minted as new vault shares
    /// - Distributed to configured fee recipients
    function getPerformanceFeeData()
        internal
        view
        returns (PlasmaVaultStorageLib.PerformanceFeeData memory performanceFeeData)
    {
        return PlasmaVaultStorageLib.getPerformanceFeeData();
    }

    /// @notice Configures the performance fee settings for the vault
    /// @param feeAccount_ The address that will receive performance fees
    /// @param feeInPercentage_ The performance fee rate in basis points (100 = 1%)
    /// @dev Updates fee configuration and emits event
    ///
    /// Parameter requirements:
    /// - feeAccount_: Must be non-zero address. The address of the technical Performance Fee Account that will receive the performance fee collected by the Plasma Vault and later on distributed to IPOR DAO and recipients by FeeManager
    /// - feeInPercentage_: Must not exceed PERFORMANCE_MAX_FEE_IN_PERCENTAGE (50%)
    ///
    /// Fee account types:
    /// - FeeManager contract: Distributes fees to IPOR DAO and other recipients
    /// - EOA/MultiSig: Receives fees directly without distribution
    /// - Technical account: Temporary fee collection before distribution
    ///
    /// Fee percentage format:
    /// - Uses 2 decimal places (basis points)
    /// - Examples:
    ///   - 10000 = 100%
    ///   - 100 = 1%
    ///   - 1 = 0.01%
    ///
    /// Security considerations:
    /// - Only callable by authorized governance functions
    /// - Validates fee percentage against maximum limit
    /// - Emits event for tracking changes
    /// - Critical for vault incentive structure
    ///
    /// @dev Important: Changes affect:
    /// - Profit sharing calculations
    /// - Alpha incentive alignment
    /// - Vault performance metrics
    /// - Revenue distribution model
    function configurePerformanceFee(address feeAccount_, uint256 feeInPercentage_) internal {
        if (feeAccount_ == address(0)) {
            revert Errors.WrongAddress();
        }
        if (feeInPercentage_ > PERFORMANCE_MAX_FEE_IN_PERCENTAGE) {
            revert InvalidPerformanceFee(feeInPercentage_);
        }

        PlasmaVaultStorageLib.PerformanceFeeData storage performanceFeeData = PlasmaVaultStorageLib
            .getPerformanceFeeData();

        performanceFeeData.feeAccount = feeAccount_;
        performanceFeeData.feeInPercentage = feeInPercentage_.toUint16();

        emit PerformanceFeeDataConfigured(feeAccount_, feeInPercentage_);
    }

    /// @notice Updates the management fee timestamp for fee accrual tracking
    /// @dev Updates lastUpdateTimestamp to current block timestamp for fee calculations
    ///
    /// Function behavior:
    /// - Sets lastUpdateTimestamp to current block.timestamp
    /// - Used to mark points of fee realization
    /// - Critical for time-based fee calculations
    ///
    /// Called during:
    /// - Fee realization operations
    /// - Deposit transactions
    /// - Withdrawal transactions
    /// - Share minting/burning
    ///
    /// Integration points:
    /// - PlasmaVault._realizeManagementFee()
    /// - PlasmaVault.deposit()
    /// - PlasmaVault.withdraw()
    /// - PlasmaVault.mint()
    ///
    /// @dev Important considerations:
    /// - Must be called after fee realization
    /// - Affects future fee calculations
    /// - Uses uint32 for timestamp storage
    /// - Critical for fee accounting accuracy
    function updateManagementFeeData() internal {
        PlasmaVaultStorageLib.ManagementFeeData storage feeData = PlasmaVaultStorageLib.getManagementFeeData();
        feeData.lastUpdateTimestamp = block.timestamp.toUint32();
    }

    /// @notice Gets the ordered list of instant withdrawal fuses
    /// @return address[] Array of fuse addresses in withdrawal priority order
    /// @dev Retrieves the configured withdrawal path sequence
    ///
    /// Function behavior:
    /// - Returns ordered array of fuse addresses
    /// - Empty array if no withdrawal paths configured
    /// - Order determines withdrawal attempt sequence
    /// - Same fuse can appear multiple times with different params
    ///
    /// Used during:
    /// - Withdrawal operations
    /// - Instant withdrawal processing
    /// - Withdrawal path validation
    /// - Withdrawal strategy execution
    ///
    /// Integration points:
    /// - PlasmaVault._withdrawFromMarkets()
    /// - Withdrawal execution logic
    /// - Balance validation
    /// - Fuse interaction coordination
    ///
    /// @dev Important considerations:
    /// - Order is critical for withdrawal efficiency
    /// - Multiple entries of same fuse allowed
    /// - Each fuse needs corresponding params
    /// - Used in conjunction with getInstantWithdrawalFusesParams
    function getInstantWithdrawalFuses() internal view returns (address[] memory) {
        return PlasmaVaultStorageLib.getInstantWithdrawalFusesArray().value;
    }

    /// @notice Gets the parameters for a specific instant withdrawal fuse at a given index
    /// @param fuse_ The address of the withdrawal fuse contract
    /// @param index_ The position of the fuse in the withdrawal sequence
    /// @return bytes32[] Array of parameters configured for this fuse instance
    /// @dev Retrieves withdrawal configuration parameters for specific fuse execution
    ///
    /// Parameter structure:
    /// - params[0]: Reserved for withdrawal amount (set during execution)
    /// - params[1+]: Fuse-specific parameters such as:
    ///   - Market identifiers
    ///   - Asset addresses
    ///   - Slippage tolerances
    ///   - Protocol-specific configuration
    ///
    /// Storage pattern:
    /// - Uses keccak256(abi.encodePacked(fuse_, index_)) as key
    /// - Allows same fuse to have different params at different indices
    /// - Supports protocol-specific parameter requirements
    ///
    /// Used during:
    /// - Withdrawal execution
    /// - Parameter validation
    /// - Withdrawal path configuration
    /// - Fuse interaction setup
    ///
    /// @dev Important considerations:
    /// - Parameters must match fuse expectations
    /// - Index must correspond to getInstantWithdrawalFuses array
    /// - First parameter reserved for withdrawal amount
    /// - Critical for proper withdrawal execution
    function getInstantWithdrawalFusesParams(address fuse_, uint256 index_) internal view returns (bytes32[] memory) {
        return
            PlasmaVaultStorageLib.getInstantWithdrawalFusesParams().value[keccak256(abi.encodePacked(fuse_, index_))];
    }

    /// @notice Configures the instant withdrawal fuse sequence and parameters
    /// @param fuses_ Array of fuse configurations with their respective parameters
    /// @dev Sets up withdrawal paths and their execution parameters
    ///
    /// Configuration process:
    /// - Creates ordered list of withdrawal fuses
    /// - Stores parameters for each fuse instance, in most cases are substrates used for instant withdraw
    /// - Validates fuse support status
    /// - Updates storage and emits event
    ///
    /// Parameter validation:
    /// - Each fuse must be supported
    /// - Parameters must match fuse requirements
    /// - Fuse order determines execution priority
    /// - Same fuse can appear multiple times
    ///
    /// Storage updates:
    /// - Clears existing configuration
    /// - Stores new fuse sequence
    /// - Maps parameters to fuse+index combinations
    /// - Maintains parameter ordering
    ///
    /// Security considerations:
    /// - Only callable by authorized governance
    /// - Validates all fuse addresses
    /// - Prevents invalid configurations
    /// - Critical for withdrawal security
    ///
    /// @dev Important: Configuration affects:
    /// - Withdrawal path selection
    /// - Execution sequence
    /// - Protocol interactions
    /// - Withdrawal efficiency
    ///
    /// Common configurations:
    /// - Multiple paths through same protocol
    /// - Different slippage per path
    /// - Market-specific parameters
    /// - Fallback withdrawal routes
    function configureInstantWithdrawalFuses(InstantWithdrawalFusesParamsStruct[] calldata fuses_) internal {
        address[] memory fusesList = new address[](fuses_.length);

        PlasmaVaultStorageLib.InstantWithdrawalFusesParams storage instantWithdrawalFusesParams = PlasmaVaultStorageLib
            .getInstantWithdrawalFusesParams();

        bytes32 key;

        for (uint256 i; i < fuses_.length; ++i) {
            if (!FusesLib.isFuseSupported(fuses_[i].fuse)) {
                revert FusesLib.FuseUnsupported(fuses_[i].fuse);
            }

            fusesList[i] = fuses_[i].fuse;
            key = keccak256(abi.encodePacked(fuses_[i].fuse, i));

            delete instantWithdrawalFusesParams.value[key];

            for (uint256 j; j < fuses_[i].params.length; ++j) {
                instantWithdrawalFusesParams.value[key].push(fuses_[i].params[j]);
            }
        }

        delete PlasmaVaultStorageLib.getInstantWithdrawalFusesArray().value;

        PlasmaVaultStorageLib.getInstantWithdrawalFusesArray().value = fusesList;

        emit InstantWithdrawalFusesConfigured(fuses_);
    }

    /// @notice Gets the Price Oracle Middleware address
    /// @return address The current price oracle middleware contract address
    /// @dev Retrieves the address of the price oracle middleware used for asset valuations
    ///
    /// Price Oracle Middleware:
    /// - Provides standardized price feeds for vault assets
    /// - Must support USD as quote currency
    /// - Critical for asset valuation and calculations
    /// - Required for market operations
    ///
    /// Used during:
    /// - Asset valuation calculations
    /// - Market balance updates
    /// - Fee computations
    /// - Share price determinations
    ///
    /// Integration points:
    /// - Balance fuses for market valuations
    /// - Withdrawal calculations
    /// - Performance tracking
    /// - Asset distribution checks
    ///
    /// @dev Important considerations:
    /// - Must be properly initialized
    /// - Critical for vault operations
    /// - Required for accurate share pricing
    /// - Core component for market interactions
    function getPriceOracleMiddleware() internal view returns (address) {
        return PlasmaVaultStorageLib.getPriceOracleMiddleware().value;
    }

    /// @notice Sets the Price Oracle Middleware address for the vault
    /// @param priceOracleMiddleware_ The new price oracle middleware contract address
    /// @dev Updates the price oracle middleware and emits event
    ///
    /// Validation requirements:
    /// - Must support USD as quote currency
    /// - Must maintain same quote currency decimals
    /// - Must be compatible with existing vault operations
    /// - Address must be non-zero
    ///
    /// Security considerations:
    /// - Only callable by authorized governance
    /// - Critical for vault operations
    /// - Must validate oracle compatibility
    /// - Affects all price-dependent operations
    ///
    /// Integration impacts:
    /// - Asset valuations
    /// - Share price calculations
    /// - Market balance updates
    /// - Fee computations
    ///
    /// @dev Important: Changes affect:
    /// - All price-dependent calculations
    /// - Market operations
    /// - Withdrawal validations
    /// - Performance tracking
    ///
    /// Called during:
    /// - Initial vault setup
    /// - Oracle upgrades
    /// - Protocol improvements
    /// - Emergency oracle changes
    function setPriceOracleMiddleware(address priceOracleMiddleware_) internal {
        PlasmaVaultStorageLib.getPriceOracleMiddleware().value = priceOracleMiddleware_;
        emit PriceOracleMiddlewareChanged(priceOracleMiddleware_);
    }

    /// @notice Gets the Rewards Claim Manager address
    /// @return address The current rewards claim manager contract address
    /// @dev Retrieves the address of the contract managing reward claims and distributions
    ///
    /// Rewards Claim Manager:
    /// - Handles protocol reward claims
    /// - Manages reward token distributions
    /// - Tracks claimable rewards
    /// - Coordinates reward strategies
    ///
    /// Used during:
    /// - Reward claim operations
    /// - Total asset calculations
    /// - Fee computations
    /// - Performance tracking
    ///
    /// Integration points:
    /// - Protocol reward systems
    /// - Asset valuation calculations
    /// - Performance fee assessments
    /// - Governance operations
    ///
    /// @dev Important considerations:
    /// - Can be zero address (rewards disabled)
    /// - Critical for reward accounting
    /// - Affects total asset calculations
    /// - Impacts performance metrics
    function getRewardsClaimManagerAddress() internal view returns (address) {
        return PlasmaVaultStorageLib.getRewardsClaimManagerAddress().value;
    }

    /// @notice Sets the Rewards Claim Manager address for the vault
    /// @param rewardsClaimManagerAddress_ The new rewards claim manager contract address
    /// @dev Updates rewards manager configuration and emits event
    ///
    /// Configuration options:
    /// - Non-zero address: Enables reward claiming functionality
    /// - Zero address: Disables reward claiming system
    ///
    /// Security considerations:
    /// - Only callable by authorized governance
    /// - Critical for reward system operation
    /// - Affects total asset calculations
    /// - Impacts performance metrics
    ///
    /// Integration impacts:
    /// - Protocol reward claiming
    /// - Asset valuation calculations
    /// - Performance tracking
    /// - Fee computations
    ///
    /// @dev Important: Changes affect:
    /// - Reward claiming capability
    /// - Total asset calculations
    /// - Performance measurements
    /// - Protocol integrations
    ///
    /// Called during:
    /// - Initial vault setup
    /// - Rewards system upgrades
    /// - Protocol improvements
    /// - Emergency system changes
    function setRewardsClaimManagerAddress(address rewardsClaimManagerAddress_) internal {
        PlasmaVaultStorageLib.getRewardsClaimManagerAddress().value = rewardsClaimManagerAddress_;
        emit RewardsClaimManagerAddressChanged(rewardsClaimManagerAddress_);
    }

    /// @notice Gets the total supply cap for the vault
    /// @return uint256 The maximum allowed total supply in underlying asset decimals
    /// @dev Retrieves the configured supply cap that limits total vault shares
    ///
    /// Supply cap usage:
    /// - Enforces maximum vault size
    /// - Limits total value locked (TVL)
    /// - Guards against excessive concentration
    /// - Supports gradual scaling
    ///
    /// Used during:
    /// - Deposit validation
    /// - Share minting checks
    /// - Fee minting operations
    /// - Governance monitoring
    ///
    /// Integration points:
    /// - ERC4626 deposit/mint functions
    /// - Fee realization operations
    /// - Governance configuration
    /// - Risk management systems
    ///
    /// @dev Important considerations:
    /// - Cap applies to total shares outstanding
    /// - Can be temporarily bypassed for fees
    /// - Critical for risk management
    /// - Affects deposit availability
    function getTotalSupplyCap() internal view returns (uint256) {
        return PlasmaVaultStorageLib.getERC20CappedStorage().cap;
    }

    /// @notice Sets the total supply cap for the vault
    /// @param cap_ The new maximum total supply in underlying asset decimals
    /// @dev Updates the vault's total supply limit and validates input
    ///
    /// Validation requirements:
    /// - Must be non-zero value
    /// - Must be sufficient for expected vault operations
    /// - Should consider asset decimals
    /// - Must accommodate fee minting
    ///
    /// Security considerations:
    /// - Only callable by authorized governance
    /// - Critical for vault size control
    /// - Affects deposit availability
    /// - Impacts risk management
    ///
    /// Integration impacts:
    /// - Deposit operations
    /// - Share minting limits
    /// - Fee realization
    /// - TVL management
    ///
    /// @dev Important: Changes affect:
    /// - Maximum vault capacity
    /// - Deposit availability
    /// - Fee minting headroom
    /// - Risk parameters
    ///
    /// Called during:
    /// - Initial vault setup
    /// - Capacity adjustments
    /// - Growth management
    /// - Risk parameter updates
    function setTotalSupplyCap(uint256 cap_) internal {
        if (cap_ == 0) {
            revert Errors.WrongValue();
        }
        PlasmaVaultStorageLib.getERC20CappedStorage().cap = cap_;
        emit TotalSupplyCapChanged(cap_);
    }

    /// @notice Controls validation of the total supply cap
    /// @param flag_ The validation control flag (0 = enabled, 1 = disabled)
    /// @dev Manages temporary bypassing of supply cap checks for fee minting
    ///
    /// Flag values:
    /// - 0: Supply cap validation enabled (default)
    ///   - Enforces maximum supply limit
    ///   - Applies to deposits and mints
    ///   - Maintains TVL controls
    ///
    /// - 1: Supply cap validation disabled
    ///   - Allows exceeding supply cap
    ///   - Used during fee minting
    ///   - Temporary state only
    ///
    /// Used during:
    /// - Performance fee minting
    /// - Management fee realization
    /// - Emergency operations
    /// - System maintenance
    ///
    /// Security considerations:
    /// - Only callable by authorized functions
    /// - Should be re-enabled after fee operations
    /// - Critical for supply control
    /// - Temporary bypass only
    ///
    /// @dev Important: State affects:
    /// - Supply cap enforcement
    /// - Fee minting operations
    /// - Deposit availability
    /// - System security
    function setTotalSupplyCapValidation(uint256 flag_) internal {
        PlasmaVaultStorageLib.getERC20CappedValidationFlag().value = flag_;
    }

    /// @notice Checks if the total supply cap validation is enabled
    /// @return bool True if validation is enabled (flag = 0), false if disabled (flag = 1)
    /// @dev Provides current state of supply cap enforcement
    ///
    /// Validation states:
    /// - Enabled (true):
    ///   - Normal operation mode
    ///   - Enforces supply cap limits
    ///   - Required for deposits/mints
    ///   - Default state
    ///
    /// - Disabled (false):
    ///   - Temporary bypass mode
    ///   - Allows exceeding cap
    ///   - Used for fee minting
    ///   - Special operations only
    ///
    /// Used during:
    /// - Deposit validation
    /// - Share minting checks
    /// - Fee operations
    /// - System monitoring
    ///
    /// @dev Important considerations:
    /// - Should generally be enabled
    /// - Temporary disable for fees only
    /// - Critical for supply control
    /// - Check before cap-sensitive operations
    function isTotalSupplyCapValidationEnabled() internal view returns (bool) {
        return PlasmaVaultStorageLib.getERC20CappedValidationFlag().value == 0;
    }

    /// @notice Sets the execution state to started for Alpha operations
    /// @dev Marks the beginning of a multi-action execution sequence
    ///
    /// Execution state usage:
    /// - Tracks active Alpha operations
    /// - Enables multi-action sequences
    /// - Prevents concurrent executions
    /// - Maintains operation atomicity
    ///
    /// Used during:
    /// - Alpha strategy execution
    /// - Complex market operations
    /// - Multi-step transactions
    /// - Protocol interactions
    ///
    /// Security considerations:
    /// - Only callable by authorized Alpha
    /// - Must be paired with executeFinished
    /// - Critical for operation integrity
    /// - Prevents execution overlap
    ///
    /// @dev Important: State affects:
    /// - Operation validation
    /// - Reentrancy protection
    /// - Transaction boundaries
    /// - Error handling
    function executeStarted() internal {
        PlasmaVaultStorageLib.getExecutionState().value = 1;
    }

    /// @notice Sets the execution state to finished after Alpha operations
    /// @dev Marks the end of a multi-action execution sequence
    ///
    /// Function behavior:
    /// - Resets execution state to 0
    /// - Marks completion of Alpha operations
    /// - Enables new execution sequences
    /// - Required for proper state management
    ///
    /// Called after:
    /// - Strategy execution completion
    /// - Market operation finalization
    /// - Protocol interaction completion
    /// - Multi-step transaction end
    ///
    /// Security considerations:
    /// - Must be called after executeStarted
    /// - Critical for execution state cleanup
    /// - Prevents execution state lock
    /// - Required for new operations
    ///
    /// @dev Important: State cleanup:
    /// - Enables new operations
    /// - Releases execution lock
    /// - Required for system stability
    /// - Prevents state corruption
    function executeFinished() internal {
        PlasmaVaultStorageLib.getExecutionState().value = 0;
    }

    /// @notice Checks if an Alpha execution sequence is currently active
    /// @return bool True if execution is in progress (state = 1), false otherwise
    /// @dev Verifies current execution state for operation validation
    ///
    /// State meanings:
    /// - True (1):
    ///   - Execution sequence active
    ///   - Alpha operation in progress
    ///   - Transaction sequence ongoing
    ///   - State modifications allowed
    ///
    /// - False (0):
    ///   - No active execution
    ///   - Ready for new operations
    ///   - Normal vault state
    ///   - Awaiting next sequence
    ///
    /// Used during:
    /// - Operation validation
    /// - State modification checks
    /// - Execution flow control
    /// - Error handling
    ///
    /// @dev Important considerations:
    /// - Critical for operation safety
    /// - Part of execution control flow
    /// - Affects state modification permissions
    /// - Used in reentrancy checks
    function isExecutionStarted() internal view returns (bool) {
        return PlasmaVaultStorageLib.getExecutionState().value == 1;
    }

    /// @notice Updates the Withdraw Manager address for the vault
    /// @param newWithdrawManager_ The new withdraw manager contract address
    /// @dev Updates withdraw manager configuration and emits event
    ///
    /// Configuration options:
    /// - Non-zero address: Enables scheduled withdrawals
    ///   - Enforces withdrawal schedules
    ///   - Manages withdrawal queues
    ///   - Handles withdrawal limits
    ///   - Coordinates withdrawal timing
    ///
    /// - Zero address: Disables scheduled withdrawals
    ///   - Turns off withdrawal scheduling
    ///   - Enables instant withdrawals only
    ///   - Bypasses withdrawal queues
    ///   - Removes withdrawal timing constraints
    ///
    /// Security considerations:
    /// - Only callable by authorized governance
    /// - Critical for withdrawal control
    /// - Affects user withdrawal options
    /// - Impacts liquidity management
    ///
    /// Integration impacts:
    /// - Withdrawal mechanisms
    /// - User withdrawal experience
    /// - Liquidity planning
    /// - Market stability
    ///
    /// @dev Important: Changes affect:
    /// - Withdrawal availability
    /// - Withdrawal timing
    /// - Liquidity management
    /// - User operations
    function updateWithdrawManager(address newWithdrawManager_) internal {
        PlasmaVaultStorageLib.getWithdrawManager().manager = newWithdrawManager_;
        emit WithdrawManagerChanged(newWithdrawManager_);
    }
}
"
    },
    "lib/ipor-fusion/contracts/rewards_fuses/syrup/ext/ISyrup.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

/// @title Interface for Syrup contract
interface ISyrup {
    /**
     * @dev Claims a token allocation.
     *      Can only claim a token allocation once.
     *      Can only be claimed before the deadline expires.
     *      Can only be claimed if the Merkle proof is valid.
     * @param id Unique identifier of the token allocation.
     * @param account Address of the token recipient.
     * @param claimAmount Amount of tokens to claim.
     * @param proof Proof that the recipient is part of the Merkle tree of token allocations.
     */
    function claim(uint256 id, address account, uint256 claimAmount, bytes32[] calldata proof) external;

    /**
     * @dev Returns the asset address in which rewards are transferred.
     * @return asset The address of the reward token.
     */
    function asset() external view returns (address asset);
}

"
    },
    "lib/ipor-fusion/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}
"
    },
    "lib/ipor-fusion/node_modules/@openzeppelin/contracts/utils/Address.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly\

Tags:
ERC20, Multisig, Mintable, Swap, Liquidity, Voting, Upgradeable, Multi-Signature, Factory, Oracle|addr:0x5b1a6b2e6af64e74275015a65687de0ca941f537|verified:true|block:23744357|tx:0x9f6c9aece80eaace649965d9531db2bec1c5834a195509507fe3107ee80b727f|first_check:1762513660

Submitted on: 2025-11-07 12:07:42

Comments

Log in to comment.

No comments yet.