PoolLogicLib

Description:

Decentralized Finance (DeFi) protocol contract providing Liquidity, Factory functionality.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "@openzeppelin/contracts/math/SafeMath.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}
"
    },
    "contracts/interfaces/IHasDaoInfo.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

interface IHasDaoInfo {
  function getDaoFee() external view returns (uint256, uint256);

  function daoAddress() external view returns (address);
}
"
    },
    "contracts/interfaces/IPoolManagerLogic.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;

interface IPoolManagerLogic {
  function poolLogic() external view returns (address);

  function isDepositAsset(address asset) external view returns (bool);

  function validateAsset(address asset) external view returns (bool);

  function assetValue(address asset) external view returns (uint256);

  function assetValue(address asset, uint256 amount) external view returns (uint256);

  function assetBalance(address asset) external view returns (uint256 balance);

  function factory() external view returns (address);

  function setPoolLogic(address fundAddress) external returns (bool);

  function totalFundValue() external view returns (uint256);

  function isMemberAllowed(address member) external view returns (bool);

  function getFee() external view returns (uint256, uint256, uint256, uint256, uint256);

  function minDepositUSD() external view returns (uint256);

  function getEntryFeeInfo()
    external
    view
    returns (uint256 entryFeeNumerator, uint256 poolFeeShareNumerator, uint256 feeDenominator);

  function getExitFeeInfo()
    external
    view
    returns (uint256 exitFeeNumerator, uint256 poolFeeShareNumerator, uint256 feeDenominator);

