Structs

  • Structs can be declared outside of a contract and imported in another contract.

  • Sometimes you need a more complex data type.

  • For this, Solidity provides structs, allowing you to create more complicated data types that have multiple properties.

struct People {
  uint256 favoriteNumber;
  string name;
}

// create a New Person:
People public person = People({favoriteNumber: 7, name: "Eridian"});

Declaring and Importing Struct

File that the struct is declared in
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
// This is saved as 'StructDeclaration.sol'

struct Todo {
    string text;
    bool completed;
}

Passing structs as arguments

  • You can pass a storage pointer to a struct as an argument to a private or internal function.

  • This is useful, for example, for passing around our Zombie structs between functions.

  • This way we can pass a reference to our person into a function instead of passing in a person ID and looking it up.

Struct packing to save gas

  • There are other types of uints: uint8, uint16, uint32, etc.

  • Normally there's no benefit to using these sub-types because Solidity reserves 256 bits of storage regardless of the uint size.

    • For example, using uint8 instead of uint (uint256) won't save you any gas.

  • But there's an exception to this: inside structs.

  • If you have multiple uints inside a struct, using a smaller-sized uintwhen possible will allow Solidity to pack these variables together to take up less storage.

  • For this reason, inside a struct you'll want to use the smallest integer sub-types you can get away with.

  • You'll also want to cluster identical data types together (i.e. put them next to each other in the struct) so that Solidity can minimize the required storage space.

  • For example, a struct with fields uint c; uint32 a; uint32 b; will cost less gas than a struct with fields uint32 a; uint c; uint32 b; because the uint32 fields are clustered together.

Example

Last updated