-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gas optimization #6
base: main
Are you sure you want to change the base?
Conversation
@@ -54,10 +57,10 @@ contract GrtLiquidityWallet is OwnableUpgradeable, UUPSUpgradeable { | |||
address to, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
if(destAddr == address(0)) | ||
revert ZeroAddressIsNotAllowed(); | ||
if(!_offers[offerId].isActive) | ||
revert OfferInactive(); | ||
(bool sent, ) = address(this).call{value: msg.value}(""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
if(destAddr == address(0)) | ||
revert ZeroAddressIsNotAllowed(); | ||
if(!_offers[offerId].isActive) | ||
revert OfferInactive(); | ||
(bool sent, ) = address(this).call{value: msg.value}(""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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?
@@ -25,56 +25,53 @@ contract GrtOffer is GrtOfferUtils { | |||
); | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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 :)
emit LogSetChainIdOffer(offerId, chainId); | ||
} | ||
|
||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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