Pack Rule

Pack variables into the same slot (32 bytes) whenever possible, manual packing is most efficient but least readable, EVM packing is okay, but no packing is the least effificient.

Example

pragma solidity ^0.8.17;

contract Pack {
    uint256 public packedData;
    uint32 public num;
    address public secondAddress;

    // This function packs a uint32 and an address into packedData
    function packData(uint32 data, address addr) external {
        // Shift the address 32 bits to the left and bitwise OR it with the uint32 data
        // This places the address in the higher bits and the uint32 in the lower bits of the uint256
        packedData = (uint256(uint160(addr)) << 32) | uint32(data);
    }

    // This function unpacks the uint32 from packedData
    function unpack() external view returns (uint32, address) {
        // Bitwise AND with a mask to isolate the lower 32 bits
        uint32 number = uint32(packedData & 0xFFFFFFFF);
        address addr = address(uint160(packedData >> 32));
        return (number, addr);
    }

    function storeData(uint32 data, address addr) external{
        num = data;
        secondAddress = addr;
    }

    function getData() external view returns(uint32, address){
        return (num, secondAddress);
    }
}

Calling function storeData and getData would cost 23863 gas and calling function packData and unpack would cost 23807 gas only, proving that packing variables manually saves gas. Although EVM has already packed the variables for the data structure uint32 and address, but manual packing is still the most efficient way.

The same goes for struct ordering.

Test Environment

  • Compiler: solc 0.8.17
  • Testing Framework: Foundry

ETH saved over 100 transactions

100 tx * 30 gwei * 0.000000001 * (909-875) = 0.000102 ~= 0.0001 ETH1

USD Saved over 100 transactions

  • At \$4000 / ETH: \$0.4
  • At \$3000/ETH: \$0.3
  • At \$2000/ETH: \$0.2
  1. Assumed gas price: 30 gwei 

results matching ""

    No results matching ""