When calling Vault memory vault = _vaults[vaultId]; all the struct is read from storage to memory. If we are interested in only some values we can use Vault storage vault = _vaults[vaultId]; which saves a reference to storage, meaning that SLOADs happen later only for the value we access.
These are all instances where it can save gas (see @audit comments for diff)
function buyOption(uint256 vaultId) external payable returns (uint256 optionId) {
Vault storage vault = _vaults[vaultId]; //@audit from memory to storage
// vaultId should always be odd
require(vaultId % 2 != 0, "Not vault type");
// check vault exists
require(ownerOf(vaultId) != address(0), "Vault does not exist");
// check that the vault still has the NFTs as collateral
require(vault.isExercised == false, "Vault already exercised");
// check that the vault is not in withdrawing state
require(vault.isWithdrawing == false, "Vault is being withdrawn");
// check enough eth was sent to cover premium
uint256 premium = getPremium(vaultId);
require(msg.value >= premium, "Incorrect ETH amount sent");
// check option associated with the vault has expired
uint32 auctionStartTimestamp = vault.currentExpiration;
require(block.timestamp >= auctionStartTimestamp, "Auction not started");
// set new currentStrike
//@audit also updates storage
vault.currentStrike = getDutchAuctionStrike(
strikeOptions[vault.dutchAuctionStartingStrikeIndex],
vault.currentExpiration + AUCTION_DURATION,
vault.dutchAuctionReserveStrike
);
// set new expiration
//@audit also updates storage
vault.currentExpiration = uint32(block.timestamp) + (vault.durationDays * 1 days);
//@audit no needed - already updated
// update the vault with the new option expiration and strike
//_vaults[vaultId] = vault;
// force transfer the vault's associated option from old owner to new owner
// option id for a respective vault is always vaultId + 1
optionId = vaultId + 1;
_forceTransfer(msg.sender, optionId);
// increment vault beneficiary's unclaimed premiums
address beneficiary = getVaultBeneficiary(vaultId);
ethBalance[beneficiary] += msg.value;
emit BoughtOption(optionId, msg.sender, vault.token);
}
Usage of
storage
instead ofmemory
can save gasWhen calling
Vault memory vault = _vaults[vaultId];
all the struct is read from storage to memory. If we are interested in only some values we can useVault storage vault = _vaults[vaultId];
which saves a reference to storage, meaning that SLOADs happen later only for the value we access.These are all instances where it can save gas (see
@audit
comments for diff)getPremium
buyOption
exercise
withdraw
L325