Skip to content

Save gas by writing to storage once rather than twice in .updateOffer() #46

Open
@ghost

Description

Description

.updateOffer() updates both the offer.total property and the offer.expiresAt property of an offer struct.

However, it writes each of these changes in two separate writes to storage.

We can save gas by making a single write to storage, rather than two.

Scenario

Every time that .updateOffer() is called to raise the price of an offer, we waste gas by writing to storage twice rather than once.

Impact

Medium: It costs 5,000 gas for each write to storage. If we do a single write to storage (and pack the properties more efficiently as mentioned in Issue #45), we can save 5,000 gas every single time the function is run.

Reproduction

(1) In .updateOffer(), we retrieve a pointer to the offer struct that we will update:

Offer storage offer = tokenIdToOffer[_tokenId];

(2) If msg.value is greater than zero, we update offer.total. Since this is a pointer to storage that we are updating, this costs 5,000 gas, a very expensive operation gas-wise:

offer.total += uint128(msg.value);

(3) Only after that do we update a different property of the same struct in storage, again costing us another 5,000 gas:

offer.expiresAt = uint64(newExpiresAt);

Fix

Instead, we can make both changes locally, and then do a single write to storage. If we combine this with the better struct-packing from Issue #45, we will save 5,000 gas on every write. Change this:

uint256 newExpiresAt = now + globalDuration;

// Check if the caller wants to raise the offer as well
if (msg.value > 0) {
    // Set the new price
    offer.total += uint128(msg.value);
}

offer.expiresAt = uint64(newExpiresAt);

to this:

uint256 newExpiresAt = now + globalDuration;

Offer updatedOffer = offer;

// Check if the caller wants to raise the offer as well
if (msg.value > 0) {
    // Set the new price
    updatedOffer.total += uint128(msg.value);
}

updatedOffer.expiresAt = uint64(newExpiresAt);

offer = updatedOffer;

We would also need to reorder the properties of the Offer struct, as outlined in Issue #45.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions