Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Numerous modifications and optimization for Template.NEP5.CSharp #304

Merged
merged 24 commits into from
Jul 31, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 0 additions & 53 deletions templates/Template.NEP5.CSharp/NEP5.Admin.cs

This file was deleted.

29 changes: 10 additions & 19 deletions templates/Template.NEP5.CSharp/NEP5.Crowdsale.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@ private static BigInteger GetTransactionAmount(object state)

public static bool Mint()
{
if (Runtime.InvocationCounter != 1)
throw new Exception();
if (Runtime.InvocationCounter != 1) throw new Exception("InvocationCounter must be 1.");

var notifications = Runtime.GetNotifications();
if (notifications.Length == 0)
throw new Exception("Contribution transaction not found");
if (notifications.Length == 0) throw new Exception("Contribution transaction not found.");

BigInteger neo = 0;
BigInteger gas = 0;
Expand All @@ -49,27 +47,20 @@ public static bool Mint()
}
}

StorageMap contract = Storage.CurrentContext.CreateMap(StoragePrefixContract);
var supply = contract.Get("totalSupply");
if (supply == null)
throw new Exception("Contract not deployed");
var totalSupply = TotalSupplyStorage.Get();
if (totalSupply <= 0) throw new Exception("Contract not deployed.");

var current_supply = supply.ToBigInteger();
var avaliable_supply = MaxSupply - current_supply;
var avaliable_supply = MaxSupply - totalSupply;

var contribution = (neo * TokensPerNEO) + (gas * TokensPerGAS);
if (contribution <= 0)
throw new Exception();
if (contribution > avaliable_supply)
throw new Exception();
if (contribution <= 0) throw new Exception("Contribution cannot be zero.");
if (contribution > avaliable_supply) throw new Exception("Insufficient supply for mint tokens.");

StorageMap balances = Storage.CurrentContext.CreateMap(StoragePrefixBalance);
Transaction tx = (Transaction)ExecutionEngine.ScriptContainer;
var balance = balances.Get(tx.Sender)?.ToBigInteger() ?? 0;
balances.Put(tx.Sender, balance + contribution);
contract.Put("totalSupply", current_supply + contribution);
AssetStorage.Increase(tx.Sender, contribution);
TotalSupplyStorage.Increase(contribution);

OnTransfer(null, tx.Sender, balance + contribution);
OnTransfer(null, tx.Sender, contribution);
return true;
}
}
Expand Down
15 changes: 10 additions & 5 deletions templates/Template.NEP5.CSharp/NEP5.Helpers.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using System.Numerics;

namespace Template.NEP5.CSharp
{
public partial class NEP5 : SmartContract
{
private static bool ValidateAddress(byte[] address)
{
if (address.Length != 20)
return false;
if (address.ToBigInteger() == 0)
return false;
return true;
return address.Length == 20 && address.TryToBigInteger() != 0;
}

private static bool IsPayable(byte[] address)
Expand All @@ -20,4 +17,12 @@ private static bool IsPayable(byte[] address)
return c == null || c.IsPayable;
}
}

