How To Write Smart Contract With Scrypt.
Tags: beginners, bitcoinsmartcontracts, bsvdevelopers, blockchaindevelopers
Published: 2024-05-29 14:18:45

## WHAT IS A SMART CONTRACT
   A smart contract is a self-executing contract that automatically enforces the rules and terms of an agreement between parties. It is a computer program that runs on a blockchain network and can facilitate, verify, or enforce the negotiation or performance of a contract. A smart contract is like a written agreement, but instead of being on paper and handled by a person, it's a piece of computer code on a blockchain.
## How Smart Contract Works.
1. Digital Agreement: A smart contract is a digital agreement written in code. It has all the terms and conditions of the agreement clearly stated.
2. Automatic Execution: Once the smart contract is on the blockchain, it automatically enforces the terms. No one can change it or cheat.
3. No Middleman Needed: Unlike the written agreement where you need a trusted third party to ensure fairness, the smart contract itself ensures fairness by automatically carrying out the agreement based on the pre-set rules.
4. Security and Trust: The blockchain technology behind the smart contract ensures security. It’s decentralized, meaning it’s not controlled by any single person or organization, making it almost impossible to tamper with.
So, in essence, a smart contract is a self-executing contract where the terms are directly written into lines of code. The code and the agreements it contains exist across a distributed, decentralized blockchain network. This ensures that the contract is transparent, secure, and executed exactly as agreed without the need for intermediaries.

## How do Bitcoin Smart Contracts work?
Smart contracts on Bitcoin are based on the UTXO model, which is very different from an account model like Ethereum used.

### A Bitcoin transaction
Each bitcoin transaction consists of some inputs and outputs. A single bitcoin is divisible into 100,000,000 satoshis, similar to how a dollar is divisible into 100 cents or pennies.

An output contains:
a. The amount of bitcoins (satoshis) it contains.
b. bytecodes (the `locking script`).
While an input contains:
a. A reference to the previous transaction output.
b. bytecodes (the `unlocking script`).
#### UTXO model
An Unspent Transaction Output (UTXO) is an output not consumed in any transaction yet. The low-level bytecode/opcode is called Bitcoin Script, which is interpreted by the Bitcoin Virtual Machine (BVM).

![An image of a lock and key with a boolean function illustrating
 UTXO model](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ds2m6dv2hbn0vtdx9mnu.jpg)
In the example above, we have two transactions, each having one input (in green) and one output (in red). And the transaction on the right spends the one on the left. The locking script can be regarded as a boolean function f that specifies conditions to spend the bitcoins in the UTXO, acting as a lock (thus the name "locking"). The unlocking script in turns provides the function arguments that makes f evaluates to true, i.e., the "key" (also called witness) needed to unlock. Only when the “key” in an input matches previous output’s “lock”, it can spend bitcoins contained in the output.

In a regular Bitcoin payment to a Bitcoin address, the locking script is Pay To Pubkey Hash (P2PKH). It checks the spender has the right private key corresponding to the address so she can produce a valid signature in the unlocking script. The expressive Script enables the locking script to specify arbitrarily more complex spending conditions than simple P2PKH, i.e., Bitcoin smart contracts.
## Components of A Smart Contract Written On Scrypt.
 In case you are new to Scrypt you can follow the previous article on    scrypt syntax and data types [here](https://dev.to/bravolakmedia/introduction-to-scrypt-syntax-and-data-types-2k2l).
A smart contract is a class that extends the `SmartContract` base class. It has the following components:
### 1. Properties
A smart contract can have two kinds of properties:

a. With `@prop` decorator: these properties are only allowed to have types specified below and they shall only be initialized in the constructor.
b. Without `@prop` decorator: these properties are regular TypeScript properties without any special requirement, meaning they can use any types. Accessing these properties is prohibited in methods decorated with the `@method` decorator.

### 2. @prop decorator
This decorator is used to mark any property that intends to be stored on chain. It takes a boolean parameter. By default, it is set to false, meaning the property cannot be changed after the contract is deployed. 
If the value is true, the property is a so-called **stateful** property and its value can be updated in subsequent contract calls.

```
// good, `a` is stored on chain, and it's **readonly** after the contract is deployed
@prop()
readonly a: bigint

// valid, but not good enough, `a` cannot be changed after the contract is deployed
@prop()
a: bigint

// good, `b` is stored on chain, and its value can be updated in subsequent contract calls
@prop(true)
b: bigint

// invalid, `b` is a stateful property that cannot be readonly
@prop(true)
readonly b: bigint

// good
@prop()
static c: bigint = 1n

// invalid, static property must be initialized when declared
@prop()
static c: bigint

// invalid, stateful property cannot be static
@prop(true)
static c: bigint = 1n

// good, `UINT_MAX` is a compile-time constant (CTC), and doesn't need to be typed explicitly
static readonly UINT_MAX = 0xffffffffn

// valid, but not good enough, `@prop()` is not necessary for a CTC
@prop()
static readonly UINT_MAX = 0xffffffffn

// invalid
@prop(true)
static readonly UINT_MAX = 0xffffffffn
```
### 3. Constructor
A smart contract must have an explicit `constructor()` if it has at least one `@prop` that is not `static`. The `super` method must be called in the constructor and all the arguments of the constructor should be passed to super in the same order as they are passed into the constructor. For example,
```
class A extends SmartContract {
  readonly p0: bigint

  @prop()
  readonly p1: bigint

  @prop()
  readonly p2: boolean

  constructor(p0: bigint, p1: bigint, p2: boolean) {
    super(...arguments) // same as super(p0, p1, p2)
    this.p0 = p0
    this.p1 = p1
    this.p2 = p2
  }
}
```
`arguments` is an array containing the values of the arguments passed to that function. `...` is the `spread syntax`.
### 4. Methods
Like properties, a smart contract can also have two kinds of methods:
a. With `@method` decorator: these methods can only call methods also decorated by `@method` or **[functions](https://docs.scrypt.io/how-to-write-a-contract/#functions)** specified below. Also, only the properties decorated by `@prop` can be accessed.

b. Without `@method` decorator: these methods are just regular TypeScript class methods.

a. `@method` decorator
This decorator is used to mark any method that intends to run on chain. It takes a [sighash flag](https://docs.scrypt.io/how-to-write-a-contract/scriptcontext#sighash-type) as a parameter.
#### Public `@methods`
Each contract must have at least one public @method. It is denoted with the public modifier and does not return any value. It is visible outside the contract and acts as the main method into the contract (like `main` in C and Java).
A public `@method` can be called from an external transaction. The call succeeds if it runs to completion without violating any conditions in [assert()](https://docs.scrypt.io/how-to-write-a-contract/built-ins#assert). An example is shown below.
```
@method()
public unlock(x: bigint, y: bigint) {
  assert(x + y == this.sum, 'incorrect sum')
  assert(x - y == this.diff, 'incorrect diff')
}
```
Ending rule
A public `@method` method must end with `assert()` in all reachable code paths. A detailed example is shown below.
```
class PublicMethodDemo extends SmartContract {

  @method()
  public foo() {
    // valid, last statement is `assert()` statement
    assert(true);
  }

  @method()
  public foo() {
    // valid, `console.log` calls will be ignored when verifying the last `assert()` statement
    assert(true); //
    console.log();
    console.log();
  }

  @method()
  public foo() {
    // valid, last statement is `for` statement
    for (let index = 0; index < 3; index++) {
        assert(true);
    }
  }

  @method()
  public foo(z: bigint) {
    // valid, last statement is `if-else` statement
    if(z > 3n) {
        assert(true)
    } else {
        assert(true)
    }
  }

  @method()
  public foo() {
    // invalid, the last statement of every public method should be an `assert()` statement
  }

  @method()
  public foo() {
    assert(true);
    return 1n;  // invalid, because a public method cannot return any value
  }

  @method()
  public foo() {
    // invalid, the last statement in the `for` statement body doesn't end with `assert()`
    for (let index = 0; index < 3; index++) {
        assert(true);
        z + 3n;
    }
  }

  @method()
  public foo() {
    // invalid, because each conditional branch does not end with `assert()`
    if(z > 3n) {
      assert(true)
    } else {

    }
  }

  @method()
  public foo() {
    // invalid, because each conditional branch does not end with `assert()`
    if(z > 3n) {
      assert(true)
    }
  }
}
```
#### Non-public `@methods`
Without a `public` modifier, a `@method` is internal and cannot be directly called from an external transaction.
```
@method()
xyDiff(): bigint {
  return this.x - this.y
}

// static method
@method()
static add(a: bigint, b: bigint): bigint {
  return a + b;
}
```
NOTE
Recursion is disallowed. A `@method`, whether public or not, cannot call itself either directly in its own body, nor indirectly call another method that transitively calls itself. A more detailed example is shown below.
```
class MethodsDemo extends SmartContract {
  @prop()
  readonly x: bigint;
  @prop()
  readonly y: bigint;

  constructor(x: bigint, y: bigint) {
    super(...arguments);
    this.x = x;
    this.y = y;
  }

  // good, non-public static method without access `@prop` properties
  @method()
  static add(a: bigint, b: bigint): bigint {
    return a + b;
  }

  // good, non-public method
  @method()
  xyDiff(): bigint {
    return this.x - this.y
  }

  // good, public method
  @method()
  public checkSum(z: bigint) {
    // good, call `sum` with the class name
    assert(z == MethodsDemo.add(this.x, this.y), 'check sum failed');
  }

  // good, another public method
  @method()
  public sub(z: bigint) {
    // good, call `xyDiff` with the class instance
    assert(z == this.xyDiff(), 'sub check failed');
  }

  // valid but bad, public static method
  @method()
  public static alwaysPass() {
    assert(true)
  }
}
```
## A SIMPLE SUMMATION SMART CONTRACT
A smart contract is a class that extends the SmartContract base class. A simple example is shown below.
```
import { SmartContract, method, prop, assert } from "scrypt-ts"

class Equations extends SmartContract {

  @prop()
  sum: bigint

  @prop()
  diff: bigint

  constructor(sum: bigint, diff: bigint) {
    super(...arguments)
    this.sum = sum
    this.diff = diff
  }

  @method()
  public unlock(x: bigint, y: bigint) {
    assert(x + y == this.sum, 'incorrect sum')
    assert(x - y == this.diff, 'incorrect diff')
  }

}
```
The smart contract above adds up two unknown variables, x and y.
Class members decorated with `@prop` and `@method` will end up on the blockchain and thus must be a strict subset of TypeScript. Everywhere decorated with them can be regarded in the on-chain context. Members decorated with neither are regular TypeScript and are kept off chain. The significant benefit of sCrypt is that both on-chain and off-chain code are written in the same language: TypeScript.
For further reading on how to write smart contracts on scrypt you can visit the [scrypt doc](https://docs.scrypt.io/how-to-write-a-contract/).