Frequently Asked Questions
- What is a finite state machine?
- What can they usefully map to?
- What do states represent?
- How is Fismo different?
- What is a Fismo Machine?
- What’s in a machine configuration?
- What does Fismo.sol actually do?
What is a finite state machine?
The Finite State Machine (FSM) is an abstract “machine” with various states and rules for moving between them. The primary features are:
- A finite number of States, represented in a directed graph.
- The edge connecting one State to another is a Transition.
- Transitions between States are initiated by Actions.
- States can also have associated Guard logic, triggered on exit from or entry to a State, which have the ability to halt a Transition.
What are state machines used for?
As a software pattern, they are frequently used to map processes. A couple of common examples:
- Software installation wizards; a series of forms or choices with validation rules controlling progress.
- The myriad steps in a commercial home loan process, each of which has rules about moving to the next.
- Regular expression parsing.
- Linquistic morphology.
- Issue management and workflow systems.
What do states represent?
Practically anything that can be described with a directed graph could be modeled as states.
- Positions in a tournament bracket.
- Signal-controlled sets of crypto trading strategies. e.g., When in strategy X signal Y will trigger a transition to strategy Z.
- A player’s health, e.g., While in hungry state, eating is required before moving to other states except death.
- A stateful object such as a door, which could be opened, closed, or locked.
Locking Door Example FSM
How is Fismo different?
Most FSM implementations are set up to track state for a thing, not those who interact with the thing.
For instance, even though multiple people may interact with an FSM-based auction contract, it is the current state of the auction that’s being tracked (pending, open, closed). What the users are allowed to do is based on the state of the machine. The user has no “state” to speak of.
Fismo flips all this on its head. It tracks the state of each user in every machine they interact with.
So, Anna can be in state A of the machine while Bob is in state B. Each user’s path through the machine is tracked and their current position in any machine can be queried as well as the last machine and state they visited.
Just as token-gating allows any contract to make decisions based on a user’s token holdings, they can now also make decisions based upon the states of the machines that a user has visited or is currently in.
What is a Fismo Machine
A Machine is a combination of static configuration and guard logic that governs the current state of a user on that machine.
One part is purely configuration…
- A graph of states
- Valid transitions between states
- The actions that can trigger transitions
The other, much more interesting part is “guard code”…
- Each state can have an entrance guard; a function that will be called when a user enters a state
- Each state can have an exit guard; a function that will be called when a user exits a state
- Passing out of one state and into another, then, could trigger zero through two functions
- Guard code can do anything, but is so-called because it is a chance to revert the transaction.
- An adventurer is chained to a post in the middle of the room
- They were chained there by a troll when they came into the room. (This happened in the entrance guard logic.)
- The exit guard for the room can revert if the user’s state for the machine representing the chain is “shackled”.
- Some action a user takes in that machine could switch them to the “unshackled” state.
- Once unshackled, the user can attempt the transition to the other room again.
- Now the guard lets the user exit, but who knows what the entrance guard to the next room has in store?
- An adventurer is chained to a post in the middle of the room
What’s in a Fismo Machine configuration?
- The address of an operator contract which is used to invoke actions.
- Aside from allowing the owner of the contract to create or extend machines, Fismo defers all other access control to the implementer.
- Actions on a Fismo machine must be invoked by the specified operator contract.
- This allows the implementer to include custom logic that filters who can interact with the machine, when, and under what conditions. For instance it could be used to enforce that all activity on a machine must occur between two times, or that all users must hold a specific token.
- Any number of discrete state definitions.
- The valid transitions to other states and the actions that trigger them.
- Whether proxied guard logic exists for exiting a state.
- Whether proxied guard logic exists for entering a state.
- An off-chain metadata URI for each machine that describes this machine configuration in JSON format.
- Like NFT metadata, commonly stored on IPFS.
- Can have images and longer descriptions than is financially feasible for casual building on-chain.
Locking Door Example FSM Configuration
What does Fismo.sol actually do?
It is a combination of…
- The Proxy pattern for executing guard logic in the context of the Fismo contract.
- A registry of machines and users’ states within them.
- Orchestrator of all state transitions in all machines for all users.
- A self-cloning Minimal Proxy factory.
It maintains…
- Configurations for any number of named machines
- Current state in any number of machines for any number of wallet addresses
- A history of each user’s positions (machine and state)
It executes…
- Actions that trigger user transitions between states
- State-specific entrance and exit guard logic by delegating to logic contracts
- This is similar to the facets of the Diamond proxy pattern.
- Except, function signatures on Fismo’s proxied logic contracts are…
- Deterministic. Based on the machine and the states involved in a transition.
- Guard function signatures look like this:
MachineName_StateName_Enter(address _user, string calldata _action, string memory _priorStateName)
MachineName_StateName_Exit(address _user, string calldata _action, string memory _nextStateName)
.
- Simpler to maintain while avoiding name collisions.
It emits events when…
- A machine is created
- A machine is modified
- A state is added to an existing machine
- A transition is added to an existing state
- A state’s definition is updated e.g., its guard logic contract is changed
- A user transitioned to a new state in some machine
- A user cloned the Fismo contract
- Ownership is transferred
Typical revert reasons…
- An added machine, state, or transition is misconfigured in some way
- An address supplied for a guard logic contract has no code
- Action invocation not called from declared operator address
- Action invoked is not valid for the user’s current state in the given machine
- An exit guard function reverts during action invocation
- An entrance guard function reverts during action invocation
- Attempting to clone a clone