Donut Farm - Smart Contract Audit Report
Summary
Donut Farm is building a layered yield farming platform on the Binance Smart Chain.
For this audit we reviewed the project's MasterChef, Referrals, TimelockController, NativeToken, NativeStrategy, and PCS Strategy contracts.
We reviewed the contracts at commit 88778b6c4c4a523b7d279da60ac4ab0ff5270f5e on GitHub.
BSC Mainnet Addresses:
- TimelockController: 0xeD1f240170E56319AB7C91CBEBda7D85500A2841
- Referrals: 0x21885657e4514aD427B07Fc918A69fA2e9E3027D
- NativeToken: 0x4ad4C0497B7C7e41BfeA3BcB00814d475F17d18E
- MasterChef: 0x53eCFb347Dd46BF07CaDb9A5fAF906994Ff6a9b6
- StrategyNative: 0xDF2b0CF70be1ddfd0C1C620AF62CEce582C68AB8
- StrategyPancake: 0x26d333b913261397AcEba5E201040CE318534815
- Strategy_PCS: 0x156A1DF37270C8B9B80f9600f0A9451376F023E5
Notes of the Contracts:Audit Findings Summary:
- Users can stake various tokens into the MasterChef contract in order to earn yield and rewards in form of the project's Native Token.
- Users who refer others to deposit can also earn further tokens as a reward for their referral.
- There is a fee associated with making a deposit to and withdrawing from the contract, set on a per-pool basis by the team.
- Based upon the pool staked into, user's assets will be forwarded to strategies for Different protocols. The PCS and Native strategies were reviewed as part of this audit.
- The strategy contracts are designed to be owned and utilized only by the MasterChef, though the governance address.
- The governance address can also set platform fees associated with use of each strategy contract, update the the buyback rate of each strategy, and recover tokens that are not the staking or reward token from the contract.
- The team can create additional strategies in the future for new pools, but cannot update strategy contracts for existing pools.
- Yield from deposits will be denominated in the deposit asset and is additional to a user's earned Native Token rewards.
- 10% of Native Token rewards minted by the MasterChef will be allocated to the team.
- An emergency withdraw function is present, allowing users to withdraw their tokens without a withdraw fee in case of an issue, but that user's rewards will be forfeited.
- The project team can add different types of tokens for staking, and can update the reward rates for each staking token.
- The owner must excercise caution when adding tokens for staking and ensure not to add any fee-on-transfer tokens.
- The owner can also update the deposit and withdraw fees associated with the contract to any value.
- The owner has the ability to update the start date of rewards a single time.
- The owner can transfer ownership of the token contract to any address.
- The owner of the MasterChef contract is designed to be the TimelockController contract, which is designed to delay the execution of transactions.
- The TimelockController's default minimum delay is only 60 seconds. We advise the team raise this to 12 or 24 hours.
- Utilization of SafeMath to prevent overflow issues and ReentrancyGuard to prevent reentrancy attacks.
- The team has implemented a series of recommendations from our team to save users gas on each call and the team gas on deployment.
- No issues from external attackers were identified.
- Ensure trust in the team as they have substantial control in the ecosystem.
- Date: September 25th, 2021 - Commit 9e806...
- Updated: September 27th, 2021 - Commit 88778... Implementation of gas optimizations.
- Updated: October 10th, 2021 - Deployment to mainnet.
- Updated: October 25th, 2021 - New mainnet deployments.
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 |
Flash Loans | N/A | PASS |
Integer Over/Underflow | 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 |
Details: MasterChef Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Lib] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Prv] _verifyCallResult
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ ReentrancyGuard
- [Int] #
+ 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 #
+ [Int] IStrategy
- [Ext] wantLockedTotal
- [Ext] sharesTotal
- [Ext] earn #
- [Ext] deposit #
- [Ext] withdraw #
- [Ext] inCaseTokensGetStuck #
+ [Int] IReferrals
- [Ext] updateEarn #
- [Ext] getListReferrals
- [Ext] getSponsor
- [Ext] isMember
- [Ext] addMember #
- [Ext] membersList
+ [Int] IHelp
- [Ext] Bytecode_2_0_3
+ NativeToken (ERC20)
- [Pub] mint #
+ MasterChef (Ownable, ReentrancyGuard)
- [Pub] #
- [Ext] poolLength
- [Pub] add #
- modifiers: onlyOwner
- [Pub] set #
- modifiers: onlyOwner
- [Pub] setDepositFee #
- modifiers: onlyOwner
- [Pub] getMultiplier
- [Ext] pendingNATIVE
- [Ext] stakedWantTokens
- [Ext] getWantLockedTotal
- [Pub] massUpdatePools #
- [Pub] updatePool #
- [Pub] harvestAll #
- modifiers: nonReentrant
- [Pub] deposit #
- modifiers: nonReentrant
- [Pub] withdraw #
- modifiers: nonReentrant
- [Pub] emergencyWithdraw #
- modifiers: nonReentrant
- [Int] safeNATIVETransfer #
- [Pub] inCaseOfRequiringChangeOfInitialDate #
- modifiers: onlyOwner
- [Pub] transferEarningTokenOwnership #
- modifiers: onlyOwner
- [Pub] getWithdrawFee
- [Pub] setWithdrawFee #
- modifiers: onlyOwner
- [Pub] setPercReferrals #
- modifiers: onlyOwner
Details: Referrals Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Lib] SafeMath
- [Int] tryAdd
- [Int] trySub
- [Int] tryMul
- [Int] tryDiv
- [Int] tryMod
- [Int] add
- [Int] sub
- [Int] mul
- [Int] div
- [Int] mod
- [Int] sub
- [Int] div
- [Int] mod
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ [Int] IERC165
- [Ext] supportsInterface
+ [Int] IERC721 (IERC165)
- [Ext] balanceOf
- [Ext] ownerOf
- [Ext] safeTransferFrom #
- [Ext] transferFrom #
- [Ext] approve #
- [Ext] getApproved
- [Ext] setApprovalForAll #
- [Ext] isApprovedForAll
- [Ext] safeTransferFrom #
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Int] IHelp
- [Ext] Bytecode_2_0_3
+ Referrals (Ownable)
- [Pub] addMember #
- modifiers: onlyOwner
- [Pub] updateEarn #
- modifiers: onlyOwner
- [Pub] getListReferrals
- [Pub] getSponsor
- [Pub] isMember
Details: TimelockController Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [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 #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Prv] _verifyCallResult
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ Context
- [Int] _msgSender
- [Int] _msgData
+ [Lib] EnumerableSet
- [Prv] _add #
- [Prv] _remove #
- [Prv] _contains
- [Prv] _length
- [Prv] _at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
+ AccessControl (Context)
- [Pub] hasRole
- [Pub] getRoleMemberCount
- [Pub] getRoleMember
- [Pub] getRoleAdmin
- [Pub] grantRole #
- [Pub] revokeRole #
- [Pub] renounceRole #
- [Int] _setupRole #
- [Int] _setRoleAdmin #
- [Prv] _grantRole #
- [Prv] _revokeRole #
+ ReentrancyGuard
- [Int] #
+ [Int] IHelp
- [Ext] Bytecode_2_0_3
+ [Int] INativeFarm
- [Ext] add #
- [Ext] set #
- [Ext] setWithdrawFee #
+ [Int] IStrategy
- [Ext] earn #
- [Ext] farm #
- [Ext] pause #
- [Ext] unpause #
- [Ext] rebalance #
- [Ext] deleverageOnce #
- [Ext] wrapBNB #
- [Ext] noTimeLockFunc1 #
- [Ext] noTimeLockFunc2 #
- [Ext] noTimeLockFunc3 #
+ [Int] ILottery
- [Ext] drawAndReset #
- [Ext] drawAndEnter #
- [Ext] reset #
- [Ext] enterDrawingPhase #
- [Ext] drawing #
+ TimelockController (AccessControl, ReentrancyGuard)
- [Pub] #
- [Ext] ($)
- [Pub] isOperationPending
- [Pub] isOperationReady
- [Pub] isOperationDone
- [Pub] getTimestamp
- [Pub] getMinDelay
- [Pub] hashOperation
- [Pub] hashOperationBatch
- [Pub] schedule #
- modifiers: onlyRole
- [Pub] scheduleBatch #
- modifiers: onlyRole
- [Prv] _schedule #
- [Pub] cancel #
- modifiers: onlyRole
- [Pub] execute ($)
- modifiers: onlyRole,nonReentrant
- [Pub] executeBatch ($)
- modifiers: onlyRole,nonReentrant
- [Prv] _beforeCall
- [Prv] _afterCall #
- [Prv] _call #
- [Ext] updateMinDelay #
- [Ext] updateMinDelayReduced #
- [Pub] setDevWalletAddress #
- [Pub] scheduleSet #
- modifiers: onlyRole
- [Pub] executeSet ($)
- modifiers: onlyRole,nonReentrant
- [Pub] withdrawBNB ($)
- [Pub] withdrawBEP20 ($)
- [Pub] add #
- modifiers: onlyRole
- [Pub] setWithdrawFee #
- modifiers: onlyRole
- [Pub] earn #
- modifiers: onlyRole
- [Pub] farm #
- modifiers: onlyRole
- [Pub] pause #
- modifiers: onlyRole
- [Pub] unpause #
- modifiers: onlyRole
- [Pub] rebalance #
- modifiers: onlyRole
- [Pub] deleverageOnce #
- modifiers: onlyRole,nonReentrant
- [Pub] wrapBNB #
- modifiers: onlyRole
- [Pub] noTimeLockFunc1 #
- modifiers: onlyRole
- [Pub] noTimeLockFunc2 #
- modifiers: onlyRole
- [Pub] noTimeLockFunc3 #
- modifiers: onlyRole
- [Pub] drawAndReset #
- modifiers: onlyRole
- [Pub] drawAndEnter #
- modifiers: onlyRole
- [Pub] reset #
- modifiers: onlyRole
- [Pub] enterDrawingPhase #
- modifiers: onlyRole
- [Pub] drawing #
- modifiers: onlyRole
Details: Strategy_PCS Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Int] IHelp
- [Ext] Bytecode_2_0_3
+ [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 #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Prv] _verifyCallResult
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ ReentrancyGuard
- [Int] #
+ Context
- [Int] _msgSender
- [Int] _msgData
+ Pausable (Context)
- [Int] #
- [Pub] paused
- [Int] _pause #
- modifiers: whenNotPaused
- [Int] _unpause #
- modifiers: whenPaused
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Int] IXswapFarm
- [Ext] poolLength
- [Ext] userInfo
- [Ext] getMultiplier
- [Ext] deposit #
- [Ext] withdraw #
- [Ext] emergencyWithdraw #
+ [Int] IXRouter01
- [Ext] factory
- [Ext] WETH
- [Ext] addLiquidity #
- [Ext] addLiquidityETH ($)
- [Ext] removeLiquidity #
- [Ext] removeLiquidityETH #
- [Ext] removeLiquidityWithPermit #
- [Ext] removeLiquidityETHWithPermit #
- [Ext] swapExactTokensForTokens #
- [Ext] swapTokensForExactTokens #
- [Ext] swapExactETHForTokens ($)
- [Ext] swapTokensForExactETH #
- [Ext] swapExactTokensForETH #
- [Ext] swapETHForExactTokens ($)
- [Ext] quote
- [Ext] getAmountOut
- [Ext] getAmountIn
- [Ext] getAmountsOut
- [Ext] getAmountsIn
+ [Int] IXRouter02 (IXRouter01)
- [Ext] removeLiquidityETHSupportingFeeOnTransferTokens #
- [Ext] removeLiquidityETHWithPermitSupportingFeeOnTransferTokens #
- [Ext] swapExactTokensForTokensSupportingFeeOnTransferTokens #
- [Ext] swapExactETHForTokensSupportingFeeOnTransferTokens ($)
- [Ext] swapExactTokensForETHSupportingFeeOnTransferTokens #
+ Strategy_PCS (Ownable, ReentrancyGuard, Pausable)
- [Pub] #
- [Pub] deposit #
- modifiers: onlyOwner,nonReentrant,whenNotPaused
- [Pub] farm #
- modifiers: nonReentrant
- [Int] _farm #
- [Pub] withdraw #
- modifiers: onlyOwner,nonReentrant
- [Pub] earn #
- modifiers: nonReentrant,whenNotPaused
- [Int] _earn #
- [Int] buyBack #
- [Int] distributeFees #
- [Int] rewardFees #
- [Pub] convertDustToEarned #
- modifiers: whenNotPaused
- [Pub] pause #
- modifiers: onlyAllowGov
- [Ext] unpause #
- modifiers: onlyAllowGov
- [Pub] setEntranceFeeFactor #
- modifiers: onlyAllowGov
- [Pub] setExitFeeFactor #
- modifiers: onlyAllowGov
- [Pub] setControllerFee #
- modifiers: onlyAllowGov
- [Pub] setDepositFeeFactor #
- modifiers: onlyAllowGov
- [Pub] setWithdrawFeeFactor #
- modifiers: onlyAllowGov
- [Pub] setbuyBackRate #
- modifiers: onlyAllowGov
- [Pub] setGov #
- modifiers: onlyAllowGov
- [Pub] setBuybackRouterAddress #
- modifiers: onlyAllowGov
- [Pub] inCaseTokensGetStuck #
- modifiers: onlyAllowGov
Details: StrategyNative Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ [Int] IHelp
- [Ext] Bytecode_2_0_3
+ Context
- [Int] _msgSender
- [Int] _msgData
+ [Lib] SafeMath
- [Int] add
- [Int] sub
- [Int] sub
- [Int] mul
- [Int] div
- [Int] div
- [Int] mod
- [Int] mod
+ [Int] IERC20
- [Ext] totalSupply
- [Ext] balanceOf
- [Ext] transfer #
- [Ext] allowance
- [Ext] approve #
- [Ext] transferFrom #
+ 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] Address
- [Int] isContract
- [Int] sendValue #
- [Int] functionCall #
- [Int] functionCall #
- [Int] functionCallWithValue #
- [Int] functionCallWithValue #
- [Int] functionStaticCall
- [Int] functionStaticCall
- [Int] functionDelegateCall #
- [Int] functionDelegateCall #
- [Prv] _verifyCallResult
+ [Lib] SafeERC20
- [Int] safeTransfer #
- [Int] safeTransferFrom #
- [Int] safeApprove #
- [Int] safeIncreaseAllowance #
- [Int] safeDecreaseAllowance #
- [Prv] _callOptionalReturn #
+ [Lib] EnumerableSet
- [Prv] _add #
- [Prv] _remove #
- [Prv] _contains
- [Prv] _length
- [Prv] _at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
- [Int] add #
- [Int] remove #
- [Int] contains
- [Int] length
- [Int] at
+ Ownable (Context)
- [Int] #
- [Pub] owner
- [Pub] renounceOwnership #
- modifiers: onlyOwner
- [Pub] transferOwnership #
- modifiers: onlyOwner
+ [Int] IPancakeswapFarm
- [Ext] poolLength
- [Ext] userInfo
- [Ext] getMultiplier
- [Ext] pendingCake
- [Ext] deposit #
- [Ext] withdraw #
- [Ext] enterStaking #
- [Ext] leaveStaking #
- [Ext] emergencyWithdraw #
+ [Int] IPancakeRouter01
- [Ext] factory
- [Ext] WETH
- [Ext] addLiquidity #
- [Ext] addLiquidityETH ($)
- [Ext] removeLiquidity #
- [Ext] removeLiquidityETH #
- [Ext] removeLiquidityWithPermit #
- [Ext] removeLiquidityETHWithPermit #
- [Ext] swapExactTokensForTokens #
- [Ext] swapTokensForExactTokens #
- [Ext] swapExactETHForTokens ($)
- [Ext] swapTokensForExactETH #
- [Ext] swapExactTokensForETH #
- [Ext] swapETHForExactTokens ($)
- [Ext] quote
- [Ext] getAmountOut
- [Ext] getAmountIn
- [Ext] getAmountsOut
- [Ext] getAmountsIn
+ [Int] IPancakeRouter02 (IPancakeRouter01)
- [Ext] removeLiquidityETHSupportingFeeOnTransferTokens #
- [Ext] removeLiquidityETHWithPermitSupportingFeeOnTransferTokens #
- [Ext] swapExactTokensForTokensSupportingFeeOnTransferTokens #
- [Ext] swapExactETHForTokensSupportingFeeOnTransferTokens ($)
- [Ext] swapExactTokensForETHSupportingFeeOnTransferTokens #
+ ReentrancyGuard
- [Int] #
+ Pausable (Context)
- [Int] #
- [Pub] paused
- [Int] _pause #
- modifiers: whenNotPaused
- [Int] _unpause #
- modifiers: whenPaused
+ StrategyNative (Ownable, ReentrancyGuard, Pausable)
- [Pub] #
- [Pub] deposit #
- modifiers: onlyOwner,whenNotPaused,nonReentrant
- [Pub] farm #
- modifiers: nonReentrant
- [Int] _farm #
- [Pub] withdraw #
- modifiers: onlyOwner,nonReentrant
- [Pub] earn #
- modifiers: whenNotPaused
- [Int] _earn #
- [Int] buyBack #
- [Int] distributeFees #
- [Pub] convertDustToEarned #
- modifiers: whenNotPaused
- [Pub] pause #
- [Ext] unpause #
- [Pub] setEntranceFeeFactor #
- [Pub] setControllerFee #
- [Pub] setbuyBackRate #
- [Pub] setGov #
- [Pub] inCaseTokensGetStuck #