public static class Helper
{
public static BigInteger TryToBigInteger(this byte[] value)
{
return value?.ToBigInteger() ?? 0;
shargon marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
43 changes: 10 additions & 33 deletions templates/Template.NEP5.CSharp/NEP5.Methods.cs
Original file line number Diff line number Diff line change
@@ -1,51 +1,28 @@
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using Neo.SmartContract.Framework.Services.System;
using System;
using System.Numerics;

namespace Template.NEP5.CSharp
{
public partial class NEP5 : SmartContract
{
public static BigInteger TotalSupply()
{
StorageMap contract = Storage.CurrentContext.CreateMap(StoragePrefixContract);
return contract.Get("totalSupply")?.ToBigInteger() ?? 0;
}

public static BigInteger BalanceOf(byte[] account)
{
if (!ValidateAddress(account)) throw new FormatException("The parameter 'account' SHOULD be 20-byte addresses.");
public static BigInteger TotalSupply() => TotalSupplyStorage.Get();

StorageMap balances = Storage.CurrentContext.CreateMap(StoragePrefixBalance);
return balances.Get(account)?.ToBigInteger() ?? 0;
}
public static BigInteger BalanceOf(byte[] account) => AssetStorage.Get(account);
shargon marked this conversation as resolved.
Show resolved Hide resolved

public static bool Transfer(byte[] from, byte[] to, BigInteger amount)
{
if (!ValidateAddress(from)) throw new FormatException("The parameter 'from' SHOULD be 20-byte addresses.");
if (!ValidateAddress(to)) throw new FormatException("The parameters 'to' SHOULD be 20-byte addresses.");
if (!IsPayable(to)) return false;
if (amount <= 0) throw new InvalidOperationException("The parameter amount MUST be greater than 0.");
if (!Runtime.CheckWitness(from)) return false;

StorageMap balances = Storage.CurrentContext.CreateMap(StoragePrefixBalance);
BigInteger fromAmount = balances.Get(from).ToBigInteger();

if (fromAmount < amount) return false;
if (!ValidateAddress(from) || !ValidateAddress(to)) throw new Exception("The parameters from and to SHOULD be 20-byte addresses.");
if (amount <= 0) throw new Exception("The parameter amount MUST be greater than 0.");
if (!IsPayable(to)) throw new Exception("Receiver cannot receive.");
if (!Runtime.CheckWitness(from) && !from.Equals(ExecutionEngine.CallingScriptHash)) throw new Exception("No authorization.");
if (AssetStorage.Get(from) < amount) throw new Exception("Insufficient balance.");
if (amount == 0 || from == to) return true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

amount <= 0 will throw exception, so amount == 0 is impossible in there?


if (fromAmount == amount)
{
balances.Delete(from);
}
else
{
balances.Put(from, fromAmount - amount);
}

BigInteger toAmount = balances.Get(to)?.ToBigInteger() ?? 0;
balances.Put(to, toAmount + amount);
AssetStorage.Reduce(from, amount);
AssetStorage.Increase(to, amount);

OnTransfer(from, to, amount);
return true;
Expand Down
39 changes: 39 additions & 0 deletions templates/Template.NEP5.CSharp/NEP5.Owner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using Neo.SmartContract.Framework.Services.System;
using System;

namespace Template.NEP5.CSharp
{
public partial class NEP5 : SmartContract
{
public static bool Deploy()
{
if (!IsOwner()) throw new Exception("No authorization.");
if (TotalSupplyStorage.Get() > 0) throw new Exception("Contract has been deployed.");

TotalSupplyStorage.Increase(InitialSupply);

OnTransfer(null, Owner, InitialSupply);
return true;
}

public static bool Migrate(byte[] script, string manifest)
{
if (!IsOwner()) throw new Exception("No authorization.");
if (script.Length == 0 || manifest.Length == 0) return false;
if (script != null && script.Equals(Blockchain.GetContract(ExecutionEngine.ExecutingScriptHash))) return true;
shargon marked this conversation as resolved.
Show resolved Hide resolved
Contract.Update(script, manifest);
return true;
}

public static bool Destroy()
{
if (!IsOwner()) throw new Exception("No authorization.");
Contract.Destroy();
shargon marked this conversation as resolved.
Show resolved Hide resolved
return true;
}

private static bool IsOwner() => Runtime.CheckWitness(Owner);
}
}
37 changes: 8 additions & 29 deletions templates/Template.NEP5.CSharp/NEP5.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using System;
using System.ComponentModel;
using System.Numerics;
Expand All @@ -15,48 +14,28 @@ public partial class NEP5 : SmartContract
#region Token Settings
static readonly ulong MaxSupply = 10_000_000_000_000_000;
static readonly ulong InitialSupply = 2_000_000_000_000_000;
static readonly byte[] Owner = new byte[] { 0xf6, 0x64, 0x43, 0x49, 0x8d, 0x38, 0x78, 0xd3, 0x2b, 0x99, 0x4e, 0x4e, 0x12, 0x83, 0xc6, 0x93, 0x44, 0x21, 0xda, 0xfe };
static readonly byte[] Owner = "NiNmXL8FjEUEs1nfX9uHFBNaenxDHJtmuB".ToScriptHash();
static readonly ulong TokensPerNEO = 1_000_000_000;
static readonly ulong TokensPerGAS = 1;
static readonly byte[] NeoToken = new byte[] { 0x89, 0x77, 0x20, 0xd8, 0xcd, 0x76, 0xf4, 0xf0, 0x0a, 0xbf, 0xa3, 0x7c, 0x0e, 0xdd, 0x88, 0x9c, 0x20, 0x8f, 0xde, 0x9b };
static readonly byte[] GasToken = new byte[] { 0x3b, 0x7d, 0x37, 0x11, 0xc6, 0xf0, 0xcc, 0xf9, 0xb1, 0xdc, 0xa9, 0x03, 0xd1, 0xbf, 0xa1, 0xd8, 0x96, 0xf1, 0x23, 0x8c };
static readonly byte[] NeoToken = "0xde5f57d430d3dece511cf975a8d37848cb9e0525".HexToBytes();
static readonly byte[] GasToken = "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc".HexToBytes();
#endregion

#region Notifications
[DisplayName("Transfer")]
public static event Action<byte[], byte[], BigInteger> OnTransfer;
#endregion

#region Storage key prefixes
static readonly byte[] StoragePrefixBalance = new byte[] { 0x01, 0x01 };
static readonly byte[] StoragePrefixContract = new byte[] { 0x02, 0x02 };
#endregion

// When this contract address is included in the transaction signature,
// this method will be triggered as a VerificationTrigger to verify that the signature is correct.
public static bool Verify()
{
return Runtime.CheckWitness(Owner);
}
public static bool Verify() => IsOwner();

public static string Name()
{
return "Token Name";
}
public static string Name() => "Token Name";

public static string Symbol()
{
return "TokenSymbol";
}
public static string Symbol() => "TokenSymbol";

public static ulong Decimals()
{
return 8;
}
public static ulong Decimals() => 8;

public static string[] SupportedStandards()
{
return new string[] { "NEP-5", "NEP-10" };
}
public static string[] SupportedStandards() => new string[] { "NEP-5", "NEP-10" };
shargon marked this conversation as resolved.
Show resolved Hide resolved
}
}
20 changes: 20 additions & 0 deletions templates/Template.NEP5.CSharp/Storage/AssetStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Neo.SmartContract.Framework.Services.Neo;
using System.Numerics;

namespace Template.NEP5.CSharp
{
public static class AssetStorage
{
public static readonly string mapName = "asset";

public static void Increase(byte[] key, BigInteger value) => Put(key, Get(key) + value);

public static void Reduce(byte[] key, BigInteger value) => Put(key, Get(key) - value);

public static void Put(byte[] key, BigInteger value) => Storage.CurrentContext.CreateMap(mapName).Put(key, value);

public static BigInteger Get(byte[] key) => Storage.CurrentContext.CreateMap(mapName).Get(key).TryToBigInteger();

public static void Remove(byte[] key) => Storage.CurrentContext.CreateMap(mapName).Delete(key);
}
}
21 changes: 21 additions & 0 deletions templates/Template.NEP5.CSharp/Storage/TotalSupplyStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Neo.SmartContract.Framework.Services.Neo;
using System.Numerics;

namespace Template.NEP5.CSharp
{
public static class TotalSupplyStorage
{
public static readonly string mapName = "contract";

public static readonly string key = "totalSupply";

public static void Increase(BigInteger value) => Put(Get() + value);

public static void Reduce(BigInteger value) => Put(Get() - value);

public static void Put(BigInteger value) => Storage.CurrentContext.CreateMap(mapName).Put(key, value);

public static BigInteger Get() => Storage.CurrentContext.CreateMap(mapName).Get(key).TryToBigInteger();

}
}
25 changes: 0 additions & 25 deletions templates/Template.NEP5.CSharp/Template.NEP5.CSharp.sln

This file was deleted.

2 changes: 1 addition & 1 deletion tests/Template.NEP5.UnitTests/UnitTest_NEP5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ TestEngine CreateEngine()
engine.AddEntryScript(new string[]
{
"../../../../../templates/Template.NEP5.CSharp/NEP5.cs",
"../../../../../templates/Template.NEP5.CSharp/NEP5.Admin.cs",
"../../../../../templates/Template.NEP5.CSharp/NEP5.Owner.cs",
"../../../../../templates/Template.NEP5.CSharp/NEP5.Crowdsale.cs",
"../../../../../templates/Template.NEP5.CSharp/NEP5.Helpers.cs",
"../../../../../templates/Template.NEP5.CSharp/NEP5.Methods.cs"
Expand Down