Gas optimization - #6
Conversation
| @@ -54,10 +57,10 @@ contract GrtLiquidityWallet is OwnableUpgradeable, UUPSUpgradeable { | |||
| address to, | |||
There was a problem hiding this comment.
@tcoratger do you think it's valid to check if the address is zero for token and to params?
There was a problem hiding this comment.
@juniormp Yes we can do that to be sure that there is no mistake on this side!
- No payment with a wrong token (zero address) is valid.
- No payment to a zero address. It is unlikely that Lisa gave a payment address 0 but it is always good to check it: in this case the procedure cancels.
| revert ZeroAddressIsNotAllowed(); | ||
| if(!_offers[offerId].isActive) | ||
| revert OfferInactive(); | ||
| (bool sent, ) = address(this).call{value: msg.value}(""); |
There was a problem hiding this comment.
Maybe we can move this call to the bottom of the function to protect against reentrancy ?
And also to follow Solidity security Guidelines with Checks-Effects-Interactions pattern.
https://docs.soliditylang.org/en/v0.6.11/security-considerations.html
There was a problem hiding this comment.
@juniormp I understand your point here but I don't think it applies in this case.
You point to the fact that an attacker could call this function recursively and since the rest of the calculations would not yet be finished, he could then call the function ten times.
- First, in any case, the funds are transferred to our smart contract and not to an external account, so this attack would be rather beneficial for us :)
- Then, I think it is important to keep this call here because this allows us to first make the deposit on our contract and then the following calculations (in the event that the deposit fails everything is canceled afterwards). Whereas if we position this call at the end, it is possible that all the calculations are done then that the deposit fails at the end and in this case it can cause a bug on our side.
@SAPikachu Maybe you have a better opinion here?
|
@juniormp Can you have a look at all the In this context, your This is for our final user to read a proper sentence rather that a function name like |
@tcoratger makes sense. |
@juniormp Not obviously, there is also this option with an explicit message (to be seen in terms of transaction costs): On my side, I'm more used to seeing |
I think the same. The |
4d8bdc7 to
6b9a6ed
Compare
| "Grindery wallet: insufficient balance." | ||
| ); | ||
| if(address(this).balance < amount) | ||
| revert InsufficientBalance(); |
There was a problem hiding this comment.
@juniormp Like for the other revert, it would be better to use a message in the form of a string that can be read directly by an average user who is not necessarily familiar with Solidity, like this example, WDT?
There was a problem hiding this comment.
@juniormp Can you have a look at this part when you have time so that we can merge before the audit (17 April)?
| @@ -54,10 +57,10 @@ contract GrtLiquidityWallet is OwnableUpgradeable, UUPSUpgradeable { | |||
| address to, | |||
There was a problem hiding this comment.
@juniormp Yes we can do that to be sure that there is no mistake on this side!
- No payment with a wrong token (zero address) is valid.
- No payment to a zero address. It is unlikely that Lisa gave a payment address 0 but it is always good to check it: in this case the procedure cancels.
| revert ZeroAddressIsNotAllowed(); | ||
| if(!_offers[offerId].isActive) | ||
| revert OfferInactive(); | ||
| (bool sent, ) = address(this).call{value: msg.value}(""); |
There was a problem hiding this comment.
@juniormp I understand your point here but I don't think it applies in this case.
You point to the fact that an attacker could call this function recursively and since the rest of the calculations would not yet be finished, he could then call the function ten times.
- First, in any case, the funds are transferred to our smart contract and not to an external account, so this attack would be rather beneficial for us :)
- Then, I think it is important to keep this call here because this allows us to first make the deposit on our contract and then the following calculations (in the event that the deposit fails everything is canceled afterwards). Whereas if we position this call at the end, it is possible that all the calculations are done then that the deposit fails at the end and in this case it can cause a bug on our side.
@SAPikachu Maybe you have a better opinion here?
| event LogSetStatusOffer(bytes32 indexed _idOffer, bool indexed _isActive); | ||
|
|
||
| function setChainIdOffer(bytes32 offerId, uint256 chainId) external { | ||
| modifier isOwner(Offer memory offer) { |
There was a problem hiding this comment.
@juniormp A comment for detail but can you just change the name of this function to make it more explicit? Owner is already associated with a condition of the contract ownable and so this can be confusing when reading :)
|
|
||
| function setTokenOffer(bytes32 offerId, address token) external { | ||
| function setTokenOffer(bytes32 offerId, address token) external isOwner(_offers[offerId]) { | ||
| require( |
There was a problem hiding this comment.
@juniormp If we have the isOwner modifier, is there a reason to keep the require? I think that's a duplication, right?
GrtPool
Before gas optimization.
After gas optimization.
Savings
Methods
setIsActive: 33873 - 33735 = 138 gassetOffer: 165779 - 165628 = 151 gasdepositETHAndAcceptOffer: 196657 - 173566 = 23091 gasapprove: 59656 - 46234 = 13422 gasmint: 59656 - 59656 = 0 gasDeployment
GrtPool: 1979188 - 1734279 = 244909 gasERC20Example: 669119 - 669119 = 0 gasGrtOffer
before gas optimization.
before gas optimization.
Savings
Methods
setChainIdOffer: 35765 - 35729 = 36 gassetIsActive: 33873 - 33735 = 138 gassetMaxPriceLimit: 37303 - 37245 = 58 gassetMinPriceLimit: 37344 - 37286 = 58 gassetOffer: 165780 - 165629 = 151 gassetTokenOffer: 36136 - 36069 = 67 gasapprove: 39127 - 39127 = 0 gasmint: 55998 - 55998 = 0 gasDeployment
GrtPool: 1734279 - 1734279 = 0 gasERC20Example: 669119 - 669119 = 0 gas