Celer dApps are highly interactive, secure and low-cost state-channel applications running on Celer Network together with Celer generic payment channel.
This repo provides templates and examples for developing the on-chain contract parts of dApps that can smoothly run on Celer mobile and web SDK CelerX. Note that most of the app interactions happen off-chain. On-chain operations are only needed when players cannot reach consensus off-chain and want to dispute.
-
Multi-Session App: initially deployed once by the developer and can be repeatedly shared by all players. No additional code needs to be deployed when players want to dispute on-chain.
-
Single-Session App: mostly used as a one-time virtual contract for fixed players without initial deployment. The player who wants to bring the off-chain game to on-chain dispute needs first to deploy the contract.
- Contract address: 0xb753e7bfc74bdd669bbf8075637f6e9a1f575c4c
- Constructor: minStoneOffchain=5, maxStoneOnchain=3
- Contract address: 0xa48c84f8b1926688209f45bce4525e26a2a45592
- Constructor: minStoneOffchain=5, maxStoneOnchain=3
API required by Celer Payment Channel
API required by CelerX.
We provide templates to implement the common state-channel logics of external APIs, so that the developers can focus on the app-specific logic.
Developers using the provided templates only need to implement the following interfaces. For detailed usages, please refer to these simplest example contracts and tests
/**
* @notice Get the app outcome
* @param _session Session ID
* @param _query Query arg
* @return True if query satisfied
*/
function getOutcome(bytes32 _session, bytes memory _query) internal view returns (bool) {}
/**
* @notice Update on-chain state according to off-chain state proof
* @param _session Session ID
* @param _state Signed off-chain state
*/
function updateByState(bytes32 _session, bytes memory _state) internal returns (bool) {}
/**
* @notice Update state according to an on-chain action
* @param _session Session ID
* @param _action Action data
* @return True if update succeeds
*/
function updateByAction(bytes32 _session, bytes memory _action) internal returns (bool) {}
/**
* @notice Finalize the session based on current state in case of on-chain action timeout
* @param _session Session ID
*/
function finalizeOnTimeout(bytes32 _session) internal {}
/**
* @notice Get app state associated with the given key
*/
function getState(bytes32 _session, uint _key) external view returns (bytes memory);
/**
* @notice Get the app outcome
* @param _query Query args
* @return True if query satisfied
*/
function getOutcome(bytes memory _query) public view returns (bool) {}
/**
* @notice Update state according to an off-chain state proof
* @param _state Signed off-chain app state
* @return True if update succeeds
*/
function updateByState(bytes memory _state) internal returns (bool) {}
/**
* @notice Update state according to an on-chain action
* @param _action Action data
* @return True if update succeeds
*/
function updateByAction(bytes memory _action) internal returns (bool) {}
/**
* @notice Finalize based on current state in case of on-chain action timeout
*/
function finalizeOnTimeout() internal {}
/**
* @notice Get app state associated with the given key
*/
function getState(uint _key) external view returns (bytes memory);
We leverage Protocol Buffers to define a series of blockchain-neutral generalized data structures, which can be seamlessly used in off-chain communication protocols and instantly extended to other blockchains that we plan to support. We also developed and open sourced a Solidity library generator for decoding proto3 called pb3-gen-sol.
Below are the protos used by Celer dApps. CelerX takes care of the protobuf encode and decode for app developers.
message AppState {
// nonce should be unique for each app session among the same signers
uint64 nonce = 1 [(soltype) = "uint"];
// for each nonce, new state has higher sequence number
uint64 seq_num = 2 [(soltype) = "uint"];
// app specific state
bytes state = 3;
// on-chain response (settle, action) timeout
uint64 timeout = 4 [(soltype) = "uint"];
}
message StateProof {
// serialized AppState
bytes app_state = 1;
repeated bytes sigs = 2;
}
// used for multi-session app
message SessionQuery {
// session ID
bytes session = 1 [(soltype) = "bytes32"];
// query related to the specified session
bytes query = 2;
}