简体   繁体   中英

Bit operators and gas saving on solidity

I've only started looking into solidity like a month ago and I'm trying to understand and run some tests on reducing gas consumption. I've read this ( https://medium.com/@novablitz/storing-structs-is-costing-you-gas-774da988895e ) and it seems like a super interesting way of reducing the number of storage/read calls but when I try this I'm getting quite different results. Not sure if I'm doing something incorrectly or if maybe solidity recently updated the bit operators but it doesn't seem to be working. Using solidity version 0.8.9.

My code:

uint224 entryRange = uint224(uint160(msg.sender));
entryRange |= ref.entryCount<<160;
entryRange |= (ref.entryCount + amount)<<192;
ref.raffleEntries.push(entryRange);

entryCount is a uint32 so if I understand correctly, address takes up 160 bytes, so can be converted to a uint160, each uint32 is 32 bytes on in total I would need 224 bytes. So a uint224 should be enough to fit my data.

My read is as follows:

console.log(address(uint160(entryRange)));
console.log(uint32(entryRange>>160));
console.log(uint32(entryRange>>192));

The result is, the address is being read nicely but the two uints are always 0. I've tried to place console logs in the storing and I noticed the result doesn't change so:

    uint224 entryRange = uint224(uint160(msg.sender));
    console.log(entryRange);
    entryRange |= ref.entryCount<<160;
    entryRange |= (ref.entryCount + amount)<<192;
    ref.raffleEntries.push(entryRange);
    console.log(entryRange);

This outputs twice the same value almost like the |= is simply not doing anything, either that or the console.log is only taking the result due to some... async if any? even tho I believe that's not the case in solitidy.

Never the less, on the read I'm getting 0 for both uints and a correct address. Any ideas what the issue could be here?

Thanks, João.

I hope you were able to solve the problem. If not, entryCount needs to be converted to uint224 before being left shifted. Otherwise, it's like shifting a 4 bit number 4 times or more.

1101 << 4:
1010
0100
1000
0000

As you can see all the info is lost after shifting 4 times. Same thing happens when shifting entryCount 160 or 192 times and entryRange is bitwise ORed with 0 which has no effect. That is why entryRange only has the address information.

entryRange |= uint224(ref.entryCount)<<160;
entryRange |= uint224(ref.entryCount + amount)<<192;

This should solve the problem of getting 0 for the other two uints.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM