# Smart Contract

# Basic Information of Smart Contract

Miyabi allows users to use smart contracts for handling complex operations towards tables. When using a smart contract, the user needs to specify the name of the smart contract, functions, and parameters. All the direct operations to tables can be defined in the smart contract. Miyabi supports smart-contract written in C# 8.0. A smart contract is a C# class inherited from ContractBase in Miyabi and import-related modules for operations. ContractBase provides some methods to access the world state and a predefined binary table that is owned by the smart contract for storing metadata. Smart contracts support fundamental operations in and whitelisted libraries in C#. The World State can be accessed and modified through a smart contract if necessary credentials are included in the required credential of the transaction that invokes the smart contract.

A smart contract in Miyabi has a complete life cycle. First, the source code and dependencies will be compiled and analyzed by a Roslyn Analyzer where several checks are applied. Once the code passes analysis, it can be deployed to the Miyabi. The user needs to instantiate the smart contract first and specify an instance owner to it. Then, the user can invoke methods of the instance by transactions. When a node executes these transactions, the node will create an instance of the smart contract and bind it to the internal table for execution. If an exception is thrown, the transaction will be marked as failed and discard changes. Users can also query the smart contract through API to read data according to the logic. To abolish one instance, the instance owner can delete the instance record, so that no one can invoke/query this instance.

# Create a Smart Contract

A normal smart contract is written in C# like following:

public class SampleContract:ContractBase
{
    public override bool Instantiate(string[] args)
    {
        // instantiate code
    }
    public void InvokeMethod(string[] args)
    {
        // Method invokes through transactions
    }
    public string QueryMethod(string[] args)
    {
        // Method queried through API
    }
}

A contract must inherit from ContractBase, and the invoked method should not return any value because transactions only return the result code. To update the world state in the invoked method, the user can use the StateWriter member defined in ContractBase.

Miyabi provides two templates derived from the ContractBase for developers. TransformableSmartContractdefines a SaveState function. Developers can override it with logic that the user wants to execute after every invocation. UpgradableContractBase provides some tool functions to hand over table ownership. Developers can use the preserved GrantTables method to implement the logic that needs to be done when upgrading one instance to a different instance and call it from the new instances.

More details are in the SDK documents and sample code.

# Deploy Smart Contract

A Miyabi smart contract's method can be used only after it is deployed, which means the source code is stored to all nodes of Miyabi. To deploy a smart contract, the transaction should be signed by an address with Deploy permission, who should apply the first layer security check for the smart contracts. Once a smart contract is deployed, the compiled source code will become a part of World State, and registered to a predefined table for managing smart contracts. Miyabi uses a unique assembly Id, the hash value of source code, to distinguish different smart contracts. Since the same source code will have the same assembly Id, developers cannot deploy the same smart contract twice.

To deploy a smart contract, user need to provide the following parameters.

Item Type Description
Referenced Assemblies List of string libraries used by the smart contract that needed to be imported
Source Code List of string the source codes
Instantiators List of Public Key The owner of the smart contract who can instantiate this smart contract.

# Instantiate Smart Contract

Since a smart contract is a class, we need to create an instance for the smart contract before using it. The user needs to instantiate the smart contract, which will create an instance record and an internal table to store metadata of this instance. Instantiating a smart contract needs the assembly Id, class name, and an instance name for that instance. In Miyabi, the hash of the above three parameters is theInstanceId for strictly distinguish different instances.

Method Instantiate is defined in ContractBase as an empty method. Developers can override the Instantiate function to store variables and create tables for other methods. A predefined internal table can store the metadata of the smart contract used and created during the instantiating.

To Instantiate an instance, the user needs to provide the following parameters. The transaction needs to be signed by one instantiator of the assembly, and other addresses according to the required permissions.

Item Type Description
Assembly Id string The assembly Id of the deployed smart contract. It can be checked by cli command getassemblyid
Instance Name string The Instance Name provided by user to distinguish different instance
Contract Name string The Class inherited Contract Base and whose instantiate function will be called
Instance Owners List of Addresses The addresses who can delete this instance
Arguments list of string An array provide all the parameters needed for instantiate functions

# Invoke Smart Contract

In Miyabi, the user can invoke different methods of the smart contract to change the World State. Users can only invoke the method with a void return type and check the result by transaction result code. To invoke a method, the user needs to create an entry to point out which method of which instance will be called and provide the required parameters.

The input parameters can only be:1. ByteString(Defined in Miyabi); 2. PublicKey; 3. Address(Defined in Miyabi); 4. Json string. The following objects cannot be treated as input parameters: 1. Object; 2. Empty; 3. DateTime; 4. DBNull. The user needs to serialize all the parameters into a JSON format string, and the executor will deserialize them according to the definition of methods in the smart contract.

To Invoke a method of smart contract, the user needs to provide the following parameters.

Item Type Description
Assembly Id string The assembly Id of the deployed smart contract. It can be checked by cli command getassemblyid
Instance Name string The Instance Name provided by user to distinguish different instance
Contract Name string The class inherited Contract Base and whose instantiate function will be called
Method Name string The Method invoked in the smart contract. Must return void.
Arguments list of string An array provide all the parameters needed for instantiate functions

# Query Smart Contract

Users can use the API to query the smart contract. Since the query will not be a part of the consensus, query methods cannot change the world state. In return, the query methods have a non-void return type as the HTTP response.

To query a method, the following parameters are needed:

Item Type Description
Assembly Id string the assembly Id of the deployed smart contract. It can be checked by cli command getassemblyid
Instance Name string The Instance Name provided by user to distinguish different instance
Contract Name string The class inherited Contract Base and whose instantiate function will be called
Method Name string The Method invoked in the smart contract. Must return void.
Arguments List of string An array provide all the parameters needed for instantiate functions

The endpoint is {miyabiAPI}/query/{assemblyId}/{contractName}/{instanceName}/{methodName}?{Aruguments[0]}="xxx".... The result will be returned through the HTTP message.

# Contract Event

Users can also store their customized data into the event through the smart contract. Users need to define their event data derived from ContractEventBase and use ExecutionContext.TriggerEvent(event) to trigger the event builder. Each event can define some bytes string in the filter FilterData, used in the bloom filter of the block event for quick searching in a block.