You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since the variable being compared is uint, the value will never be below 0, thus checking if != 0 is sufficient and more gas efficient.
I suggest changing from > 0 to != 0 in these lines:
Cally.sol:170require(durationDays>0,"durationDays too small");Cally.sol:283if(feeRate>0){
Unecessary initialization of variables with default values
Uninitialized variables are assigned with a default value depending on its type (0 for uint256). Thus, explicitly initializing a variable with its default value costs unnecesary gas.
Comparing to a constant (true or false) is a bit more expensive than directly checking the boolean value.
Considering changing the following lines from var == false to !var:
Cally.sol:217require(vault.isExercised==false,"Vault already exercised");Cally.sol:220require(vault.isWithdrawing==false,"Vault is being withdrawn");Cally.sol:328require(vault.isExercised==false,"Vault already exercised");
Unchecking arithmetic operations that cannot underflow/overflow
Since Solidity v0.8.0, all arithmetic operations come with implicit overflow and underflow checks. In some instances, an overflow/underflow is impossible, such as:
A check is in place before the arithmetic operation
The value realistically cannot overflow, such as amount of ETH sent
As such, gas can be saved by using an unchecked block to remove the implicit checks:
Some variables are defined even though they are only referenced once in their respective functions. Not defining these variables can help to reduce gas cost and contract size.
Cally.sol:223-224:
// Original codeuint256premium=getPremium(vaultId);require(msg.value>=premium,"Incorrect ETH amount sent");// Change to:require(msg.value>=getPremium(vaultId),"Incorrect ETH amount sent");
Cally.sol:227-228:
// Original codeuint32auctionStartTimestamp=vault.currentExpiration;require(block.timestamp>=auctionStartTimestamp,"Auction not started");// Change to:require(block.timestamp>=vault.currentExpiration,"Auction not started");
Cally.sol:333-334:
// Original codeuint256optionId=vaultId+1;_burn(optionId);// Change to:_burn(vaultId+1);
Cally.sol:395-396:
// Original codeVaultmemoryvault=_vaults[vaultId];returnpremiumOptions[vault.premiumIndex];// Change to:returnpremiumOptions[_vaults[vaultId].premiumIndex];
Cally.sol:444-445:
// Original codeboolisVaultToken=id%2!=0;if(isVaultToken){// Change to:if(id%2!=0){
buyOption() can be optimized when an invalid vaultId is provided
Cally.sol:208-214:
Vaultmemoryvault=_vaults[vaultId];// vaultId should always be oddrequire(vaultId%2!=0,"Not vault type");// check vault existsrequire(ownerOf(vaultId)!=address(0),"Vault does not exist");
In buyOption(), the function should check if vaultId is valid before fetching vault from storage. This would reduce gas cost when an invalid vaultId is provided.
Consider fetching vault from storage after parameter validation:
// vaultId should always be oddrequire(vaultId%2!=0,"Not vault type");// check vault existsrequire(ownerOf(vaultId)!=address(0),"Vault does not exist");Vaultmemoryvault=_vaults[vaultId];
exercise() can be optimized
In Cally.sol:278-279, _vaults[vaultId].isExercised can be updated directly instead of using vault:
// Original codevault.isExercised=true;_vaults[vaultId]=vault;// Change to:_vaults[vaultId].isExercised=true;
Use custom errors instead of revert strings
Since Solidity v0.8.4, custom errors should be used instead of revert strings due to:
Starting from Solidity v0.8.4, there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. Until now, you could already use strings to give more information about failures (e.g., revert("Insufficient funds.");), but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them.
Custom errors can be defined using of the error statement, both inside or outside of contracts.
Instances where custom errors can be used instead:
CallyNft.sol:15require(to!=address(0),"INVALID_RECIPIENT");CallyNft.sol:16require(_ownerOf[id]==address(0),"ALREADY_MINTED");CallyNft.sol:36require(owner!=address(0),"ZERO_ADDRESS");CallyNft.sol:42require(to!=address(0),"INVALID_RECIPIENT");Cally.sol:167require(premiumIndex<premiumOptions.length,"Invalid premium index");Cally.sol:168require(dutchAuctionStartingStrikeIndex<strikeOptions.length,"Invalid strike index");Cally.sol:169require(dutchAuctionReserveStrike<strikeOptions[dutchAuctionStartingStrikeIndex],"Reserve strike too small");Cally.sol:170require(durationDays>0,"durationDays too small");Cally.sol:171require(tokenType==TokenType.ERC721||tokenType==TokenType.ERC20,"Invalid token type");Cally.sol:211require(vaultId%2!=0,"Not vault type");Cally.sol:214require(ownerOf(vaultId)!=address(0),"Vault does not exist");Cally.sol:217require(vault.isExercised==false,"Vault already exercised");Cally.sol:220require(vault.isWithdrawing==false,"Vault is being withdrawn");Cally.sol:224require(msg.value>=premium,"Incorrect ETH amount sent");Cally.sol:228require(block.timestamp>=auctionStartTimestamp,"Auction not started");Cally.sol:260require(optionId%2==0,"Not option type");\
Cally.sol:263require(msg.sender==ownerOf(optionId),"You are not the owner");Cally.sol:269require(block.timestamp<vault.currentExpiration,"Option has expired");Cally.sol:272require(msg.value==vault.currentStrike,"Incorrect ETH sent for strike");Cally.sol:304require(vaultId%2!=0,"Not vault type");Cally.sol:307require(msg.sender==ownerOf(vaultId),"You are not the owner");Cally.sol:320require(vaultId%2!=0,"Not vault type");Cally.sol:323require(msg.sender==ownerOf(vaultId),"You are not the owner");Cally.sol:328require(vault.isExercised==false,"Vault already exercised");Cally.sol:329require(vault.isWithdrawing,"Vault not in withdrawable state");Cally.sol:330require(block.timestamp>vault.currentExpiration,"Option still active");Cally.sol:353require(vaultId%2!=0,"Not vault type");Cally.sol:354require(msg.sender==ownerOf(vaultId),"Not owner");Cally.sol:436require(from==_ownerOf[id],"WRONG_FROM");Cally.sol:437require(to!=address(0),"INVALID_RECIPIENT");Cally.sol:438-441require(msg.sender==from||isApprovedForAll[from][msg.sender]||msg.sender==getApproved[id],"NOT_AUTHORIZED");Cally.sol:456require(_ownerOf[tokenId]!=address(0),"URI query for NOT_MINTED token");
The text was updated successfully, but these errors were encountered:
Gas Optimizations
Use
!= 0
instead of> 0
for unsigned integersSince the variable being compared is
uint
, the value will never be below 0, thus checking if!= 0
is sufficient and more gas efficient.I suggest changing from
> 0
to!= 0
in these lines:Unecessary initialization of variables with default values
Uninitialized variables are assigned with a default value depending on its type (
0
foruint256
). Thus, explicitly initializing a variable with its default value costs unnecesary gas.I suggest changing
Cally.sol:94-95
from:to
Consider declaring constants as non-public to save gas
If a constant is not used outside of its contract, declaring it as
private
orinternal
instead ofpublic
can save gas.I suggest changing the visibility of the following from
public
tointernal
orprivate
:Boolean comparisons
Comparing to a constant (
true
orfalse
) is a bit more expensive than directly checking the boolean value.Considering changing the following lines from
var == false
to!var
:Unchecking arithmetic operations that cannot underflow/overflow
Since Solidity v0.8.0, all arithmetic operations come with implicit overflow and underflow checks. In some instances, an overflow/underflow is impossible, such as:
As such, gas can be saved by using an unchecked block to remove the implicit checks:
Below are instances that can be left
unchecked
:Unnecessary definition of variables in
Cally.sol
Some variables are defined even though they are only referenced once in their respective functions. Not defining these variables can help to reduce gas cost and contract size.
Cally.sol:223-224
:Cally.sol:227-228
:Cally.sol:333-334
:Cally.sol:395-396
:Cally.sol:444-445
:buyOption()
can be optimized when an invalidvaultId
is providedCally.sol:208-214
:In
buyOption()
, the function should check ifvaultId
is valid before fetchingvault
from storage. This would reduce gas cost when an invalidvaultId
is provided.Consider fetching
vault
from storage after parameter validation:exercise()
can be optimizedIn
Cally.sol:278-279
,_vaults[vaultId].isExercised
can be updated directly instead of usingvault
:Use custom errors instead of revert strings
Since Solidity v0.8.4, custom errors should be used instead of revert strings due to:
Taken from Custom Errors in Solidity:
Custom errors can be defined using of the
error
statement, both inside or outside of contracts.Instances where custom errors can be used instead:
The text was updated successfully, but these errors were encountered: