Skip to content
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

Save gas by packing total and expiresAt into the same 256-bit word in the Offer struct #45

Open
ghost opened this issue Nov 19, 2018 · 5 comments
Assignees

Comments

@ghost
Copy link

ghost commented Nov 19, 2018

Description

The Offer struct is composed of two 256-bit words. Since the function .updateOffer() only updates a portion of this struct (the total and the expiresAt portions), we can pack these two properties together to save gas.

Scenario

If the total and the expiresAt properties are placed in the same word, we can save gas by only having to update one 256-bit word rather than two 256-bit words.

As they are currently structured:

The first 256-bit word is:
64 bits of expiresAt
160 bits of bidder
16 bits of offerCut
The first 16 bits of total

The second 256-bit word is:
The remaining 112 bits of total
128 bits of unsuccessfulFee

So total and expiresAt are not in the same word.

According to my suggestion, it would be structured as:

The first 256-bit word would be:
64 bits of expiresAt
128 bits of total
The first 64 bits of bidder

The second 256-bit word would be:
The remaining 96 bits of bidder
16 bits of offerCut
128 bits of unsuccessfulFee

Impact

Gas Savings: We can save gas by only paying 5000 gas to update one 256-bit word rather than 10,000 gas to update 256-bit words.

Reproduction

Observe that the expiresAt property is in the first 256-bit word of the Offer struct, whereas the total property is in the second 256-bit word:

struct Offer {
        // Time when offer expires
        uint64 expiresAt;
        // Bidder The creator of the offer
        address bidder;
        // Offer cut in basis points, which ranges from 0-10000.
        // It's the cut that CFO takes when the offer is successfully accepted by the owner.
        // This is stored in the offer struct so that it won't be changed if COO updates
        // the `offerCut` for new offers.
        uint16 offerCut;
        // Total value (in wei) a bidder sent in msg.value to create the offer
        uint128 total;
        // Fee (in wei) that CFO takes when the offer is expired or overbid.
        // This is stored in the offer struct so that it won't be changed if COO updates
        // the `unsuccessfulFee` for new offers.
        uint128 unsuccessfulFee;
    }

Fix

Reorder the struct to have the expiresAt property and the total property in the same half of the struct:

struct Offer {
        // Time when offer expires
        uint64 expiresAt;
        // Total value (in wei) a bidder sent in msg.value to create the offer
        uint128 total;
        // Bidder The creator of the offer
        address bidder;
        // Offer cut in basis points, which ranges from 0-10000.
        // It's the cut that CFO takes when the offer is successfully accepted by the owner.
        // This is stored in the offer struct so that it won't be changed if COO updates
        // the `offerCut` for new offers.
        uint16 offerCut;
        // Fee (in wei) that CFO takes when the offer is expired or overbid.
        // This is stored in the offer struct so that it won't be changed if COO updates
        // the `unsuccessfulFee` for new offers.
        uint128 unsuccessfulFee;
    }
@sunsetlover
Copy link

Aren’t those variables already in the same 256 bit word? They just have to be in the same word I think, not next to each other in that word.

@ghost
Copy link
Author

ghost commented Nov 19, 2018

Nope! The offer struct falls across two 256-bit words. As they originally structured it:

The first 256-bit word is:
64 bits of expiresAt
160 bits of bidder
16 bits of offerCut
The first 16 bits of total

The second 256-bit word is:
The remaining 112 bits of total
128 bits of unsuccessfulFee

So not only are they not next to each other in memory, they are not in the same word.

According to my suggestion, it would be structured as:

The first 256-bit word would be:
64 bits of expiresAt
128 bits of total
The first 64 bits of bidder

The second 256-bit word would be:
The remaining 96 bits of bidder
16 bits of offerCut
128 bits of unsuccessfulFee

@sunsetlover
Copy link

Ah thanks. I forgot a unit conversion from 20 bytes to 160 bits for the address. Thanks. Anyway, as I’ve stated here, this doesn’t help save gas anyway: #46 (comment)

@ghost ghost changed the title Save gas by packing total and expiresAt next to each other in the Offer struct Save gas by packing total and expiresAt into the same 256-bit word in the Offer struct Nov 19, 2018
@hwrdtm
Copy link
Contributor

hwrdtm commented Nov 19, 2018

Thanks @michaelKim4736 for the feedback! We will take this into consideration.

@hwrdtm hwrdtm self-assigned this Nov 19, 2018
@arthcmr
Copy link
Contributor

arthcmr commented Nov 27, 2018

Thanks for your participation, @michaelKim4736! Our team has reviewed your submission and decided to reject the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants