Skip to main content

State Machine

The Strategy Framework is built as a State Machine. Where the states are re-entrant. At any point the computer running the code could be turned off (powered down) and on restart, the strategy state machine would pick up where it left off. Such a design makes the the framework very robust to handle SadFlows and errors.

The minimum required states are:

  • INITIALIZATION: This state happens only once in the life of the strategy, at the very beginning. It is used to do any operation that happens only once, like preparing swapping from ETH or Stables into assets of interest for the strategy. This state can be empty and do nothing, but has to be present.
  • COMPLETED: This state does no action. This state allows the system to breath a little bit in between cycles (i.e. uninterruptable sequences). A cycle could be something like a rebalance involving 3 different states: Close Position, Swap Assets back to 50:50, Open Position. That sequence should not be interrupted. However, once that sequence is completed the main can run other things.
  • TEARDOWN: This state is in some way the opposite of the Initialization. This state also happens only once in the life of the strategy, at the very end. This state can be empty and do nothing, but has to be present.
  • TERMINATED: This state indicates that the Teardown has executed and this strategy is terminated for good.

The robustness of the system really comes from our Prepare / Validate / Sadflow design.

Each Action state, i.e. a state performing actions - not just updating internal states or displaying messages - must use the Prepare -> Validate | Sadflow design.

Prepare: The function responsible to preparing (i.e. creating) the Action(s).
Validate: The function responsible to validating that the action executed as intented. For example by looking at the Transaction details (i.e. the receipt) to confirm that the swap amount is what was intented and then update internal accounting accordingly. The only way for the state machine to move on to the next state from an action state is after the validate was successful (returned True).
Sadflow: The function responsible for any sadflow. Actions will fail, transactions will revert, error will occur. In these situations the strategy will enter into a Sadflow.

Each state should be saved in a different python file in the /states/ folder.

The entry function of the state (e.g. close_position(...))will call the handle_state_with_actions() The entry function of the state should have the same name as the state. And then preparestate_name, validate_state_name, sadflowstate_name. This convention makes it very easy to navigate the code of a strategy.

# Example of Close Position state
def close_position(strat: "StrategyDegenLPChaser") -> ActionBundle:
"""
...
"""
return strat.handle_state_with_actions(
prepare_fn=partial(prepare_close_position, strat),
validate_fn=partial(validate_close_position, strat),
sadflow_fn=partial(sadflow_close_position, strat),
next_state=strat.State.SWAP_ASSETS,
)