Phame
Smart Contract Audit Report
Audit Summary
Phame is a new leveraged trading platform with support for earning rewards by staking and providing liquidity.
For this audit, we reviewed the contracts provided to us by the project team.
Audit Findings
No findings were identified, though some centralized aspects are present.
Date: August 10th, 2023.
Updated: August 25th, 2023 with updated contracts.
Contracts Overview
USDPH Contract:
- The contracts utilize ReentrancyGuard to protect against reentrancy attacks in applicable functions.
- The team must exercise caution when assigning staking tokens to avoid using fee-on-transfer tokens.
PHLP Contract:
- These tokens are used to represent a user's share of deposited liquidity to the Phame Vault.
- The PHLP Manager, Vault, or Router address can mint or burn USDPH from any address at any time.
- This contract complies with the ERC-20 standard.
PhlpManager Contract:
- This contract defines the Phame LP [$PHLP] token.
- The PhlpManager address may mint any amount of tokens to any address at any time.
- The PhlpManager address may burn any amount of tokens from any address at any time.
- Users may not send PHLP tokens unless the "cooldown duration" has elapsed from the user's "last added" time in the PhlpManager contract.
- There are no fees associated with transferring tokens.
- The contract complies with the ERC-20 standard.
PHAME Contract:
- This contract allows users to add liquidity to the Vault contract in exchange for PHLP tokens.
- Any address may use this account to add liquidity to the Vault.
- Users may specify any amount of any token to be deposited into the Vault along with a minimum amount of USDPH and PHLP.
- Users may also add liquidity by depositing ETH. The ETH will be converted into WETH for the user.
- The deposited tokens will be used to "purchase" USDPH from the Vault. The amount must be more than the specified minimum USDPH amount.
- Users will be minted an amount of PHLP based on the ratio of PHLP total supply to the total value in the Vault.
- The PHLP amount must be greater than the specified minimum PHLP amount.
- The user's last added time will be set to the current timestamp.
- Users may remove liquidity at any time.
- Users may specify any token to be withdrawn from the Vault along with a minimum amount of tokens to receive.
- The specified amount of PHLP will be burned from the user.
- An amount of USDPH will be transferred to the vault PHLP based on the ratio of the total value in the Vault to the PHLP total supply.
- The contract will mint any needed USDPH if its balance is insufficient.
- The USDPH will be "sold" in the vault for an amount of the output tokens. The amount must be greater than the specified minimum amount of tokens.
- If the user elected to receive ETH, the withdrawn WETH will be unwrapped before being sent to the user.
- The Treasury address may convert collected fees to liquidity.
- Fees for all of the whitelisted tokens in the Vault, PositionManager, and PositionRouter contracts will be withdrawn to this address.
- The fees will be used to add liquidity to the Vault. The PHLP tokens will be minted to this contract.
- Once all PHLP tokens have been minted they will be transferred to the Treasury address.
- The owner may set the cooldown duration at any time to any value up to the "max cooldown duration" of 48 hours.
- The Treasury address may set its own address at any time.
PhameFeeDistribution Contract:
- The maximum supply of the token is 55.555 million $PHAME (55,555,000).
- No one can transfer any tokens until the mint start time has passed.
- Users can mint the tokens that are allotted to them once the mint start time has passed, but not after the mint expiration time.
- The owner can allocate tokens to any user, deducting from the Treasury's mintable amount, only before the mint lock time has passed.
- Once the mint expiration time has passed, any remaining tokens that are alloted to users can be minted by the Treasury address to the Treasury's wallet.
- The Treasury address can transfer the Treasury role to any user at any time; the new Treasury address will inherit the previous Treasury's remaining mintable amount, if any.
PositionManager Contract:
- This contract is used to reward stakers in multiple types of reward tokens.
- Users will earn rewards as rewards tokens are transferred to the contract.
- Rewards will not begin accumulating until the getRewards() function is called after the reward token is initially added.
- Each time the getRewards() function is called all new tokens transferred to the contract will be distributed to token holders over a "rewards period".
- Tokens are distributed based on the amount of time staked from the last time rewards are claimed and the current reward rate.
- Rewards are accumulated when users deposit, unstake, and withdraw but must be manually collected.
- The Treasury address will accumulate rewards for the total supply of the staking token that is not currently staked in this contract.
- Any address may stake a specified amount of the staking token at any time.
- Users may unstake their staked tokens at any time, but may not withdraw them until the "unstake duration" has passed.
- Unstaked tokens will continue to accumulate rewards until they are withdrawn.
- Users may cancel an unstake until the unstake duration has passed.
- Users may withdraw their unstaked tokens after the unstake duration has passed and before the "withdraw duration" passes.
- Once the withdraw duration has passed users will need to unstake their tokens and wait the unstake duration again.
- Users may claim their accumulated rewards at any time.
- The owner may add a new reward token at any time.
- The Treasury address may withdraw any non-staking and non-reward tokens at any time.
- The Treasury address may update its own address at any time.
- The Treasury address may trigger the PhlpManager address to convert collected fees to liquidity at any time.
PositionRouter Contract:
- This contract allows users to execute transactions.
- Any address may execute a swap order once the minimum time delay has passed.. This will cause the OrderBook contract to execute the swap on behalf of the specified address.
- Any address may execute an increase once the minimum time delay has passed.
- This will update the global short data in the ShortsTracker contract and execute the increase order in the OrderBook contract.
- Any address may execute a decrease order at any once the minimum time delay has passed..
- This will update the global short data in the ShortsTracker contract and execute the decrease order in the OrderBook contract.
- Any address may liquidate a specified accounts position at any time.
- This will update the global short data in the ShortsTracker contract and execute the liquidation in the Vault contract.
- The fee associated with the position will be transferred to the Treasury address.
- The PhlpManager may withdraw the collected fees for any token at any time.
- The owner may set the deposit fee up to the maximum value at any time.
- The owner may set the position increase buffer basis points up to the maximum value at any time.
- The owner may set the max global value for short and long positions to any values at any time.
- The owner may add and remove any address as an OrderKeeper at any time.
- The owner may add and remove any address as a Liquidator at any time.
- The owner may toggle whether the contract will validate an increase order at any time.
- The owner may set the max gas used in an ETH transfer at any time.
OrderBook Contract:
- This contract is used to create and execute position increase and decrease requests.
- Any address may create an increase position request.
- The user must provide an ETH execution fee of at least the minimum execution fee.
- The specified amount of input tokens or ETH will be stored in the contract and the request added to the increase position execution queue.
- Any address may create a decrease position request.
- The user must provide an ETH execution fee of at least the minimum execution fee.
- The request is then added to the decrease position execution queue.
- Users may execute their own increase position requests after the minimum public time delay has passed and before the maximum time delay has passed.
- The specified amount of input tokens will be transferred to the vault.
- If a path was provided the tokens will be swapped for the specified output tokens from the Vault.
- A deposit fee is taken if the position is long, the size of the position is changing, and the new leverage would be lower than the current leverage.
- The remaining tokens after applicable fees are deposited in to the Vault.
- The contract ensures the maximum global shorts and maximum global long values are not exceeded after executing the increase position request.
- The execution fee is transferred to the Execution Fee Receiver address.
- Users may execute their own decrease position requests after the minimum public time delay has passed and before the maximum time delay has passed.
- The current price for the position's index token must be outside of the strike price (depending on whether the position is a short or long).
- If a path was provided the tokens will be swapped for the specified output tokens from the Vault.
- The execution fee is transferred to the Execution Fee Receiver address.
- Users may cancel their increase position requests once the minimum public delay time has passed.
- Users are returned their deposited ETH or tokens.
- The execution fee is transferred to the Execution Fee Receiver address.
- Users may cancel their decrease position requests once the minimum public delay time has passed.
- The execution fee is transferred to the Execution Fee Receiver address.
- Position Keepers may execute any queued increase or decrease position requests after the minimum Keeper delay has passed and before the maximum time delay has passed.
- The owner may set the deposit fee up to the max deposit fee at any time.
- The owner may set the position increase buffer basis points up to the max position increase buffer basis points at any time.
- The owner may set the max global value for short and long positions to any values at any time.
- The PhlpManager may withdraw the collected fees for any token at any time.
- The owner may toggle any address as a Position Keeper at any time.
- The owner may set the minimum execution fee up to the maximum minimum execution fee at any time.
- The owner may set the minimum delay for general users and for Position Keepers up to the maximum values at any time.
- The owner may set the maximum time delay to any value at any time.
- The owner may set the next request to be executed at any time.
- The owner may set the max gas used in an ETH transfer at any time.
- The owner may set the minimum time delay for a non-Keeper execution at any time.
Router Contract:
- This contract is used to create and execute swap, increase, and decrease orders.
- Any address may create a swap order at any time.
- The provided ETH execution fee must be greater than the minimum execution fee.
- The specified ETH or tokens will be transferred into the contract and a swap order created on behalf of the user.
- Any address may update one of their existing non-executed swap order's minimum amount out, trigger ratio, and whether to trigger above the threshold.
- Any address may execute one of their swap orders at any time.
- The contract will ensure the ratio of input to output tokens is above the threshold if the user specified the swap should trigger above a threshold.
- The specified input tokens will be swapped along the path for the specified output tokens.
- The ETH execution fee is sent to the specified fee receiver address.
- Any address may create an increase order at any time.
- The provided ETH execution fee must be greater than the minimum execution fee.
- If a path was provided the tokens will be swapped for the specified output tokens from the Vault and stored in this contract. An increase order is then created on behalf of the user.
- The USD value of received tokens must be greater than the specified minimum USD purchase amount.
- Any address may update one of their existing non-executed increase order's trigger price, size delta, and whether to trigger above or below the threshold.
- Any address may execute one of their existing increase orders if the index token is above or below the threshold accordingly.
- The specified amount of the input tokens will be transferred to the vault.
- The input tokens will be swapped for the specified collateral tokens if they are not the same.
- The execution fee will be transferred to the fee receiver address.
- Any address may create a decrease order at any time.
- The provided ETH execution fee must be greater than the minimum execution fee. A decrease order is created on behalf of the user.
- Any address may update one of their existing non-executed decrease order's trigger price, size delta, collateral delta, and whether to trigger above or below the threshold.
- Any address may execute one of their existing decrease orders if the index token is above or below the threshold accordingly.
- The ETH execution fee will be transferred to the fee receiver address.
- Any address may cancel any of their orders at any time.
- The owner may set the minimum execution fee to any value at any time.
- The owner may set the minimum purchase amount of tokens to any value at any time
ShortsTracker Contract:
- This contract is used to validate and execute position changes through "plugins" and swap tokens.
- Only the OrderBook, PositionManager, and PositionRouter contracts may perform a plugin.
- These contracts may perform a transfer plugin which will transfer tokens from the specified address to the "receiver" address.
- These contracts may perform an increase position plugin which will increase the specified address' position in the vault.
- These contracts may perform a decrease position plugin which will decrease the specified address' position in the vault.
- Any address may perform a "direct deposit" which will transfer the specified amount of tokens to the vault.
- Any address may perform a swap which will swap the input tokens along the path to the output token from the vault.
- Users may also perform a swap from or to ETH.
Vault Contract:
- This contract is used to track global short data and return various measures of global and individual positions.
- The Position Manager and Position Router contracts may update the global short data at any time.
- Any address may request the current profit or loss of an account's position.
- Any address may request the global short data at any time.
- Any address may request the global short data after a hypothetical position change at any time.
VaultConfigurator Contract:
- This contract facilitates core functionality including adding and removing liquidity, token swaps, leverage trading, and liquidations.
- The PHLPManager contract is minted USDPH upon any liquidity add through the PhlpManager contract.
- A buy fee is taken based on the Vault's mint/burn fee, available supply of the deposited token relative to its target supply, which is influenced by its current weight.
- A swap fee is also taken based on the available supplies of each tokens being swapped, their weight, and whether they are stable tokens or not.
- A lower available supply of a token in relation to its target supply results in a lower fee when it is used for a buy.
- A user can also remove liquidity through the PhlpManager contract in order to receive a specified whitelisted token at any time, where mint/burn and swap fees are taken based on the same factors mentioned above.
- While swapping is enabled, a user can swap any whitelisted token for a whitelisted token held by the Vault.
- A swap fee is taken based on the factors mentioned above.
- The Vault's stable fee is used in fee calculations if both tokens involved in the swap are marked as stable tokens. Otherwise, the Vault's standard swap fee is used.
- Users cannot swap or add liquidity using a token if it results in the token exceeding the token's maximum USDPH amount.
- A swap cannot occur if the resulting pool balance of the withdrawn token is less than the token's buffer amount.
- While leverage trading is enabled, a user can create or increase a long or short Position by supplying collateral at a specified leverage amount.
- A token must have shorting enabled and must not result in the platform exceeding the token's maximum total short size in order to be shorted.
- A user can decrease or close an existing Position at any time.
- Any profits or losses are realized when a Position is decreased. Profits are transferred to the user along with their withdrawal amount, while losses are deducted from the Position's collateral.
- Margin fees made up of a position fee and a funding fee must be paid whenever a Position is opened, closed, or adjusted.
- The position fee is determined by the change in the Position's size multiplied by Vault's margin fee.
- The funding fee is determined by the Position's total size multiplied by the increase in the collateral's funding rate since the Position was last edited.
- A collateral's funding rate increases after each "interval" passed at a rate calculated as Vault's funding rate factor multiplied by the ratio of the collateral's reserved funds to its total pool balance.
- If a stable token is used as collateral, the Vault's stable funding rate factor is used. Otherwise, the default funding rate factor is used.
- When increasing a Position, margin fees are taken out of the Position's collateral amount.
- When decreasing a Position, margin fees are taken from the user's withdrawal amount. If the fee amount is larger than the withdrawal amount, it is deducted from the Position's collateral amount instead.
- Profits are only given if the Vault's minimum profit time has passed from the last time the Position was increased.
- Collateral tokens equal to the Position's size are reserved for potential profit payouts while the Position is open. This amount is adjusted whenever a Position's size is increased or decreased.
- All leverage trading actions must be executed through the Router address.
- A Position can be liquidated if the sum of its losses, margin fee, and the Vault's liquidation fee exceed its collateral.
- When a Position in this state is liquidated, margin fees are taken from the collateral pool, and a liquidation fee is also taken and transferred to the liquidator. The Position is subsequently deleted.
- A Position can also be liquidated if it exceeds the Vault's maximum permitted leverage.
- If the Position in this state's collateral remains larger than its losses and fees, the losses are realized and the Position's size is decreased instead of deleted.
- A portion of all fees collected are added back into the associated collateral pool as "LP fees". The remainder is stored until withdrawn by the project team.
- The PHLPManager address can withdraw any accumulated fees of any token at any time.
- The PhlpManager address can purchase USDPH without fees at any time, intented to only be used for converting fees.
- The project team should ensure that Positions that exceed the maximum leverage threshold are immediately liquidated.
- The project team should ensure that the liquidation fee is large enough to incentivize liquidators to perform liquidations on unhealthy Positions in order to avoid losses for the platform and liquidity providers.
PhameBackupPriceOracle Contract:
- This contract allows its owner to configure the its associated Vault.
- The owner can toggle swap functionality at any time.
- The owner can toggle leverage functionality at any time.
- The owner can update the maximum leverage at any time.
- The owner can update the tax, stable tax, mint and burn fee, swap fee, stable swap fee, and margin fee to up to 5% each at any time.
- The owner can update the liquidation fee to up to 100 USD at any time.
- The owner can update the minimum profit time to any period at any time.
- The owner can toggle dynamic fee functionality at any time.
- The owner can update the LP fee to up to 100% at any time.
- The owner can update the funding interval to any length greater or equal to one hour at any time.
- The owner can update the funding rate and stable funding rate factors to up to 1% each at any time.
- The owner can update a token's settings at any time, including its weight, minimum profit basis points, maximum USDPH amount, whether it can be shorted, whitelist status, and buffer amount at any time.
- The owner can update a tokens maximum total short amount at any time.
- The owner can manually set the tracked total USDPH value of any token pool at any time.
PhamePriceOracle Contract:
- This contract is used to generate prices for assets using a manually entered price, a reference price, and a Chainlink price as a basis.
- The last updated time of the manual price must be within the acceptable duration for which prices are valid in order to be taken into consideration; otherwise, the reference price will be used.
- The oracle's price proposal is based on an average of the Chainlink price and the manual price based on the weight that has been assigned to the Chainlink aggregator price.
- If there is no Chainlink feed set for a particular asset, the contract will use the manual price set by the Keeper address as the oracle's price proposal.
- The price proposal is accepted if there was no reference price provided.
- The reference price is used to define boundaries to determine the acceptable range that the price proposal can be within.
- The owner can set the max deviation bps that is used to determine the maximum and minimum acceptable price to any value at any time.
- Any Keeper address can set the price of any asset to any value as long as the block interval has passed since the last manual update.
- Upon setting the price, the Keeper will assign a timestamp to the price as well, which must be within the maximum time deviation of the current time.
- The owner can set the minimum block interval and maximum time deviation to any value at any time.
- The owner can set the address of the pricing source of each asset to any address at any time.
- The owner can set the weight assigned to the Chainlink aggregator price to any value up to the maximum of 10000 bps at any time.
- The owner can add or remove any address as a Keeper at any time.
- The owner can set the duration for which prices are valid to any value up to the maximum of 5 minutes at any time.
- The owner can set the array of tokens and their precision factors to any value at any time.
PhameMultisigGov Contract:
- This contract is used to generate prices primarily using Chainlink as a source.
- The oracle will fetch recent price data from Chainlink as a primary source and also price data from the Backup Price Oracle in order to make its decision.
- The oracle retrieves the latest rounds of prices (up to the limit defined by the priceSampleSpace variable) from the Chainlink Aggregator and chooses either the highest or lowest returned value, depending on if maximization is desired.
- The chosen price is passed into the Backup Price Oracle which will deliver the ultimate price to be used.
- If the token is marked as a strict stable token, the price will be rounded to 1 USD if the price is within the max strict price deviation set by the team.
- If the price is outside of the max strict price deviation, either the price or 1 USD will be used, depending on if maximization is desired.
- Otherwise, the spread basis points will be applied to the price.
- If there are adjustment basis points associated with the token, those are applied to the price as well.
- The owner can set the adjustment basis points to any value up to the maximum of +/- 20 bps every 2 hours.
- The owner can set the Backup Price Oracle address to any address at any time.
- The owner can set the spread basis points to any value up to the maximum of 50 bps at any time.
- The owner can set the spread threshold bps to any value at any time.
- The owner can set the price sample space, which determines how many rounds to consider when retrieving the Chainlink price, to any value at any time.
- The owner can set the max strict price deviation value to any value at any time.
- The owner can set the oracle address for any token to any address at any time.
- The owner can set the oracle decimals for any token to any value at any time.
- The owner can add or remove any token as a strict stable token at any time.
PhameMultisigTreasury Contract:
- This contract defines a multi-sig wallet in which 2 or more owners can execute functions once a quorum is met.
- The owners can collectively decide to execute any arbitrary function call.
- Any owner can propose a transaction.
- Once proposed, the transaction must be confirmed by a sufficient amount of owners.
- An owner can revoke their confirmation for a transaction only before it has been executed.
- Once a quorum is met, the transaction can be executed.
- The owners must reach a quorum in order to add, remove, or replace an owner; there cannot be more than 50 owners.
- The owners must reach a quorum in order to change the quorum requirement; the quorum requirement cannot exceed the amount of owners.
- The owners may set the PhameFeeDistribution address at any time through an approved transaction.
PhameTimelockController Contract:
- This contract defines a multi-sig wallet that is intended to serve as the platform's Treasury wallet.
- The owners can collectively decide to execute any arbitrary function call.
- Any owner can propose a transaction.
- Once proposed, the transaction must be confirmed by a sufficient amount of owners.
- An owner can revoke their confirmation for a transaction only before it has been executed.
- Once a quorum is met, the transaction can be executed.
- The owners must reach a quorum in order to add, remove, or replace an owner; there cannot be more than 50 owners.
- The owners must reach a quorum in order to change the quorum requirement; the quorum requirement cannot exceed the amount of owners.
- The owners must reach a quorum to set the Phame Fee Distribution address.
- Any owner can use this contract to mint the allotted amount of PHAME tokens to this contract.
- Any owner can use this contract to call the mintByTreasury function on the PHAME contract.
- Any address can call the collectReward functions on the Phame Fee Distribution contract.
AddressesProvider Contract:
- This contract is used to schedule and execute arbitrary transactions in a time and order controlled manner.
- The admin address can schedule any operation at any time, specifying any preceding operations, if applicable.
- There is a minimum 2 day delay time for executing operations after they have been scheduled; the delay time is set upon scheduling.
- The admin address can cancel any operations that have not yet been executed.
- The admin address must manually execute operations once the delay timestamp has passed and all of the preceding operations have already been executed.
- The admin must schedule and execute an operation in order to transfer the admin role to another address.
- The admin address can use this contract to call the setUsdphAmount function on the Configurator contract.
- This contract is used to maintain addresses of various contracts used throughout the platform.
- All associated addresses used by the platform are fetched from this contract.
- The owner may update any address for any contract used in the platform at any time.
Audit Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Jump/Storage Write | N/A | PASS |
Centralization of Control |
|
WARNING |
Compiler Issues | N/A | PASS |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Ether/Token Theft | N/A | PASS |
Flash Loans | N/A | PASS |
Front Running | N/A | PASS |
Improper Events | N/A | PASS |
Improper Authorization Scheme | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Logical Issues | N/A | PASS |
Oracle Issues | N/A | PASS |
Outdated Compiler Version | N/A | PASS |
Race Conditions | N/A | PASS |
Reentrancy | N/A | PASS |
Signature Issues | N/A | PASS |
Sybil Attack | N/A | PASS |
Unbounded Loops | N/A | PASS |
Unused Code | N/A | PASS |
Overall Contract Safety | {PASS/WARNING/FAIL} |
Contract Source Summary and Visualizations
Name |
Address/Source Code |
Visualized |
PHLP |
N/A |
|
PhlpManager |
N/A |
|
PhameFeeDistribution |
N/A |
|
PositionManager |
N/A |
|
PositionRouter |
N/A |
|
ShortsTracker |
N/A |
|
PhameBackupPriceOracle |
N/A |
|
PhamePriceOracle |
N/A |
|
AddressesProvider |
N/A |
|
PHAME |
N/A |
|
PhameMultisigGov |
N/A |
|
PhameTimelockController |
N/A |
|
PhameMultisigTreasury |
N/A |
|
USDPH |
N/A |
|
VaultConfigurator |
N/A |
|
Vault |
N/A |
|
Router |
N/A |
|
OrderBook |
N/A |
About SourceHat
SourceHat has quickly grown to have one of the most experienced and well-equipped smart contract auditing teams in the industry. Our team has conducted 1800+ solidity smart contract audits covering all major project types and protocols, securing a total of over $50 billion U.S. dollars in on-chain value!
Our firm is well-reputed in the community and is trusted as a top smart contract auditing company for the review of solidity code, no matter how complex. Our team of experienced solidity smart contract auditors performs audits for tokens, NFTs, crowdsales, marketplaces, gambling games, financial protocols, and more!
Contact us today to get a free quote for a smart contract audit of your project!
What is a SourceHat Audit?
Typically, a smart contract audit is a comprehensive review process designed to discover logical errors, security vulnerabilities, and optimization opportunities within code. A SourceHat Audit takes this a step further by verifying economic logic to ensure the stability of smart contracts and highlighting privileged functionality to create a report that is easy to understand for developers and community members alike.
How Do I Interpret the Findings?
Each of our Findings will be labeled with a Severity level. We always recommend the team resolve High, Medium, and Low severity findings prior to deploying the code to the mainnet. Here is a breakdown on what each Severity level means for the project:
- High severity indicates that the issue puts a large number of users' funds at risk and has a high probability of exploitation, or the smart contract contains serious logical issues which can prevent the code from operating as intended.
- Medium severity issues are those which place at least some users' funds at risk and has a medium to high probability of exploitation.
- Low severity issues have a relatively minor risk association; these issues have a low probability of occurring or may have a minimal impact.
- Informational issues pose no immediate risk, but inform the project team of opportunities for gas optimizations and following smart contract security best practices.