Platform: Code4rena
Start Date: 08/09/2023
Pot Size: $70,000 USDC
Total HM: 8
Participants: 84
Period: 6 days
Judge: gzeon
Total Solo HM: 2
Id: 285
League: ETH
Rank: 42/84
Findings: 2
Award: $85.12
๐ Selected for report: 0
๐ Solo Findings: 0
50.4324 USDC - $50.43
https://github.com/code-423n4/2023-09-centrifuge/blob/512e7a71ebd9ae76384f837204216f26380c9f91/src/LiquidityPool.sol#L160-L162 https://github.com/code-423n4/2023-09-centrifuge/blob/512e7a71ebd9ae76384f837204216f26380c9f91/src/LiquidityPool.sol#L170-L172 https://github.com/code-423n4/2023-09-centrifuge/blob/512e7a71ebd9ae76384f837204216f26380c9f91/src/LiquidityPool.sol#L176-L184 https://github.com/code-423n4/2023-09-centrifuge/blob/512e7a71ebd9ae76384f837204216f26380c9f91/src/LiquidityPool.sol#L148-L152 https://github.com/code-423n4/2023-09-centrifuge/blob/512e7a71ebd9ae76384f837204216f26380c9f91/src/InvestmentManager.sol#L569-L582
As per EIP 4626's Security Considerations
Finally, EIP-4626 Vault implementers should be aware of the need for specific, opposing rounding directions across the different mutable and view methods, as it is considered most secure to favor the Vault itself during calculations over its users.
If (1) itโs calculating how many shares to issue to a user for a certain amount of the underlying tokens they provide or (2) itโs determining the amount of the underlying tokens to transfer to them for returning a certain amount of shares, it should round down.
If (1) itโs calculating the amount of shares a user has to supply to receive a given amount of the underlying tokens or (2) itโs calculating the amount of underlying tokens a user has to provide to receive a certain amount of shares, it should round up.
Thus, the result of the mint
, withdraw
, previewMint
and previewWithdraw
should be rounded up.
The mint
, withdraw
, previewMint
and previewWithdraw
from the LiquidityPool.sol calls thier respective functions in InvestmentManager.sol which ultimately calls the _calculatePrice function. This function rounds_down
the prices which is not expected as per the EIP-4626 standard.
//In File::src/InvestmentManager.sol function _calculatePrice(uint128 currencyAmount, uint128 trancheTokenAmount, address liquidityPool) public view returns (uint256 depositPrice) { (uint8 currencyDecimals, uint8 trancheTokenDecimals) = _getPoolDecimals(liquidityPool); uint256 currencyAmountInPriceDecimals = _toPriceDecimals(currencyAmount, currencyDecimals, liquidityPool); uint256 trancheTokenAmountInPriceDecimals = _toPriceDecimals(trancheTokenAmount, trancheTokenDecimals, liquidityPool); depositPrice = currencyAmountInPriceDecimals.mulDiv( 10 ** PRICE_DECIMALS, trancheTokenAmountInPriceDecimals, MathLib.Rounding.Down //@audit rounds down ); }
Manual review
Other users/ protocols that integrate with Centrifuge's Liquidity Pools might wrongly assume that the functions handle rounding as per ERC4626 expectation. Thus, it might cause some integration problem in the future that can lead to wide range of issues for both parties.
Ensure that the rounding of vault's functions behave as expected. Following are the expected rounding direction for each vault function:
previewMint() - Round Up :arrow_up:
previewWithdraw() - Round Up :arrow_up:
mint() - Round Up :arrow_up:
withdraw() - Round Up :arrow_up:
Other functions are expected to Round down :arrow_down:, which atm is working.
For implementing this, we can use an ENUM
ENUM Rounding{ UP, DOWN }
Which can be passed to the functions and it can be used to have an if statement
to determine whether to round up or down.
Library
#0 - c4-pre-sort
2023-09-15T21:52:23Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2023-09-15T21:52:39Z
raymondfam marked the issue as duplicate of #34
#2 - c4-judge
2023-09-25T13:41:42Z
gzeon-c4 changed the severity to 2 (Med Risk)
#3 - c4-judge
2023-09-26T18:11:17Z
gzeon-c4 marked the issue as satisfactory
๐ Selected for report: ciphermarco
Also found by: 0x3b, 0xbrett8571, 0xmystery, 0xnev, K42, Kral01, Sathish9098, castle_chain, catellatech, cats, emerald7017, fouzantanveer, foxb868, grearlake, hals, jaraxxus, kaveyjoe, lsaudit, rokinot
34.6879 USDC - $34.69
The codebase for Centrifuge's Liquidity Pools is well-structured and effectively integrates cross-chain communication. This structure aligns with Centrifuge's mission to bridge businesses or "Asset Originators" and investors through Decentralized Finance (DeFi). Here is a step-by-step process flow of the protocol from a user's perspective:
deposit
, redeem
, mint
, withdraw
etc., follow this execution order.Access controls are well-implemented using 'root.sol', which serves as the central access control entity for all contracts through a ward feature. The tests are comprehensive and utilize fuzzing, providing a robust coverage. The gateway routers adhere to best practices, and the ERC4626 implementations are mostly compliant with recommended guidelines.
The protocol has a few centralization risks that should be addressed:
The audit took a total of 4 days:
1st Day: Understanding the protocol's documentation, process flow, and end user flow, and taking notes and drawing diagrams. 2nd Day: Linking the documentation's logic to the codebase by following the user's entry point, scanning for vulnerabilities by executing the user flow, taking notes of potential vulnerabilities, and reading reports for similar vault-based protocols. 3rd Day: Focusing on different types of attack vectors and documenting found vulnerabilities also reading the tests provided some insight into potential vulnerability and edge cases. 4th Day: Summarizing the audit by completing the QA report and analysis .
48 hours
#0 - c4-pre-sort
2023-09-17T02:10:57Z
raymondfam marked the issue as low quality report
#1 - c4-judge
2023-09-26T17:12:37Z
gzeon-c4 marked the issue as grade-b