Curriculum·G303 Storage, Upgrades, and Trust·about 34 min

How state is really laid out

By the end of this lesson you can

  • →Explain that a contract is its stored state as well as its code, laid out in numbered storage slots
  • →Describe how a flaw in Team Finance's migration logic let an attacker drain about 15.8 million dollars
  • →Reason that migrations and upgrades are the moment stored assumptions are rewritten and can be mis-mapped
  • →Treat storage layout as ground a builder must understand before moving or reinterpreting state

Graduate · enrolled learners

This lesson opens with Team Finance, October 2022.

What happened
Team Finance offered token-locking and vesting services, holding projects' locked Uniswap v2 liquidity in its Liquidity Locks contract. A migrate() function let a project move a locked v2 position to Uniswap v3, and it was meant to act only for the owner of the lock being moved. PeckShield found that check could be bypassed by locking any token: the attacker locked a token of their own to obtain a valid lock, and the function did not confirm that the liquidity being migrated was the liquidity that lock held. The attacker then moved other projects' real v2 liquidity into a v3 pair they controlled, set at a skewed price, and kept the leftover the migration refunded, about 15.8 million dollars by Rekt's count on October 27, 2022. Nothing cryptographic was broken and no signing key was stolen. The function had been in scope of Zokyo Security's August 2022 audit. The contract's stored record said what each lock held; the migration acted without checking the request against it.
The decision point
A contract is not only its code but its stored state, held in numbered storage slots whose meaning is defined entirely by the code that reads them, so state has no inherent meaning of its own; it means whatever the current code says it means. Team Finance is the case: a migration that moved locked liquidity from Uniswap v2 to v3 did not check the request against the contract's own stored record of what each lock held, and an attacker who locked a worthless token used that gap to move other projects' liquidity and drain about 15.8 million dollars, without breaking any cryptography. This is why a builder must understand how state is really laid out, in slots, interpreted by code, before moving or reinterpreting it: an upgrade or migration is precisely the operation that rewrites what the stored bytes mean, and the moment the reading code changes but the stored bytes do not, or the bytes are moved without matching the new layout, the contract's assumptions about its own state can be silently false. So the discipline is to treat storage layout as load-bearing ground: know which slot holds which variable, know that the meaning of a slot is only the code's interpretation of it, and treat every migration and upgrade as a dangerous re-mapping of state that must be reasoned through slot by slot, because the state does not carry its meaning with it. Team Finance is what happens when state is moved without being checked against what the stored record says it is: the migration and the lock record disagreed, and the attacker lived in the disagreement.
Recorded loss
$15,800,000

What you will be able to answer

  • →How was Team Finance drained (October 2022)?
  • →What is a contract beyond its code?
  • →Why are migrations and upgrades especially fragile?
  • →How should a builder treat storage layout?

Orientation and Year One are open: anyone can read them without an account. From Year Two onward the lessons are for enrolled learners, because progress through the later years only means anything if it is tracked against a record.

It is free. We do not sell the list and there is nothing to buy at the end of it.

Sources and review

Confidence high·Volatility low·Reviewed 2026-09-17·Owner unassigned

Contested

Rekt puts the October 2022 loss at 15.8 million dollars, about 11.5 million in CAW, 1.7 million in TSUKA, 0.7 million in KNDX and 1.9 million in FEG; Halborn and CoinDesk give about 14.5 million, so accounts differ with the prices used. CoinDesk reported on October 31, 2022 that the attacker, calling themselves a whitehat, had returned about 7 million dollars in DAI, ETH and project tokens to the four projects (Tsuka, Kondux, FEG and CAW) and said they would keep 10 percent as a bounty. The lesson uses the migration mechanism, not a precise net loss.

The post-mortems describe a missing validation in migrate(): the authorization check passed for any lock, and the function did not compare the lock's stored token with the liquidity being moved. They do not describe a storage-layout collision. Reading the case as a migration that acted without checking the contract's own stored record is this lesson's reading, and the slot-layout material around it is general teaching from the Solidity documentation, not a finding of the post-mortems.