Skip to content

Latest commit

 

History

History
329 lines (214 loc) · 13.4 KB

eip-0006.md

File metadata and controls

329 lines (214 loc) · 13.4 KB

EIP-0006: Informal Smart Contract Protocol Specification Format

  • Author: Robert Kornacki
  • Status: Proposed
  • Created: 21-Apr-2020
  • License: CC0
  • Forking: No fork needed

Contents

Terminology

Script/Contract

The code which locks a given box/UTXO.

Smart Contract Protocol

An on-chain smart-contract based protocol which consists of one or more stages and two or more possible actions.

Multi-Stage Protocol

A smart-contract protocol with at least two or more stages.

NFT/Singleton Token

An NFT or singleton token is a non-fungible token which is unique. In other words, it is a token that is created with a quantity of 1, and thus is the only token in existence with it's given token id.

Stage

A state within a smart contract protocol that is reachable by users. A stage is strictly defined by its:

  1. Contract
  2. Values that are to be held in the registers of the box locked by said contract
  3. Data that is to be provided by the user via context extension values

Within the contract of each stage the following are also defined:

  1. Hard-coded values relevant to the given stage
  2. Mandatory stage spending conditions
  3. Actions (spending paths)
Hard-coded Values

Values relevant to the contract which are encoded directly within it, rather than in a register. An expiration block height or a user's address are common examples of hard-coded values which will not change as the protocol runs.

Mandatory Stage Spending Conditions

Logical checks/conditions which are encoded within the contract that must be met no matter which action is taken from the given stage. This is useful for multi-stage protocols with numerous actions per stage which you need to put wide limits on (Ex. Only allowing actions to be taken from a stage after a certain block height)

Context Extension Values

Input values which are expected to be provided by the user when they are creating a transaction to go down a spending path. Within the contract itself the context extension values are used in order to perform checks and calculations which are encoded within the spending conditions.

Action

An action which a user is allowed to perform from a given stage in order to progress forward in the protocol into a new state/stage. A single stage may have one or more actions (alternatively known as spending paths), each of which has a set of conditions.

Action Conditions

Action conditions (aka spending conditions), are logical checks which are encoded within a contract which allow/disallow a user from using a given spending path/action.

Bootstrap Action

An action which allows a user to bootstrap themselves into one of the stages of the protocol.

Background And Motivation

UTXO-based smart contracts are a fascinating new area beginning to be explored for implementing dApp protocols. The model allows for great expressiveness and approachability due to the fact that different stages of a complex protocol can be cleanly separated into their own contracts.

With that said, this is an extremely nascent model for designing smart contract protocols. This means that though they may be simpler when compared to the current standard today, complexity is still going to be present when building protocols that require numerous actions or stages. Furthermore, we could benefit from conveying to others how a given protocol is supposed to be implemented and/or work without writing a single line of code.

As such it would be quite handy to have a format to informally define specifications for our utxo-based smart contract protocols which are understandable, easily traversable, and can be used as a guide for eventually writing both the on-chain and off-chain code.

How Informal Smart Contract Protocol Specs Are Written

Let's look at the markdown-based schema in it's entirety and drill down how it works below.

# Smart Contract Protocol Name
Preamble

