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

Add Nep11Token #1670

Closed
wants to merge 132 commits into from
Closed
Show file tree
Hide file tree
Changes from 116 commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
22469d3
init
bettybao1209 Apr 22, 2020
8b0565c
Merge remote-tracking branch 'upstream/master' into nns
bettybao1209 Apr 22, 2020
643b566
functions in ntf contract
bettybao1209 Apr 24, 2020
c45940d
add admaininfo and recordinfo
bettybao1209 Apr 26, 2020
252480d
add functions
bettybao1209 Apr 26, 2020
6a9c7c9
add access control
bettybao1209 Apr 26, 2020
815f1d7
remove unused namespace
bettybao1209 Apr 27, 2020
dd0cb86
Merge remote-tracking branch 'upstream/master' into nns
bettybao1209 Apr 27, 2020
51ab9a3
registerrootname
bettybao1209 Apr 27, 2020
5afec85
optimize
bettybao1209 Apr 27, 2020
635c41a
refactor and optimiza
bettybao1209 Apr 27, 2020
62b33a1
add ttl check
bettybao1209 Apr 27, 2020
ec3dd26
add cross level check
bettybao1209 Apr 28, 2020
14a14d7
optimize
bettybao1209 Apr 28, 2020
634d3e3
transfer gas when renew ttl
bettybao1209 Apr 28, 2020
b23f7a4
change based on review
bettybao1209 Apr 28, 2020
9e24c15
modify transfer
bettybao1209 Apr 29, 2020
fa60149
init
doubiliu May 7, 2020
d16096d
modify iterator
doubiliu May 8, 2020
77ebfd3
improve
doubiliu May 11, 2020
31bc011
improve2
doubiliu May 11, 2020
d2c0dd6
format
doubiliu May 11, 2020
6b5783b
improve2
doubiliu May 12, 2020
cf9ed6e
improve3
doubiliu May 12, 2020
46a0981
Add UT
doubiliu May 13, 2020
b62cd60
Add UT 2
doubiliu May 14, 2020
e4aef91
Add UT3
doubiliu May 14, 2020
d6b5051
format
doubiliu May 14, 2020
28b7c40
Add UT3
doubiliu May 14, 2020
3645e39
Add UT5
doubiliu May 14, 2020
a7b96fc
Merge branch 'master' into nns-improve
doubiliu May 14, 2020
5d291dd
Remove useless code
May 15, 2020
41f493f
Add UT5
doubiliu May 15, 2020
d10e4a8
Remove ToJson
May 18, 2020
529d730
Update default value
May 18, 2020
3226cd5
format
May 18, 2020
ae5ed65
Unify nns ut
May 18, 2020
af418e6
optize code
May 18, 2020
5bc2345
Optimze src/neo/SmartContract/NNS/NNSContract.Resolver.cs
May 18, 2020
b689e2f
Remove constuctor
May 19, 2020
4e3a966
Reset partial
May 19, 2020
3ddbaf3
Rename NNSContract to NnsContract
May 19, 2020
acf1cbb
Merge branch 'master' into nns-improve
vncoelho May 19, 2020
ea974b7
fix conflicts
May 20, 2020
e35cab8
Remove RecordType:NS
doubiliu May 20, 2020
cca7086
reset neo.sln
May 20, 2020
c3d9d28
Reset neo.sln
May 20, 2020
de49064
Rename NNS to Nns
May 20, 2020
8e76e90
Rename Nep11TokenState.Name to TokenId
May 21, 2020
0283d0d
Change RecordInfo.Text from string to byte[]
May 21, 2020
c09f8fa
fix and optimize NNSContract.Resolver
May 21, 2020
58c8b19
Optimize resolver and nns.transfer
May 21, 2020
c716579
format
May 21, 2020
70be161
optimize registertable/registercenter
May 21, 2020
14f3219
Remove nns.GetInnerKey
May 21, 2020
cc6f4cb
Change nep11.getInnerKey from uint256 to uint160
May 21, 2020
6c8fe32
Remove NNSContract.RegisterTable.cs
May 21, 2020
fd240e2
remove NNS foleder
May 21, 2020
0b196a8
Rename to Nns folder
May 21, 2020
577a877
optimize nep11.Burn
May 21, 2020
8ca85f6
Reset incorrect check
May 21, 2020
96b34d5
Remove src/neo/SmartContract/Nns/NnsContract.RegisterCenter.cs
May 21, 2020
ebaa66f
Optize nep11token
May 22, 2020
b2fc4a7
Adjust function permissions
May 22, 2020
b57ce76
Remove the config of ReceiptAddress and RentalPrice
May 22, 2020
f341213
Remove admin, add register method, optimize transfer
May 22, 2020
8e88558
Remove RecordInfo
May 22, 2020
47cda90
Remove Cross-Level
May 22, 2020
cca3209
optimize resolve
May 22, 2020
b2aec08
fix ut
May 22, 2020
dfd15b3
reset nep5
May 22, 2020
583a875
Rename Prefix_Ownership
May 22, 2020
bd1de48
fix
May 22, 2020
96e9d83
Reorder
May 23, 2020
76c2291
Merge branch 'master' into nns-improve
May 23, 2020
ed6e402
Add comments
May 23, 2020
9d47028
optimize register/transfer method
May 25, 2020
30766fe
fix ut
May 26, 2020
e8a39f8
add SetOperator
May 26, 2020
5e34a29
format
May 26, 2020
9f6fef6
Merge remote-tracking branch 'upstream/master' into nns-improve
May 26, 2020
d2cdcb9
fix
May 26, 2020
7d29183
Merge branch 'master' into nns-improve
May 26, 2020
94948b4
Order static vars
shargon May 26, 2020
13e4660
init
doubiliu May 26, 2020
dcb2b52
Merge branch 'master' into nep11token
shargon May 26, 2020
10dac9b
Clean method
shargon May 26, 2020
f29bd9b
Update src/neo/SmartContract/Native/Tokens/Nep11Token.cs
vncoelho May 26, 2020
ea0ca45
Update src/neo/SmartContract/Native/Tokens/Nep11Token.cs
vncoelho May 26, 2020
9720b58
apply commits
May 26, 2020
19e7d17
fix ut
May 26, 2020
e1bc6d6
Rename
erikzhang May 27, 2020
30206f0
Merge branch 'master' into nep11token
erikzhang May 27, 2020
23a23ca
Reset UT_IOHelper
May 27, 2020
da94b8b
Merge branch 'nep11token' of https://github.com/bettybao1209/neo into…
May 27, 2020
171e9b9
Revert neo.sln
erikzhang May 27, 2020
3d49819
Rename
erikzhang May 27, 2020
5355bc8
Rename
erikzhang May 27, 2020
7ea6638
Modify Mint()
erikzhang May 27, 2020
adf9c4d
Rename
erikzhang May 27, 2020
1506cbc
Update Nep11Token.cs
erikzhang May 27, 2020
ab7287c
Set deciamls = 0
May 28, 2020
d87a15e
format
May 28, 2020
7a9d11c
fix ownerOf
May 28, 2020
a19dfda
remove useless codes
May 28, 2020
c24af36
add UT
doubiliu May 28, 2020
66b76d3
Merge branch 'nep11token' of github.com:bettybao1209/neo into nep11token
doubiliu May 28, 2020
9bbb6ee
add UT
doubiliu May 28, 2020
405a4e7
optimize prefix
May 28, 2020
718404f
fix ownerof and tokensof
May 28, 2020
efdcd9a
format
May 28, 2020
8ce35ba
Merge branch 'master' into nep11token
Jun 1, 2020
d964521
Merge remote-tracking branch 'upstream/master' into nep11token
Jun 1, 2020
9f8149a
fix conflicts
Jun 1, 2020
e1335f1
Merge branch 'nep11token' of https://github.com/bettybao1209/neo into…
Jun 1, 2020
4efb913
Merge branch 'master' into nep11token
shargon Jun 1, 2020
26382c6
Update src/neo/SmartContract/Native/Tokens/Nep11Token.cs
doubiliu Jun 3, 2020
07921ba
Update src/neo/SmartContract/Native/Tokens/Nep11Token.cs
doubiliu Jun 3, 2020
56025de
Fix bug
doubiliu Jun 4, 2020
f2c1ad4
remove const
doubiliu Jun 4, 2020
63ebdb2
Merge branch 'master' into nep11token
shargon Jun 4, 2020
a5ac5b1
fix OwnerOf
Jun 5, 2020
30c2def
Merge branch 'nep11token' of https://github.com/bettybao1209/neo into…
Jun 5, 2020
e034c54
Merge branch 'master' into nep11token
doubiliu Jun 12, 2020
6c11a4c
Fix conficts
doubiliu Jun 12, 2020
d5c5d5c
format
doubiliu Jun 12, 2020
7f8489f
adapter the interface
doubiliu Jun 15, 2020
c1ca1ad
adapter
doubiliu Jun 15, 2020
b7d8758
Merge branch 'master' into nep11token
doubiliu Jun 15, 2020
c695cc1
Merge branch 'master' into nep11token
shargon Jul 2, 2020
333f255
Merge branch 'master' into nep11token
doubiliu Jul 7, 2020
844b6d7
Merge branch 'master' into nep11token
Tommo-L Oct 22, 2020
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
5 changes: 3 additions & 2 deletions src/neo/IO/Caching/DataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public DataCache<TKey, TValue> CreateSnapshot()
/// Delete key from cached Dictionary or search in Internal.
/// </summary>
/// <param name="key">Key to be deleted.</param>
public void Delete(TKey key)
public bool Delete(TKey key)
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
{
lock (dictionary)
{
Expand All @@ -130,7 +130,7 @@ public void Delete(TKey key)
else
{
TValue item = TryGetInternal(key);
if (item == null) return;
if (item == null) return false;
dictionary.Add(key, new Trackable
{
Key = key,
Expand All @@ -140,6 +140,7 @@ public void Delete(TKey key)
changeSet.Add(key);
}
}
return true;
}

protected abstract void DeleteInternal(TKey key);
Expand Down
29 changes: 29 additions & 0 deletions src/neo/SmartContract/Enumerators/CollectionWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

using Neo.VM.Types;

namespace Neo.SmartContract.Enumerators
{
public class CollectionWrapper : IEnumerator
{
private System.Collections.Generic.IEnumerator<StackItem> enumerator;

public CollectionWrapper(System.Collections.Generic.IEnumerator<StackItem> enumerator)
{
this.enumerator = enumerator;
}

public void Dispose()
{
}

public bool Next()
{
return enumerator.MoveNext();
}

public StackItem Value()
{
return enumerator.Current;
}
}
}
269 changes: 269 additions & 0 deletions src/neo/SmartContract/Native/Tokens/Nep11Token.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
#pragma warning disable IDE0060

using Neo.Cryptography;
using Neo.IO;
using Neo.IO.Json;
using Neo.Ledger;
using Neo.Persistence;
using Neo.SmartContract.Enumerators;
using Neo.SmartContract.Manifest;
using Neo.VM;
using Neo.VM.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Array = Neo.VM.Types.Array;

namespace Neo.SmartContract.Native.Tokens
{
public abstract class Nep11Token<TToken, TAccount> : NativeContract
where TToken : Nep11TokenState, new()
where TAccount : AccountState, new()
{
public override string[] SupportedStandards { get; } = { "NEP-10", "NEP-11" };
public abstract string Symbol { get; }
public BigInteger Factor { get; }

public const byte Decimals = 0;
Copy link
Member

Choose a reason for hiding this comment

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

We can remove this const


private const byte Prefix_TotalSupply = 20;
private const byte Prefix_OwnerToTokenId = 21;
private const byte Prefix_TokenIdToOwner = 22;
private const byte Prefix_TokenId = 23;

private const int MaxTokenIdLength = 256;
shargon marked this conversation as resolved.
Show resolved Hide resolved

protected Nep11Token()
{
this.Factor = BigInteger.Pow(10, Decimals);

Manifest.Features = ContractFeatures.HasStorage;

var events = new List<ContractEventDescriptor>(Manifest.Abi.Events)
{
new ContractMethodDescriptor()
{
Name = "Transfer",
Parameters = new ContractParameterDefinition[]
{
new ContractParameterDefinition()
{
Name = "from",
Type = ContractParameterType.Hash160
},
new ContractParameterDefinition()
{
Name = "to",
Type = ContractParameterType.Hash160
},
new ContractParameterDefinition()
{
Name = "amount",
Type = ContractParameterType.Integer
},
new ContractParameterDefinition()
{
Name = "tokenId",
Type = ContractParameterType.ByteArray
}
},
ReturnType = ContractParameterType.Boolean
}
};

Manifest.Abi.Events = events.ToArray();
}

[ContractMethod(0, ContractParameterType.String, CallFlags.None, Name = "name")]
protected StackItem NameMethod(ApplicationEngine engine, Array args)
{
return Name;
}

[ContractMethod(0, ContractParameterType.String, CallFlags.None, Name = "symbol")]
protected StackItem SymbolMethod(ApplicationEngine engine, Array args)
{
return Symbol;
}

[ContractMethod(0, ContractParameterType.Integer, CallFlags.None, Name = "decimals")]
protected StackItem DecimalsMethod(ApplicationEngine engine, Array args)
{
return (uint)Decimals;
}

[ContractMethod(0_01000000, ContractParameterType.Integer, CallFlags.AllowStates)]
protected StackItem TotalSupply(ApplicationEngine engine, Array args)
{
return TotalSupply(engine.Snapshot);
}

public virtual BigInteger TotalSupply(StoreView snapshot)
{
StorageItem storage = snapshot.Storages.TryGet(CreateStorageKey(Prefix_TotalSupply));
if (storage is null) return BigInteger.Zero;
return new BigInteger(storage.Value);
}

[ContractMethod(0_01000000, ContractParameterType.Integer, CallFlags.AllowStates, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.ByteArray }, ParameterNames = new[] { "account", "tokenId" })]
protected StackItem BalanceOf(ApplicationEngine engine, Array args)
{
UInt160 account = new UInt160(args[0].GetSpan());
byte[] tokenId = args[1].GetSpan().ToArray();
doubiliu marked this conversation as resolved.
Show resolved Hide resolved
if (tokenId.Length > MaxTokenIdLength) return false;
return BalanceOf(engine.Snapshot, account, tokenId);
}

public virtual BigInteger BalanceOf(StoreView snapshot, UInt160 account, byte[] tokenId)
{
UInt160 innerKey = GetInnerKey(tokenId);
StorageItem storage = snapshot.Storages.TryGet(CreateOwnershipKey(Prefix_OwnerToTokenId, account, innerKey));
if (storage is null) return BigInteger.Zero;
return storage.GetInteroperable<TAccount>().Balance;
}

[ContractMethod(0_01000000, ContractParameterType.Array, CallFlags.AllowStates, ParameterTypes = new[] { ContractParameterType.Hash160 }, ParameterNames = new[] { "owner" })]
public StackItem TokensOf(ApplicationEngine engine, Array args)
{
UInt160 owner = new UInt160(args[0].GetSpan());
return new InteropInterface(TokensOf(engine.Snapshot, owner));
}

public virtual IEnumerator TokensOf(StoreView snapshot, UInt160 owner)
{
return new CollectionWrapper(snapshot.Storages.Find(CreateStorageKey(Prefix_OwnerToTokenId, owner).ToArray()).Select(p =>
{
UInt160 innerKey = new UInt160(p.Key.Key.Skip(1 + UInt160.Length).Take(UInt160.Length).ToArray());
TToken token = snapshot.Storages.TryGet(CreateTokenKey(innerKey)).GetInteroperable<TToken>();
return (StackItem)token.Id;
}).GetEnumerator());
}

[ContractMethod(0_01000000, ContractParameterType.InteropInterface, CallFlags.None, ParameterTypes = new[] { ContractParameterType.ByteArray }, ParameterNames = new[] { "tokenId" })]
public StackItem OwnerOf(ApplicationEngine engine, Array args)
{
byte[] tokenId = args[0].GetSpan().ToArray();
if (tokenId.Length > MaxTokenIdLength) return false;
return new InteropInterface(OwnerOf(engine.Snapshot, tokenId));
}

public virtual IEnumerator OwnerOf(StoreView snapshot, byte[] tokenId)
Copy link
Member

Choose a reason for hiding this comment

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

IEnumerable<StackItem> ?

{
doubiliu marked this conversation as resolved.
Show resolved Hide resolved
UInt160 innerKey = GetInnerKey(tokenId);
return new CollectionWrapper(snapshot.Storages.Find(CreateStorageKey(Prefix_TokenIdToOwner, innerKey).ToArray()).Select(p =>
{
var owner = p.Key.Key.Skip(1 + UInt160.Length).Take(UInt160.Length).ToArray();
return (StackItem)owner;
}).GetEnumerator());
}

[ContractMethod(0_08000000, ContractParameterType.Boolean, CallFlags.AllowModifyStates, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.ByteArray }, ParameterNames = new[] { "to", "tokenId" })]
public virtual StackItem Transfer(ApplicationEngine engine, Array args)
{
UInt160 to = new UInt160(args[0].GetSpan());
byte[] tokenId = args[1].GetSpan().ToArray();
if (tokenId.Length > MaxTokenIdLength) return false;
Copy link
Member

Choose a reason for hiding this comment

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

Accorging to
https://github.com/neo-project/proposals/pull/41/files?short_path=afd2225#diff-afd22253b102da74b022d8c022201ee6

The parameter tokenid SHOULD be a valid NFT. If not, this method SHOULD throw an exception.

return Transfer(engine, to, tokenId);
}

public virtual bool Transfer(ApplicationEngine engine, UInt160 to, byte[] tokenId)
{
IEnumerator enumerator = OwnerOf(engine.Snapshot, tokenId);
if (!enumerator.Next()) return false;
UInt160 owner = new UInt160(enumerator.Value().GetSpan().ToArray());
if (!engine.CheckWitnessInternal(owner)) return false;
Copy link
Member

Choose a reason for hiding this comment

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

If the owner it's the second in the enumerator?

Copy link
Contributor

Choose a reason for hiding this comment

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

It has only one owner, when Decimals = 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will not happen, because in this contract NFT is restricted to be indivisible, so there is no second owner.

Copy link
Member

Choose a reason for hiding this comment

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

Then why the enumerator?

Copy link
Contributor

Choose a reason for hiding this comment

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

We need IEnumerator for tokensOf methods of nep11 .

public static enumerator tokensOf(byte[] owner)

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we can use UInt160 as the return type of the internal tokensOf, it's ok for me.


var snapshot = engine.Snapshot;
ContractState contract_to = snapshot.Contracts.TryGet(to);
if (contract_to?.Payable == false) return false;

UInt160 innerKey = GetInnerKey(tokenId);
snapshot.Storages.Delete(CreateOwnershipKey(Prefix_OwnerToTokenId, owner, innerKey));
snapshot.Storages.Delete(CreateOwnershipKey(Prefix_TokenIdToOwner, innerKey, owner));
snapshot.Storages.Add(CreateOwnershipKey(Prefix_OwnerToTokenId, to, innerKey), new StorageItem(new TAccount() { Balance = Factor }));
snapshot.Storages.Add(CreateOwnershipKey(Prefix_TokenIdToOwner, innerKey, to), new StorageItem(new byte[0]));
doubiliu marked this conversation as resolved.
Show resolved Hide resolved

engine.SendNotification(Hash, new Array(new StackItem[] { "Transfer", owner.ToArray(), to.ToArray(), Factor, tokenId }));
return true;
}

[ContractMethod(0_01000000, ContractParameterType.Boolean, CallFlags.AllowModifyStates, ParameterTypes = new[] { ContractParameterType.ByteArray }, ParameterNames = new[] { "tokenId" })]
protected StackItem Properties(ApplicationEngine engine, Array args)
{
byte[] tokenId = args[0].GetSpan().ToArray();
if (tokenId.Length > MaxTokenIdLength) return false;
return Properties(engine.Snapshot, tokenId).ToString();
}

public abstract JObject Properties(StoreView snapshot, byte[] tokenId);

internal protected virtual void Mint(ApplicationEngine engine, UInt160 account, TToken token)
{
doubiliu marked this conversation as resolved.
Show resolved Hide resolved
var storages = engine.Snapshot.Storages;
UInt160 innerKey = GetInnerKey(token.Id);
StorageKey tokenKey = CreateTokenKey(innerKey);
if (storages.TryGet(tokenKey) != null) throw new InvalidOperationException("Token already exist");

storages.Add(tokenKey, new StorageItem(token));
storages.Add(CreateOwnershipKey(Prefix_OwnerToTokenId, account, innerKey), new StorageItem(new TAccount() { Balance = Factor }));
storages.Add(CreateOwnershipKey(Prefix_TokenIdToOwner, innerKey, account), new StorageItem(new byte[0]));
doubiliu marked this conversation as resolved.
Show resolved Hide resolved

IncreaseTotalSupply(engine.Snapshot);

engine.SendNotification(Hash, new Array(new StackItem[] { "Transfer", StackItem.Null, account.ToArray(), Factor, token.Id }));
}

internal protected virtual void Burn(ApplicationEngine engine, byte[] tokenId)
{
var storages = engine.Snapshot.Storages;
UInt160 innerKey = GetInnerKey(tokenId);
StorageKey tokenKey = CreateTokenKey(innerKey);
if (!storages.Delete(tokenKey)) throw new InvalidOperationException("Token doesn't exist");

IEnumerator enumerator = OwnerOf(engine.Snapshot, tokenId);
if (enumerator.Next())
{
UInt160 owner = new UInt160(enumerator.Value().GetSpan().ToArray());
storages.Delete(CreateOwnershipKey(Prefix_TokenIdToOwner, innerKey, owner));
storages.Delete(CreateOwnershipKey(Prefix_OwnerToTokenId, owner, innerKey));
}

DecreaseTotalSupply(engine.Snapshot);

engine.SendNotification(Hash, new Array(new StackItem[] { "Transfer", StackItem.Null, StackItem.Null, Factor, tokenId }));
}

public virtual UInt160 GetInnerKey(byte[] tokenId)
{
return new UInt160(Crypto.Hash160(tokenId));
}

private StorageKey CreateOwnershipKey(byte prefix, UInt160 first, UInt160 second)
{
byte[] byteSource = new byte[first.Size + second.Size];
System.Array.Copy(first.ToArray(), 0, byteSource, 0, first.Size);
System.Array.Copy(second.ToArray(), 0, byteSource, first.Size, second.Size);
return CreateStorageKey(prefix, byteSource);
}

protected StorageKey CreateTokenKey(UInt160 innerKey)
{
return CreateStorageKey(Prefix_TokenId, innerKey.ToArray());
}

private void IncreaseTotalSupply(StoreView snapshot)
{
StorageItem storage_totalSupply = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem() { Value = BigInteger.Zero.ToByteArray() });
storage_totalSupply.Value = (new BigInteger(storage_totalSupply.Value) + BigInteger.One).ToByteArray();
}

private void DecreaseTotalSupply(StoreView snapshot)
{
StorageItem storage_totalSupply = snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_TotalSupply), () => new StorageItem() { Value = BigInteger.Zero.ToByteArray() });
BigInteger totalSupply = new BigInteger(storage_totalSupply.Value);
if (totalSupply.Equals(BigInteger.Zero)) return;
shargon marked this conversation as resolved.
Show resolved Hide resolved
storage_totalSupply.Value = (totalSupply - BigInteger.One).ToByteArray();
}
}
}
20 changes: 20 additions & 0 deletions src/neo/SmartContract/Native/Tokens/Nep11TokenState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Neo.VM;
using Neo.VM.Types;

namespace Neo.SmartContract.Native.Tokens
{
public class Nep11TokenState : IInteroperable
{
public byte[] Id { set; get; }

public virtual void FromStackItem(StackItem stackItem)
{
Id = ((Struct)stackItem)[0].GetSpan().ToArray();
}

public virtual StackItem ToStackItem(ReferenceCounter referenceCounter)
{
return new Struct(referenceCounter) { Id };
}
}
}
21 changes: 21 additions & 0 deletions tests/neo.UnitTests/SmartContract/Native/Tokens/UT_AccountState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.SmartContract.Native.Tokens;
using Neo.VM.Types;

namespace Neo.SmartContract.NNS.Tests
{
[TestClass()]
public class UT_AccountState
{
[TestMethod()]
public void Check_FromAndToStackItem()
{
AccountState nepAccountState = new AccountState();
nepAccountState.Balance = 100;
StackItem stackitem = nepAccountState.ToStackItem(new VM.ReferenceCounter());
AccountState result = new AccountState();
result.FromStackItem(stackitem);
Assert.AreEqual(nepAccountState.Balance, result.Balance);
}
}
}
Loading