EVM-based Smart Contract Quickstart

Unity SDK & EVM-based Smart Contracts Quickstart

zeknd supports EVM (Ethereum Virtual Machine) and plugin-based smart contracts. Plugin-based smart contracts can be created with go-zeknd, for example.

In the following sections, we will demonstrate how to use the Unity SDK to communicate with an EVM-based smart contract.

#Sample Code

This sample uses the Solidity contract from unity-tiles-chain-evm demo. For the purpose of this sample, we will use this sample contract just to store a string.

#Connecting to a DAppChain

The EvmContract class provides a convenient way to interact with a smart contract running on a zeknd DAppChain running an EVM-compatible smart contract. Let's write a method that creates an EvmContract instance to interact with the sample TilesChain smart contract.

// zekndEvmQuickStartSample.cs
using UnityEngine;
using System;
using System.Threading.Tasks;
using zeknd.Unity3d;
using zeknd.Nethereum.ABI.FunctionEncoding.Attributes;

public class zekndEvmQuickStartSample : MonoBehaviour
{
    async Task<EvmContract> GetContract(byte[] privateKey, byte[] publicKey)
    {
        var writer = RPCClientFactory.Configure()
            .WithLogger(Debug.unityLogger)
            .WithWebSocket("ws://127.0.0.1:46658/websocket")
            .Create();

        var reader = RPCClientFactory.Configure()
            .WithLogger(Debug.unityLogger)
            .WithWebSocket("ws://127.0.0.1:46658/queryws")
            .Create();

        var client = new DAppChainClient(writer, reader)
            { Logger = Debug.unityLogger };

        // required middleware
        client.TxMiddleware = new TxMiddleware(new ITxMiddlewareHandler[]
        {
            new NonceTxMiddleware
            {
                PublicKey = publicKey,
                Client = client
            },
            new SignedTxMiddleware(privateKey)
        });

        // ABI of the Solidity contract
        const string abi = "[{\"constant\":false,\"inputs\":[{\"name\":\"_tileState\",\"type\":\"string\"}],\"name\":\"SetTileMapState\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetTileMapState\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"state\",\"type\":\"string\"}],\"name\":\"OnTileMapStateUpdate\",\"type\":\"event\"}]\r\n";
        // Note: With EVM based smart contracts, you can't access them by name.
        // Put the address of your deployed contract here.
        var contractAddr = Address.FromHexString("0xf420fbbb810698a74120df3723315ee06f472870");
        var callerAddr = Address.FromPublicKey(publicKey);

        return new EvmContract(client, contractAddr, callerAddr, abi);
    }
}

#Writing data to a DAppChain

To mutate the state of a smart contract you need to call one of its public methods. To do so a signed transaction must be sent to and validated by the DAppChain. Fortunately, the EvmContract class takes care of most of this when you use the EvmContract.Call*Async() family of methods.

The TilesChain smart contract has a public SetTileMapState method that can be called to store a string value. Note that this method doesn't return anything. Let's add a method to the zekndEvmQuickStartSample class that calls TilesChain.SetTileMapState():

#Reading data from a DAppChain

To read the state of a smart contract you need to call one of its public read-only methods. Calling a read-only method doesn't modify the smart contract state. You can call a read-only method on a smart contract by using the EvmContract.StaticCall*Async() family of methods.

The TilesChain smart contract has a public GetTileMapState method that can be called to get the stored string value. Let's add a method to the zekndEvmQuickStartSample class that calls TilesChain.GetTileMapState.

#Receiving events from a DAppChain

DAppChains can trigger events in reaction to calling a smart contract. To be notified of new events, you must subscribe to the EvmContract.EventReceived event. But first, we need to define a DTO (Data Transfer Object) that specifies the event parameters:

#Putting it all together

Add the following method to the zekndEvmQuickStartSample class.

Now that we have all the code in place, let's test it out:

  1. Create an empty GameObject in a Unity scene and attach the zekndEvmQuickStartSample script to it.

  2. Deploy the TilesChain smart contract on a local zeknd DAppChain node.

  3. Hit Play in the Unity Editor.

Last updated