FeeManager

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": {
    "src/extensions/FeeManager.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Ownable2Step } from "@openzeppelin/contracts/access/Ownable2Step.sol";

import { IManager } from "@jigsaw/src/interfaces/core/IManager.sol";
import { IStrategyManager } from "@jigsaw/src/interfaces/core/IStrategyManager.sol";

import { IFeeManager } from "./interfaces/IFeeManager.sol";

/**
 * @title FeeManager
 *
 * @notice Contract that manages custom fee configurations for Jigsaw Protocol strategies
 *
 * @dev Allows setting and retrieving custom performance fees for specific holding-strategy pairs
 * @dev Inherits from `Ownable2Step`.
 *
 * @author Hovooo (@hovooo)
 *
 * @custom:security-contact support@jigsaw.finance
 *
 */
contract FeeManager is IFeeManager, Ownable2Step {
    // -- State variables --

    /**
     * @notice The Manager contract.
     */
    IManager public override manager;

    /**
     * @notice Stores custom performance fee rates for each holding in each strategy.
     *
     * @dev Maps a holding address to a nested mapping of strategy address to fee amount.
     * @dev When a custom fee is not set (value is 0), the getHoldingFee function will return the default performance
     * fee for the strategy instead. Fee values are expressed in basis points (e.g., 1000 = 10%).
     */
    mapping(address holding => mapping(address strategy => uint256 fee)) private holdingFee;

    // -- Constructor --

    /**
     * @notice Creates a new FeeManager contract.
     * @param _initialOwner The address of the initial owner of the contract.
     * @param _manager The address of the Manager contract.
     */
    constructor(address _initialOwner, address _manager) Ownable(_initialOwner) {
        manager = IManager(_manager);
    }

    // -- Administration --

    /**
     * @notice Sets performance fee for a specific `_holding` in a specific `_strategy`.
     *
     * @param _holding The address of the holding.
     * @param _strategy The address of the strategy.
     * @param _fee The performance fee to set.
     */
    function setHoldingCustomFee(address _holding, address _strategy, uint256 _fee) external override onlyOwner {
        _setHoldingCustomFee({ _holding: _holding, _strategy: _strategy, _fee: _fee });
    }

    /**
     * @notice Sets performance fee for a list of `_holdings` in a specified `_strategies` list.
     *
     * @param _holdings The list of the holding addresses to set `_fees` for.
     * @param _strategies The list of the strategies addresses to set `_holdings`' `_fees` for.
     * @param _fees The list of performance fees to set for specified `_holdings` and `_strategies`.
     */
    function setHoldingCustomFee(
        address[] calldata _holdings,
        address[] calldata _strategies,
        uint256[] calldata _fees
    ) external override onlyOwner {
        require(_holdings.length == _strategies.length && _holdings.length == _fees.length, "3047");
        for (uint256 i = 0; i < _strategies.length; i++) {
            _setHoldingCustomFee({ _holding: _holdings[i], _strategy: _strategies[i], _fee: _fees[i] });
        }
    }

    // -- Getters --

    /**
     * @notice Returns `_holding`'s performance fee for specified `_strategy`.
     * @dev Returns default performance fee stored in StrategyManager contract, if it's set to zero.
     *
     * @param _strategy The address of the strategy.
     * @param _holding The address of the holding.
     *
     * @return `_holding`'s performance fee for `_strategy`.
     */
    function getHoldingFee(address _holding, address _strategy) external view override returns (uint256) {
        // Check if a custom fee is set for this holding-strategy pair and return if set.
        if (holdingFee[_holding][_strategy] != 0) return holdingFee[_holding][_strategy];

        // If no custom fee is set, return the default performance fee from the strategy manager
        (uint256 defaultPerformanceFee,,) = IStrategyManager(manager.strategyManager()).strategyInfo(address(_strategy));
        return defaultPerformanceFee;
    }

    // -- Utilities --

    /**
     * @notice Sets performance fee for a specific holding.
     *
     * @param _strategy The address of the strategy.
     * @param _holding The address of the holding.
     * @param _fee The custom fee to set.
     */
    function _setHoldingCustomFee(address _holding, address _strategy, uint256 _fee) private {
        require(_strategy != address(0), "3000");
        require(_holding != address(0), "3000");
        require(_fee < manager.MAX_PERFORMANCE_FEE(), "3018");
        require(holdingFee[_holding][_strategy] != _fee, "3017");

        emit HoldingFeeUpdated({
            holding: _holding,
            strategy: _strategy,
            oldFee: holdingFee[_holding][_strategy],
            newFee: _fee
        });
        holdingFee[_holding][_strategy] = _fee;
    }
}
"
    },
    "lib/jigsaw-protocol-v1/lib/openzeppelin-contracts/contracts/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
"
    },
    "lib/jigsaw-protocol-v1/lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is specified at deployment time in the constructor for `Ownable`. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Returns the address of the pending owner.
     */
    function pendingOwner() public view virtual returns (address) {
        return _pendingOwner;
    }

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        if (pendingOwner() != sender) {
            revert OwnableUnauthorizedAccount(sender);
        }
        _transferOwnership(sender);
    }
}
"
    },
    "lib/jigsaw-protocol-v1/src/interfaces/core/IManager.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import { IOracle } from "../oracle/IOracle.sol";

/**
 * @title IManager.
 * @dev Interface for the Manager Contract.
 */
interface IManager {
    // -- Events --

    /**
     * @notice Emitted when a new contract is whitelisted.
     * @param contractAddress The address of the contract that is whitelisted.
     */
    event ContractWhitelisted(address indexed contractAddress);

    /**
     * @notice Emitted when a contract is removed from the whitelist.
     * @param contractAddress The address of the contract that is removed from the whitelist.
     */
    event ContractBlacklisted(address indexed contractAddress);

    /**
     * @notice Emitted when a new token is whitelisted.
     * @param token The address of the token that is whitelisted.
     */
    event TokenWhitelisted(address indexed token);

    /**
     * @notice Emitted when a new token is removed from the whitelist.
     * @param token The address of the token that is removed from the whitelist.
     */
    event TokenRemoved(address indexed token);

    /**
     * @notice Emitted when a withdrawable token is added.
     * @param token The address of the withdrawable token.
     */
    event WithdrawableTokenAdded(address indexed token);

    /**
     * @notice Emitted when a withdrawable token is removed.
     * @param token The address of the withdrawable token.
     */
    event WithdrawableTokenRemoved(address indexed token);

