Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- GeneralUtils
- Optimization enabled
- true
- Compiler version
- v0.7.6+commit.7338295f
- Optimization runs
- 200
- EVM Version
- istanbul
- Verified at
- 2024-06-07T07:01:10.653537Z
contracts/protocol/libraries/utils/GeneralUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
import "../../../dependencies/openzeppelin/contracts/IERC20.sol";
import "../../../dependencies/openzeppelin/contracts/SafeMath.sol";
import "../../../interfaces/IAddressesProvider.sol";
import "../../../interfaces/IVault.sol";
import "../../../interfaces/IVaultConfigurator.sol";
import "../../../interfaces/IPhamePriceOracle.sol";
library GeneralUtils {
function validate(bool condition, uint256 errorCode) public pure {
require(condition, _uint2str(errorCode));
}
function _uint2str(uint256 _i) private pure returns (string memory str) {
if (_i == 0) {
return "0";
}
uint256 j = _i;
uint256 length;
while (j != 0) {
length++;
j /= 10;
}
bytes memory bstr = new bytes(length);
uint256 k = length;
j = _i;
while (j != 0) {
bstr[--k] = bytes1(uint8(48 + (j % 10)));
j /= 10;
}
str = string(bstr);
}
}
contracts/interfaces/IAddressesProvider.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;
interface IAddressesProvider {
function getUsdph() external view returns (address);
function getPhlp() external view returns (address);
function getPhlpManager() external view returns (address);
function getVault() external view returns (address);
function getVaultConfigurator() external view returns (address);
function getRouter() external view returns (address);
function getOrderBook() external view returns (address);
function getPositionManager() external view returns (address);
function getPositionRouter() external view returns (address);
function getPriceOracle() external view returns (address);
function getShortsTracker() external view returns (address);
function getTreasury() external view returns (address payable);
function getFeeDistribution() external view returns (address);
}
contracts/dependencies/openzeppelin/contracts/IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount)
external
returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender)
external
view
returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
contracts/dependencies/openzeppelin/contracts/SafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.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/IPhamePriceOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
interface IPhamePriceOracle {
function backupPriceOracle() external view returns (address);
function adjustmentBps(address _token) external view returns (uint256);
function isAdjustmentAdditive(address _token) external view returns (bool);
function setAdjustment(
address _token,
bool _isAdditive,
uint256 _adjustmentBps
) external;
function setSpreadBps(address _token, uint256 _spreadBps) external;
function setSpreadThresholdBps(uint256 _spreadThresholdBps) external;
function setPriceSampleSpace(uint256 _priceSampleSpace) external;
function setMaxStrictPriceDeviation(
uint256 _maxStrictPriceDeviation
) external;
function getPrice(
address _token,
bool _maximise
) external view returns (uint256);
function setTokenConfig(
address _token,
address _priceFeed,
uint256 _priceDecimals,
bool _isStrictStable
) external;
}
contracts/interfaces/IVault.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
import "../protocol/libraries/types/DataTypes.sol";
import "./IAddressesProvider.sol";
interface IVault {
struct Position {
uint256 size;
uint256 collateral;
uint256 averagePrice;
uint256 entryFundingRate;
uint256 reserveAmount;
int256 realisedPnl;
uint256 lastIncreasedTime;
}
event BuyUSDPH(
address account,
address token,
uint256 tokenAmount,
uint256 usdphAmount,
uint256 feeBps
);
event SellUSDPH(
address account,
address token,
uint256 usdphAmount,
uint256 tokenAmount,
uint256 feeBps
);
event Swap(
address account,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOut,
uint256 amountOutAfterFees,
uint256 feeBps
);
event IncreasePosition(
bytes32 key,
address account,
address collateralToken,
address indexToken,
uint256 collateralDelta,
uint256 sizeDelta,
bool isLong,
uint256 price,
uint256 fee
);
event DecreasePosition(
bytes32 key,
address account,
address collateralToken,
address indexToken,
uint256 collateralDelta,
uint256 sizeDelta,
bool isLong,
uint256 price,
uint256 fee
);
event LiquidatePosition(
bytes32 key,
address account,
address collateralToken,
address indexToken,
bool isLong,
uint256 size,
uint256 collateral,
uint256 reserveAmount,
int256 realisedPnl,
uint256 markPrice
);
event UpdatePosition(
bytes32 key,
uint256 size,
uint256 collateral,
uint256 averagePrice,
uint256 entryFundingRate,
uint256 reserveAmount,
int256 realisedPnl,
uint256 markPrice
);
event ClosePosition(
bytes32 key,
uint256 size,
uint256 collateral,
uint256 averagePrice,
uint256 entryFundingRate,
uint256 reserveAmount,
int256 realisedPnl
);
event UpdateFundingRate(address token, uint256 fundingRate);
event UpdatePnl(bytes32 key, bool hasProfit, uint256 delta);
event CollectSwapFees(address token, uint256 feeUsd, uint256 feeTokens);
event CollectMarginFees(address token, uint256 feeUsd, uint256 feeTokens);
event PayLpFees(address token, uint256 feeTokens);
event DirectPoolDeposit(address token, uint256 amount);
event IncreasePoolAmount(address token, uint256 amount);
event DecreasePoolAmount(address token, uint256 amount);
event IncreaseUsdphAmount(address token, uint256 amount);
event DecreaseUsdphAmount(address token, uint256 amount);
event IncreaseReservedAmount(address token, uint256 amount);
event DecreaseReservedAmount(address token, uint256 amount);
event IncreaseGuaranteedUsd(address token, uint256 amount);
event DecreaseGuaranteedUsd(address token, uint256 amount);
function addressesProvider() external view returns (IAddressesProvider);
function getVaultConfig()
external
view
returns (DataTypes.VaultConfig memory);
function setVaultConfig(
DataTypes.VaultConfig calldata vaultConfig
) external;
function allWhitelistedTokensLength() external view returns (uint256);
function totalTokenWeights() external view returns (uint256);
function allWhitelistedTokens(uint256) external view returns (address);
function getTokenConfig(
address _token
) external view returns (DataTypes.TokenConfig memory);
function setTokenConfig(
address _token,
DataTypes.TokenConfig calldata tokenConfig
) external;
function clearTokenConfig(address _token) external;
function getAccountTokenConfig(
address _account,
address _token
) external view returns (DataTypes.AccountTokenConfig memory);
function setAccountTokenConfig(
address _account,
address _token,
DataTypes.AccountTokenConfig calldata accountTokenConfig
) external;
function getAccountTokenPositionSizeLimit(
address _account,
address _token,
bool _isLong
) external view returns (uint256);
function setUsdphAmount(address _token, uint256 _amount) external;
function tokenBalances(address _token) external view returns (uint256);
function lastFundingTimes(address _token) external view returns (uint256);
function withdrawFees(
address _token,
address _receiver
) external returns (uint256);
function directPoolDeposit(address _token) external;
function buyUSDPH(
address _token,
address _receiver
) external returns (uint256);
function buyUSDPHwithoutFee(address _token) external returns (uint256);
function sellUSDPH(
address _token,
address _receiver
) external returns (uint256);
function swap(
address _tokenIn,
address _tokenOut,
address _receiver
) external returns (uint256);
function increasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _sizeDelta,
bool _isLong
) external;
function decreasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _collateralDelta,
uint256 _sizeDelta,
bool _isLong,
address _receiver
) external returns (uint256);
function validateLiquidation(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong,
bool _raise
) external view returns (uint256, uint256);
function liquidatePosition(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong,
address _feeReceiver
) external;
function tokenToUsdMin(
address _token,
uint256 _tokenAmount
) external view returns (uint256);
function cumulativeFundingRates(
address _token
) external view returns (uint256);
function getNextFundingRate(address _token) external view returns (uint256);
function getFeeBps(
address _token,
uint256 _usdphDelta,
uint256 _feeBps,
uint256 _taxBps,
bool _increment
) external view returns (uint256);
function feeReserves(address _token) external view returns (uint256);
function globalShortSizes(address _token) external view returns (uint256);
function guaranteedUsd(address _token) external view returns (uint256);
function poolAmounts(address _token) external view returns (uint256);
function reservedAmounts(address _token) external view returns (uint256);
function usdphAmounts(address _token) external view returns (uint256);
function getRedemptionAmount(
address _token,
uint256 _usdphAmount
) external view returns (uint256);
function getMinProfitTime(
address _indexToken,
uint256 _size,
bool _isLong
) external view returns (uint256);
function getDelta(
address _indexToken,
uint256 _size,
uint256 _averagePrice,
bool _isLong,
uint256 _lastIncreasedTime
) external view returns (bool, uint256);
function getPosition(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong
)
external
view
returns (
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
bool,
uint256
);
}
contracts/interfaces/IVaultConfigurator.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
interface IVaultConfigurator {
function setIsLeverageEnabled(bool _isLeverageEnabled) external;
function setStakingBps(uint256 _stakingBps) external;
function setUsdphAmount(address _token, uint256 _amount) external;
function setTokenConfig(
address _token,
uint256 _tokenDecimals,
uint256 _tokenWeight,
uint256 _maxUsdphAmount,
bool _isStable,
bool _isShortable
) external;
function setTokenMinProfit(
address _token,
uint256 _minProfitBps,
uint256 _minProfitTime,
bool _hasMinProfitTimeFloor,
uint256 _minProfitTimeCoefBps
) external;
function setTokenMaxSizes(
address _token,
uint256 maxGlobalLongSize,
uint256 maxGlobalShortSize,
uint256 maxPositionLongSize,
uint256 maxPositionShortSize
) external;
function setAccountTokenConfig(
address _account,
address _token,
bool _isLongBlacklisted,
bool _isShortBlacklisted,
uint256 _maxPositionLongSizeOverride,
uint256 _maxPositionShortSizeOverride
) external;
function getSwapFeeAndTaxBps(
bool isStableSwap
) external view returns (uint256, uint256);
}
contracts/protocol/libraries/types/DataTypes.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.7.6;
library DataTypes {
struct VaultConfig {
bool isSwapEnabled;
bool isLeverageEnabled;
uint256 maxLeverage;
// fees
uint256 taxBps;
uint256 stableTaxBps;
uint256 mintBurnFeeBps;
uint256 swapFeeBps;
uint256 stableSwapFeeBps;
uint256 liquidationFeeUsd;
bool hasDynamicFees;
// staking
uint256 stakingBps;
}
struct TokenConfig {
// should always be true if token exists
bool isWhitelisted;
// basic parameters
uint256 decimals;
uint256 weight; // customisation of index composition
uint256 minProfitBps;
uint256 minProfitTime;
bool hasMinProfitTimeFloor;
uint256 minProfitTimeCoefBps; // coefficient for minProfitTime
uint256 maxUsdphAmount; // a max amount of USDPH debt for a token
bool isStable;
bool isShortable;
// risk parameters
// bufferAmount allows specification of an amount to exclude from swaps
// this can be used to ensure a certain amount of liquidity is available for leverage positions
uint256 bufferAmount;
uint256 maxGlobalLongSize;
uint256 maxGlobalShortSize;
uint256 maxPositionLongSize;
uint256 maxPositionShortSize;
// fees
uint256 longMarginFeeBps;
uint256 shortMarginFeeBps;
// funding rate
uint256 fundingInterval;
uint256 fundingRateFactor;
}
struct TokenConfigs {
uint256 totalTokenWeights;
address[] allWhitelistedTokens;
mapping(address => TokenConfig) tokenConfigs;
}
struct AccountTokenConfig {
bool isLongBlacklisted;
bool isShortBlacklisted;
uint256 maxPositionLongSizeOverride;
uint256 maxPositionShortSizeOverride;
}
}
Compiler Settings
{"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{},"evmVersion":"istanbul"}
Contract ABI
[{"type":"function","stateMutability":"pure","outputs":[],"name":"validate","inputs":[{"type":"bool","name":"condition","internalType":"bool"},{"type":"uint256","name":"errorCode","internalType":"uint256"}]}]
Contract Creation Code
0x610216610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c8063cda9d2871461003a575b600080fd5b61004d61004836600461015e565b61004f565b005b8161005982610085565b906100805760405162461bcd60e51b8152600401610077919061018d565b60405180910390fd5b505050565b6060816100aa57506040805180820190915260018152600360fc1b6020820152610159565b8160005b81156100c257600101600a820491506100ae565b60008167ffffffffffffffff811180156100db57600080fd5b506040519080825280601f01601f191660200182016040528015610106576020820181803683370190505b508593509050815b831561015357600a840660300160f81b8282600190039250828151811061013157fe5b60200101906001600160f81b031916908160001a905350600a8404935061010e565b50925050505b919050565b60008060408385031215610170578182fd5b8235801515811461017f578283fd5b946020939093013593505050565b6000602080835283518082850152825b818110156101b95785810183015185820160400152820161019d565b818111156101ca5783604083870101525b50601f01601f191692909201604001939250505056fea2646970667358221220fa04eb9f6d617eccbe5dee71d60e12491ff29ea4160b9508dce91e8bf707b62964736f6c63430007060033
Deployed ByteCode
0x73a60f20ac5322e698d15aeb169e72f8977d939da230146080604052600436106100355760003560e01c8063cda9d2871461003a575b600080fd5b61004d61004836600461015e565b61004f565b005b8161005982610085565b906100805760405162461bcd60e51b8152600401610077919061018d565b60405180910390fd5b505050565b6060816100aa57506040805180820190915260018152600360fc1b6020820152610159565b8160005b81156100c257600101600a820491506100ae565b60008167ffffffffffffffff811180156100db57600080fd5b506040519080825280601f01601f191660200182016040528015610106576020820181803683370190505b508593509050815b831561015357600a840660300160f81b8282600190039250828151811061013157fe5b60200101906001600160f81b031916908160001a905350600a8404935061010e565b50925050505b919050565b60008060408385031215610170578182fd5b8235801515811461017f578283fd5b946020939093013593505050565b6000602080835283518082850152825b818110156101b95785810183015185820160400152820161019d565b818111156101ca5783604083870101525b50601f01601f191692909201604001939250505056fea2646970667358221220fa04eb9f6d617eccbe5dee71d60e12491ff29ea4160b9508dce91e8bf707b62964736f6c63430007060033