QUAI Invest - Smart Contract Audit Report

Summary

QUAI Invest Audit Report QUAI DAO is building a platform for investors to convert their assets to LP tokens and stake their LP tokens through various means to earn rewards in a decentralized manner.

We reviewed QUAI DAO's Interchange contracts at commit b5738989951352a4d25d61f378ecfc130b7a2f49 on the team's GitHub repository.

Audit Findings Summary:
  • No security issues from outside attackers were identified.
  • Please ensure trust in the project team as they have considerable control in the ecosystem.
  • Date: November 11th, 2021.
Notes on Individual Contracts:
QuaiAccessControl Contract:
  • This contract defines the Governance, Strategist, and Keeper roles.
  • There may be only one address with each role at any given time.
  • The Governance address may change the address associated with these roles at any time.
QuaiAccessControlDefended Contract:
  • This contract builds upon the QuaiAccessControl scheme by managing approved addresses.
  • This prevents proxied calls to contracts by only allowing approved addresses and function calls where the message sender is the original function caller.
  • The Governance address may add or remove any address from the approved addresses at any time.
QUAI Controller Contract:
  • This contract serves as the Controller for the entire QUAI platform.
  • The QuaiAccessControl scheme is implemented to manage permissions.
  • The Governance address may perform all of the following actions:
    • Grant or revoke approval to use a Strategy contract with a specific token.
    • Set the rewards address that receives fees.
    • Set the split value in the contract.
    • Set the address of the OneSplit router used to convert tokens.
  • The Governance or Strategist address may perform all of the following actions:
    • Set the Vault address for a given token. This may only be done once per token.
    • Set the Strategy contract for a token. If there is an existing Strategy, all of the funds will be withdrawn into the token's Vault. A separate call will be needed to deposit them into the Strategy.
    • Set a Converter address to swap between specified tokens.
    • Transfer the entire balance of the primary token from a Strategy into the token's corresponding Vault.
    • Transfer any non-primary token out of a Strategy into this contract. Non-primary tokens are not intended to ever be within the Strategy, so this is implemented with the intent of being a safeguard.
    • Withdraw any token within the Controller at any time. Tokens are not intended to ever be within the Controller, so this is implemented with the intent of being a safeguard.
  • The Governance, Strategist, Keeper, or a Vault may deposit tokens from the Controller into a Strategy contract. Tokens will be converted to the Strategy contract's primary token if needed.
  • A Vault can use this contract to withdraw funds from its corresponding Strategy at any time.
QUAI Vault Contract:
  • Users can deposit a designated token into the QUAI Vault, and will receive back tokens that represent shares.
  • Deposited tokens will stay in the contract until an approved address allocates them to the Strategy.
  • Users are able to withdraw from the Vault thereby burning their tokens for a proportional share of the Vault's underlying asset.
  • Users are able to transfer their tokens to another address.
  • A user may perform only one deposit, withdrawal, or transfer in any given block.
  • The contract must maintain a minimum value of the underlying asset; this defaults to 5% of the total balance.
  • The QuaiAccessControl scheme is implemented to manage permissions.
  • The Governance address may change the amount of underlying asset the Vault must maintain to any value at any time.
  • The Governance address may update the Controller used to manage the Vault at any time.
  • The Controller address may withdraw any tokens from the contract, except the designated underlying asset token, from the contract at any time.
StrategyPancakeLpOptimizer and StrategyApeSwapLpOptimizer Contracts:
  • Users are able to deposit a designated LP token into the Strategy through a Vault whereafter they are transferred into a MasterChef staking contract to earn rewards.
  • Authorized addresses are able to collect the rewards from the MasterChef where subsequently a percentage of the earned rewards are taken as fees.
  • After fees, the remaining tokens are swapped into the LP token's underlying token pair and used to add liquidity. All LP tokens received from the liquidity-add are re-staked into the MasterChef, contributing to each user's share of the pool.
  • The QuaiAccessControl scheme is implemented to manage permissions.
  • The Governance or Guardian address is able to pause and unpause the contract at any time disabling all deposit, withdrawal, and rewards harvesting functionality.
  • The Governance address may adjust all fees to any value at any time.
  • The Governance address may update this contract's associated Controller contract at anytime.
StrategySushiLpOptimizer Contract:
  • Users are able to deposit a designated LP token into the Strategy through a Vault whereafter they are transferred into the SushiSwap MasterChef staking contract to earn SUSHI rewards.
  • Authorized addresses are able to "tend" the contract. This will take all the SUSHI rewards from the MasterChef and deposit them into the SushiBar in exchange for xSUSHI tokens.
  • Authorized addresses are able to collect the rewards from the MasterChef and the SushiBar where subsequently a percentage of the earned rewards are taken as fees.
  • After fees, the remaining tokens are swapped into the LP token's underlying token pair and used to add liquidity. All LP tokens received from the liquidity-add are re-staked into the MasterChef, contributing to each user's share of the pool.
  • The QuaiAccessControl scheme is implemented to manage permissions.
  • The Governance or Guardian address is able to pause and unpause the contract at any time, disabling all deposit, withdrawal, and rewards harvesting functionality.
  • The Governance address can adjust all fees to any value at any time.
  • The Governance address can update this contract's associated Controller contract at anytime.
StrategyCurveGaugeSbtcCrv and StrategyCurveGaugeRenBtcCrv Contracts:
  • Users are able to deposit a designated LP token into the Strategy through a Vault whereafter they are transferred into a Curve Staking Liquidity Gauge to earn CRV tokens.
  • Authorized addresses are able to collect rewards from the Gauge contract where subsequently a portion of the CRV is taken as fees.
  • After fees, the remaining tokens are swapped into one of the LP token's underlying token in the pair and used to add liquidity.
  • Fees are taken once again, then all remaining LP tokens from the liquidity-add are deposited back into the Curve Staking Liquidity Gauge, contributing to each user's share of the pool.
  • The QuaiAccessControl scheme is implemented to manage permissions.
  • The Governance or Guardian address is able to pause and unpause the contract at any time disabling all deposit, withdrawal, and rewards harvesting functionality.
  • The Governance address can adjust all fees to any value at any time.
  • The Governance address can update this contract's associated Controller contract at anytime.
StrategyEllipsisRenBtcBtcb Contract:
  • Users are able to deposit a designated LP token into the Strategy through a Vault whereafter they are transferred into the Ellipsis MasterChef staking contract to earn EPS tokens.
  • Authorized addresses are able to collect rewards from the MasterChef where subsequently a percentage is taken as fees.
  • After fees, the remaining tokens are swapped into one of the LP token's underlying token in the pair and used to add liquidity.
  • Fees are taken once again, then all remaining LP tokens from the liquidity-add are deposited back into the Ellipsis MasterChef, contributing to each user's share of the pool..
  • The QuaiAccessControl scheme is implemented to manage permissions.
  • The Governance or Guardian address is able to pause and unpause the contract at any time disabling all deposit, withdrawal, and rewards harvesting functionality.
  • The Governance address can adjust all fees to any value at any time.
  • The Governance address can update this contract's associated Controller contract at anytime.
Pancakeswap, SushiSwap, Uniswap ZapIn Contracts:
  • While the ZapIn functionality is not paused, anyone can use these contracts to provide liquidity to any pair in the corresponding DEX using any single asset; any ERC20 token or ETH can be used as the input asset.
  • The user is able to specify the minimum amount of LP tokens to receive from the transaction in order to account for high fluctuations in price.
  • The user can also choose to receive back any residual amounts of the asset tokens after the transaction has completed.
  • When providing the asset to use to add to liquidity, a portion of the asset (up to 1%) is taken as fees; this fee does not apply to users who are whitelisted from fees.
  • A portion of the fees determined by the team (up to 100%) may be provided to a valid affiliate address, if the user has provided one.
  • The user can provide a swap target from the platform's approved targets along with swap data in order to perform the initial swap from the remaining amount of the asset to one of the desired tokens in the pair; initially, only 0x Exchange's TransformERC20Feature is considered an approved swap target within the Pancakeswap and Sushiswap ZapIn contracts. There is no check for approved targets in the Uniswap ZapIn contract.
  • A portion of the received tokens is swapped for the second desired token in the most optimal way such that the potential residual returns of the individual tokens is minimized when the tokens are ultimately added as liquidity to the DEX pair.
  • The formula used by the team takes into account the change in asset ratios and the swap fee charged by the DEX when adding liquidity. The formula assumes a swap fee of 0.3%; however, Pancakeswap charges a 0.25% swap fee, so users should expect some residual returns from the liquidity add, albeit minimal, when using the Pancakeswap ZapIn contract.
  • The user can choose to deliver the LP tokens to their wallet address, or to automatically deposit them in the QUAI Vault to accrue additional rewards.