    /**
     * @notice Emitted when invoker is updated.
     * @param component The address of the invoker component.
     * @param allowed Boolean indicating if the invoker is allowed or not.
     */
    event InvokerUpdated(address indexed component, bool allowed);

    /**
     * @notice Emitted when the holding manager is set.
     * @param oldAddress The previous address of the holding manager.
     * @param newAddress The new address of the holding manager.
     */
    event HoldingManagerUpdated(address indexed oldAddress, address indexed newAddress);

    /**
     * @notice Emitted when a new liquidation manager is requested.
     * @param oldAddress The previous address of the liquidation manager.
     * @param newAddress The new address of the liquidation manager.
     */
    event NewLiquidationManagerRequested(address indexed oldAddress, address indexed newAddress);

    /**
     * @notice Emitted when the liquidation manager is set.
     * @param oldAddress The previous address of the liquidation manager.
     * @param newAddress The new address of the liquidation manager.
     */
    event LiquidationManagerUpdated(address indexed oldAddress, address indexed newAddress);

    /**
     * @notice Emitted when the stablecoin manager is set.
     * @param oldAddress The previous address of the stablecoin manager.
     * @param newAddress The new address of the stablecoin manager.
     */
    event StablecoinManagerUpdated(address indexed oldAddress, address indexed newAddress);

    /**
     * @notice Emitted when the strategy manager is set.
     * @param oldAddress The previous address of the strategy manager.
     * @param newAddress The new address of the strategy manager.
     */
    event StrategyManagerUpdated(address indexed oldAddress, address indexed newAddress);

    /**
     * @notice Emitted when a new swap manager is requested.
     * @param oldAddress The previous address of the swap manager.
     * @param newAddress The new address of the swap manager.
     */
    event NewSwapManagerRequested(address indexed oldAddress, address indexed newAddress);

    /**
     * @notice Emitted when the swap manager is set.
     * @param oldAddress The previous address of the swap manager.
     * @param newAddress The new address of the swap manager.
     */
    event SwapManagerUpdated(address indexed oldAddress, address indexed newAddress);

    /**
     * @notice Emitted when the default fee is updated.
     * @param oldFee The previous fee.
     * @param newFee The new fee.
     */
    event PerformanceFeeUpdated(uint256 indexed oldFee, uint256 indexed newFee);

    /**
     * @notice Emitted when the withdraw fee is updated.
     * @param oldFee The previous withdraw fee.
     * @param newFee The new withdraw fee.
     */
    event WithdrawalFeeUpdated(uint256 indexed oldFee, uint256 indexed newFee);

    /**
     * @notice Emitted when the liquidator's bonus is updated.
     * @param oldAmount The previous amount of the liquidator's bonus.
     * @param newAmount The new amount of the liquidator's bonus.
     */
    event LiquidatorBonusUpdated(uint256 oldAmount, uint256 newAmount);

    /**
     * @notice Emitted when the fee address is changed.
     * @param oldAddress The previous fee address.
     * @param newAddress The new fee address.
     */
    event FeeAddressUpdated(address indexed oldAddress, address indexed newAddress);

    /**
     * @notice Emitted when the receipt token factory is updated.
     * @param oldAddress The previous address of the receipt token factory.
     * @param newAddress The new address of the receipt token factory.
     */
    event ReceiptTokenFactoryUpdated(address indexed oldAddress, address indexed newAddress);

    /**
     * @notice Emitted when the liquidity gauge factory is updated.
     * @param oldAddress The previous address of the liquidity gauge factory.
     * @param newAddress The new address of the liquidity gauge factory.
     */
    event LiquidityGaugeFactoryUpdated(address indexed oldAddress, address indexed newAddress);

    /**
     * @notice Emitted when new oracle is requested.
     * @param newOracle The address of the new oracle.
     */
    event NewOracleRequested(address newOracle);

    /**
     * @notice Emitted when the oracle is updated.
     * @param oldOracle The address of the old oracle.
     * @param newOracle The address of the new oracle.
     */
    event OracleUpdated(address indexed oldOracle, address indexed newOracle);

    /**
     * @notice Emitted when oracle data is updated.
     * @param oldData The address of the old oracle data.
     * @param newData The address of the new oracle data.
     */
    event OracleDataUpdated(bytes indexed oldData, bytes indexed newData);

    /**
     * @notice Emitted when a new timelock amount is requested.
     * @param oldVal The previous timelock amount.
     * @param newVal The new timelock amount.
     */
    event TimelockAmountUpdateRequested(uint256 oldVal, uint256 newVal);

    /**
     * @notice Emitted when timelock amount is updated.
     * @param oldVal The previous timelock amount.
     * @param newVal The new timelock amount.
     */
    event TimelockAmountUpdated(uint256 oldVal, uint256 newVal);

    // -- Mappings --

    /**
     * @notice Returns true/false for contracts' whitelist status.
     * @param _contract The address of the contract.
     */
    function isContractWhitelisted(
        address _contract
    ) external view returns (bool);

    /**
     * @notice Returns true if token is whitelisted.
     * @param _token The address of the token.
     */
    function isTokenWhitelisted(
        address _token
    ) external view returns (bool);

    /**
     * @notice Returns true if the token can be withdrawn from a holding.
     * @param _token The address of the token.
     */
    function isTokenWithdrawable(
        address _token
    ) external view returns (bool);

    /**
     * @notice Returns true if caller is allowed invoker.
     * @param _invoker The address of the invoker.
     */
    function allowedInvokers(
        address _invoker
    ) external view returns (bool);

    // -- Essential tokens --

    /**
     * @notice WETH address.
     */
    function WETH() external view returns (address);

    // -- Protocol's stablecoin oracle config --

    /**
     * @notice Oracle contract associated with protocol's stablecoin.
     */
    function jUsdOracle() external view returns (IOracle);

    /**
     * @notice Extra oracle data if needed.
     */
    function oracleData() external view returns (bytes calldata);

    // -- Managers --

    /**
     * @notice Returns the address of the HoldingManager Contract.
     */
    function holdingManager() external view returns (address);

    /**
     * @notice Returns the address of the LiquidationManager Contract.
     */
    function liquidationManager() external view returns (address);

    /**
     * @notice Returns the address of the StablesManager Contract.
     */
    function stablesManager() external view returns (address);

    /**
     * @notice Returns the address of the StrategyManager Contract.
     */
    function strategyManager() external view returns (address);

    /**
     * @notice Returns the address of the SwapManager Contract.
     */
    function swapManager() external view returns (address);

