# Smart Contract
# Introduction
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.
A smart contract is a C# class inherited from ContractBase
in Miyabi.
ContractBase
provides World State read and write abstraction.
A smart contract owned Binary table is also created when a smart contract instance is created, the developers can use this for storing various data (general metadata and bookkeeping etc.).
The smart contracts can use allowed assemblies and members to accomplish various operations.
The World State can be accessed and modified through a smart contract if necessary credentials are included in the transaction that invokes the smart contract instance.
The process begins with compiling and analyzing the source code and its dependencies using a Roslyn Analyzer, which applies various checks. After the code successfully passes the analysis, it can be deployed to Miyabi. The user needs to instantiate the smart contract and specify an instance owner. Following this, the user can interact with the contract by invoking its methods using transactions or querying its read-only methods. If an exception is thrown, the transaction will be marked as failed and the changes will be discarded. Also, the instance owner can delete the instance record so no one can invoke/query this instance.
This document shall provide CLI examples with the following sample smart contract: SampleContract.cs (opens new window)
# Create a Smart Contract
A simple smart contract, written in C#, looks like the 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
}
}
All the smart contracts in Miyabi inherit from the ContractBase
class, either directly or indirectly.
To update the World State in the invoked method, the user can use the StateWriter
member defined in ContractBase
.
Miyabi also provides two templates derived from the ContractBase
:
TransformableSmartContract
defines aSaveState
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 preservedGrantTables
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.
# Get Assembly Id
The Assembly Id is the hash of the Miyabi smart contract source code.
getassemblyid
is an offline command that calculates the Assembly Id of the smart contract without compiling the source code.
Miyabi uses the hash value of source code Assembly Id to distinguish different smart contracts.
Since the same source code will have the same Assembly Id, developers cannot deploy the same smart contract twice.
# Example
$ ./miyabi-cli.exe getassemblyid -f SampleContract.cs
8819851eae0bca115266bd329527c595f6320a19a2975de9773c4c8d352c0ff6
# Deploy Smart Contract
The first step to use a smart contract is to deploy it to Miyabi. The deployment step ensures that the smart contract is using valid code (no disallowed assemblies and members) and also that the source code is compilable. The assembly of the smart contract is then stored by Miyabi nodes.
To deploy a smart contract, the transaction should be signed by an address with contract Deploy
permission.
Once a smart contract is deployed, the compiled source code will be stored in the World State, and registered to a predefined table for managing smart contracts.
The deploycontract
command has the following parameters:
Item | Type | Description |
---|---|---|
Contract Admin Private Keys | PrivateKey[] | Private key(s) of the signer with 'Deploy' contract permission (optional) |
Source Files | string[] | File path to the smart contract source code |
LanguageVersion | string | C# Language version to compile |
Instantiators | Address[] | Address(es) which can administer the creation of the contract instances |
Dependencies | string[] | Assembly name of third party dependencies (optional) |
Debug | bool | Flag to indicate if the smart contract can be debugged |
# Example
$ ./miyabi-cli.exe sendtransaction deploycontract -lv CSharp10 -p 14e3a2d16c8a43a4eb1b088b32bca2abaf274e3f185afc9c15b33491c8deb9a6 -i 026beca06739461a20249fd4b24cf27542013624d18710bc418e8de10d6ef68568 -f SampleContract.cs
8afa45fd1497c69c92a9dc11b8c4db1ef1b04b5095433f6106d0ad27fdd7dcac
# Instantiate Smart Contract
The deployed smart contract exists as a compiled assembly in Miyabi.
To use the deployed smart contract, the user needs to create an instance of the smart contract.
The contract instantiation 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 aforementioned three parameters constitutes the InstanceId
for strictly distinguishing different instances.
The transaction needs to be signed by at least one Instantiator
address, and other addresses according to the required permissions.
The instantiatecontract
command has the following parameters:
Item | Type | Description |
---|---|---|
Assembly Id | ByteString | Assembly Id of the deployed smart contract |
Instance Name | string | Instance name for the new instance of the deployed smart contract |
Contract Name | string | The class inherited ContractBase and whose instantiate function will be called |
Instance Owners | Address[] | Address(es) of instance owner. |
Private Keys | PrivateKey[] | Private key of user or valid signer as defined in contract (optional) |
Arguments | string[] | An array containing all the parameters needed for the instantiate function (optional) |
# Example
$ ./miyabi-cli.exe sendtransaction instantiatecontract -p 6591bfae609236291e2d22609aeb1ce74550dcbbc628f91b6eef3c6f350a79da -p 10425b7e6ebf5e0d5918717f77ce8a66aaf92bc64b65996f885ff12bd94ef529 -a 8819851eae0bca115266bd329527c595f6320a19a2975de9773c4c8d352c0ff6 -c "SmartContractSample.ContractFiles.SampleContract" -i "test_SampleContract_instance" -o 0249a37736e3290729ea5cd12abe5575cc4153f76dbb540b9b94d929e63d1b6077
4816c26ee6e4d6efcb72006e24fcd25f2940720c9a7ae8236ede162987aa3826
# Invoke Smart Contract
Users can invoke methods of a smart contract instance to do various operations. A smart contract method can potentially:
- Make changes to the World State
- Make changes to the data of the smart contract instance
- Communicate with other smart contracts
- Perform some idempotent operations
Users can only invoke the method with a void
return type and check the result by transaction result code.
Contract invocation can be done using a ContractInvoke
transaction entry, in which, the user can input the method name and the respective arguments of the method to be invoked.
The invokecontract
command has the following parameters:
Item | Type | Description |
---|---|---|
Assembly Id | ByteString | Assembly Id of the deployed smart contract |
Instance Name | string | Instance name provided by user to distinguish different instance |
Contract Name | string | The class inherited ContractBase and whose instantiate function will be called |
Method Name | string | The method invoked in the smart contract. Must return void |
Arguments | string[] | An array provide all the arguments needed for the method being invoked (optional) |
Private keys | PrivateKey[] | Private key of user or valid signer as defined in contract (optional) |
The method arguments can be of following types:
ByteString
PublicKey
Address
- Primitive types
- Miyabi types serialized as JSON string
The following objects cannot be treated as input parameters: Object
, Empty
(Null reference), DateTime
, 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.
# Example
$ ./miyabi-cli.exe sendtransaction invokecontract -a 8819851eae0bca115266bd329527c595f6320a19a2975de9773c4c8d352c0ff6 -c "SmartContractSample.ContractFiles.SampleContract" -i "test_SampleContract_instance" -m "RegisterAccount" --argument 032fc2558d4df2e251a79be12926abf9f5fa0932311d6e19a63fb0ab46c39e35be
9303d672fd1dc9a9a26b159fbf12f46ad23b7b080fb1bcbac6ab05106530bc02
# Contract Event
Users can also store their customized data into the event through smart contracts.
Users need to define their event data derived from ContractEventBase
and use IContractExecutionContext.TriggerEvent(event)
to trigger the event builder.
The event data can be serialized to ByteString and stored in the filter FilterData
, used in the bloom filter of the block event for quick searching in a block.
# Query Smart Contract
Users can use the API to query the smart contract. The contract query request is a read request to the World State and can't make any changes to it. In return, the query methods have a non-void return type as the HTTP response.
The querycontract
command has the following parameters:
Item | Type | Description |
---|---|---|
Assembly Id | ByteString | Assembly Id of the deployed smart contract |
Instance Name | string | Instance name provided by user to distinguish different instance |
Contract Name | string | The class inherited ContractBase and whose instantiate function will be called |
Method Name | string | Name of the smart contract method |
Parameters | string[] | An array containing all the parameters needed for the query method being invoked (optional) |
# Example
$ ./miyabi-cli.exe querycontract -a 8819851eae0bca115266bd329527c595f6320a19a2975de9773c4c8d352c0ff6 -c "SmartContractSample.ContractFiles.SampleContract" -i "test_SampleContract_instance" -m "IsAccountRegistered" -p 032fc2558d4df2e251a79be12926abf9f5fa0932311d6e19a63fb0ab46c39e35be
true
# Delete Smart Contract Instance
In Miyabi, smart contract users can delete the instance of a deployed contract with the help of instance owner's signatures.
The deletecontractinstance
command has the following parameters.
Item | Type | Description |
---|---|---|
Assembly Id | ByteString | Assembly Id of the deployed smart contract |
Instance Name | string | Instance name of the smart contract to be deleted |
Contract Name | string | The class inherited ContractBase and whose instantiate function will be called |
Private keys | Privatekey[] | Private key(s) of the smart contract instance owners (optional) |
# Example
$ ./miyabi-cli.exe sendtransaction deletecontractinstance -p 6591bfae609236291e2d22609aeb1ce74550dcbbc628f91b6eef3c6f350a79da -p 6591bfae609236291e2d22609aeb1ce74550dcbbc628f91b6eef3c6f350a79dc -a 8819851eae0bca115266bd329527c595f6320a19a2975de9773c4c8d352c0ff6 -c "SmartContractSample.ContractFiles.SampleContract" -i test_SampleContract_instance
1b80556428619de86557acb761c19368a52826cc75e8ddfcbd39841f3f385502