Curve ZapIn:
  • While the ZapIn functionality is not paused, anyone can use this contract to provide liquidity to any Curve pair using any single asset; any ERC20 token or ETH can be used as the input asset.
  • The user is able to specify the minimum amount of LP tokens to receive from the transaction in order to account for high fluctuations in price.
  • When providing the asset to use to add to liquidity, a portion of the asset (up to 1%) is taken as fees; this fee does not apply to users who are whitelisted from fees.
  • A portion of the fees determined by the team (up to 100%) may be provided to a valid affiliate address, if the user has provided one.
  • The remaining amount of the input asset may be swapped for the underlying asset in the Curve pool, if needed, using a swap target and swap data provided by the user.
  • The received asset is then used to add liquidity either the Curve pool itself or the metapool within the Curve pool, depending on which pool it serves as the underlying asset for.
  • In the event that the liquidity is added to the metapool, the received LP tokens are added as liquidity in the target Curve pool.
  • The user can choose to deliver the LP tokens to their wallet address, or to automatically deposit them in the QUAI Vault to accrue additional rewards.
Pancakeswap, SushiSwap, Uniswap ZapOut Contracts:
  • While the ZapOut functionality is not paused, anyone can use this contract to remove liquidity from any Pancakeswap pair and receive the pair tokens in return.
  • Users can also choose to receive the output tokens in any single asset; BNB or any BEP20 token can be used as the output asset.
  • The contract allows users to use a signed approval to grant the contract an allowance to spend a pre-determined amount of the user's LP tokens prior to performing the ZapOut without spending any gas.
  • In the event that the user chooses to receive back only a single asset, after liquidity is removed from the pair, the contract performs a call to a swap target address passing in swap data provided by the user in order to swap each of the received tokens to the desired output token; initially, the platform only considers 0x Exchange's TransformERC20Feature as an approved swap target within the Pancakeswap and Sushiswap ZapIn contracts. There is no check for approved targets in the Uniswap ZapIn contract.
  • The user is able to specify the minimum amount of asset tokens to receive from the transaction in order to account for high fluctuations in price.
  • A portion of the received output tokens (up to 1%) is taken as fees; this fee does not apply to users who are whitelisted from fees.
  • A portion of the fees (up to 100%) may be provided to a valid affiliate address, if the user has provided one.
  • After taking fees, the output tokens are transferred to the user's wallet address.
Curve ZapOut:
  • While the ZapOut functionality is not paused, anyone can use this contract to remove liquidity from any Curve pool and receive the output tokens in any single asset; ETH or any ERC20 token can be used as the output asset.
  • After liquidity is removed from the target pool (and the metapool, if applicable), the contract performs a call to a swap target address passing in swap data provided by the user in order to swap the received token to the desired output token.
  • The user is able to specify the minimum amount of asset tokens to receive from the transaction in order to account for high fluctuations in price.
  • A portion of the received output tokens (up to 1%) is taken as fees; this fee does not apply to users who are whitelisted from fees.
  • A portion of the fees (up to 100%) may be provided to a valid affiliate address, if the user has provided one.
  • After taking fees, the output tokens are transferred to the user's wallet address.
ZapBase Contracts:
  • These contracts are used to facilitate ownership controls within the ZapIn and ZapOut contracts.
  • The owner can pause or unpause the ZapIn/ZapOut functionality at any time.
  • The owner can add or remove any address from the fee whitelist at any time.
  • The owner can set the fee percentage to any value up to 1% at any time.
  • The owner can set the affiliate percentage to any value up to 100% at any time.
  • The owner can add or remove any address as a valid affiliate at any time.
  • The owner can withdraw any tokens or BNB collected as fees from the contract at any time.
  • Any affiliate can withdraw any tokens or BNB due to them at any time.
  • The owner can add or remove any address as an approved target address for swapping at any time.
  • The owner can set the QUAI Controller address to any address at any time.
Curve Registry Contract:
  • The Curve Registry contract is an API used by the Curve ZapIn/ZapOut contracts to interact with the Curve platform.
  • The owner can use this contract to update the Curve Registry address and the Curve Factory Address based on the value set in the Curve Address Provider.
  • The owner can use this contract to provide data to the Curve ZapIn/ZapOut contracts uses to determine if the underlying asset should be added to the Curve pool.
  • The owner can use this contract to update the deposit addresses associate with any Curve pool address.
  • The owner can withdraw any tokens or ETH from the contract at any time.