    // -- Fees --

    /**
     * @notice Returns the default performance fee.
     * @dev Uses 2 decimal precision, where 1% is represented as 100.
     */
    function performanceFee() external view returns (uint256);

    /**
     * @notice Returns the maximum performance fee.
     * @dev Uses 2 decimal precision, where 1% is represented as 100.
     */
    function MAX_PERFORMANCE_FEE() external view returns (uint256);

    /**
     * @notice Fee for withdrawing from a holding.
     * @dev Uses 2 decimal precision, where 1% is represented as 100.
     */
    function withdrawalFee() external view returns (uint256);

    /**
     * @notice Returns the maximum withdrawal fee.
     * @dev Uses 2 decimal precision, where 1% is represented as 100.
     */
    function MAX_WITHDRAWAL_FEE() external view returns (uint256);

    /**
     * @notice Returns the fee address, where all the fees are collected.
     */
    function feeAddress() external view returns (address);

    // -- Factories --

    /**
     * @notice Returns the address of the ReceiptTokenFactory.
     */
    function receiptTokenFactory() external view returns (address);

    // -- Utility values --

    /**
     * @notice Minimum allowed jUSD debt amount for a holding to ensure successful liquidation.
     */
    function minDebtAmount() external view returns (uint256);

    /**
     * @notice Returns the collateral rate precision.
     * @dev Should be less than exchange rate precision due to optimization in math.
     */
    function PRECISION() external view returns (uint256);

    /**
     * @notice Returns the exchange rate precision.
     */
    function EXCHANGE_RATE_PRECISION() external view returns (uint256);

    /**
     * @notice Timelock amount in seconds for changing the oracle data.
     */
    function timelockAmount() external view returns (uint256);

    /**
     * @notice Returns the old timelock value for delayed timelock update.
     */
    function oldTimelock() external view returns (uint256);

    /**
     * @notice Returns the new timelock value for delayed timelock update.
     */
    function newTimelock() external view returns (uint256);

    /**
     * @notice Returns the timestamp when the new timelock was requested.
     */
    function newTimelockTimestamp() external view returns (uint256);

    /**
     * @notice Returns the new oracle address for delayed oracle update.
     */
    function newOracle() external view returns (address);

    /**
     * @notice Returns the timestamp when the new oracle was requested.
     */
    function newOracleTimestamp() external view returns (uint256);

    /**
     * @notice Returns the new swap manager address for delayed swap manager update.
     */
    function newSwapManager() external view returns (address);

    /**
     * @notice Returns the timestamp when the new swap manager was requested.
     */
    function newSwapManagerTimestamp() external view returns (uint256);

    /**
     * @notice Returns the new liquidation manager address for delayed liquidation manager update.
     */
    function newLiquidationManager() external view returns (address);

    /**
     * @notice Returns the timestamp when the new liquidation manager was requested.
     */
    function newLiquidationManagerTimestamp() external view returns (uint256);

    // -- Setters --

    /**
     * @notice Whitelists a contract.
     *
     * @notice Requirements:
     * - `_contract` must not be whitelisted.
     *
     * @notice Effects:
     * - Updates the `isContractWhitelisted` mapping.
     *
     * @notice Emits:
     * - `ContractWhitelisted` event indicating successful contract whitelist operation.
     *
     * @param _contract The address of the contract to be whitelisted.
     */
    function whitelistContract(
        address _contract
    ) external;

    /**
     * @notice Blacklists a contract.
     *
     * @notice Requirements:
     * - `_contract` must be whitelisted.
     *
     * @notice Effects:
     * - Updates the `isContractWhitelisted` mapping.
     *
     * @notice Emits:
     * - `ContractBlacklisted` event indicating successful contract blacklist operation.
     *
     * @param _contract The address of the contract to be blacklisted.
     */
    function blacklistContract(
        address _contract
    ) external;

    /**
     * @notice Whitelists a token.
     *
     * @notice Requirements:
     * - `_token` must not be whitelisted.
     *
     * @notice Effects:
     * - Updates the `isTokenWhitelisted` mapping.
     *
     * @notice Emits:
     * - `TokenWhitelisted` event indicating successful token whitelist operation.
     *
     * @param _token The address of the token to be whitelisted.
     */
    function whitelistToken(
        address _token
    ) external;

    /**
     * @notice Removes a token from whitelist.
     *
     * @notice Requirements:
     * - `_token` must be whitelisted.
     *
     * @notice Effects:
     * - Updates the `isTokenWhitelisted` mapping.
     *
     * @notice Emits:
     * - `TokenRemoved` event indicating successful token removal operation.
     *
     * @param _token The address of the token to be whitelisted.
     */
    function removeToken(
        address _token
    ) external;

    /**
     * @notice Registers the `_token` as withdrawable.
     *
     * @notice Requirements:
     * - `msg.sender` must be owner or `strategyManager`.
     * - `_token` must not be withdrawable.
     *
     * @notice Effects:
     * - Updates the `isTokenWithdrawable` mapping.
     *
     * @notice Emits:
     * - `WithdrawableTokenAdded` event indicating successful withdrawable token addition operation.
     *
     * @param _token The address of the token to be added as withdrawable.
     */
    function addWithdrawableToken(
        address _token
    ) external;

    /**
     * @notice Unregisters the `_token` as withdrawable.
     *
     * @notice Requirements:
     * - `_token` must be withdrawable.
     *
     * @notice Effects:
     * - Updates the `isTokenWithdrawable` mapping.
     *
     * @notice Emits:
     * - `WithdrawableTokenRemoved` event indicating successful withdrawable token removal operation.
     *
     * @param _token The address of the token to be removed as withdrawable.
     */
    function removeWithdrawableToken(
        address _token
    ) external;

    /**
     * @notice Sets invoker as allowed or forbidden.
     *
     * @notice Effects:
     * - Updates the `allowedInvokers` mapping.
     *
     * @notice Emits:
     * - `InvokerUpdated` event indicating successful invoker update operation.
     *
     * @param _component Invoker's address.
     * @param _allowed True/false.
     */
    function updateInvoker(address _component, bool _allowed) external;

    /**
     * @notice Sets the Holding Manager Contract's address.
     *
     * @notice Requirements:
     * - `_val` must be different from previous `holdingManager` address.
     *
     * @notice Effects:
     * - Updates the `holdingManager` state variable.
     *
     * @notice Emits:
     * - `HoldingManagerUpdated` event indicating the successful setting of the Holding Manager's address.
     *
     * @param _val The holding manager's address.
     */
    function setHoldingManager(
        address _val
    ) external;

    /**
     * @notice Sets the Liquidation Manager Contract's address.
     *
     * @notice Requirements:
     * - Can only be called once.
     * - `_val` must be non-zero address.
     *
     * @notice Effects:
     * - Updates the `liquidationManager` state variable.
     *
     * @notice Emits:
     * - `LiquidationManagerUpdated` event indicating the successful setting of the Liquidation Manager's address.
     *
     * @param _val The liquidation manager's address.
     */
    function setLiquidationManager(
        address _val
    ) external;

    /**
     * @notice Initiates the process to update the Liquidation Manager Contract's address.
     *
     * @notice Requirements:
     * - `_val` must be non-zero address.
     * - `_val` must be different from previous `liquidationManager` address.
     *
     * @notice Effects:
     * - Updates the the `_newLiquidationManager` state variable.
     * - Updates the the `_newLiquidationManagerTimestamp` state variable.
     *
     * @notice Emits:
     * - `LiquidationManagerUpdateRequested` event indicating successful liquidation manager change request.
     *
     * @param _val The new liquidation manager's address.
     */
    function requestNewLiquidationManager(
        address _val
    ) external;

    /**
     * @notice Sets the Liquidation Manager Contract's address.
     *
     * @notice Requirements:
     * - `_val` must be different from previous `liquidationManager` address.
     * - Timelock must expire.
     *
     * @notice Effects:
     * - Updates the `liquidationManager` state variable.
     * - Updates the the `_newLiquidationManager` state variable.
     * - Updates the the `_newLiquidationManagerTimestamp` state variable.
     *
     * @notice Emits:
     * - `LiquidationManagerUpdated` event indicating the successful setting of the Liquidation Manager's address.
     */
    function acceptNewLiquidationManager() external;

    /**
     * @notice Sets the Stablecoin Manager Contract's address.
     *
     * @notice Requirements:
     * - `_val` must be different from previous `stablesManager` address.
     *
     * @notice Effects:
     * - Updates the `stablesManager` state variable.
     *
     * @notice Emits:
     * - `StablecoinManagerUpdated` event indicating the successful setting of the Stablecoin Manager's address.
     *
     * @param _val The Stablecoin manager's address.
     */
    function setStablecoinManager(
        address _val
    ) external;

    /**
     * @notice Sets the Strategy Manager Contract's address.
     *
     * @notice Requirements:
     * - `_val` must be different from previous `strategyManager` address.
     *
     * @notice Effects:
     * - Updates the `strategyManager` state variable.
     *
     * @notice Emits:
     * - `StrategyManagerUpdated` event indicating the successful setting of the Strategy Manager's address.
     *
     * @param _val The Strategy manager's address.
     */
    function setStrategyManager(
        address _val
    ) external;

    /**
     * @notice Sets the Swap Manager Contract's address.
     *
     * @notice Requirements:
     * - Can only be called once.
     * - `_val` must be non-zero address.
     *
     * @notice Effects:
     * - Updates the `swapManager` state variable.
     *
     * @notice Emits:
     * - `SwapManagerUpdated` event indicating the successful setting of the Swap Manager's address.
     *
     * @param _val The Swap manager's address.
     */
    function setSwapManager(
        address _val
    ) external;

    /**
     * @notice Initiates the process to update the Swap Manager Contract's address.
     *
     * @notice Requirements:
     * - `_val` must be non-zero address.
     * - `_val` must be different from previous `swapManager` address.
     *
     * @notice Effects:
     * - Updates the the `_newSwapManager` state variable.
     * - Updates the the `_newSwapManagerTimestamp` state variable.
     *
     * @notice Emits:
     * - `NewSwapManagerRequested` event indicating successful swap manager change request.
     *
     * @param _val The new swap manager's address.
     */
    function requestNewSwapManager(
        address _val
    ) external;

    /**
     * @notice Updates the Swap Manager Contract    .
     *
     * @notice Requirements:
     * - Timelock must expire.
     *
     * @notice Effects:
     * - Updates the `swapManager` state variable.
     * - Resets `_newSwapManager` to address(0).
     * - Resets `_newSwapManagerTimestamp` to 0.
     *
     * @notice Emits:
     * - `SwapManagerUpdated` event indicating the successful setting of the Swap Manager's address.
     */
    function acceptNewSwapManager() external;

    /**
     * @notice Sets the performance fee.
     *
     * @notice Requirements:
     * - `_val` must be smaller than `FEE_FACTOR` to avoid wrong computations.
     *
     * @notice Effects:
     * - Updates the `performanceFee` state variable.
     *
     * @notice Emits:
     * - `PerformanceFeeUpdated` event indicating successful performance fee update operation.
     *
     * @dev `_val` uses 2 decimal precision, where 1% is represented as 100.
     *
     * @param _val The new performance fee value.
     */
    function setPerformanceFee(
        uint256 _val
    ) external;

    /**
     * @notice Sets the withdrawal fee.
     *
     * @notice Requirements:
     * - `_val` must be smaller than `FEE_FACTOR` to avoid wrong computations.
     *
     * @notice Effects:
     * - Updates the `withdrawalFee` state variable.
     *
     * @notice Emits:
     * - `WithdrawalFeeUpdated` event indicating successful withdrawal fee update operation.
     *
     * @dev `_val` uses 2 decimal precision, where 1% is represented as 100.
     *
     * @param _val The new withdrawal fee value.
     */
    function setWithdrawalFee(
        uint256 _val
    ) external;

    /**
     * @notice Sets the global fee address.
     *
     * @notice Requirements:
     * - `_val` must be different from previous `holdingManager` address.
     *
     * @notice Effects:
     * - Updates the `feeAddress` state variable.
     *
     * @notice Emits:
     * - `FeeAddressUpdated` event indicating successful setting of the global fee address.
     *
     * @param _val The new fee address.
     */
    function setFeeAddress(
        address _val
    ) external;

    /**
     * @notice Sets the receipt token factory's address.
     *
     * @notice Requirements:
     * - `_val` must be different from previous `receiptTokenFactory` address.
     *
     * @notice Effects:
     * - Updates the `receiptTokenFactory` state variable.
     *
     * @notice Emits:
     * - `ReceiptTokenFactoryUpdated` event indicating successful setting of the `receiptTokenFactory` address.
     *
     * @param _factory Receipt token factory's address.
     */
    function setReceiptTokenFactory(
        address _factory
    ) external;

