Pancake Amoeba - Smart Contract Audit Report
Summary
Pancake Amoeba is developing serveral yield farming strategy vaults users deposit a single asset and earn rewards from an LP yield farming platform.We reviewed Pancake Amoeba's AMVChef, VaultAMV, VaultCakeToCake, VaultFlipToBNB, VaultFlipToFlip, and VaultVenus contracts at commit bb6225245a538945049e22b75842b9eaea4dea89 on the team's private GitHub repository.
Notes on Individual Contracts:
AMVChef Contract:VaultAMV Contract:
- The AMVChef contract is used by the project team and the Vault addresses to manage rewards across the platform's various Vaults.
- The Vaults can use this contract to store data related to user's deposits, withdrawals, and rewards.
- This contract also stores all the rewards tokens; the rewards tokens are pulled from this contract to a user or a Vault upon request from the appropriate Vault.
- Only specific Vault addresses can use this contract; The qualified Vault addresses are maintained in the contract by the owner.
- The owner is able to add any Vault to the AMVChef. Once a Vault is added, the owner is able to set various properties related to the Vault rewards such as the allocation points and the rewards rate.
- The owner is able to set the Minter contract address to any address at any time.
- The owner is able to recover any tokens, except for AMV token, erroneously sent to the contract.
VaultCakeToCake Contract:
- This contract is used as a single-asset staking contract, where the staked asset is intended to be AMV tokens.
- Users are able to deposit and withdraw staking tokens at any time. The contract stores the staking data in the AMVChef contract where it keeps track of the user's due rewards.
- There is an uncapped withdrawal fee determined by the Minter contract.
- Users must withdraw all their staked tokens from the system in order to claim any rewards.
- The owner is able to set the Minter contract and AMVChef contract addresses to any address at any time.
- The owner is able to recover any tokens, except for the staking token, erroneously sent to the contract.
VaultFlipToBNB Contract:
- This contract is used as a single-asset staking contract, where the staked asset is intended to be CAKE tokens.
- On deposits, the user receives an amount of shares based on their contribution of CAKE tokens to the pool.
- The CAKE tokens are deposited into the PancakeSwap MasterChef staking contract where rewards are subsequently harvested and reinvested back into the MasterChef.
- Users can choose to withdraw all their shares at once and pay a withdrawal fee and a performance fee on the profit in order to do so; whitelisted users are excluded from the withdrawal and performance fees.
- Non-whitelisted users are able to choose to withdraw only their principal amount at any time and pay a withdrawal fee to do so; no performance fee applies in this case.
- Anyone is able to realize their own rewards and pay a performance fee on the profit in order to do so.
- The withdrawal and performance fees are uncapped fees determined by the Minter contract.
- Anyone is able to manually trigger a harvest on the PancakeSwap MasterChef in order realize the platform's rewards and reinvest them back into the MasterChef.
- The owner is able to withdraw any tokens from the contract at any time.
VaultFlipToFlip Contract:
- This contract is used as a single-asset staking contract, where the staked asset is intended to be an LP token from the PancakeSwap MasterChef staking contract.
- As long as the system is not paused, anyone can deposit the designated staking token into the contract. The contract stores the staking data in the AMVChef contract where it keeps track of the user's due rewards.
- The staked tokens are deposited into the PancakeSwap MasterChef staking contract where rewards are subsequently harvested and reinvested back into the MasterChef.
- Users pay a withdrawal and a performance fee on the profit in order to withdraw.
- Anyone is able to realize their own rewards and pay a performance fee on the profit in order to do so; The reward token is swapped for WBNB and deposited in the user's wallet address.
- The withdrawal and performance fees are uncapped fees determined by the Minter contract.
- Anyone is able to manually trigger a harvest on the PancakeSwap MasterChef in order realize the platform's rewards and reinvest them back into the MasterChef.
- The owner is able to set the Minter contract address to any address at any time.
- The owner is able to set the rewards duration time to any value only if the currently set duration time has elapsed.
VaultVenus Contract:
- This contract is used as a single-asset staking contract, where the staked asset is intended to be an LP token from the PancakeSwap MasterChef staking contract.
- As long as the system is not paused, anyone can deposit the designated staking token into the contract. The contract stores the staking data in the AMVChef contract where it keeps track of the user's due rewards.
- Users are also able to deposit on behalf of others.
- On deposits, the user receives an amount of shares based on their contribution of staking tokens to the pool.
- Users can choose to withdraw all their shares at once and pay a withdrawal fee and a performance fee on the profit in order to do so; whitelisted users are excluded from the withdrawal and performance fees.
- Users can also choose to withdraw only their principal amount at any time and pay a withdrawal fee to do so; no performance fee applies in this case.
- Anyone is able to realize their own rewards and pay a performance fee on the profit in order to do so.
- The withdrawal and performance fees are uncapped fees determined by the Minter contract.
- Only the Keeper address controlled by the project team is able to trigger a harvest on the PancakeSwap MasterChef in order realize the platform's rewards and reinvest them back into the MasterChef. This contains an interaction with a ZapBSC contract that was not provided in the scope of this audit, so we are unable to verify its security at this time.
- The owner is able to deposit the staking token in the contract and subsequently deposit it into the MasterChef; these staking tokens are proportionally allocated to all stakers in the Vault based on their amount of shares.
- The owner is able to change the MasterChef staking pool ID and token to any values only when there is nothing staked in the platform.
- The owner is able to use the contract to migrate the LP tokens from one decentralized exchange and corresponding MasterChef to another at any time.
- The owner is able to recover any tokens erroneously sent to the contract.
General notes across all contracts:
- This contract is used as a single-asset staking contract, where the staked asset is set by the owner on deployment.
- As long as the system is not paused, anyone can deposit the designated staking token into the contract. The contract stores the staking data in the AMVChef contract where it keeps track of the user's due rewards.
- Users can choose to withdraw all their shares at once and pay a withdrawal fee, a performance fee on the profit, and a redeem fee in order to do so. The collateral ratio is evaluated and rebalanced if necessary following the withdrawal.
- Users can also choose to withdraw only their principal amount at any time and pay a withdrawal fee and a redeem fee to do so; no performance fee applies in this case.
- Anyone is able to realize their own rewards and pay a performance fee on the profit and a redeem fee in order to do so. The collateral ratio is evaluated and rebalanced if necessary following the withdrawal.
- The withdrawal and performance fees are uncapped fees determined by the Minter contract, and the redeem fee is an uncapped fee based on the Venus exit ratio value determined by the project team.
- When the system is not paused, the Keeper address is able to harvest rewards from Venus and increase the collateral borrowed by a fixed amount.
- The Keeper address is able to increase or decrease the collateral borrowed from Venus at any time based on the Venus factors; anyone is able to recalibrate the Venus factors at any time.
- The owner is able to set the collateral ratio factor and the collateral depth values at any time; the collateral ratio factor must be less than the maximum value defined by the contract.
- The owner is able to set the collateral ratio system value to any value up to the system default at any time.
- The owner is able to set the reserve ratio to any value up to 1000 at any time.
- The owner is able to set the Venus exit ratio value to any value up to the base ratio at any time.
- The owner is able to set the SafeVenus, Minter, and AMVChef contract addresses to any address at any time.
- The owner is able to recover any tokens erroneously sent to the contract.
- The team should exercise caution when integrating tokens with the system as to avoid fee-on-transfer tokens and ERC777-compliant tokens.
- The Vault contracts extend the functionality of either the VaultAMVController or the VaultController contracts. The Minter contract is responsible for determining fee rates based on withdrawals and performance. The ZapBSC contract is used within the harvest() function of the VaultFlipToFlip contract. The VaultVenusBridgeOwner contract is used within the harvest() function of the VaultVenus contract. As these contract were not provided in the scope of the audit, we are unable to provide an assessment of these contracts based on security.
- SafeMath is utilized to prevent overflows and ReentrancyGuard to prevent reentrancy attacks.
Audit Findings Summary:
- No security issues from outside attackers were identified.
- Ensure trust in the team as they have substantial control in the ecosystem.
- Date: October 26th, 2021.
External Threat Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS |
Delegate Call to Untrusted Contract | N/A | PASS |
Dependence on Predictable Variables | N/A | PASS |
Deprecated Opcodes | N/A | PASS |
Ether Thief | N/A | PASS |
Exceptions | N/A | PASS |
External Calls | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Multiple Sends | N/A | PASS |
Suicide | N/A | PASS |
State Change External Calls | N/A | PASS |
Unchecked Retval | N/A | PASS |
User Supplied Assertion | N/A | PASS |
Critical Solidity Compiler | N/A | PASS |
Overall Contract Safety | PASS |
AMVChef Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ AMVChef (IAMVChef, OwnableUpgradeable)
- [Ext] initialize #
- modifiers: initializer
- [Pub] timeMultiplier
- [Pub] tokenSupplyOf
- [Ext] vaultInfoOf
- [Ext] vaultUserInfoOf
- [Pub] pendingAMV
- [Pub] addVault #
- modifiers: onlyOwner
- [Pub] updateVault #
- modifiers: onlyOwner
- [Ext] setMinter #
- modifiers: onlyOwner
- [Ext] setAMVPerBlock #
- modifiers: onlyOwner
- [Ext] notifyDeposited #
- modifiers: onlyVaults,updateRewards
- [Ext] notifyWithdrawn #
- modifiers: onlyVaults,updateRewards
- [Ext] safeAMVTransfer #
- modifiers: onlyVaults,updateRewards
- [Ext] safeAMVTransferToVaults #
- modifiers: onlyVaults,updateRewards
- [Pub] bulkUpdateRewards #
- [Pub] updateRewardsOf #
- modifiers: updateRewards
- [Ext] recoverToken #
- modifiers: onlyOwner
VaultAMV Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ VaultAMV (VaultAMVController, IAMVStrategy, ReentrancyGuardUpgradeable)
- [Ext] initialize #
- modifiers: initializer
- [Ext] totalSupply
- [Ext] balance
- [Ext] balanceOf
- [Ext] sharesOf
- [Ext] principalOf
- [Ext] depositedAt
- [Pub] withdrawableBalanceOf
- [Ext] rewardsToken
- [Ext] priceShare
- [Pub] earned
- [Pub] deposit #
- [Ext] depositAll #
- [Pub] withdraw #
- modifiers: nonReentrant
- [Ext] withdrawAll #
- [Pub] getReward #
- modifiers: nonReentrant
- [Pub] harvest #
- [Pub] setMinter #
- modifiers: onlyOwner
- [Pub] setAMVChef #
- modifiers: onlyOwner
- [Prv] _deposit #
- modifiers: nonReentrant,notPaused
- [Ext] recoverToken #
- modifiers: onlyOwner
VaultCakeToCake Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ VaultCakeToCake (VaultController, IStrategy)
- [Ext] initialize #
- modifiers: initializer
- [Pub] balance
- [Pub] balanceOf
- [Pub] withdrawableBalanceOf
- [Pub] sharesOf
- [Pub] principalOf
- [Pub] earned
- [Ext] priceShare
- [Ext] depositedAt
- [Ext] rewardsToken
- [Pub] deposit #
- [Ext] depositAll #
- [Ext] withdrawAll #
- [Ext] harvest #
- [Ext] withdraw #
- modifiers: onlyWhitelisted
- [Ext] withdrawUnderlying #
- [Ext] getReward #
- [Prv] _depositStakingToken #
- [Prv] _withdrawStakingToken #
- [Prv] _harvest #
- [Prv] _deposit #
- modifiers: notPaused
- [Prv] _cleanupIfDustShares #
- [Ext] recoverToken #
- modifiers: onlyOwner
VaultFlipToBNB Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ VaultFlipToBNB (VaultController, IStrategy, RewardsDistributionRecipientUpgradeable, ReentrancyGuardUpgradeable)
- [Ext] initialize #
- modifiers: initializer
- [Ext] balance
- [Ext] balanceOf
- [Ext] sharesOf
- [Ext] principalOf
- [Ext] depositedAt
- [Pub] withdrawableBalanceOf
- [Ext] rewardsToken
- [Ext] priceShare
- [Pub] lastTimeRewardApplicable
- [Pub] rewardPerToken
- [Pub] earned
- [Ext] getRewardForDuration
- [Pub] deposit #
- [Ext] depositAll #
- [Pub] withdraw #
- modifiers: nonReentrant,updateReward
- [Ext] withdrawAll #
- [Pub] getReward #
- modifiers: nonReentrant,updateReward
- [Pub] harvest #
- [Pub] setMinter #
- modifiers: onlyOwner
- [Pub] setRewardsToken #
- modifiers: onlyOwner
- [Pub] notifyRewardAmount #
- modifiers: onlyRewardsDistribution
- [Ext] setRewardsDuration #
- modifiers: onlyOwner
- [Prv] _approveTokenIfNeeded #
- [Prv] _swapTokenToToken #
- [Prv] _deposit #
- modifiers: nonReentrant,notPaused,updateReward
- [Prv] _depositStakingToken #
- [Prv] _withdrawStakingToken #
- [Prv] _harvest #
- [Prv] _notifyRewardAmount #
- modifiers: updateReward
VaultFlipToFlip Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ VaultFlipToFlip (VaultController, IStrategy)
- [Ext] initialize #
- modifiers: initializer
- [Pub] balance
- [Pub] balanceOf
- [Pub] withdrawableBalanceOf
- [Pub] sharesOf
- [Pub] principalOf
- [Pub] earned
- [Ext] depositedAt
- [Ext] rewardsToken
- [Ext] priceShare
- [Pub] deposit #
- [Ext] depositAll #
- [Ext] withdrawAll #
- [Ext] harvest #
- modifiers: onlyKeeper
- [Prv] _harvest #
- modifiers: updateCakeHarvested
- [Ext] withdraw #
- modifiers: onlyWhitelisted
- [Ext] withdrawUnderlying #
- [Ext] getReward #
- [Prv] _depositTo #
- modifiers: notPaused,updateCakeHarvested
- [Prv] _withdrawTokenWithCorrection #
- modifiers: updateCakeHarvested
- [Prv] _cleanupIfDustShares #
- [Ext] recoverToken #
- modifiers: onlyOwner
- [Pub] migrate #
- [Pub] migrateToken #
- modifiers: onlyOwner
- [Ext] setPidToken #
- modifiers: onlyOwner
- [Ext] approveZap #
- modifiers: onlyOwner
- [Prv] _flipOutV1 #
- [Prv] _flipInV2 #
- [Prv] _dustInV2 #
- [Prv] _approveTokenIfNeededV1 #
- [Prv] _approveTokenIfNeededV2 #
VaultVenus Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ VaultVenus (VaultAMVController, IAMVStrategy, ReentrancyGuardUpgradeable)
- [Ext] ($)
- [Ext] initialize #
- modifiers: initializer
- [Ext] totalSupply
- [Pub] balance
- [Pub] balanceAvailable
- [Pub] balanceReserved
- [Pub] balanceOf
- [Pub] withdrawableBalanceOf
- [Pub] sharesOf
- [Pub] principalOf
- [Pub] earned
- [Ext] depositedAt
- [Ext] rewardsToken
- [Ext] priceShare
- [Ext] getUtilizationInfo
- [Pub] setVenusBridge ($)
- modifiers: onlyOwner
- [Pub] setMinter #
- modifiers: onlyOwner
- [Pub] setAMVChef #
- modifiers: onlyOwner
- [Ext] setCollateralFactors #
- modifiers: onlyOwner
- [Ext] setCollateralRatioSystem #
- modifiers: onlyOwner
- [Ext] setReserveRatio #
- modifiers: onlyOwner
- [Ext] setVenusExitRatio #
- modifiers: onlyOwner
- [Pub] setSafeVenus #
- modifiers: onlyOwner
- [Ext] increaseCollateral #
- modifiers: onlyKeeper
- [Ext] decreaseCollateral ($)
- modifiers: onlyKeeper
- [Pub] updateVenusFactors #
- [Pub] deposit #
- modifiers: notPaused,nonReentrant
- [Ext] depositAll #
- [Pub] depositBNB ($)
- modifiers: notPaused,nonReentrant
- [Ext] withdrawAll #
- [Ext] withdraw #
- [Ext] withdrawUnderlying #
- [Pub] getReward #
- modifiers: nonReentrant
- [Pub] harvest #
- modifiers: notPaused,onlyKeeper
- [Prv] _getBufferedAmountMin
- [Prv] _getAmountWithExitRatio
- [Prv] _increaseCollateral #
- [Prv] _decreaseCollateral #
- [Ext] recoverToken #
- modifiers: onlyOwner