Skip to content

Commit

Permalink
nullable Storage.Get
Browse files Browse the repository at this point in the history
  • Loading branch information
Hecate2 committed Oct 24, 2024
1 parent 6e651f5 commit 8df1f98
Show file tree
Hide file tree
Showing 14 changed files with 173 additions and 239 deletions.
5 changes: 0 additions & 5 deletions src/Neo.SmartContract.Framework/ByteString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ IEnumerator IEnumerable.GetEnumerator()
[OpCode(OpCode.CONVERT, StackItemType.ByteString)]
public static extern explicit operator ByteString(byte[] buffer);

[OpCode(OpCode.DUP)]
[OpCode(OpCode.ISNULL)]
[OpCode(OpCode.JMPIFNOT, "0x04")]
[OpCode(OpCode.DROP)]
[OpCode(OpCode.PUSH0)]
[OpCode(OpCode.CONVERT, StackItemType.Integer)]
public static extern explicit operator BigInteger(ByteString text);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Nullable>enable</Nullable>
<TargetFramework>net8.0</TargetFramework>
<AssemblyTitle>Neo.SmartContract.Framework</AssemblyTitle>
<AssemblyName>Neo.SmartContract.Framework</AssemblyName>
Expand Down
4 changes: 2 additions & 2 deletions src/Neo.SmartContract.Framework/Nep17Token.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace Neo.SmartContract.Framework
[ContractPermission(Permission.Any, Method.OnNEP17Payment)]
public abstract class Nep17Token : TokenContract
{
public delegate void OnTransferDelegate(UInt160 from, UInt160 to, BigInteger amount);
public delegate void OnTransferDelegate(UInt160? from, UInt160? to, BigInteger amount);

[DisplayName("Transfer")]
public static event OnTransferDelegate OnTransfer;
Expand Down Expand Up @@ -64,7 +64,7 @@ protected static void Burn(UInt160 account, BigInteger amount)
PostTransfer(account, null, amount, null);
}

