Recommendations Explanation
Last updated
Last updated
Rivera uses latest standards in smart contracts. No critical issues were detected on that front. Moreover the use of Gelato is a good choice keeping in view the current alternatives available. However, moderate improvements are needed and some general recommendations which will be discussed one by one.
ROI: 2x
Blast radius: Medium
Time-to-market: 1 week
Rationale
If a fund manager or vault owner wishes to update their strategy parameters then a new strategy contract is deployed. Either a new contract can be deployed or current can be manipulated by updating variables. But this will take multiple transactions.
A better approach is to keep the same one that can be ‘’upgraded’’ using the UUPS proxy of Openzeppelin which is a industry standard: https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable
A strategy factory can also be developed which deploys these upgradeable strategy contracts which can further reduce gas costs and it will give further control to the users. Diagram : https://drive.google.com/file/d/18GOMVFGl1xivf9W-2SFUhpo_JOlJcS3Z/view?usp=sharing
ROI: 5x
Blast radius: High
Time-to-market: 2 week
Rationale
CCIP by Chainlink offers all functionalities of Router protocol plus CCIP rate limits are configurable per-token-pool and per-lane and are set up in alignment with the token issuer. This is a feature which compliments the Rivera value proposition also and this is not available via Router protocol
ROI: 5x
Blast radius: High
Time-to-market: 2 week
Rationale
If you don’t wish to update the vault logic to interact with CCIP directly or want to add more logic before transactions go to CCIP router then a RIVERA ROUTER contract can have all that logic. It will act as a intermediary between CCIP router and vault.
ROI: 5x
Blast radius: High
Time-to-market: 1 week
Rationale
It is crucial to have a better UX to onboard and retain your users. That includes giving the user to pay gas pay in a token of their choice on any chain. This can be achieved by the same Gelato Network that Rivera is using.
Gasless transaction are batched hence users get a lot of saving on transaction costs also by up to 50%. https://forum.storj.io/t/batch-smart-contract-transactions-fee-test/11293#:~:text=This transaction is more expensive,shared and (hopefully) lower.&text=It appears that adding multiple,transaction fees by around 50%25.
ROI: 5x
Blast radius: High
Time-to-market: 1 week
Rationale
To onboard the next million users it is crucial to have a better UX. That includes giving the user option to login using Web2 ids (for example google , apple id, etc.) and Web3 wallets also.
This can simply be integrated using Privy https://www.privy.io/.
Privy also reduces number of clicks needed to onboard a user. You can reduce up 50% of the clicks in the onboarding process.
ROI: 5x
Blast radius: Low
Time-to-market: 3 days
Rationale
In the [withdraw
function](https://github.com/RiveraMoney/farming-vault-factory/blob/9e7d6ee55e9bd4c0b1467479b6f358f2aaf3e3db/src/vaults/RiveraAutoCompoundingVaultV2.sol#L152C4-L152C4), withdrawals may be affected by slippage. Hence, the user won’t be able to set a Slippage Percentage that he is comfortable with. Unexpected Slippage Cuts can make withdrawing from Rivera Vaults inconsistent for both Users and Dapps built upon Rivera.
We recommend using a wrapper that performs these checks such as ERC4626Router to provide a consistent interface to users and Dapps for interacting with Rivera Vaults. It protects the Users against unexpected slippage in general by verifying the amount received is as expected.
ROI: 3x
Blast radius: Low
Time-to-market: 1 week
Rationale
Rivera has whitelisted and public vaults which may or may not use multisig wallets and multiple whitelisted addresses.
This Rivera library, for instance, uses a mapping:
https://github.com/RiveraMoney/farming-vault-factory/blob/master/src/libs/WhitelistFilter.sol
Merkle Proofs have more computation cost than storage cost but mappings have a very high storage cost and storage cost is always more expensive on blockchain than computation cost.
A better way to handle those wallets is using Merkle Proof based access control. This will greatly increase the ease of use for corporate investor or people who want to use multiple wallets.
For example:
Setting 3 address to whitelist true costs = 100728 gas units
Setting a single proof which represents these 3 addresses costs = 49772 gas units
That is a 50.5% improvement.
ROI: 3x
Blast radius: Low
Time-to-market: 3 days
Rationale
Owners are managed by ownable library and managers are a address variable in the contract. These roles and any more future roles are better managed if they are implemented using Access Control library.
For example:
User A
has private vault but they want their own asset manager and funds auditor people to have access to that vault. Adding such roles will be easy via access control compared to hard coding anything or re-deploying a contract. https://docs.openzeppelin.com/contracts/4.x/api/access#AccessControl
ROI: 1.5x
Blast radius: Low
Time-to-market: 3 days
Rationale
Solidity Compiler 0.8 onwards uses safemath
approach by default. This safemath
library should be removed and it is not needed. Its operations are causing extra gas costs which can saved using native solidity arithmetic operations.
By testing on same 0.8.19 compiler with 200 optimizer as used by Rivera https://explorer.testnet.mantle.xyz/address/0xff2AAe557c626b6097abB582638cbD01c8d7F5AA/contracts?contract-tab=code#address-tabs
For Example:
A simple 0+10 with safemath costs = 372 units and without safemath costs = 349 units
That is a 6.1% improvement**.** In the vault contract safemath
related operations are used in more than 5 places. and each of those operations could save 6.1% more.
ROI: 1.5x
Blast radius: Low
Time-to-market: 2 days
Rationale
We noticed a lot of variables are set only once either at the time of contract creation or after that. And even as per the contract logic those variables do not need to be updated repeatedly. They can be made immutable.
For example:
strategy
and approvalDelay
variable is updated only once here: https://github.com/RiveraMoney/farming-vault-factory/blob/master/src/vaults/RiveraAutoCompoundingVaultV2.sol