    /**
     * @notice Registers jUSD's oracle change request.
     *
     * @notice Requirements:
     * - Contract must not be in active change.
     *
     * @notice Effects:
     * - Updates the the `_isActiveChange` state variable.
     * - Updates the the `_newOracle` state variable.
     * - Updates the the `_newOracleTimestamp` state variable.
     *
     * @notice Emits:
     * - `NewOracleRequested` event indicating successful jUSD's oracle change request.
     *
     * @param _oracle Liquidity gauge factory's address.
     */
    function requestNewJUsdOracle(
        address _oracle
    ) external;

    /**
     * @notice Updates jUSD's oracle.
     *
     * @notice Requirements:
     * - Contract must be in active change.
     * - Timelock must expire.
     *
     * @notice Effects:
     * - Updates the the `jUsdOracle` state variable.
     * - Updates the the `_isActiveChange` state variable.
     * - Updates the the `_newOracle` state variable.
     * - Updates the the `_newOracleTimestamp` state variable.
     *
     * @notice Emits:
     * - `OracleUpdated` event indicating successful jUSD's oracle change.
     */
    function acceptNewJUsdOracle() external;

    /**
     * @notice Updates the jUSD's oracle data.
     *
     * @notice Requirements:
     * - `_newOracleData` must be different from previous `oracleData`.
     *
     * @notice Effects:
     * - Updates the `oracleData` state variable.
     *
     * @notice Emits:
     * - `OracleDataUpdated` event indicating successful update of the oracle Data.
     *
     * @param _newOracleData New data used for jUSD's oracle data.
     */
    function setJUsdOracleData(
        bytes calldata _newOracleData
    ) external;

    /**
     * @notice Sets the minimum debt amount.
     *
     * @notice Requirements:
     * - `_minDebtAmount` must be greater than zero.
     * - `_minDebtAmount` must be different from previous `minDebtAmount`.
     *
     * @param _minDebtAmount The new minimum debt amount.
     */
    function setMinDebtAmount(
        uint256 _minDebtAmount
    ) external;

    /**
     * @notice Registers timelock change request.
     *
     * @notice Requirements:
     * - `_oldTimelock` must be set zero.
     * - `_newVal` must be greater than zero.
     *
     * @notice Effects:
     * - Updates the the `_oldTimelock` state variable.
     * - Updates the the `_newTimelock` state variable.
     * - Updates the the `_newTimelockTimestamp` state variable.
     *
     * @notice Emits:
     * - `TimelockAmountUpdateRequested` event indicating successful timelock change request.
     *
     * @param _newVal The new timelock value in seconds.
     */
    function requestNewTimelock(
        uint256 _newVal
    ) external;

    /**
     * @notice Updates the timelock amount.
     *
     * @notice Requirements:
     * - Contract must be in active change.
     * - `_newTimelock` must be greater than zero.
     * - The old timelock must expire.
     *
     * @notice Effects:
     * - Updates the the `timelockAmount` state variable.
     * - Updates the the `_oldTimelock` state variable.
     * - Updates the the `_newTimelock` state variable.
     * - Updates the the `_newTimelockTimestamp` state variable.
     *
     * @notice Emits:
     * - `TimelockAmountUpdated` event indicating successful timelock amount change.
     */
    function acceptNewTimelock() external;

    // -- Getters --

    /**
     * @notice Returns the up to date exchange rate of the protocol's stablecoin jUSD.
     *
     * @notice Requirements:
     * - Oracle must have updated rate.
     * - Rate must be a non zero positive value.
     *
     * @return The current exchange rate.
     */
    function getJUsdExchangeRate() external view returns (uint256);
}
"
    },
    "lib/jigsaw-protocol-v1/src/interfaces/core/IStrategyManager.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import { IStrategy } from ".//IStrategy.sol";
import { IManager } from "./IManager.sol";
import { IStrategyManagerMin } from "./IStrategyManagerMin.sol";

/**
 * @title IStrategyManager
 * @dev Interface for the StrategyManager contract.
 */
interface IStrategyManager is IStrategyManagerMin {
    // -- Custom Types --

    /**
     * @notice Contains details about a specific strategy, such as its performance fee, active status, and whitelisted
     * status.
     * @param performanceFee fee charged as a percentage of the profits generated by the strategy.
     * @param active flag indicating whether the strategy is active.
     * @param whitelisted flag indicating whether strategy is approved for investment.
     */
    struct StrategyInfo {
        uint256 performanceFee;
        bool active;
        bool whitelisted;
    }

    /**
     * @notice Contains data required for moving investment from one strategy to another.
     * @param strategyFrom strategy's address where investment is taken from.
     * @param strategyTo strategy's address where to invest.
     * @param shares investment amount.
     * @param dataFrom data required by `strategyFrom` to perform `_claimInvestment`.
     * @param dataTo data required by `strategyTo` to perform `_invest`.
     * @param strategyToMinSharesAmountOut minimum amount of shares to receive.
     */
    struct MoveInvestmentData {
        address strategyFrom;
        address strategyTo;
        uint256 shares;
        bytes dataFrom;
        bytes dataTo;
        uint256 strategyToMinSharesAmountOut;
    }

    /**
     * @dev Struct used for _claimInvestment function
     * @param strategyContract The strategy contract instance being interacted with
     * @param withdrawnAmount The amount of the asset withdrawn from the strategy
     * @param initialInvestment The amount of initial investment
     * @param yield The yield amount (positive for profit, negative for loss)
     * @param fee The amount of fee charged by the strategy
     * @param remainingShares The number of shares remaining after the withdrawal
     */
    struct ClaimInvestmentData {
        IStrategy strategyContract;
        uint256 withdrawnAmount;
        uint256 initialInvestment;
        int256 yield;
        uint256 fee;
        uint256 remainingShares;
    }

    // -- Events --

    /**
     * @notice Emitted when a new strategy is added to the whitelist.
     * @param strategy The address of the strategy that was added.
     */
    event StrategyAdded(address indexed strategy);

    /**
     * @notice Emitted when an existing strategy is removed from the whitelist.
     * @param strategy The address of the strategy that was removed.
     */
    event StrategyRemoved(address indexed strategy);

    /**
     * @notice Emitted when an existing strategy info is updated.
     * @param strategy The address of the strategy that was updated.
     * @param active Indicates if the strategy is active.
     * @param fee The fee associated with the strategy.
     */
    event StrategyUpdated(address indexed strategy, bool active, uint256 fee);

    /**
     * @notice Emitted when an investment is created.
     * @param holding The address of the holding.
     * @param user The address of the user.
     * @param token The address of the token invested.
     * @param strategy The address of the strategy used for investment.
     * @param amount The amount of tokens invested.
     * @param tokenOutResult The result amount of the output token.
     * @param tokenInResult The result amount of the input token.
     */
    event Invested(
        address indexed holding,
        address indexed user,
        address indexed token,
        address strategy,
        uint256 amount,
        uint256 tokenOutResult,
        uint256 tokenInResult
    );

    /**
     * @notice Emitted when an investment is moved between strategies.
     * @param holding The address of the holding.
     * @param user The address of the user.
     * @param token The address of the token invested.
     * @param strategyFrom The address of the strategy from which the investment is moved.
     * @param strategyTo The address of the strategy to which the investment is moved.
     * @param shares The amount of shares moved.
     * @param tokenOutResult The result amount of the output token.
     * @param tokenInResult The result amount of the input token.
     */
    event InvestmentMoved(
        address indexed holding,
        address indexed user,
        address indexed token,
        address strategyFrom,
        address strategyTo,
        uint256 shares,
        uint256 tokenOutResult,
        uint256 tokenInResult
    );

    /**
     * @notice Emitted when collateral is adjusted from a claim investment or claim rewards operation.
     * @param holding The address of the holding.
     * @param token The address of the token.
     * @param value The value of the collateral adjustment.
     * @param add Indicates if the collateral is added (true) or removed (false).
     */
    event CollateralAdjusted(address indexed holding, address indexed token, uint256 value, bool add);

    /**
     * @notice Emitted when an investment is withdrawn.
     * @param holding The address of the holding.
     * @param user The address of the user.
     * @param token The address of the token withdrawn.
     * @param strategy The address of the strategy from which the investment is withdrawn.
     * @param shares The amount of shares withdrawn.
     * @param withdrawnAmount The amount of tokens withdrawn.
     * @param initialInvestment The amount of initial investment.
     * @param yield The yield amount (positive for profit, negative for loss)
     * @param fee The amount of fee charged by the strategy
     */
    event StrategyClaim(
        address indexed holding,
        address indexed user,
        address indexed token,
        address strategy,
        uint256 shares,
        uint256 withdrawnAmount,
        uint256 initialInvestment,
        int256 yield,
        uint256 fee
    );

    /**
     * @notice Emitted when rewards are claimed.
     * @param token The address of the token rewarded.
     * @param holding The address of the holding.
     * @param amount The amount of rewards claimed.
     */
    event RewardsClaimed(address indexed token, address indexed holding, uint256 amount);

    /**
     * @notice Contract that contains all the necessary configs of the protocol.
     * @return The manager contract.
     */
    function manager() external view returns (IManager);

    // -- User specific methods --

    /**
     * @notice Invests `_token` into `_strategy`.
     *
     * @notice Requirements:
     * - Strategy must be whitelisted.
     * - Amount must be non-zero.
     * - Token specified for investment must be whitelisted.
     * - Msg.sender must have holding.
     *
     * @notice Effects:
     * - Performs investment to the specified `_strategy`.
     * - Deposits holding's collateral to the specified `_strategy`.
     * - Adds `_strategy` used for investment to the holdingToStrategy data structure.
     *
     * @notice Emits:
     * - Invested event indicating successful investment operation.
     *
     * @param _token address.
     * @param _strategy address.
     * @param _amount to be invested.
     * @param _minSharesAmountOut minimum amount of shares to receive.
     * @param _data needed by each individual strategy.
     *
     * @return tokenOutAmount receipt tokens amount.
     * @return tokenInAmount tokenIn amount.
     */
    function invest(
        address _token,
        address _strategy,
        uint256 _amount,
        uint256 _minSharesAmountOut,
        bytes calldata _data
    ) external returns (uint256 tokenOutAmount, uint256 tokenInAmount);

    /**
     * @notice Claims investment from one strategy and invests it into another.
     *
     * @notice Requirements:
     * - The `strategyFrom` and `strategyTo` must be valid and active.
     * - The `strategyFrom` and `strategyTo` must be different.
     * - Msg.sender must have a holding.
     *
     * @notice Effects:
     * - Claims the investment from `strategyFrom`.
     * - Invests the claimed amount into `strategyTo`.
     *
     * @notice Emits:
     * - InvestmentMoved event indicating successful investment movement operation.
     *
     * @dev Some strategies won't give back any receipt tokens; in this case 'tokenOutAmount' will be 0.
     * @dev 'tokenInAmount' will be equal to '_amount' in case the '_asset' is the same as strategy 'tokenIn()'.
     *
     * @param _token The address of the token.
     * @param _data The MoveInvestmentData object containing strategy and amount details.
     *
     * @return tokenOutAmount The amount of receipt tokens returned.
     * @return tokenInAmount The amount of tokens invested in the new strategy.
     */
    function moveInvestment(
        address _token,
        MoveInvestmentData calldata _data
    ) external returns (uint256 tokenOutAmount, uint256 tokenInAmount);

    /**
     * @notice Claims a strategy investment.
     *
     * @notice Requirements:
     * - The `_strategy` must be valid.
     * - Msg.sender must be allowed to execute the call.
     * - `_shares` must be of valid amount.
     * - Specified `_holding` must exist within protocol.
     *
     * @notice Effects:
     * - Withdraws investment from `_strategy`.
     * - Updates `holdingToStrategy` if needed.
     *
     * @notice Emits:
     * - StrategyClaim event indicating successful claim operation.
     *
     * @dev Withdraws investment from a strategy.
     * @dev Some strategies will allow only the tokenIn to be withdrawn.
     * @dev 'AssetAmount' will be equal to 'tokenInAmount' in case the '_asset' is the same as strategy 'tokenIn()'.
     *
     * @param _holding holding's address.
     * @param _token address to be received.
     * @param _strategy strategy to invest into.
     * @param _shares shares amount.
     * @param _data extra data.
     *
     * @return withdrawnAmount The amount of tokens withdrawn.
     * @return initialInvestment The amount of initial investment.
     * @return yield The yield amount (positive for profit, negative for loss)
     * @return fee The amount of fee charged by the strategy
     */
    function claimInvestment(
        address _holding,
        address _token,
        address _strategy,
        uint256 _shares,
        bytes calldata _data
    ) external returns (uint256 withdrawnAmount, uint256 initialInvestment, int256 yield, uint256 fee);

