Skip to content

Latest commit

 

History

History
139 lines (110 loc) · 6.23 KB

05.md

File metadata and controls

139 lines (110 loc) · 6.23 KB
title actions requireLogin material
Understanding the _deploy Function
checkAnswer
hints
true
editor
language startingCode answer
cs
nns-client.cs
using Neo.SmartContract.Framework; using Neo.SmartContract.Framework.Attributes; using Neo.SmartContract.Framework.Native; using Neo.SmartContract.Framework.Services; using System; using System.ComponentModel; using System.Numerics; namespace Neo.SmartContract.CryptoZombies { [DisplayName("TestNNS")] [ManifestExtra("Author", "CryptoZombies")] [ManifestExtra("Email", "[email protected]")] [ManifestExtra("Description", "This is a a client for invoking NNS")] [ContractPermission("*", "*")] public class NNSClient : Framework.SmartContract { [InitialValue("NdUL5oDPD159KeFpD5A9zw5xNF1xLX6nLT", ContractParameterType.Hash160)] private static readonly UInt160 owner = default; private static readonly byte[] ownerKey = owner.ToByteArray(); public static UInt160 GetOwner() { return (UInt160)ContractMap.Get(ownerKey); } private const byte Prefix_Contract = 0x02; public static readonly StorageMap ContractMap = new(Storage.CurrentContext, Prefix_Contract); [InitialValue("0x50ac1c37690cc2cfc594472833cf57505d5f46de", ContractParameterType.Hash160)] private static readonly UInt160 nnsHash = default; public static bool RegisterDomain(string name) { bool result = (bool)Contract.Call(nnsHash, "register", CallFlags.All, name, Runtime.ExecutingScriptHash); return result; } // Start here } }
using Neo.SmartContract.Framework; using Neo.SmartContract.Framework.Attributes; using Neo.SmartContract.Framework.Native; using Neo.SmartContract.Framework.Services; using System; using System.ComponentModel; using System.Numerics; namespace Neo.SmartContract.CryptoZombies { [DisplayName("TestNNS")] [ManifestExtra("Author", "CryptoZombies")] [ManifestExtra("Email", "[email protected]")] [ManifestExtra("Description", "This is a a client for invoking NNS")] [ContractPermission("*", "*")] public class NNSClient : Framework.SmartContract { [InitialValue("NdUL5oDPD159KeFpD5A9zw5xNF1xLX6nLT", ContractParameterType.Hash160)] private static readonly UInt160 owner = default; private static readonly byte[] ownerKey = owner.ToByteArray(); public static UInt160 GetOwner() { return (UInt160)ContractMap.Get(ownerKey); } private const byte Prefix_Contract = 0x02; public static readonly StorageMap ContractMap = new(Storage.CurrentContext, Prefix_Contract); [InitialValue("0x50ac1c37690cc2cfc594472833cf57505d5f46de", ContractParameterType.Hash160)] private static readonly UInt160 nnsHash = default; public static bool RegisterDomain(string name) { bool result = (bool)Contract.Call(nnsHash, "register", CallFlags.All, name, Runtime.ExecutingScriptHash); return result; } public static void _deploy(object data, bool update) { if (update) return; ContractMap.Put(ownerKey, owner); } } }

Now that you've learned how to invoke the Neo Name Service smart contract, we'll move on and look at two key aspects of building on Neo - how contracts are deployed and updated.

To facilitate contract initialization and storage setup, Neo provides a designated entry point in the form a function named _deploy.

The _deploy function has the following signature:

public static void _deploy(object data, bool update)
{
  // Deployment logic
}

Let's break down the parameters of the _deploy function:

  • data: An optional parameter that can be used to pass additional data to the _deploy function during contract deployment. It can be any object or information needed for initialization purposes.
  • update: A boolean parameter that indicates whether the contract is being deployed for the first time or being updated. If update is true, it means the contract is being updated and not freshly deployed.

Next, when a contract is updated, Neo provides a similar function named Update. As this function is public it means that anybody could call it which can become a problem. To solve this issue, we need to save the address of the owner when the contract is deployed and then, the Update function must ensure that it's invoked by the owner of the contract.

That being said, the first thing the _deploy function should do is to verify that the value of the update parameter is false, using something like this:

if (update) return;

Next, you would want to store the address of the owner in the contract storage. As you probably remember from one of the previous chapters, you can only store and retrieve data as key-value pairs, so you'll use the owner key as the key and the owner address as the value.

We went ahead and wrote some boilerplate code that specifies the owner address and determines the owner key. Check out the code we've written and make sure you understand what it does before you continue.

Note: If you want to use this code in your own smart contract, make sure to update the line of code that sets the address of the owner!

Next, you must declare the _invoke function and invoke the Put method of the ContractMap object to store the owner address and key. This method takes two parameters - a key under which the value will be stored and the value to be stored in the storage map.

Putting it to the Test

  1. Create a new public static void function named _deploy that takes two parameters - data of type object and update of type bool.
  2. The first line of your new fucntion should use the example above to ensure that the value of the update parameter is false.
  3. Next, you must call the Put function of the ContractMap object, passing it ownerKey and owner.