# Design Pattern Solidity: Stages

Author: Markus Waas

Published: 2020-02-22T06:26:23.000Z

Updated: 2026-09-13T14:25:30.000Z

Source: [https://soliditydeveloper.com/design-pattern-solidity-stages](<https://soliditydeveloper.com/design-pattern-solidity-stages>)

## Compatibility and review

Before you start

The code is a schematic state-machine example: replace the ellipses with application logic before compiling. Stage checks do not replace administrator authorization.

[Official reference](<https://docs.soliditylang.org/en/latest/common-patterns.html#state-machine>)

Closely related to the concept of finite-state machines, this pattern will help you restrict functions in your contract. You will find a lot of situations where it might be useful. Any time a contract should allow function calls only in certain stages. Let's look at an example:

```solidity
contract Pool {
  enum Stages {
        Initialize,
        Contribute,
        Collect
  }
  
  Stages public stage = Stages.Initialize;

  modifier atStage(Stages _stage) {
        require(
            stage == _stage,
            "Wrong pooling stage. Action not allowed."
        );
        _;
   }

  function init(...) external atStage(Stages.Initialize) {
        ...
        stage = Stages.Contribute;
  }

  function contribute(...) external atStage(Stages.Contribute) {
        ...
        if (hasContributionThresholdReached) {
            stage = Stages.Collect;
        }
  }

  function collect(...) external atStage(Stages.Collect) { }
}
```

The pooling contract has three stages:

1. The administrator has to set the parameters using `init()`.
2. Users contribute funds to the pool using `contribute()`.
3. Once sufficient funds are collected, the pool automatically goes into the last stage which then allows users to receive their share of whatever was purchased by the contract using `collect()`.

The staging system keeps a clear separation and access control of functions. Further, having a public `stage` variable makes it clear for the user as well.

The ellipses mark application-specific code, so this is an outline rather than a standalone compilable contract. Also add the appropriate administrator check to `init`: `atStage` controls *when* a function runs, not *who* may run it.
