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.
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.
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: