Skip to content

Latest commit

 

History

History
135 lines (105 loc) · 5.52 KB

File metadata and controls

135 lines (105 loc) · 5.52 KB
title actions material
Static variables & Storage of Key-Value Pairs
checkAnswer
hints
editor
language startingCode answer
c#
public class AlienFinder : SmartContract { public class Alien { public uint Xna { get; set; } public string AlienName { get; set; } public BigInteger Id { get; set; } } ...... public static BigInteger GenerateAlien (string alienName, byte[] owner) { if (owner.Length != 20 && owner.Length != 33) throw new InvalidOperationException ("The parameter owner should be a 20-byte address or a 33-byte public key"); if (!Runtime.CheckWitness (owner)) return 0; uint xna = FindXna (RandomNumber ()); Alien someAlien = new Alien { Xna = xna, AlienName = alienName // Implement (3) here }; Runtime.Notify (alienName, "created"); // Implement (4) here return 1; } ...... private static BigInteger getCounter () { // Implement (1) here } private static BigInteger updateCounter () { // Implement (2) here } }
...... public static BigInteger GenerateAlien (string alienName, byte[] owner) { if (owner.Length != 20 && owner.Length != 33) throw new InvalidOperationException ("The parameter owner should be a 20-byte address or a 33-byte public key"); if (!Runtime.CheckWitness (owner)) return 0; uint xna = FindXna (RandomNumber ()); Alien someAlien = new Alien { Xna = xna, AlienName = alienName Id = UpdateCounter (); }; Runtime.Notify (someAlien.Id, "created"); return someAlien.Id; } ...... private static BigInteger GetCounter () { BigInteger counter = 0; byte[] value = Storage.Get ("alienCount"); if (value.Length != 0) counter = value.ToBigInteger (); return counter; } private static BigInteger UpdateCounter () { BigInteger counter = GetCounter (); counter = counter + 1; Storage.Put (Storage.CurrentContext, "alienCount", counter); return counter; }

You may have noticed that a new field was added for the Alien class, called Id. The goal is to implement a couner that increments each time an alien is created, and use that as a unique id for each new alien.

Normally in C#, we would write a static field inside the Alien class like this

static uint counter = 0; 

But Neo contracts does not support static fields, unless it is read-only, which means only constant variables such as owner of the contract can have the static keyword. Here is an example of such:

public static readonly byte[] Owner = "ATrzHaicmhRj15C3Vv6e6gLfLqhSD2PtTr"; 

With this line, users or developers can call the Owner variable to access the address that owns this contract. And since it is readonly, it cannot be changed once deployed.

One work-around would be to put the number of aliens created so far into Neo network's persistent storage.

The Storage Class

Neo provides the storage class to store data on the blockchain. All data are stored in key-value pairs. Here are some of the attributes and methods inside the Storage class.

  • Storage.CurrentContext: Returns a StorageContext type, specific to the current contract.
  • Storage.Put (StorageContext, key, value)
  • Storage.Put (key, value)
  • Storage.Get (StorageContext, key)
  • Storage.Get (key)
  • Storage.Delete (StorageContext)
  • Storage.Delete (key)

Note that StorageContext is a custom type provided in Neo's framework. Each contract has its own StorageContext, by default, all Put () and Get () operations passes in the current context unless otherwise specified. Contracts sometimes pass their own StorageContext to other contracts as a way of authorising other code to modify their storage.

key can be of type string or byte[].

value can be of type string, BigInteger or byte[].

Here is an example of storing, accessing, and deleting data on the blockchain:

// Key is totalSupply and value is 100000000
Storage.Put (Storage.CurrentContext, "totalSupply", 100000000);

BigInteger totalSupply; 
var value = Storage.Get ("totalSupply"); // returns a byte[]
if (value.Length != 0)
    totalSupply = value.ToBigInteger (); // totalSupply is 100000000

Storage.Delete ("totalSupply"); 

Storage.Get ("totalSupply"); // returns a byte[] of length 0

Instructions

  1. In GetCounter (), initiate counter with value of 0. If the value in storage with key alienCount does not return a byte[] of Length 0, set counter to that value. Otherwise, return counter with value of 0.
  2. In UpdateCounter (), initiate counter and pass in the result of GetCounter (). Increment counter by 1. Save the value into storage with key alienCount. Return the new counter.
    • Note: conventional increment statments counter++ cannot be interpreted by Neo compiler, use counter = counter + 1 instead.
  3. In the new Alien call, add a third line, and set Id to the return value of UpdateCoutner ().
  4. Change the return value to the new Alien's Id.