Starstream Finance - Smart Contract Audit Report
Audit Summary
Starstream Finance intends to build a yield aggregator on Metis.
For this audit, we reviewed the project team's StarstreamTreasury, StarstreamVault, StarstreamAutoCompoundTethys contracts at commit e271a71bde88d12f11e2edc41b44c5e4caa9a703 on the team's GitHub repository.
Audit Findings
Please ensure trust in the team prior to investing as they have substantial control in the ecosystem.
Date: February 3rd, 2022.Finding #1 - StartstreamTreasury, StarstreamVault, StarstreamAutoCompoundTethys - Informational
Description: Several functions are declared public, but are never called internally.Recommendation: We recommend declaring these functions external for additional gas savings on each call.- StartstreamTreasury: viewWithdrawal, markReviewed, setAccountant - StarstreamVault: initialize, getPricePerFullShare, proposeStrat, upgradeStrat - StarstreamAutoCompoundTethys: balanceOf, panic
Finding #2 - StarstreamAutoCompoundTethys - Informational
Description: Several state variables can never be modified, but are not declared constant.Recommendation: We recommend declaring these state variables constant for additional gas savings on each call.masterChef, rewardToken, securityFee, uniRouter, wftm
Contracts Overview
StarstreamVault Contract:
- The contracts utilize ReentrancyGuard to prevent re-entrancy attacks in applicable functions.
- The contracts utilize SafeMath libraries to prevent overflow/underflow attacks.
StarstreamAutoCompoundTethys Contract:
- Users can stake a designated LP Token into the Vault, and will get back tokens that represent shares of rewards.
- The Vault will then transfer the designated tokens to the Strategy contract to earn yield.
- Users are able to withdraw out of the Strategy contract through the Vault. This will send back the LP tokens, burning the Vault tokens in the process.
- There is no fee associated with making a deposit into the Vault contract.
- There is no fee associated with withdrawing from the Vault but there is a fee of .1% for withdrawing from the Strategy contract. This fee is redistributed back amongst the shareholders.
- The strategy can be changed by the owner. They must first propose the contract, which will have a publicly available address.
- After waiting the designated delay period, the owner can then set the Strategy contract to the new strategy.
- When a new strategy is set, all tokens will be withdrawn from the previous contract and deposited into the new one.
- The owner is able to withdraw the total balance of any of the non-designated tokens in the Vault.
- The owner can propose a new Strategy contract at any time.
StarstreamTreasury Contract:
- This contract serves as a valid Strategy contract for the StarstreamVault contract.
- All LP tokens deposited into this contract from the Starstream Vault are deposited into a MasterChef contract that is set upon deployment.
- We did not review this MasterChef contract and did not verify the security as a part of this audit.
- When rewards are harvested from the MasterChef contract, they are used to create more LP tokens. These are then deposited back into the MasterChef.
- There are fees taken from the MasterChef rewards. The team takes a portion which is sent to their Treasury contract. The user who called the harvest function also gets a portion of the rewards as well.
- There is a 0.1% fee on withdrawals from the contract.
- The combined total of all fees cannot exceed 5%. The call fee and Treasury fee are calculated as a percent of the total fee.
- The treasury fee defaults to 90% of the total fee upon deployment.
- The call fee defaults to 10% of the total fee upon deployment.
- Pausing the contract prevents deposits, and removes allowances from all the other contracts. Users can still withdraw when the contract is paused. Unpausing allows deposits and gives back the allowances.
- The owner is also able to use the panic function. This will pause the deposits and subsequently withdraw all tokens from the MasterChef into this contract.
- When the retireStrat() function is called by the vault address, all funds are withdrawn from the MasterChef and transferred to the vault address.
- The owner is able to pause and unpause the contract at any time.
- The owner can set the call and Treasury fees to any percentage of the total fee at any time.
- The owner can set the total fee to any value up to 5% at any time.
- The owner can change the treasury address at any time.
- This contract allows the team to withdraw the tokens collected as Treasury fees.
- The accountant address can mark withdrawals from the contract as reviewed.
- The owner can withdraw any tokens from the contract to any address at any time.
- The owner can set the accountant address at any time.
External Threat Results
Vulnerability Category | Notes | Result |
---|---|---|
Arbitrary Storage Write | N/A | PASS |
Arbitrary Jump | N/A | PASS | Centralization of Control | 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 |
Flash Loans | N/A | PASS |
Integer Over/Underflow | N/A | PASS |
Logical Issues | N/A | PASS |
Multiple Sends | N/A | PASS |
Oracles | 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 |
StarstreamVault Contract
($) = payable function
# = non-constant function
+ Context
- [Int] _msgSender
- [Int] _msgData
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Prv] _functionCallWithValue #
+ ERC20 (Context, IERC20)
- [Pub] #
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] decreaseAllowance #
- [Int] _transfer #
- [Int] _mint #
- [Int] _burn #
- [Int] _approve #
- [Int] _setupDecimals #
- [Int] _beforeTokenTransfer #
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ ReentrancyGuard
- [Int] #
+ [Int] IStrategy
- [Ext] deposit #
- [Ext] withdraw #
- [Ext] balanceOf
- [Ext] harvest #
- [Ext] retireStrat #
- [Ext] panic #
- [Ext] pause #
- [Ext] unpause #
- [Ext] updateTotalFee #
- [Ext] updateCallFee #
- [Ext] updateTreasuryFee #
+ StarstreamVault (ERC20, Ownable, ReentrancyGuard)
- [Pub] #
- modifiers: ERC20
- [Pub] initialize #
- modifiers: onlyOwner
- [Pub] balance
- [Pub] available
- [Pub] getPricePerFullShare
- [Ext] depositAll #
- [Pub] deposit #
- modifiers: nonReentrant
- [Pub] earn #
- [Ext] withdrawAll #
- [Pub] withdraw #
- modifiers: nonReentrant
- [Pub] proposeStrat #
- modifiers: onlyOwner
- [Pub] upgradeStrat #
- modifiers: onlyOwner
- [Int] incrementDeposits #
- [Int] incrementWithdrawals #
- [Ext] inCaseTokensGetStuck #
- modifiers: onlyOwner
StarstreamTreasury Contract
($) = payable function
# = non-constant function
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Prv] _functionCallWithValue #
+ ERC20 (Context, IERC20)
- [Pub] #
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] decreaseAllowance #
- [Int] _transfer #
- [Int] _mint #
- [Int] _burn #
- [Int] _approve #
- [Int] _setupDecimals #
- [Int] _beforeTokenTransfer #
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ StarstreamTreasury (Ownable)
- [Pub] viewWithdrawal
- [Pub] markReviewed #
- [Ext] withdrawTokens #
- modifiers: onlyOwner
- [Ext] withdrawFTM #
- modifiers: onlyOwner
- [Pub] setAccountant #
- modifiers: onlyOwner
- [Ext] ($)
StarstreamAutoCompoundTethys Contract
($) = payable function
# = non-constant function
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Prv] _functionCallWithValue #
+ ERC20 (Context, IERC20)
- [Pub] #
- [Pub] name
- [Pub] symbol
- [Pub] decimals
- [Pub] totalSupply
- [Pub] balanceOf
- [Pub] transfer #
- [Pub] allowance
- [Pub] approve #
- [Pub] transferFrom #
- [Pub] increaseAllowance #
- [Pub] decreaseAllowance #
- [Int] _transfer #
- [Int] _mint #
- [Int] _burn #
- [Int] _approve #
- [Int] _setupDecimals #
- [Int] _beforeTokenTransfer #
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ Pausable (Context)
- [Int] #
- [Pub] paused
- [Int] _pause #
- modifiers: whenNotPaused
- [Int] _unpause #
- modifiers: whenPaused
+ [Int] IUniswapRouterETH
- [Ext] addLiquidity #
- [Ext] addLiquidityETH ($)
- [Ext] removeLiquidity #
- [Ext] removeLiquidityETH #
- [Ext] swapExactTokensForTokens #
- [Ext] swapExactETHForTokens ($)
- [Ext] swapExactTokensForETH #
- [Ext] swapExactTokensForTokensSupportingFeeOnTransferTokens #
+ [Int] IUniswapV2Pair
- [Ext] token0
- [Ext] token1
+ [Int] IMasterChef
- [Ext] poolLength
- [Ext] pendingTethys
- [Ext] massUpdatePools #
- [Ext] updatePool #
- [Ext] deposit #
- [Ext] withdraw #
- [Ext] userInfo
- [Ext] emergencyWithdraw #
+ StarstreamAutoCompoundTethys (Ownable, Pausable)
- [Pub] #
- [Pub] deposit #
- modifiers: whenNotPaused
- [Ext] withdraw #
- [Ext] harvest #
- modifiers: whenNotPaused
- [Int] chargeFees #
- [Int] addLiquidity #
- [Pub] balanceOf
- [Pub] balanceOfLpPair
- [Pub] balanceOfPool
- [Ext] retireStrat #
- [Pub] panic #
- modifiers: onlyOwner
- [Pub] pause #
- modifiers: onlyOwner
- [Ext] unpause #
- modifiers: onlyOwner
- [Int] giveAllowances #
- [Int] removeAllowances #
- [Ext] updateTotalFee #
- modifiers: onlyOwner
- [Ext] updateCallFee #
- modifiers: onlyOwner
- [Ext] updateTreasury #
- modifiers: onlyOwner