Track 4 · Solidity foundations · lesson 7

Arrays and structs

10 min


Mappings answer "what is the value for this key?". Arrays answer "what have I got, and how many?".

uint256[] public scores;   // grows and shrinks
uint256[5] public fixedScores;  // exactly five, forever

Dynamic arrays support .push(), .pop() and .length. Fixed-size ones support none of that, and are cheaper because their size is known at compile time.

Scoreboard.solRepair
Loading editor…
total() should add up every score, not just the first.
Run the code to see what happens.
Nudge
`count` is right, so pushing works. Look at what `total` actually returns.
Show me the approach
`scores[0]` is one element. You need to walk the whole array and keep a running sum.
Show me the code
Declare `uint256 sum = 0;`, loop `for (uint256 i = 0; i < scores.length; i++)`, add `scores[i]` to sum, return sum.
Explain the solution
Loops over storage arrays are correct here but dangerous in production: gas grows with the array, and an array that grows without bound eventually makes the function cost more than a block allows. Contracts have been frozen exactly this way.

The loop you just wrote is a liability

That for loop is correct, and in production it is a genuine hazard.

Gas grows with the number of elements. Ten scores is nothing. Ten thousand is a function that costs more gas than a block permits — at which point it can never be called again, by anyone, ever.

The contract is not broken. It is frozen, permanently, and no upgrade can retrieve funds it is holding.

The habit to build: never loop over an array that anyone else can grow. If strangers can call add(), your loop has an attacker-controlled length. Keep a running total instead, or make each user pull their own share.

Predict

A charity contract loops over all donors to pay them a refund. What could an attacker do?

Choose one answer

Structs

A struct groups related fields under one name:

struct Task {
    string title;
    bool done;
    address owner;
}

Task[] public tasks;
mapping(uint256 => Task) public taskById;

Structs are how you avoid five parallel arrays that must be kept in step — a pattern that goes wrong the first time one of them is updated and another is not.

Check

Why is `uint256[5]` cheaper than `uint256[]`?

Choose one answer

Worth remembering

  • Dynamic arrays support push, pop and length; fixed-size arrays are cheaper but cannot change size.
  • Looping over an array costs gas proportional to its length.
  • Never loop over an array that other people can grow — that is a denial-of-service waiting to happen.
  • Prefer the pull pattern: let each user claim their own share.
  • Structs group related fields and prevent parallel arrays drifting out of step.