    /**
     * @notice Claims rewards from strategy.
     *
     * @notice Requirements:
     * - The `_strategy` must be valid.
     * - Msg.sender must have valid holding within protocol.
     *
     * @notice Effects:
     * - Claims rewards from strategies.
     * - Adds accrued rewards as a collateral for holding.
     *
     * @param _strategy strategy to invest into.
     * @param _data extra data.
     *
     * @return rewards reward amounts.
     * @return tokens reward tokens.
     */
    function claimRewards(
        address _strategy,
        bytes calldata _data
    ) external returns (uint256[] memory rewards, address[] memory tokens);

    // -- Administration --

    /**
     * @notice Adds a new strategy to the whitelist.
     * @param _strategy strategy's address.
     */
    function addStrategy(
        address _strategy
    ) external;

    /**
     * @notice Updates an existing strategy info.
     * @param _strategy strategy's address.
     * @param _info info.
     */
    function updateStrategy(address _strategy, StrategyInfo calldata _info) external;

    /**
     * @notice Triggers stopped state.
     */
    function pause() external;

    /**
     * @notice Returns to normal state.
     */
    function unpause() external;

    // -- Getters --

    /**
     * @notice Returns all the strategies holding has invested in.
     * @dev Should be only called off-chain as can be high gas consuming.
     * @param _holding address for which the strategies are requested.
     */
    function getHoldingToStrategy(
        address _holding
    ) external view returns (address[] memory);

    /**
     * @notice Returns the number of strategies the holding has invested in.
     * @param _holding address for which the strategy count is requested.
     * @return uint256 The number of strategies the holding has invested in.
     */
    function getHoldingToStrategyLength(
        address _holding
    ) external view returns (uint256);
}
"
    },
    "src/extensions/interfaces/IFeeManager.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;

import { IManager } from "@jigsaw/src/interfaces/core/IManager.sol";

interface IFeeManager {
    // -- Events --

    /**
     * @notice Emitted when the default fee is updated.
     *
     * @param holding The holding address the fee is updated for.
     * @param strategy The strategy address the fee is updated for.
     * @param oldFee The old fee.
     * @param newFee The new fee.
     */
    event HoldingFeeUpdated(address indexed holding, address indexed strategy, uint256 oldFee, uint256 newFee);

    // -- State variables --

    /**
     * @notice The Manager contract.
     */
    function manager() external view returns (IManager);

    // -- Administration --

    /**
     * @notice Sets performance fee for a specific `_holding` in a specific `_strategy`.
     *
     * @param _holding The address of the holding.
     * @param _strategy The address of the strategy.
     * @param _fee The performance fee to set.
     */
    function setHoldingCustomFee(address _holding, address _strategy, uint256 _fee) external;

    /**
     * @notice Sets performance fee for a list of `_holdings` in a specified `_strategies` list.
     *
     * @param _holdings The list of the holding addresses to set `_fees` for.
     * @param _strategies The list of the strategies addresses to set `_holdings`' `_fees` for.
     * @param _fees The list of performance fees to set for specified `_holdings` and `_strategies`.
     */
    function setHoldingCustomFee(
        address[] calldata _holdings,
        address[] calldata _strategies,
        uint256[] calldata _fees
    ) external;

    // -- Getters --

    /**
     * @notice Returns `_holding`'s performance fee for specified `_strategy`.
     *
     * @dev Returns default performance fee stored in StrategyManager contract, if it's set to zero.
     *
     * @param _strategy The address of the strategy.
     * @param _holding The address of the holding.
     *
     * @return `_holding`'s performance fee for `_strategy`.
     */
    function getHoldingFee(address _holding, address _strategy) external view returns (uint256);
}
"
    },
    "lib/jigsaw-protocol-v1/lib/openzeppelin-contracts/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
"
    },
    "lib/jigsaw-protocol-v1/src/interfaces/oracle/IOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IOracle {
    // -- State variables --

    /**
     * @notice Returns the address of the token the oracle is for.
     */
    function underlying() external view returns (address);

    // -- Functions --

    /**
     * @notice Returns a human readable name of the underlying of the oracle.
     */
    function name() external view returns (string memory);

    /**
     * @notice Returns a human readable symbol of the underlying of the oracle.
     */
    function symbol() external view returns (string memory);

    /**
     * @notice Check the last exchange rate without any state changes.
     *
     * @param data Implementation specific data that contains information and arguments to & about the oracle.
     *
     * @return success If no valid (recent) rate is available, returns false else true.
     * @return rate The rate of the requested asset / pair / pool.
     */
    function peek(
        bytes calldata data
    ) external view returns (bool success, uint256 rate);
}
"
    },
    "lib/jigsaw-protocol-v1/src/interfaces/core/IStrategy.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import { IReceiptToken } from "../core/IReceiptToken.sol";

/**
 * @title IStrategy
 * @notice Interface for a Strategies.
 *
 * @dev This interface defines the standard functions and events for a strategy contract.
 * @dev The strategy allows for the deposit, withdrawal, and reward claiming functionalities.
 * @dev It also provides views for essential information about the strategy's token and rewards.
 */
interface IStrategy {
    // -- Custom types --

    /**
     * @notice Struct containing parameters for a withdrawal operation.
     * @param shares The number of shares to withdraw.
     * @param totalShares The total shares owned by the user.
     * @param shareRatio The ratio of the shares to withdraw relative to the total shares owned by the user.
     * @param shareDecimals The number of decimals of the strategy's shares.
     * @param investment The amount of initial investment corresponding to the shares being withdrawn.
     * @param assetsToWithdraw The underlying assets withdrawn by the user, including yield and excluding fee.
     * @param balanceBefore The user's `tokenOut` balance before the withdrawal transaction.
     * @param withdrawnAmount The amount of underlying assets withdrawn by the user, excluding fee.
     * @param yield The yield generated by the strategy excluding fee, as fee are taken from the yield.
     * @param fee The amount of fee taken by the protocol.
     */
    struct WithdrawParams {
        uint256 shares;
        uint256 totalShares;
        uint256 shareRatio;
        uint256 shareDecimals;
        uint256 investment;
        uint256 assetsToWithdraw;
        uint256 balanceBefore;
        uint256 withdrawnAmount;
        int256 yield;
        uint256 fee;
    }

