Organization
- @plether
Engagement Type
Cantina Reviews
Period
-
Repositories
Researchers
Findings
Medium Risk
2 findings
2 fixed
0 acknowledged
Low Risk
5 findings
4 fixed
1 acknowledged
Informational
1 findings
1 fixed
0 acknowledged
Medium Risk2 findings
Basket Weights Should Be Constrainted to Unit Value
State
Severity
- Severity: Medium
Submitted by
red-swan
Description
BasketOracledoes not demand that its weights sum to one. InlatestRoundData, this would cause the_checkDeviationcheck to fail because the price comparison would be in different numéraires or skip that check entirely and return zero prices if all the weights were zero.Recommendation
Consider adding a
requirestatement that enforces the basket weights to sum to one.Adapter Asset Don't Account For Accrued Interest
State
Severity
- Severity: Medium
≈
Likelihood: High×
Impact: Medium Submitted by
red-swan
Description
MorphoAdapter.totalAssetshas comments that state it returns accrued interest but the Morpho Blue documentation (under Best Practices) states:> Interest Accrual: Remember that totalBorrowAssets and totalSupplyAssets are only updated when an interaction triggers _accrueInterest.Morpho's
positionmethod therefore can't call_accrueInterestbecause it is aviewfunction and indeed upon inspectingMorpho.solwe see that interest is only accrued when funds enter/exit the contract.This feeds into many other ERC-4626 methods like
maxWithdraw,previewDeposit, andconvertToSharesas well as intoSyntheticSplittersuch asharvestYieldandpreviewBurn.Recommendation
Consider accruing interest in
MorphoAdapter.totalAssetsor utilizingMorphoBalancesLib'sexpectedTotalSupplyAssetsif you wish to save gas.
Low Risk5 findings
Duplicate Event Emissions
State
- Acknowledged
Severity
- Severity: Low
Submitted by
red-swan
Description
The following functions do not check that the new item being written to storage is not the same as the old and therefore will fire an event when nothing noteworthy has changed. Doing so may mislead off-chain systems.
BasketOracle.proposeCurvePoolMorphoAdapter.setUrdSyntheticSplitter.proposeAdapter
Recommendation
Consider reverting if the item to be written is the same as what is already in storage
Missing Security Contact In Source Files
State
Severity
- Severity: Low
Submitted by
red-swan
Description
The smart contract files do not include a security contact (such as an email address, a link to a bug bounty program, or a dedicated security policy) in the contracts that will be deployed. It is often the case that third-parties will only interact with the code through other platforms like sourcify, blockscout, or etherscan rather than the code's actual repository. In the event that a vulnerability is discovered by a third-party researcher or a "white-hat" hacker a contact in the source code allows them to easily, reliably, and privately report findings to the development team. Without a clear disclosure process, researchers may resort to public communication (e.g., social media) to get the team’s attention, inadvertently alerting malicious actors to the flaw before it can be patched or mitigated.
Recommendation
Consider adding a security contact at the top of each source file.
AggegatorV3Interface Conformity
State
Severity
- Severity: Low
Submitted by
red-swan
Description
BasketOracle'sgetRoundDatafunction doesn't strictly conform to theAggregatorV3Interfacein that it doesn't actually return data for the input round ID.Recommendation
Consider reverting when this method is called, or alternatively, revert only when called with a round ID that is not the latest round ID. Either approach would provide clear error messaging and prevent silent data corruption in external integrations that expect standard Chainlink oracle behavior
Owner Can Circumvent Rescue Constraint
State
Severity
- Severity: Low
≈
Likelihood: Low×
Impact: High Submitted by
red-swan
Description
In SytheticSplitter.rescueToken, the owner is not allowed to transfer USDC out of the contract. However, they are still able to transfer yield adapter tokens out, which are redeemable for 90% of the contract's USDC.
Recommendation
Consider reverting if
token == address(yieldAdapter).New Adapter Could Have Different Underlying Asset
State
Severity
- Severity: Low
≈
Likelihood: Low×
Impact: High Submitted by
red-swan
Description
In
proposeAdapterandfinalizeAdapter, it is possible, however unlikely, that the new adapter have a different underlying asset than the previous adapter orSyntheticSplitter'sUSDC. If this is the case it would throw all math and assumptions of the contract up in the air.Recommendation
Consider requiring that
pendingAdapter.asset() == USDCinproposeAdapterto ensure that the new adapter shares the same asset.
Informational1 finding
Code Accuracy
State
Severity
- Severity: Informational
Submitted by
red-swan
Description and Recommendations
There are several locations where the code can be made to align better with the intent of the protocol.
SyntheticSplitter'sTOKEN_AandTOKEN_Bhave specific roles within the system and are referred to as BEAR and BULL constantly. Consider naming them as such.MorphoAdapter'smarketParamsis set in storage only once and there can be immutable.SyntheticSplitter'sMIN_SURPLUS_THRESHOLDis hard-coded toUSDC's 6 decimals whileUSDC_MULTIPLIERis not. Consider whether you should hard code everthing to six decimals or not.BasketOracle'sgetRoundDatacreates an external call to what could be an internal function. Consider makinglatestRoundDatapublicand making this call internal.CAPis defined but not used byBasketOracle. Consider removing it.- In
previewHarvestthe variableadapterAssetsrepresents the same concept asharvestYield'stotalAssetsbut they have different names. Consider changingharvestYield's variable to matchpreviewHarvest's.