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
}
}
}}
Submitted on: 2025-09-22 17:06:17
Comments
Log in to comment.
No comments yet.