## Stage ToC
1. [Stage A](<#Stage-A>)
2. [Stage B](<#Stage-B>)


## Action ToC
1. [Bootstrap Action](<#Action-Bootstrap>)
2. [X Action](<#Action-X>)
---

## Stage: A
Preamble

### Registers
- R4: ...
- R5: ...

### Hard-coded Values
- ...

### Context Extension Values
1. ...

### Mandatory Stage Spending Conditions
- ...

### Actions/Spending Paths
- [X Action](<#Action-X>)

---

## Stage: B
Preamble

### Registers
- R4: ...
- R5: ...

### Hard-coded Values
- ...

### Context Extension Values
1. ...

### Mandatory Stage Spending Conditions
- ...

### Actions/Spending Paths
- [X Action](<#X-Action>)

---

## Action: Bootstrap
Preamble

### Inputs
1. A box with at least y Erg.
3. ...

### Outputs
1. A box in [Stage A](<#Stage-A>) with X in R4.
2. ...
3. ...

---

## Action: X
Preamble

### Data-Inputs
1. ...
2. ...

### Inputs
1. A box in [Stage A](<#Stage-A>).
2. A box with at least x Erg.
3. ...

### Outputs
1. A box in [Stage B](<#Stage-B>).
2. ...
3. ...

### Action Conditions
1. ...
2. ...

---

As you can see above, each smart contract protocol is made out of a number of stages. Each stage is a state that is reachable by a user. A stage is defined by a specific contract, the values expected to be in it's registers, and the values expected to be provided by context extension (user input during tx creation). There are also hard-coded values which are encoded within the contract itself, and mandatory stage spending conditions which are logical checks that must be met in order for any action to take place. (If a given stage does not use one of these (ex. hard-coded values), then they can be omitted in order to save space.)

From each stage you have one or more actions. These are state transitions from the current stage to another (or to itself recursively with a mutation in either the data or tokens held). Each action specifies the required data-inputs, inputs boxes, output boxes, and action conditions. Action conditions are the logical checks which are encoded within the contract which must be met in order to allow for a state transition to occur and thus for said action (or spending path) to be taken.

Note, bootstrap actions have no action conditions because there is no smart contract to enforce them yet and no data-inputs because during bootstrapping data can be arbitrarily added by the user (no need to reference existing boxes). Furthermore, it is possible for a multi-stage protocol to have one or more bootstrap actions which allow different actors to enter the protocol potentially at different stages.

Every stage, action, and the protocol itself has room for a preamble/explanation of what is going on in the given section. This allows for the spec writer to add extra comments and/or make clarifications so that it is painfully clear how the protocol is supposed to work when sharing with others.

Using markdown we get the benefit of being able to hyperlink the stages in the ToC, the actions for each stage, and where each one leads to. This provides us with a reasonable interface for going through informal specifications and gaining an understanding of how the different stages are inter-linked. With both an eagle's eye view using the ToC as well as with a targeted/sequential view via following path hyperlinks, we have the ability to dig into how the parts and the whole of any given informal specification work.

Alternative Formatting

If the list format is too crowded for inputs/outputs/conditions, the following format is available as well for more complicated protocols.

### Data-Inputs
#### Data-Input #1
...
##### Data-Input #2
...

### Inputs
#### Input #1
...
#### Input #2
...

### Outputs
#### Ouput #1
...
#### Ouput #2
...

### Action Conditions
#### Condition 1
...
#### Condition 2
...

This allows one to use lists within each given section, thereby allowing for much more room to go into detail about specifics. This can be useful for contracts which use several registers across several boxes in their spending conditions for example.

With all of that said, let's now look at an example informal specification which uses the above scheme/format to define an NFT auction protocol.

Example NFT Auction Protocol

Trustless auctions for NFT/singleton tokens (token of total amount equal to one) are a useful use case for Blockchains. These NFTs can represent physical goods in the real world, or have meaning in relation to other dApps on-chain.

As such NFTs can often be quite valuable and therefore a protocol for running on-chain auctions to sell a given NFT is going to be an important part of the smart contract stack.

The following implementation focuses strictly on an NFT, however the protocol can be trivially expanded to support auctions for any tokens (or even sets of tokens) which a seller wishes to find a buyer for.

The auction is initiated by the auction holder via the Bootstrap Auction action, which starts the auction off at a predefined starting bid price. From there anyone on the Ergo Blockchain has the ability to use the Bid On Auction action until the auction end block height.

Once the auction concludes Conclude Auction can be used which provides the auction holder the Ergs from the auction, while providing the auction winner the NFT.

Stage ToC

  1. Auction Stage

Action ToC

  1. Bootstrap Auction
  2. Bid On Auction
  3. Conclude Auction

Stage: Auction

In this stage the NFT is held up for auction and anyone who has enough Ergs can place a bid before the auction ends. All new bids must increment by at least 0.5 Erg.

Registers

  • R4: The current highest bidder's public key

Hard-coded Values

  • Auction holder's public key
  • Auction end block height

Context Extension Values

None

Actions/Spending Paths


Action: Bootstrap Auction

This action allows a user to initiate an auction. It requires that they provide their NFT and a box with Ergs which represents the starting bid.

Inputs

  1. Box which holds the NFT that is to be put up for auction.
  2. Box with Ergs equivalent to the starting bid price.

Outputs

  1. A box locked under the Auction Stage that holds the NFT and Ergs from the inputs, which also stores the auction holder's public key in register R4.

Action: Bid On Auction

This action recurses the Auction box back into the same stage however now with the newly bidded Ergs held inside and the current winning bidder in R4 updated.

Inputs

  1. The Auction Stage box.
  2. Box(es) owned by the bidder which has enough Ergs to total the previous bid + 0.5 Erg.

Outputs

  1. A new box in the Auction Stage once again which has the new bidder's public key in R4, the NFT, and the Ergs for the bid.
  2. A box owned by the previous bidder which gives them back the Ergs which they bid.

Action Conditions

  1. The current block height must be less than the auction end block height hard-coded in the Auction Stage contract.
  2. The first output box must be locked under the Auction Stage and holds the bidder's public key in R4, the NFT, and Ergs totalling at least 0.5 Erg more than the previous bid.
  3. The second output box is owned by the previous bidder and has a total number of Ergs equal to their bid.

Action: Conclude Auction

This action allows the NFT and the funds to be redeemed to the auction winner and holder respectively once the auction finish height has been reached. If no one bid on the auction then the auction holder still has their public key in register R4, and therefore can redeem both their NFT and their Ergs to themselves.

Inputs

  1. The Auction Stage box.

Outputs

  1. A box owned by the address stored in R4 which holds the NFT.
  2. A box owned by the auction holder which receives all of the Ergs bid.

Action Conditions

  1. The current block height must be grater than the auction end block height hard-coded into the Auction Stage contract.
  2. The first output box must hold the NFT and be owned by the pub key stored in R4.
  3. The second output box must hold all of the Ergs and be owned by the auction holder.


Conclusion

The informal markdown-based schema outlined in this document provides the writer the feeling of freedom via easily changing whatever they've written as if it were an essay rather than the clunky feeling of writing compiled code (or a formal spec). This flexibility is useful when figuring out how to implement a protocol which typically requires making edits often and moving fast as previous ideas become obsolete and/or are found to be broken.

Once an informal specification has been finalized, it can be used as a clear guide for:

  1. Writing a formal specification.
  2. Implementing the contracts in ErgoScript.
  3. Designing the off-chain transaction logic.

As such it is my contention that utilizing this informal specification format is important for the long-term success of contracts and dApps on the Ergo Platform.