Skip to content
6 changes: 6 additions & 0 deletions docs/kcc20-book/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ build-dir = "book"

[output.html]
site-url = "/kcc20-book/"
additional-js = ["mermaid.min.js", "mermaid-init.js"]

[preprocessor]

[preprocessor.mermaid]
command = "mdbook-mermaid"
39 changes: 39 additions & 0 deletions docs/kcc20-book/mermaid-init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

(() => {
const darkThemes = ['ayu', 'navy', 'coal'];
const lightThemes = ['light', 'rust'];

const classList = document.getElementsByTagName('html')[0].classList;

let lastThemeWasLight = true;
for (const cssClass of classList) {
if (darkThemes.includes(cssClass)) {
lastThemeWasLight = false;
break;
}
}

const theme = lastThemeWasLight ? 'default' : 'dark';
mermaid.initialize({ startOnLoad: true, theme });

// Simplest way to make mermaid re-render the diagrams in the new theme is via refreshing the page

for (const darkTheme of darkThemes) {
document.getElementById(darkTheme).addEventListener('click', () => {
if (lastThemeWasLight) {
window.location.reload();
}
});
}

for (const lightTheme of lightThemes) {
document.getElementById(lightTheme).addEventListener('click', () => {
if (!lastThemeWasLight) {
window.location.reload();
}
});
}
})();
2,609 changes: 2,609 additions & 0 deletions docs/kcc20-book/mermaid.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/kcc20-book/src/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The example is interesting because it is not just "a token owned by a pubkey". I
- token state carried in covenant state
- ownership by pubkey, by script hash, or by covenant ID
- mint-capable and non-mint-capable token branches
- a separate minter covenant that controls issuance
- a separate controller covenant that controls issuance
- cross-contract linkage through covenant IDs
- template-based validation of another contract's state shape
- covenant declaration flows for initialization, transfer, and minting
Expand Down
28 changes: 14 additions & 14 deletions docs/kcc20-book/src/kcc20-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Source: `silverscript-lang/tests/examples/kcc20.sil` [[Link]](https://github.com

## Full Source

```sil
```js
contract KCC20(byte[32] genesisPk, int genesisAmount, byte genesisIdentifierType, bool genesisIsMinter, int maxCovIns, int maxCovOuts) {
byte constant IDENTIFIER_PUBKEY = 0x00;
byte constant IDENTIFIER_SCRIPT_HASH = 0x01;
Expand Down Expand Up @@ -67,7 +67,7 @@ contract KCC20(byte[32] genesisPk, int genesisAmount, byte genesisIdentifierType

The contract constructor is:

```sil
```js
contract KCC20(
byte[32] genesisPk,
int genesisAmount,
Expand All @@ -90,7 +90,7 @@ These constructor values become the initial state and loop bounds.

The contract state is encoded as contract fields:

```sil
```js
byte[32] ownerIdentifier = genesisPk;
byte identifierType = genesisIdentifierType;
int amount = genesisAmount;
Expand All @@ -103,7 +103,7 @@ Every covenant transition reads and writes these fields as `State`.

KCC20 defines three constants:

```sil
```js
byte constant IDENTIFIER_PUBKEY = 0x00;
byte constant IDENTIFIER_SCRIPT_HASH = 0x01;
byte constant IDENTIFIER_COVENANT_ID = 0x02;
Expand All @@ -113,15 +113,15 @@ These constants drive `checkSigs`.

### Pubkey ownership

```sil
```js
require(checkSig(sigs[i], prevStates[i].ownerIdentifier));
```

The spender must supply a signature matching the previous state's pubkey.

### Script-hash ownership

```sil
```js
byte[] spk = new ScriptPubKeyP2SH(prevStates[i].ownerIdentifier);
require(tx.inputs[witnesses[i]].scriptPubKey == spk);
```
Expand All @@ -130,7 +130,7 @@ Here KCC20 does not validate signatures itself. Instead it requires that the tra

### Covenant-ID ownership

```sil
```js
require(OpInputCovenantId(witnesses[i]) == prevStates[i].ownerIdentifier);
```

Expand All @@ -148,7 +148,7 @@ identifierType = 0x02 -> covenant-ID ownership

The first major function is:

```sil
```js
function checkSigs(State[] prevStates, sig[] sigs, byte[] witnesses)
```

Expand All @@ -170,13 +170,13 @@ For the non-pubkey ownership case, see the [Inter-Covenant Communication](./kcc2

The supply rule lives in:

```sil
```js
function checkAmounts(State[] prevStates, State[] newStates)
```

It only enforces conservation when the active branch is not a minter:

```sil
```js
if(!isMinter) {
...
require(totalIn == totalOut);
Expand Down Expand Up @@ -204,13 +204,13 @@ minter branch:

The third function is:

```sil
```js
function checkMintingTransfer(State[] newStates)
```

It prevents non-minter branches from creating minter-marked outputs:

```sil
```js
if(!isMinter) {
for(i, 0, newStates.length, maxCovOuts) {
require(!newStates[i].isMinter);
Expand All @@ -224,7 +224,7 @@ This matters because otherwise an ordinary KCC20 branch could escape the supply

KCC20 exposes one covenant declaration:

```sil
```js
#[covenant(binding = cov, from = maxCovIns, to = maxCovOuts)]
function transfer(State[] prevStates, State[] newStates, sig[] sigs, byte[] witnesses)
```
Expand All @@ -237,7 +237,7 @@ The important parts are:

The body is intentionally small:

```sil
```js
checkSigs(prevStates, sigs, witnesses);
checkAmounts(prevStates, newStates);
checkMintingTransfer(newStates);
Expand Down
Loading