protected static void PostTransfer(UInt160 from, UInt160 to, BigInteger amount, object data)
protected static void PostTransfer(UInt160? from, UInt160? to, BigInteger amount, object? data)
{
OnTransfer(from, to, amount);
if (to is not null && ContractManagement.GetContract(to) is not null)
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.SmartContract.Framework/Services/Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class Contract
public readonly ContractManifest Manifest;

[Syscall("System.Contract.Call")]
public static extern object Call(UInt160 scriptHash, string method, CallFlags flags, params object[] args);
public static extern object Call(UInt160 scriptHash, string method, CallFlags flags, params object[]? args);

[Syscall("System.Contract.GetCallFlags")]
public static extern CallFlags GetCallFlags();
Expand Down
8 changes: 4 additions & 4 deletions src/Neo.SmartContract.Framework/Services/Storage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ public static extern StorageContext CurrentReadOnlyContext
/// Returns the value corresponding to the given key for Storage context (faster: generates opcode directly)
/// </summary>
[Syscall("System.Storage.Get")]
public static extern ByteString Get(StorageContext context, ByteString key);
public static extern ByteString? Get(StorageContext context, ByteString key);

/// <summary>
/// Returns the value corresponding to the given key for Storage context (faster: generates opcode directly)
/// </summary>
[Syscall("System.Storage.Get")]
public static extern ByteString Get(StorageContext context, byte[] key);
public static extern ByteString? Get(StorageContext context, byte[] key);

/// <summary>
/// Writes the key/value pair for the given Storage context (faster: generates opcode directly)
Expand Down Expand Up @@ -100,8 +100,8 @@ public static extern StorageContext CurrentReadOnlyContext
public static extern Iterator Find(StorageContext context, byte[] prefix, FindOptions options = FindOptions.None);

#region Interface with default Context
public static ByteString Get(ByteString key) => Get(CurrentReadOnlyContext, key);
public static ByteString Get(byte[] key) => Get(CurrentReadOnlyContext, key);
public static ByteString? Get(ByteString key) => Get(CurrentReadOnlyContext, key);
public static ByteString? Get(byte[] key) => Get(CurrentReadOnlyContext, key);
public static void Put(ByteString key, ByteString value) => Put(CurrentContext, key, value);
public static void Put(byte[] key, ByteString value) => Put(CurrentContext, key, value);
public static void Put(byte[] key, byte[] value) => Put(CurrentContext, key, value);
Expand Down
20 changes: 12 additions & 8 deletions src/Neo.SmartContract.Framework/Services/StorageMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class StorageMap
private readonly StorageContext context;
private readonly byte[] prefix;

public extern ByteString this[ByteString key]
public extern ByteString? this[ByteString key]
{
[CallingConvention(CallingConvention.Cdecl)]
[OpCode(OpCode.UNPACK)]
Expand All @@ -43,7 +43,7 @@ public extern ByteString this[ByteString key]
set;
}

public extern ByteString this[byte[] key]
public extern ByteString? this[byte[] key]
{
[CallingConvention(CallingConvention.Cdecl)]
[OpCode(OpCode.UNPACK)]
Expand Down Expand Up @@ -112,7 +112,9 @@ public extern ByteString this[byte[] key]
[OpCode(OpCode.CAT)]
[OpCode(OpCode.SWAP)]
[Syscall("System.Storage.Get")]
public extern ByteString Get(ByteString key);
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
public extern ByteString? Get(ByteString key);
#pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

[CallingConvention(CallingConvention.Cdecl)]
[OpCode(OpCode.UNPACK)]
Expand Down Expand Up @@ -204,7 +206,9 @@ public extern ByteString this[byte[] key]
[OpCode(OpCode.CAT)]
[OpCode(OpCode.SWAP)]
[Syscall("System.Storage.Get")]
public extern ByteString Get(byte[] key);
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
public extern ByteString? Get(byte[] key);
#pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

[CallingConvention(CallingConvention.Cdecl)]
[OpCode(OpCode.UNPACK)]
Expand Down Expand Up @@ -289,16 +293,16 @@ public extern ByteString this[byte[] key]
[OpCode(OpCode.CONVERT, StackItemType.Integer)]
public extern BigInteger GetIntegerOrZero(byte[] key);

public object GetObject(ByteString key)
public object? GetObject(ByteString key)
{
ByteString value = Get(key);
ByteString? value = Get(key);
if (value is null) return null;
return StdLib.Deserialize(value);
}

public object GetObject(byte[] key)
public object? GetObject(byte[] key)
{
ByteString value = Get(key);
ByteString? value = Get(key);
if (value is null) return null;
return StdLib.Deserialize(value);
}
Expand Down
38 changes: 26 additions & 12 deletions src/Neo.SmartContract.Framework/TokenContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,49 @@ namespace Neo.SmartContract.Framework
{
public abstract class TokenContract : SmartContract
{
protected const byte Prefix_TotalSupply = 0x00;
protected const byte Prefix_Balance = 0x01;
protected static readonly ByteString Prefix_TotalSupply = "\x00";
protected static readonly ByteString Prefix_Balance = "\x01";

public abstract string Symbol { [Safe] get; }

public abstract byte Decimals { [Safe] get; }

[Stored(Prefix_TotalSupply)]
public static BigInteger TotalSupply { [Safe] get; protected set; }
public static BigInteger TotalSupply
{
[Safe]
get
{
ByteString? stored = Storage.Get(Prefix_TotalSupply);
return stored != null ? (BigInteger)stored : 0;
}
protected set
{
Storage.Put(Prefix_TotalSupply, value);
}
}

[Safe]
public static BigInteger BalanceOf(UInt160 owner)
{
if (owner is null || !owner.IsValid)
throw new Exception("The argument \"owner\" is invalid.");
StorageMap balanceMap = new(Storage.CurrentContext, Prefix_Balance);
return (BigInteger)balanceMap[owner];
ByteString? balanceStored = Storage.Get(Prefix_Balance + owner);
return balanceStored != null ? (BigInteger)balanceStored : 0;
}

protected static bool UpdateBalance(UInt160 owner, BigInteger increment)
{
StorageMap balanceMap = new(Storage.CurrentContext, Prefix_Balance);
BigInteger balance = (BigInteger)balanceMap[owner];
StorageContext currentContext = Storage.CurrentContext;
ByteString ownerKey = Prefix_Balance + owner;
ByteString? balanceStored = Storage.Get(currentContext, ownerKey);
BigInteger balance = balanceStored != null ? (BigInteger)balanceStored : 0;
balance += increment;
if (balance < 0) return false;
if (balance.IsZero)
balanceMap.Delete(owner);
if (balance < 0)
return false;
if (balance == 0)
Storage.Delete(currentContext, ownerKey);
else
balanceMap.Put(owner, balance);
Storage.Put(currentContext, ownerKey, balance);
return true;
}
}
Expand Down
Loading

0 comments on commit 8df1f98

Please sign in to comment.