QUAICohortFarming Contract:
  • This contract allows anyone to stake a single asset determined by the project team in exchange for rewards in various tokens.
  • On deployment, the owner must specify the staking token and one or many rewards tokens.
  • Each reward token has its own reward rate and its own end date. After a reward token's end date, rewards will no longer be distributed in that token.
  • Users are able to deposit and withdraw staking tokens at any time; there are no fees associated with deposits and withdrawals.
  • Users will receive a reward amount each second based on the amount staked; staking rewards can be calculated and transferred to the user at any time.
  • There must be an adequate amount of reward tokens in the contract in order to allow users to claim; otherwise, claims will fail and users will not receive any rewards.
  • The owner is able to add a token as a reward token at any time.
  • The owner is able to set the reward rate for any reward token at any time.
  • The owner is able to set the end date and stop reward distribution for any reward token at any time.
  • The owner is able to withdraw the reward tokens from the contract at any time.
Timelock Contract:
  • This contract is used to enforce a delay period before a transaction is executed.
  • The contract Admin and delay time are set upon deployment.
  • The delay can be between 1 and 30 days.
  • The Admin is able to queue a transaction which they cannot execute until the delay period has passed.
  • After the delay period, the Admin must manually execute the transaction before the grace period of 14 days has passed.
  • Ensure trust in the Admin as the Timelock contract will execute any arbitrary code the Admin desires.
  • The Admin may cancel the transaction at any time.
  • The Admin may set a new pending Admin address at any time. This address must then accept the Admin role.
  • The Admin may set the delay to any value within the accepted range.
  • We advise users who have invested in the project to set up email alerts for the Timelock contract's activity using Etherscan to stay up to date on any proposed admin activity.
APY_Helper Contract:
  • This contract is used to help estimate yearly earnings from the various Strategy contracts. The functions in this contract are merely for reporting metrics and do not alter the state of any contract in the ecosystem.
  • The team will set the addresses of the assets to be tracked upon deployment. Once set, they cannot be altered.
  • All calculations are based on the historical average of 13.2 seconds to process a block in the Ethereum blockchain, but the team can update this as needed.
  • The current price of assets is used to determine yields and may vary over time as price fluctuates.
  • The owner can adjust the blocks per year variable as needed in order to account for changes in block times.
  • The owner can set the QUAI Controller address to any address at any time.
General Notes Across All Contracts:
  • Excellent structuring of logic to allow for fee-on-transfer tokens to be used within the Vaults and the Cohort Farm.
  • The contracts utilize ReentrancyGuard to prevent against re-entrancy attacks in applicable functions.
  • The Zap contracts are based on code pioneered by the Zapper team.
  • Some functions could have been declared external and some state variables could have been declared constant for additional gas savings. As the contracts are already deployed, this is merely informational.
  • As the contracts utilize SafeMath or are implemented with Solidity v0.8.x, they are protected from overflows/underflows.

External Threat Results

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
SuicideN/APASS
State Change External CallsN/APASS
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

Contract Source Summary and Visualizations

Name

Address/Source Code

Visualized
(Hover-Zoom Recommended)

QuaiAccessControlDefended

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

QUAI_Controller

BSC Mainnet / ETH Mainnet

Function Graph.   Inheritance Chart.

QUAI_Vault

BSC Mainnet / ETH Mainnet

Function Graph.   Inheritance Chart.

StrategyPancakeLpOptimizer

BSC Mainnet

Function Graph.   Inheritance Chart.

StrategyApeSwapLpOptimizer

BSC Mainnet

Function Graph.   Inheritance Chart.

StrategySushiLpOptimizer

ETH Mainnet

Function Graph.   Inheritance Chart.

StrategyCurveGaugeSbtcCrv

ETH Mainnet

Function Graph.   Inheritance Chart.

StrategyCurveGaugeRenBtcCrv

ETH Mainnet

Function Graph.   Inheritance Chart.

StrategyEllipsisRenBtcBtcb

BSC Mainnet

Function Graph.   Inheritance Chart.

Pancakeswap_ZapIn_V3_QUAI

BSC Mainnet

Function Graph.   Inheritance Chart.

Pancakeswap_ZapOut_V3

BSC Mainnet

Function Graph.   Inheritance Chart.

Sushiswap_ZapIn_V4_QUAI

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

Sushiswap_ZapOut_V4

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

UniswapV2_ZapIn_General_V4_QUAI

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

UniswapV2_ZapOut_General_V3_0_1

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

Curve_ZapIn_General_V3_1_1_QUAI

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

Curve_ZapOut_General_V3_0_1

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

QUAICohortFarming

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

Timelock

GitHub (Not yet deployed on mainnet)

Function Graph.   Inheritance Chart.

APY_Helper

ETH Mainnet

Function Graph.   Inheritance Chart.