    /**
     * @notice Emitted when funds are deposited.
     *
     * @param asset The address of the asset.
     * @param tokenIn The address of the input token.
     * @param assetAmount The amount of the asset.
     * @param tokenInAmount The amount of the input token.
     * @param shares The number of shares received.
     * @param recipient The address of the recipient.
     */
    event Deposit(
        address indexed asset,
        address indexed tokenIn,
        uint256 assetAmount,
        uint256 tokenInAmount,
        uint256 shares,
        address indexed recipient
    );

    /**
     * @notice Emitted when funds are withdrawn.
     *
     * @param asset The address of the asset.
     * @param recipient The address of the recipient.
     * @param shares The number of shares withdrawn.
     * @param withdrawnAmount The amount of the asset withdrawn.
     * @param yield The amount of yield generated by the user beyond their initial investment.
     */
    event Withdraw(
        address indexed asset,
        address indexed recipient,
        uint256 shares,
        uint256 withdrawnAmount,
        uint256 initialInvestment,
        int256 yield
    );

    /**
     * @notice Emitted when rewards are claimed.
     *
     * @param recipient The address of the recipient.
     * @param rewards The array of reward amounts.
     * @param rewardTokens The array of reward token addresses.
     */
    event Rewards(address indexed recipient, uint256[] rewards, address[] rewardTokens);

    /**
     * @notice Returns investments details.
     * @param _recipient The address of the recipient.
     * @return investedAmount The amount invested.
     * @return totalShares The total shares.
     */
    function recipients(
        address _recipient
    ) external view returns (uint256 investedAmount, uint256 totalShares);

    /**
     * @notice Returns the address of the token accepted by the strategy's underlying protocol as input.
     * @return tokenIn The address of the tokenIn.
     */
    function tokenIn() external view returns (address);

    /**
     * @notice Returns the address of token issued by the strategy's underlying protocol after deposit.
     * @return tokenOut The address of the tokenOut.
     */
    function tokenOut() external view returns (address);

    /**
     * @notice Returns the address of the strategy's main reward token.
     * @return rewardToken The address of the reward token.
     */
    function rewardToken() external view returns (address);

    /**
     * @notice Returns the address of the receipt token minted by the strategy itself.
     * @return receiptToken The address of the receipt token.
     */
    function receiptToken() external view returns (IReceiptToken);

    /**
     * @notice Returns the number of decimals of the strategy's shares.
     * @return sharesDecimals The number of decimals.
     */
    function sharesDecimals() external view returns (uint256);

    /**
     * @notice Returns the address of the receipt token.
     * @return receiptTokenAddress The address of the receipt token.
     */
    function getReceiptTokenAddress() external view returns (address receiptTokenAddress);

    /**
     * @notice Deposits funds into the strategy.
     *
     * @dev Some strategies won't give back any receipt tokens; in this case 'tokenOutAmount' will be 0.
     * 'tokenInAmount' will be equal to '_amount' in case the '_asset' is the same as strategy 'tokenIn()'.
     *
     * @param _asset The token to be invested.
     * @param _amount The token's amount.
     * @param _recipient The address of the recipient.
     * @param _data Extra data.
     *
     * @return tokenOutAmount The receipt tokens amount/obtained shares.
     * @return tokenInAmount The returned token in amount.
     */
    function deposit(
        address _asset,
        uint256 _amount,
        address _recipient,
        bytes calldata _data
    ) external returns (uint256 tokenOutAmount, uint256 tokenInAmount);

    /**
     * @notice Withdraws deposited funds.
     *
     * @param _shares The amount to withdraw.
     * @param _recipient The address of the recipient.
     * @param _asset The token to be withdrawn.
     * @param _data Extra data.
     *
     * @return withdrawnAmount The actual amount of asset withdrawn from the strategy.
     * @return initialInvestment The amount of initial investment.
     * @return yield The amount of yield generated by the user beyond their initial investment.
     * @return fee The amount of fee charged by the strategy.
     */
    function withdraw(
        uint256 _shares,
        address _recipient,
        address _asset,
        bytes calldata _data
    ) external returns (uint256 withdrawnAmount, uint256 initialInvestment, int256 yield, uint256 fee);

    /**
     * @notice Claims rewards from the strategy.
     *
     * @param _recipient The address of the recipient.
     * @param _data Extra data.
     *
     * @return amounts The reward tokens amounts.
     * @return tokens The reward tokens addresses.
     */
    function claimRewards(
        address _recipient,
        bytes calldata _data
    ) external returns (uint256[] memory amounts, address[] memory tokens);

    /**
     * @notice Participants info.
     */
    struct RecipientInfo {
        uint256 investedAmount;
        uint256 totalShares;
    }
}
"
    },
    "lib/jigsaw-protocol-v1/src/interfaces/core/IStrategyManagerMin.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IStrategyManagerMin {
    /**
     * @notice Returns the strategy info.
     */
    function strategyInfo(
        address _strategy
    ) external view returns (uint256, bool, bool);
}
"
    },
    "lib/jigsaw-protocol-v1/src/interfaces/core/IReceiptToken.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import { IERC20Errors } from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
import { IERC20, IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";

// Receipt token interface
interface IReceiptToken is IERC20, IERC20Metadata, IERC20Errors {
    // -- Events --

    /**
     * @notice Emitted when the minter address is updated
     *  @param oldMinter The address of the old minter
     *  @param newMinter The address of the new minter
     */
    event MinterUpdated(address oldMinter, address newMinter);

    // --- Initialization ---

    /**
     * @notice This function initializes the contract (instead of a constructor) to be cloned.
     *
     * @notice Requirements:
     * - The contract must not be already initialized.
     * - The `__minter` must not be the zero address.
     *
     * @notice Effects:
     * - Sets `_initialized` to true.
     * - Updates `_name`, `_symbol`, `minter` state variables.
     * - Stores `__owner` as owner.
     *
     * @param __name Receipt token name.
     * @param __symbol Receipt token symbol.
     * @param __minter Receipt token minter.
     * @param __owner Receipt token owner.
     */
    function initialize(string memory __name, string memory __symbol, address __minter, address __owner) external;

    /

Tags:
ERC20, Multisig, Mintable, Pausable, Swap, Liquidity, Yield, Upgradeable, Multi-Signature, Factory, Oracle|addr:0x552dd7f539d5480a2714df8ed066d67264a4544c|verified:true|block:23419957|tx:0xa361ea98359cb42d98ce7039f87126af8c4acfd637a6d744749b9e95b7cab500|first_check:1758564513

Submitted on: 2025-09-22 20:08:34

Comments

Log in to comment.

No comments yet.