Quick start (contracts)
You should begin your application design process by creating a single smart contract conforming to the ForceMoveApp
interface.
You'll want to pull this interface, as well as the Outcome
library contract, into your project using your favourite node package manager:
The ForceMoveApp
interface calls for an application-specific validTransition(a,b)
function. This function needs to decode the appData
, from state channel updates a
and b
, and decide if b
is an acceptable transition from a
. For example, in a game of chess, the position of the king in b.appData
must be within one square of its position in a.appData
.
Examples
For example, one can implement a simple counting application, where the state of the channel can only be updated by incrementing a counter variable:
In /contracts/CountingApp.sol
:
This example is unrepresentative, however, in that it does not allow any changes to the outcome
of the channel. This means nothing of any value can change hands as the application is executed. A full ForceMoveApp should specify how the outcome is allowed to change during a transition: for example, if a chess player achieves checkmate, they might be permitted to claim all of the money in the channel.
More realistic ForceMoveApp examples exist: such as games of Rock Paper Scissors and Tic Tac Toe, as well as a simple Payment Channel app.
Design guide
In more complicated applications, it can help to adopt a finite state machine model, which means the application can be represented in a digram such as this:
These finite states could be represented as a Solidity enum
. In ForceMove, the participants "leapfrog" each other on this diagram, i.e.:
- A starts at Resting
- B transitions to Propose
- A transitions to Accept
- B transitions to Reveal
- repeat
The validTransition
function returns true
only if the transition is one allowed by the arrows in the diagram (this is necessary but not sufficient, there are of course other checks made, too). On the other hand, Accept --> Propose is not allowed, so validTransition
could return false
in this case.
In fact, to provide more information, it actually calls revert('No valid transition found');
.