  function maxSupplyCap() external view returns (uint256 supplyCap);
}
"
    },
    "contracts/utils/PoolLogicLib.sol": {
      "content": "//
//        __  __    __  ________  _______    ______   ________
//       /  |/  |  /  |/        |/       \  /      \ /        |
//   ____$$ |$$ |  $$ |$$$$$$$$/ $$$$$$$  |/$$$$$$  |$$$$$$$$/
//  /    $$ |$$ |__$$ |$$ |__    $$ |  $$ |$$ | _$$/ $$ |__
// /$$$$$$$ |$$    $$ |$$    |   $$ |  $$ |$$ |/    |$$    |
// $$ |  $$ |$$$$$$$$ |$$$$$/    $$ |  $$ |$$ |$$$$ |$$$$$/
// $$ \__$$ |$$ |  $$ |$$ |_____ $$ |__$$ |$$ \__$$ |$$ |_____
// $$    $$ |$$ |  $$ |$$       |$$    $$/ $$    $$/ $$       |
//  $$$$$$$/ $$/   $$/ $$$$$$$$/ $$$$$$$/   $$$$$$/  $$$$$$$$/
//
// dHEDGE DAO - https://dhedge.org
//
// Copyright (c) 2025 dHEDGE DAO
//
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;

import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol";

import {IPoolManagerLogic} from "../interfaces/IPoolManagerLogic.sol";
import {IHasDaoInfo} from "../interfaces/IHasDaoInfo.sol";

library PoolLogicLib {
  using SafeMath for uint256;

  struct LiquidityMintTo {
    uint256 recipient;
    uint256 manager;
    uint256 dao;
  }

  struct PoolTokensAllocation {
    uint256 toBurn;
    uint256 toTransferManager;
    uint256 toTransferDao;
    uint256 toGetPortionFrom;
  }

  function computeLiquidityMintTo(
    uint256 _totalSupply,
    uint256 _depositValue,
    uint256 _totalValue,
    address _poolManagerLogic,
    address _poolFactory
  ) external view returns (LiquidityMintTo memory liquidityMintTo) {
    liquidityMintTo = _buildLiquidityMintTo(_totalSupply, _depositValue, _totalValue, _poolManagerLogic, _poolFactory);

    // Check supply cap only during deposit mintings to avoid withdrawals being halted during PoolLogic::_mintManagerFee()
    _validateMinting(
      _totalSupply,
      liquidityMintTo.recipient.add(liquidityMintTo.manager).add(liquidityMintTo.dao),
      _poolManagerLogic
    );
  }

  function computePoolTokensAllocation(
    uint256 _redeemAmount,
    address _poolManagerLogic,
    address _poolFactory
  ) external view returns (PoolTokensAllocation memory tokens) {
    tokens.toBurn = _redeemAmount;
    tokens.toGetPortionFrom = _redeemAmount;

    (uint256 exitFeeNumerator, uint256 poolFeeShareNumerator, uint256 feeDenominator) = IPoolManagerLogic(
      _poolManagerLogic
    ).getExitFeeInfo();

    // Exit fee is 0, hence burn full amount and process withdrawal according to the portion of this amount.
    if (exitFeeNumerator == 0) {
      return tokens;
    }

    uint256 exitFee = tokens.toBurn.mul(exitFeeNumerator).div(feeDenominator);

    tokens.toGetPortionFrom = tokens.toGetPortionFrom.sub(exitFee);

    uint256 exitFeeToTransfer = exitFee.mul(feeDenominator.sub(poolFeeShareNumerator)).div(feeDenominator);

    // Nothing to transfer to manager or DAO, 100% of exit fee is going to the pool. all tokens are burned, user's portion is reduced on size of the fee.
    if (exitFeeToTransfer == 0) {
      return tokens;
    }

    // Only tokens not intended for transfer are burned, user's portion still reduced on size of the fee.
    tokens.toBurn = tokens.toBurn.sub(exitFeeToTransfer);

    (uint256 daoFeeNumerator, uint256 daoFeeDenominator) = IHasDaoInfo(_poolFactory).getDaoFee();

    tokens.toTransferDao = exitFeeToTransfer.mul(daoFeeNumerator).div(daoFeeDenominator);
    tokens.toTransferManager = exitFeeToTransfer.sub(tokens.toTransferDao);

    require(tokens.toBurn > tokens.toTransferManager && tokens.toTransferManager > tokens.toTransferDao, "dh13");

    return tokens;
  }

  function _buildLiquidityMintTo(
    uint256 _totalSupply,
    uint256 _depositValue,
    uint256 _totalValue,
    address _poolManagerLogic,
    address _poolFactory
  ) internal view returns (LiquidityMintTo memory liquidityMintTo) {
    liquidityMintTo.recipient = _totalSupply > 0 ? _depositValue.mul(_totalSupply).div(_totalValue) : _depositValue;

    (uint256 entryFeeNumerator, uint256 poolFeeShareNumerator, uint256 feeDenominator) = IPoolManagerLogic(
      _poolManagerLogic
    ).getEntryFeeInfo();

    if (entryFeeNumerator == 0) {
      return liquidityMintTo;
    }

    uint256 entryFee = liquidityMintTo.recipient.mul(entryFeeNumerator).div(feeDenominator);

    liquidityMintTo.recipient = liquidityMintTo.recipient.sub(entryFee);

    uint256 entryFeeToMint = entryFee.mul(feeDenominator.sub(poolFeeShareNumerator)).div(feeDenominator);

    if (entryFeeToMint == 0) {
      return liquidityMintTo;
    }

    (uint256 daoFeeNumerator, uint256 daoFeeDenominator) = IHasDaoInfo(_poolFactory).getDaoFee();

    liquidityMintTo.dao = entryFeeToMint.mul(daoFeeNumerator).div(daoFeeDenominator);
    liquidityMintTo.manager = entryFeeToMint.sub(liquidityMintTo.dao);

    require(
      liquidityMintTo.recipient > liquidityMintTo.manager && liquidityMintTo.manager > liquidityMintTo.dao,
      "dh13"
    );

    return liquidityMintTo;
  }

  function _validateMinting(uint256 _totalSupply, uint256 _mintAmount, address _poolManagerLogic) internal view {
    uint256 supplyCap = IPoolManagerLogic(_poolManagerLogic).maxSupplyCap();
    if (supplyCap > 0) {
      require(_totalSupply.add(_mintAmount) <= supplyCap, "dh32");
    }
  }
}
"
    }
  },
  "settings": {
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "optimizer": {
      "enabled": true,
      "runs": 20
    }
  }
}}

Tags:
DeFi, Liquidity, Factory|addr:0x2ff22b46f95d0b320b7754b3c55b684702ef6010|verified:true|block:23419051|tx:0x687c0b56e2e231f0e75343bb1b1847a75d1156b9fd819ba70e7a8b6f91a25426|first_check:1758553577

Submitted on: 2025-09-22 17:06:17

Comments

Log in to comment.

No comments yet.