Introduction

Contracts are scripts that are stored and executed on Muffin Network.

Contracts primary function is to manage tokens, certificates and DAOs, but anything can be done with them and are a great way to handle payments in an application.

On the technical aspect, contracts are Javascript classes for which the instance is stored on the network.

Contracts can also be written in Typescript, but Muffin Network will only store the Javascript es2015 compiled code.

Structure of a contract

Here’s an example of what a contract looks like:

import { App, ERC20, address } from 'muffin-utils'

class MyToken extends App implements ERC20 {
  tokenName: string = 'MyToken'
  tokenSymbol: string = 'MTN'

  tokenTotalSupply: number
  balances: { [x: address]: number }
  allowed: { [x: address]: { [key: address]: number } }

  constructor(data: any) {
    super(data)

    if (!this.tokenTotalSupply) {
      this.tokenTotalSupply = 0
    }

    if (!this.balances) {
      this.balances = {}
    }

    if (!this.allowed) {
      this.allowed = {}
    }
  }

  // Events
  #Transfer = (from: address, to: address, value: number) => {
    if (value > this.balances[from]) {
      throw Error('Not enough funds.')
    }

    this.balances[from] -= value

    if (!this.balances[to]) {
      this.balances[to] = 0
    }

    this.balances[to] += value
  }

  #Approval = (owner: address, spender: address, value: number) => {
    if (!this.allowed[this.msg.sender]) {
      this.allowed[this.msg.sender] = {}
    }

    this.allowed[this.msg.sender][spender] = value
  }

  // Methods
  name = () => {
    return this.tokenName
  }

  symbol = () => {
    return this.tokenSymbol
  }

  totalSupply = () => {
    return this.tokenTotalSupply
  }

  balanceOf = (owner: address) => {
    if (!this.balances[owner]) {
      return 0
    }

    return this.balances[owner]
  }

  transfer = (to: address, value: number) => {
    this.#Transfer(this.msg.sender, to, value)
  }

  transferFrom = (from: address, to: address, value: number) => {
    if (!this.allowed[from] || !this.allowed[from][this.msg.sender]) {
      throw Error('Not allowed.')
    }

    if (value > this.allowed[from][this.msg.sender]) {
      throw Error('Amount unallowed.')
    }

    this.allowed[from][this.msg.sender] -= value

    this.#Transfer(from, to, value)
  }

  approve = (spender: address, value: number) => {
    if (
      !this.balances[this.msg.sender] ||
      value > this.balances[this.msg.sender]
    ) {
      throw Error('Not enough funds.')
    }

    this.#Approval(this.msg.sender, spender, value)
  }

  allowance = (owner: address, spender: address) => {
    if (!this.allowed[owner] || !this.allowed[owner][spender]) {
      return 0
    }

    return this.allowed[owner][spender]
  }

  // Minting
  mint = (account: address, amount: number) => {
    if (this.msg.amount < amount * 1000) {
      throw Error('Not enough funds. MyToken costs 1000 FLT.')
    }

    if (this.msg.amount > amount * 1000) {
      throw Error('Too much funds. Be careful when making transactions!')
    }

    if (!this.balances[account]) {
      this.balances[account] = 0
    }

    this.tokenTotalSupply += amount

    this.balances[account] += amount
  }

  // Burning
  burn = (account: address, amount: number) => {
    if (this.balances[account] < amount) {
      throw Error('Balance insufficient.')
    }

    this.tokenTotalSupply -= amount

    this.balances[account] -= amount

    this.msg.makeTransaction(account, amount * 1000)
  }
}

So, let’s see how it works.

Importing dependancies

import { App, ERC20, address } from 'muffin-utils'

The NPM module muffin-utils is the only one that you can import in a contract.

It provides useful tools that will help you to build your contract.

As you can see, we imported 3 things from muffin-utils for this contract, let’s dive in: