Platform: Code4rena
Start Date: 24/03/2023
Pot Size: $49,200 USDC
Total HM: 20
Participants: 246
Period: 6 days
Judge: Picodes
Total Solo HM: 1
Id: 226
League: ETH
Rank: 168/246
Findings: 1
Award: $13.13
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: brgltd
Also found by: 0x3b, 0xAgro, 0xGusMcCrae, 0xNorman, 0xRajkumar, 0xSmartContract, 0xTraub, 0xWagmi, 0xWaitress, 0xffchain, 0xhacksmithh, 0xkazim, 0xnev, 3dgeville, ArbitraryExecution, Aymen0909, BRONZEDISC, Bason, Bloqarl, BlueAlder, Brenzee, CodeFoxInc, CodingNameKiki, Cryptor, DadeKuma, DevABDee, Diana, Dug, Englave, Gde, Haipls, HollaDieWaldfee, Ignite, Infect3d, Jerry0x, Josiah, Kaysoft, Koko1912, KrisApostolov, Lavishq, LeoGold, Madalad, PNS, Rappie, RaymondFam, RedTiger, Rickard, Rolezn, Sathish9098, SunSec, T1MOH, UdarTeam, Udsen, Viktor_Cortess, Wander, adriro, ak1, alejandrocovrr, alexzoid, arialblack14, ayden, bin2chen, brevis, btk, c3phas, carlitox477, catellatech, ch0bu, chaduke, ck, climber2002, codeslide, descharre, dingo2077, ernestognw, fatherOfBlocks, favelanky, georgits, helios, hl_, inmarelibero, juancito, ks__xxxxx, lopotras, lukris02, m_Rassska, mahdirostami, maxper, nadin, navinavu, nemveer, p_crypt0, peanuts, pipoca, pixpi, qpzm, rbserver, reassor, roelio, rotcivegaf, scokaf, siddhpurakaran, slvDev, smaul, tnevler, tsvetanovv, turvy_fuzz, vagrant, wen, yac, zzzitron
13.1298 USDC - $13.13
Number | Issues Details |
---|---|
[NC-01] | Inconsistent use of function rethAddress |
[NC-02] | Inconsistent natspec for withdraw function |
[NC-03] | _amount Parameter for ethPerDerivative |
[NC-04] | Clean up arithmetic in Reth's deposit function |
[NC-05] | Floating version pragma |
In Reth.sol there are several instances of copy pasting the contents of the rethAddress() function rather than just using the function.
For example, starting at line 187:
address rocketTokenRETHAddress = RocketStorageInterface( ROCKET_STORAGE_ADDRESS ).getAddress( keccak256( abi.encodePacked("contract.address", "rocketTokenRETH") ) );
where this function could be used instead:
function rethAddress() private view returns (address) { return RocketStorageInterface(ROCKET_STORAGE_ADDRESS).getAddress( keccak256( abi.encodePacked("contract.address", "rocketTokenRETH") ) ); }
So it should be:
address rocketTokenRETHAddress = rethAddress()
And really you could just set up the interface with rethAddress() as the parameter rather than caching the address it since it's only used once.
This whole code block
address rocketTokenRETHAddress = RocketStorageInterface( ROCKET_STORAGE_ADDRESS ).getAddress( keccak256( abi.encodePacked("contract.address", "rocketTokenRETH") ) ); RocketTokenRETHInterface rocketTokenRETH = RocketTokenRETHInterface( rocketTokenRETHAddress );
could be replaced by
RocketTokenRETHInterface rocketTokenRETH = RocketTokenRETHInterface( rethAddress() );
The same issue also occurs within the poolPrice() function:
address rocketTokenRETHAddress = RocketStorageInterface( ROCKET_STORAGE_ADDRESS ).getAddress( keccak256( abi.encodePacked("contract.address", "rocketTokenRETH") ) );
can be replaced by:
address rocketTokenRETHAddress = rethAddress()
The natspec for the withdraw and deposit functions in Reth.sol does not specify that the owner is the safEth contract.
/** @notice - Deposit into derivative @dev - will either get rETH on exchange or deposit into contract depending on availability */
It does specify this in SfrEth.sol and WstEth.sol.
/** @notice - Owner only function to Deposit into derivative @dev - Owner is set to SafEth contract */
Consider adding the @dev note about ownership to the Reth.sol functions for improved clarity and consistency
The _amount parameter for the ethPerDerivative function is only used in the Reth.sol implementation. However, it's still present in the SfrxEth.sol and WstEth.sol implementations so that they conform to the IDerivative interface.
However, it may be helpful to add an @dev tag to the natspec comment explaining why the parameter is not used in those two implementations.
The parameter itself could also be commented out in the function definition:
function ethPerDerivative(uint256 /*_amount*/) public view returns (uint256)
uint rethPerEth = (10 ** 36) / poolPrice(); uint256 minOut = ((((rethPerEth * msg.value) / 10 ** 18) * ((10 ** 18 - maxSlippage))) / 10 ** 18);
There's an extra set of parentheses around 10**18 - maxSlippage which makes it a little harder to follow. So it should be:
uint256 minOut = ((((rethPerEth * msg.value) / 10 ** 18) * (10 ** 18 - maxSlippage)) / 10 ** 18);
You could also substitute in the rethPerEth expression and cancel terms so that the formula for minOut is simply:
uint256 minOut = msg.value * (10 ** 18 - maxSlippage) / poolPrice()
This also eliminates an instance of division before multiplication, so it would improve the calculation's precision.
Best practice is to set a concrete version pragma for deployment (i.e. =0.8.13 rather than ^0.8.13)
This ensures that you know which compiler version was actually used for deployment and allows you to use that version consistently across the codebase.
#0 - c4-sponsor
2023-04-10T19:20:43Z
toshiSat marked the issue as sponsor acknowledged
#1 - c4-judge
2023-04-24T17:53:58Z
Picodes marked the issue as grade-b