Platform: Code4rena
Start Date: 05/01/2023
Pot Size: $90,500 USDC
Total HM: 55
Participants: 103
Period: 14 days
Judge: Picodes
Total Solo HM: 18
Id: 202
League: ETH
Rank: 33/103
Findings: 1
Award: $363.16
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: c3phas
Also found by: 0x1f8b, 0xAgro, 0xSmartContract, 0xackermann, 0xkato, Aymen0909, Bnke0x0, CloudX, IllIllI, PaludoX0, Rageur, Rahoz, RaymondFam, ReyAdmirado, Rolezn, SadBase, SaeedAlipoor01988, caventa, chaduke, chrisdior4, fatherOfBlocks, fs0c, kaden, nogo, pfapostol, shark, synackrst
363.1567 USDC - $363.16
source: 2023-01-astaria/src/CollateralToken.sol
The _file(address) internal {}
method uses the data
variable on line 213 defined with the memory
type.
This data
variable is not modified in the code, so it can be declared with the calldata
type.
You could save an average of 547 gas per execution.
| | function name | min | avg | median | max | # calls | | --------------------------- | ------------- | ------ | ------ | ------ | ------ | ------- | | no optimization | fileBatch | 32740 | 34671 | 34671 | 36603 | 2 | | with optimization | fileBatch | 32111 | 34218 | 34218 | 36325 | 2 |
The liquidatorNFTClaim(OrderParameters) external {}
method uses a read from the storage on line 117 and 124 to perform a comparison in an if
.
We could optimize this part of the code by reading only once to create a memory variable. This memory variable can then be used to perform necessary comparisons with less gas consumption. With this modification, we can save 140 of gas per execution.
| | function name | min | avg | median | max | # calls | | ---------------------- | ------------- | ------ | ------ | ------ | ------ | ------- | | no optimization | liquidatorNFT claim | 45980 | 45980 | 45980 | 45980 | 1 | | with optimization | liquidatorNFT claim | 45840 | 45840 | 45840 | 45840 | 1 |
The liquidatorNFTClaim(OrderParameters) external {}
method, on line number 137 and 138, the variables address tokenContract
y uint256 tokenId
are declared
but not used in the code. By removing these declarations, we can get an improvement of 17 units of gas per execution and 200 units of gas in deployment.
| | function name | min | avg | median | max | # calls | deployment cost | deployment size | | ---------------------- | ------------- | ------ | ------ | ------ | ------ | ------- | ---------------- | -------------- | | no optimization | liquidatorNFT claim | 45980 | 45980 | 45980 | 45980 | 1 | 3502698 | 17719 | | with optimization | liquidatorNFT claim | 45963 | 45963 | 45963 | 45963 | 1 | 3502498 | 17718 |
The releaseToAddress(uint256 collateralId, address releaseTo) public {}
method has a redundant check on line 338, as the same check is performed on line 334 through a modifier. By removing this redundant check, we can get an improvement of 348 units of gas per execution in each execution and 11408 units of gas in deployment.
| | function name | min | avg | median | max | # calls | deployment cost | deployment size | | ---------------------- | ------------- | ------ | ------ | ------ | ------ | ------- | ---------------- | -------------- | | no optimization | releaseToAddress | 34537 | 34537 | 34537 | 34537 | 1 | 3502698 | 17719 | | with optimization | releaseToAddress | 34189 | 34189 | 34189 | 34189 | 1 | 3491290 | 17662 |
The function releaseToAddress(uint256 collateralId, address releaseTo) public {}
method on line number 342 the variable address tokenContract
are declared but not used in the code. By removing these declarations, we can get an improvement of 21 units of gas per execution and 409 units of gas in deployment.
| function name | min | avg | median | max | # calls | deployment cost | deployment size | | -------------------------------------------- | --------: | --------: | --------: | --------: | ------: | --------------: | --------------: | | releaseToAddress | 34537 | 34537 | 34537 | 34537 | 1 | 3502698 | 17719 | | releaseToAddress | 34516 | 34516 | 34516 | 34516 | 1 | 3503107 | 17721 |
source: 2023-01-astaria/src/AstariaRouter.sol
The _file(address) internal {}
method uses the data
variable on line 280 defined with the memory
type.
This data
variable is not modified in the code, so it can be declared with the calldata
type.
You could save 972 gas per execution.
| function name | min | avg | median | max | # calls | | -------------------------------------------- | --------: | --------: | --------: | --------: | ------: | | fileBatch | 84449 | 84449 | 84449 | 84449 | 1 | | fileBatch | 83477 | 83477 | 83477 | 83477 | 1 |
source: 2023-01-astaria/src/LienToken.sol
The _file(address) internal {}
method uses the data
variable on line 84 defined with the memory
type.
This data
variable is not modified in the code, so it can be declared with the calldata
type.
You could save 241 gas per execution.
| function name | min | avg | median | max | # calls | | -------------------------------------------- | --------: | --------: | --------: | --------: | ------: | | file | 28218 | 31193 | 31193 | 34169 | 2 | | file | 27977 | 30952 | 30952 | 33928 | 2 |
source: 2023-01-astaria/src/ClearingHouse.sol
The _execute(address, address, uint256, uint256) internal {}
method uses the variable payment
. We reuse and rename the variable to balance
, with the intention of saving storage reads on lines 160 and 163.
You could save 721 gas per execution.
| function name | min | avg | median | max | # calls | | -------------------------------------------- | --------: | --------: | --------: | --------: | ------: | | safeTransferFrom | 61408 | 100185 | 83728 | 207900 | 2 | | safeTransferFrom | 60687 | 99584 | 83007 | 207179 | 2 |
Code example:
{ ... balance = ERC20(paymentToken).balanceOf(address(this)); if (balance > 0) { ERC20(paymentToken).safeTransfer( ASTARIA_ROUTER.COLLATERAL_TOKEN().ownerOf(collateralId), balance ); } ... }
source: 2023-01-astaria/src/PublicVault.sol
Remove variable declaration to save memory expasion cost. You could avoid the timeToEnd
variable declaration due to the code could avoid it without loosing readable experience.
You will save 23 gas units per execution and 1209 for deployment
| function name | min | avg | median | max | # calls | | -------------------------------------------- | --------: | --------: | --------: | --------: | ------: | | updateVaultAfterLiquidation | 10589 | 10589 | 10589 | 10589 | 1 | | updateVaultAfterLiquidation | 10576 | 10576 | 10576 | 10576 | |
Please take a look to refactored method in case you consider this properly:
function updateVaultAfterLiquidation( uint256 maxAuctionWindow, AfterLiquidationParams calldata params ) public onlyLienToken returns (address withdrawProxyIfNearBoundary) { VaultData storage s = _loadStorageSlot(); _accrue(s); unchecked { _setSlope(s, s.slope - params.lienSlope.safeCastTo48()); } if (s.currentEpoch != 0) { transferWithdrawReserve(); } uint64 lienEpoch = getLienEpoch(params.lienEnd); _decreaseEpochLienCount(s, lienEpoch); if (timeToEpochEnd(lienEpoch) < maxAuctionWindow) { _deployWithdrawProxyIfNotDeployed(s, lienEpoch); withdrawProxyIfNearBoundary = s.epochData[lienEpoch].withdrawProxy; WithdrawProxy(withdrawProxyIfNearBoundary).handleNewLiquidation( params.newAmount, maxAuctionWindow ); } }
#0 - c4-judge
2023-01-25T23:21:43Z
Picodes marked the issue as grade-a