Retro DeFi Native Strategy & Timelock Controller - Smart Contract Audit Report
Summary
Retro DeFi is building a yield aggregator on the Binance Smart Chain.
For this audit we reviewed the project's Native Strategy contract and Timelock Controller contract. We reviewed the contracts at commit 92accd6f9625328b5a0157de28ccdf84d792497e and again at commit 7d2870954b49263068af101d6afcd3c1b9250bba on GitHub. We also previously reviewed the project's Native Farm and Token contract here. Please note we have not reviewed the project's other strategy contracts.
Notes of the Contracts:Users staking tokens into the projects farm will have their tokens forwarded to strategy contracts to earn yield on deposited assets when possible. As this contract is for the project's native token, there is nowhere to earn yield. Users who deposit wil still earn rewards from farming, however. There is a fee associated with making a deposit to the strategy, though this fee can only be set to a maximum of 0.5%. There is no way to claim fees in this contract, so the team should keep fees at 0%. The TimelockController contract is intended to be the owner of the Strategy contract, delaying certian ownership-restricted actions. For testing purposes, the delay is current 1 minute. Prior to deployment, we advise implementing a minimum of a 24-hour delay. Users with large amounts of funds in the ecosystem should set up BSCscan alerts for this contract to monitor its activity. The team can pause deposits into the strategy contracts and reblance them without any delay. The team can also remove any tokens or BNB erroneously sent to either contract, though user's staked tokens cannot be moved. The team has implement a series of recommendations around gas optimization. Utilization of SafeMath to prevent overflow issues. Audit Findings Summary:
- No issues from external attackers were identified.
- Ensure trust in the team as they have some control in the ecosyste.
- Date: June 2nd, 2021.
- Update Date: June 2nd, 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 |
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: Native Strategy Contract
($) = payable function
# = non-constant function
Int = Internal
Ext = External
Pub = Public
+ 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
- [Pub] farm #
- modifiers: nonReentrant
- [Int] _farm #
- [Pub] withdraw #
- modifiers: onlyOwner,nonReentrant
- [Pub] earn #
- modifiers: whenNotPaused
- [Int] buyBack #
- [Int] distributeFees #
- [Pub] convertDustToEarned #
- modifiers: whenNotPaused
- [Pub] pause #
- [Ext] unpause #
- [Pub] setEntranceFeeFactor #
- [Pub] setControllerFee #
- [Pub] setbuyBackRate #
- [Pub] setGov #
- [Pub] setOnlyGov #
- [Pub] inCaseTokensGetStuck #
Details: Timelock Controller 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] INativeFarm
- [Ext] add #
- [Ext] set #
+ [Int] IStrategy
- [Ext] earn #
- [Ext] farm #
- [Ext] pause #
- [Ext] unpause #
- [Ext] rebalance #
- [Ext] deleverageOnce #
- [Ext] wrapBNB #
- [Ext] noTimeLockFunc1 #
- [Ext] noTimeLockFunc2 #
- [Ext] noTimeLockFunc3 #
+ 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] 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