From 296a9caf30cafb1ddb86aa98307ba3fa7c546601 Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Fri, 25 Dec 2020 05:02:53 +0300 Subject: [PATCH 01/15] Dividend token moved as seperate branch --- .../DividendToken.Tests.csproj | 22 ++ .../DividendToken.Tests/DividendTokenTests.cs | 180 +++++++++++ .../DividendToken.Tests/InMemoryState.cs | 74 +++++ Testnet/DividendToken/DividendToken.sln | 31 ++ .../DividendToken/DividendToken.cs | 289 ++++++++++++++++++ .../DividendToken/DividendToken.csproj | 12 + Testnet/DividendToken/README.MD | 11 + 7 files changed, 619 insertions(+) create mode 100644 Testnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj create mode 100644 Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs create mode 100644 Testnet/DividendToken/DividendToken.Tests/InMemoryState.cs create mode 100644 Testnet/DividendToken/DividendToken.sln create mode 100644 Testnet/DividendToken/DividendToken/DividendToken.cs create mode 100644 Testnet/DividendToken/DividendToken/DividendToken.csproj create mode 100644 Testnet/DividendToken/README.MD diff --git a/Testnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj b/Testnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj new file mode 100644 index 00000000..be593740 --- /dev/null +++ b/Testnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj @@ -0,0 +1,22 @@ + + + + Exe + netcoreapp3.1 + DividendTokenContract.Tests + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs b/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs new file mode 100644 index 00000000..bf9362fb --- /dev/null +++ b/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs @@ -0,0 +1,180 @@ +using Moq; +using NBitcoin; +using Stratis.SmartContracts; +using Stratis.SmartContracts.CLR; +using Xunit; + +namespace DividendTokenContract.Tests +{ + public class DividendTokenTests + { + private readonly IPersistentState persistentState; + + private readonly Mock mContractState; + private readonly Mock mContractLogger; + private readonly Mock mTransactionExecutor; + + private readonly Address owner; + private readonly Address tokenHolder; + private readonly Address contract; + + private readonly string name; + private readonly string symbol; + private readonly ulong totalSupply; + + public DividendTokenTests() + { + this.persistentState = new InMemoryState(); + this.mContractState = new Mock(); + this.mContractLogger = new Mock(); + this.mTransactionExecutor = new Mock(); + this.mContractState.Setup(s => s.PersistentState).Returns(this.persistentState); + this.mContractState.Setup(s => s.ContractLogger).Returns(this.mContractLogger.Object); + this.mContractState.Setup(s => s.InternalTransactionExecutor).Returns(this.mTransactionExecutor.Object); + this.owner = "0x0000000000000000000000000000000000000001".HexToAddress(); + this.tokenHolder = "0x0000000000000000000000000000000000000002".HexToAddress(); + this.contract = "0x0000000000000000000000000000000000000003".HexToAddress(); + this.name = "Test Token"; + this.symbol = "TST"; + this.totalSupply = 1_000; + } + + [Fact] + public void Deposited_Dividend_Should_Be_Distributed_Equaly() + { + var dividend = 1000ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + contract.Receive(); + + Assert.Equal(dividend, contract.Dividends); + Assert.Equal(100ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(900ul, contract.GetDividends(this.owner)); + } + + [Fact] + public void Cumulative_Dividends_Should_Be_Distributed_Equaly() + { + var dividend = 1000ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + contract.Receive(); + contract.Receive(); + + Assert.Equal(2 * dividend, contract.Dividends); + Assert.Equal(2 * 100ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(2 * 900ul, contract.GetDividends(this.owner)); + } + + /// + /// In the case of dividend per token is 1.5 satoshi, + /// address that holds 1 token will have 1 dividend at first deposit despite actual earned amount is 1.5 satoshi + /// because satoshi unit doesn't support decimal points. Still 0.5 satoshi is accounted in the account + /// But after second deposit by same rate (0.5 satoshi per token), the user will be able to have 1 satoshi (0.5 + 0.5) + /// + [Fact] + public void Cumulative_Deposits_Should_Be_Distributed_Equaly_When_Dividends_Have_Decimal_Value() + { + var dividend = 500ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 1)); + + contract.Receive(); + + Assert.Equal(dividend, contract.Dividends); + Assert.Equal(0ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(499ul, contract.GetDividends(this.owner)); + + contract.Receive(); + + Assert.Equal(2 * dividend, contract.Dividends); + Assert.Equal(1ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(999ul, contract.GetDividends(this.owner)); + } + + [Fact] + public void Deposited_Dividend_Should_Be_Withdrawable() + { + var dividend = 500ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); + this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 5)).Returns(TransferResult.Transferred(true)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 11)); + + contract.Receive(); + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.tokenHolder, 0)); + + contract.Withdraw(); + + this.mTransactionExecutor.Verify(s => s.Transfer(this.mContractState.Object, this.tokenHolder, 5), Times.Once); + Assert.Equal(0ul, contract.GetDividends()); + var account = this.persistentState.GetStruct($"Account:{this.tokenHolder}"); + Assert.Equal(500ul, account.DividendBalance); + } + + [Fact] + public void GetDividends_Returns_Current_Sender_Dividends() + { + var dividend = 1000ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); + this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferResult.Transferred(true)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.tokenHolder, dividend)); + contract.Receive(); + + Assert.Equal(100ul, contract.GetDividends()); + } + + /// + /// GetTotalDividends should to return Withdrawable + Withdrawn dividends + /// + [Fact] + public void GetTotalDividends_Returns_Current_Sender_TotalDividends() + { + var dividend = 1000ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); + this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferResult.Transferred(true)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + contract.Receive(); + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.tokenHolder, 0)); + + contract.Withdraw(); + + this.mTransactionExecutor.Verify(s => s.Transfer(this.mContractState.Object, this.tokenHolder, 100), Times.Once); + Assert.Equal(0ul, contract.GetDividends()); + Assert.Equal(100ul, contract.GetTotalDividends()); + } + } +} diff --git a/Testnet/DividendToken/DividendToken.Tests/InMemoryState.cs b/Testnet/DividendToken/DividendToken.Tests/InMemoryState.cs new file mode 100644 index 00000000..5e285e68 --- /dev/null +++ b/Testnet/DividendToken/DividendToken.Tests/InMemoryState.cs @@ -0,0 +1,74 @@ +using NBitcoin; +using Stratis.SmartContracts; +using System; +using System.Collections.Generic; + +namespace DividendTokenContract.Tests +{ + public class InMemoryState : IPersistentState + { + private readonly Dictionary storage = new Dictionary(); + + public void Clear(string key) => this.storage.Remove(key); + + public T GetValue(string key) => (T)this.storage.GetValueOrDefault(key, default(T)); + + public Address GetAddress(string key) => this.GetValue
(key); + + public T[] GetArray(string key) => this.GetValue(key); + + public bool GetBool(string key) => this.GetValue(key); + + public byte[] GetBytes(byte[] key) => throw new NotImplementedException(); + + public byte[] GetBytes(string key) => this.GetValue(key); + + public char GetChar(string key) => this.GetValue(key); + + public int GetInt32(string key) => this.GetValue(key); + + public long GetInt64(string key) => this.GetValue(key); + + public string GetString(string key) => this.GetValue(key); + + public T GetStruct(string key) + where T : struct => this.GetValue(key); + + public uint GetUInt32(string key) => this.GetValue(key); + + public ulong GetUInt64(string key) => this.GetValue(key); + + public bool IsContract(Address address) + { + throw new NotImplementedException(); + } + + public void SetAddress(string key, Address value) => this.storage.AddOrReplace(key, value); + + public void SetArray(string key, Array a) => this.storage.AddOrReplace(key, a); + + public void SetBool(string key, bool value) => this.storage.AddOrReplace(key, value); + + public void SetBytes(byte[] key, byte[] value) + { + throw new NotImplementedException(); + } + + public void SetBytes(string key, byte[] value) => this.storage.AddOrReplace(key, value); + + public void SetChar(string key, char value) => this.storage.AddOrReplace(key, value); + + public void SetInt32(string key, int value) => this.storage.AddOrReplace(key, value); + + public void SetInt64(string key, long value) => this.storage.AddOrReplace(key, value); + + public void SetString(string key, string value) => this.storage.AddOrReplace(key, value); + + public void SetStruct(string key, T value) + where T : struct => this.storage.AddOrReplace(key, value); + + public void SetUInt32(string key, uint value) => this.storage.AddOrReplace(key, value); + + public void SetUInt64(string key, ulong value) => this.storage.AddOrReplace(key, value); + } +} diff --git a/Testnet/DividendToken/DividendToken.sln b/Testnet/DividendToken/DividendToken.sln new file mode 100644 index 00000000..fff0a409 --- /dev/null +++ b/Testnet/DividendToken/DividendToken.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30204.135 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DividendToken", "DividendToken\DividendToken.csproj", "{3AD529F2-7163-4BBE-80BB-F2D7D54B2DFA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DividendToken.Tests", "DividendToken.Tests\DividendToken.Tests.csproj", "{3B5AF108-6986-4E17-9A01-EB297D6F0C15}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AD529F2-7163-4BBE-80BB-F2D7D54B2DFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AD529F2-7163-4BBE-80BB-F2D7D54B2DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AD529F2-7163-4BBE-80BB-F2D7D54B2DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AD529F2-7163-4BBE-80BB-F2D7D54B2DFA}.Release|Any CPU.Build.0 = Release|Any CPU + {3B5AF108-6986-4E17-9A01-EB297D6F0C15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B5AF108-6986-4E17-9A01-EB297D6F0C15}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B5AF108-6986-4E17-9A01-EB297D6F0C15}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B5AF108-6986-4E17-9A01-EB297D6F0C15}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BA15305F-3348-4660-BF5B-3D0CD51F0FFD} + EndGlobalSection +EndGlobal diff --git a/Testnet/DividendToken/DividendToken/DividendToken.cs b/Testnet/DividendToken/DividendToken/DividendToken.cs new file mode 100644 index 00000000..140e8608 --- /dev/null +++ b/Testnet/DividendToken/DividendToken/DividendToken.cs @@ -0,0 +1,289 @@ +using Stratis.SmartContracts; +using Stratis.SmartContracts.Standards; +using System.Security.Cryptography.X509Certificates; + +[Deploy] +public class DividendToken : SmartContract, IStandardToken +{ + + public ulong Dividends + { + get => PersistentState.GetUInt64(nameof(this.Dividends)); + private set => PersistentState.SetUInt64(nameof(this.Dividends), value); + } + + private Account GetAccount(Address address) => PersistentState.GetStruct($"Account:{address}"); + + private void SetAccount(Address address, Account account) => PersistentState.SetStruct($"Account:{address}", account); + + + public DividendToken(ISmartContractState state, ulong totalSupply, string name, string symbol) + : base(state) + { + this.TotalSupply = totalSupply; + this.Name = name; + this.Symbol = symbol; + this.SetBalance(Message.Sender, totalSupply); + } + + /// + /// It is advised that deposit amount should to be evenly divided by total supply, + /// otherwise small amount of satoshi may lost(burn) + /// + public override void Receive() + { + Dividends += Message.Value; + } + + public bool TransferTo(Address to, ulong amount) + { + UpdateAccount(Message.Sender); + UpdateAccount(to); + + return TransferTokensTo(to, amount); + } + + public bool TransferFrom(Address from, Address to, ulong amount) + { + UpdateAccount(from); + UpdateAccount(to); + + return TransferTokensFrom(from, to, amount); + } + + Account UpdateAccount(Address address) + { + var account = GetAccount(address); + var newDividends = GetWithdrawableDividends(address, account); + + if (newDividends > 0) + { + account.DividendBalance = checked(account.DividendBalance + newDividends); + account.CreditedDividends = Dividends; + SetAccount(address, account); + } + + return account; + } + + private ulong GetWithdrawableDividends(Address address, Account account) + { + var newDividends = Dividends - account.CreditedDividends; + var notCreditedDividends = checked(GetBalance(address) * newDividends); + + return checked(account.DividendBalance + notCreditedDividends); //Delay divide by TotalSupply to final stage for avoid decimal value loss. + } + + /// + /// Get Withdrawable dividends + /// + /// + public ulong GetDividends() => GetDividends(Message.Sender); + + /// + /// Get Withdrawable dividends + /// + /// + /// + public ulong GetDividends(Address address) + { + var account = GetAccount(address); + + return GetWithdrawableDividends(address, account) / TotalSupply; + } + + /// + /// Get the all divididends since beginning (Withdrawable Dividends + Withdrawn Dividends) + /// + /// + public ulong GetTotalDividends() => GetTotalDividends(Message.Sender); + + /// + /// Get the all divididends since beginning (Withdrawable Dividends + Withdrawn Dividends) + /// + /// + /// + public ulong GetTotalDividends(Address address) + { + var account = GetAccount(address); + return checked(GetWithdrawableDividends(address, account) + account.WithdrawnDividends) / TotalSupply; + } + + /// + /// Withdraws all dividends + /// + public void Withdraw() + { + var account = UpdateAccount(Message.Sender); + var balance = account.DividendBalance / TotalSupply; + var remainder = account.DividendBalance % TotalSupply; + + Assert(balance > 0, "The account has no dividends."); + + var transfer = Transfer(Message.Sender, balance); + + Assert(transfer.Success, "Transfer failed."); + + account.WithdrawnDividends = checked(account.WithdrawnDividends + account.DividendBalance - remainder); + account.DividendBalance = remainder; + + SetAccount(Message.Sender, account); + } + + public struct Account + { + /// + /// Withdrawable Dividend Balance. Exact value should to divided by + /// + public ulong DividendBalance; + + /// + /// + /// + + public ulong WithdrawnDividends; + + /// + /// Dividends computed and added to + /// + + public ulong CreditedDividends; + } + + #region StandardToken code is inlined + + public string Symbol + { + get => PersistentState.GetString(nameof(this.Symbol)); + private set => PersistentState.SetString(nameof(this.Symbol), value); + } + + public string Name + { + get => PersistentState.GetString(nameof(this.Name)); + private set => PersistentState.SetString(nameof(this.Name), value); + } + + /// + public ulong TotalSupply + { + get => PersistentState.GetUInt64(nameof(this.TotalSupply)); + private set => PersistentState.SetUInt64(nameof(this.TotalSupply), value); + } + /// + public ulong GetBalance(Address address) + { + return PersistentState.GetUInt64($"Balance:{address}"); + } + + private void SetBalance(Address address, ulong value) + { + PersistentState.SetUInt64($"Balance:{address}", value); + } + + /// + private bool TransferTokensTo(Address to, ulong amount) + { + if (amount == 0) + { + Log(new TransferLog { From = Message.Sender, To = to, Amount = 0 }); + + return true; + } + + ulong senderBalance = GetBalance(Message.Sender); + + if (senderBalance < amount) + { + return false; + } + + SetBalance(Message.Sender, senderBalance - amount); + + SetBalance(to, checked(GetBalance(to) + amount)); + + Log(new TransferLog { From = Message.Sender, To = to, Amount = amount }); + + return true; + } + + /// + private bool TransferTokensFrom(Address from, Address to, ulong amount) + { + if (amount == 0) + { + Log(new TransferLog { From = from, To = to, Amount = 0 }); + + return true; + } + + ulong senderAllowance = Allowance(from, Message.Sender); + ulong fromBalance = GetBalance(from); + + if (senderAllowance < amount || fromBalance < amount) + { + return false; + } + + SetApproval(from, Message.Sender, senderAllowance - amount); + + SetBalance(from, fromBalance - amount); + + SetBalance(to, checked(GetBalance(to) + amount)); + + Log(new TransferLog { From = from, To = to, Amount = amount }); + + return true; + } + + /// + public bool Approve(Address spender, ulong currentAmount, ulong amount) + { + if (Allowance(Message.Sender, spender) != currentAmount) + { + return false; + } + + SetApproval(Message.Sender, spender, amount); + + Log(new ApprovalLog { Owner = Message.Sender, Spender = spender, Amount = amount, OldAmount = currentAmount }); + + return true; + } + + private void SetApproval(Address owner, Address spender, ulong value) + { + PersistentState.SetUInt64($"Allowance:{owner}:{spender}", value); + } + + /// + public ulong Allowance(Address owner, Address spender) + { + return PersistentState.GetUInt64($"Allowance:{owner}:{spender}"); + } + + public struct TransferLog + { + [Index] + public Address From; + + [Index] + public Address To; + + public ulong Amount; + } + + public struct ApprovalLog + { + [Index] + public Address Owner; + + [Index] + public Address Spender; + + public ulong OldAmount; + + public ulong Amount; + } + #endregion +} \ No newline at end of file diff --git a/Testnet/DividendToken/DividendToken/DividendToken.csproj b/Testnet/DividendToken/DividendToken/DividendToken.csproj new file mode 100644 index 00000000..28caaf1a --- /dev/null +++ b/Testnet/DividendToken/DividendToken/DividendToken.csproj @@ -0,0 +1,12 @@ + + + + netcoreapp2.1 + + 8.0 + + + + + + diff --git a/Testnet/DividendToken/README.MD b/Testnet/DividendToken/README.MD new file mode 100644 index 00000000..025f17cb --- /dev/null +++ b/Testnet/DividendToken/README.MD @@ -0,0 +1,11 @@ +# Dividend Token Contract + +**Contract Hash** +``` +12f8fbab891f6c3ebc5ad369d4dfb68dde1fa83eb7f0e68902fa7df685de65f5 +``` + +**Contract Byte Code** +``` +4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0102004CBCD8E00000000000000000E00022200B0130000014000000020000000000001E320000002000000040000000000010002000000002000004000000000000000400000000000000006000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000CC3100004F000000000000000000000000000000000000000000000000000000004000000C000000B03100001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000024120000002000000014000000020000000000000000000000000000200000602E72656C6F6300000C00000000400000000200000016000000000000000000000000000040000042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000320000000000004800000002000500742500003C0C000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004602280600000A72010000706F0700000A2A4A02280600000A7201000070036F0800000A2A7202280600000A7215000070038C08000001280900000A6F0100002B2A7602280600000A7215000070038C08000001280900000A046F0200002B2AC20203280C00000A0204281500000602052813000006020E0428110000060202280D00000A6F0E00000A0428170000062A660202280100000602280D00000A6F0F00000AD728020000062A8E0202280D00000A6F0E00000A280900000626020328090000062602030428180000062A6A020328090000062602042809000006260203040528190000062A0000133003003900000001000011020328030000060A020306280A0000060B07067B010000042E1D1200077D0100000412000228010000067D030000040203062804000006062A000000133002002800000002000011022801000006047B03000004DB0A0203281600000606D90228140000065C0B047B0100000407D72A4A0202280D00000A6F0E00000A280C0000062A00133003001100000003000011020328030000060A020306280A0000062A4A0202280D00000A6F0E00000A280E0000062A133003001800000003000011020328030000060A020306280A000006067B02000004D72A1330030079000000040000110202280D00000A6F0E00000A28090000060A02067B01000004166AFE03722D000070281000000A0202280D00000A6F0E00000A067B01000004281100000A0B02076F1200000A7269000070281000000A1200067B010000047D020000041200166A7D010000040202280D00000A6F0E00000A0628040000062A4602280600000A728B0000706F1300000A2A4A02280600000A728B000070036F1400000A2A4602280600000A72990000706F1300000A2A4A02280600000A7299000070036F1400000A2A4602280600000A72A30000706F0700000A2A4A02280600000A72A3000070036F0800000A2A7202280600000A72BB000070038C08000001280900000A6F0700000A2A7602280600000A72BB000070038C08000001280900000A046F0800000A2A0013300400A600000005000011042D34021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201166A7D0600000407280300002B172A0202280D00000A6F0E00000A28160000060A06043402162A0202280D00000A6F0E00000A0604DB281700000602030203281600000604D72817000006021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201047D0600000407280300002B172A000013300500AA00000006000011052D2A021202FE15040000021202037D040000041202047D050000041202166A7D0600000408280300002B172A020302280D00000A6F0E00000A281C0000060A020328160000060B0605370407053402162A020302280D00000A6F0E00000A0605DB281B00000602030705DB281700000602040204281600000605D72817000006021202FE15040000021202037D040000041202047D050000041202057D0600000408280300002B172A00001330040065000000070000110202280D00000A6F0E00000A03281C000006042E02162A0202280D00000A6F0E00000A0305281B000006021200FE1505000002120002280D00000A6F0E00000A7D070000041200037D080000041200057D0A0000041200047D0900000406280400002B172A8E02280600000A72D3000070038C08000001048C08000001281600000A056F0800000A2A8A02280600000A72D3000070038C08000001048C08000001281600000A6F0700000A2A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000030050000237E00009C0500003804000023537472696E677300000000D4090000F800000023555300CC0A0000100000002347554944000000DC0A00006001000023426C6F6200000000000000020000015717A201090A000000FA0133001600000100000010000000050000000A0000001C000000250000000100000016000000080000000700000001000000040000000800000001000000030000000300000004000000000093010100000000000600DE000D0306001D010D030600CA0060020F002D0300000A000D0158030A00760358030E00FC01EC020A00480358030A008B0058030A009F03580306008100C2010A00FE0058030A009F00580306006801C20106008403C2010A0055005803000000001500000000000100010001001000EE0100001900010001000A011000CB0300002D0001001D000A0110007B0100002D0004001D000A0110006F0100002D0007001D0006004300B5000600CC02B50006008F02B5000600E401B80006002402B8000600EC03B50006004E02B80006003502B8000600DB03B5000600EC03B500502000000000860873024A00010062200000000081088102BC0001007520000000008600BD03C10002009220000000008100C803C8000300B0200000000086185A02D0000500E12000000000C6004B0106000900FB2000000000E6010B02D90009001F2100000000E601C901E0000B003C21000000008100AF03C1000E008421000000008100A102E9000F00B821000000008600DF024A001100CC21000000008600DF02F1001100E921000000008600BA024A001200FC21000000008600BA02F10012002022000000008600010406001300A522000000008608A501F7001300B722000000008108B001FB001300CA220000000086086A00F7001400DC220000000081087300FB001400EF2200000000E6090A044A00150001230000000081081A04BC001500142300000000E6013500F1001600312300000000810040000001170050230000000081001602D90019000424000000008100D601E0001B00BC2400000000E601530107011E002D2500000000810087010F012100512500000000E6014B001801240000000100450100000100500300000100500300000200D30300000100C400000002002A04000003007C0000000400BB0100000100270200000200F30300000100E90100000200270200000300F30300000100500300000100500300000200D30300000100500300000100500300000100450100000100450100000100450100000100500300000100500300000200450100000100270200000200F30300000100E90100000200270200000300F303000001003D0200000200E50300000300F303000001005402000002003D02000003004501000001005402000002003D0202001D0009005A02010011005A02060019005A020A0029005A02060061005A0206003100B000100069000100150069000B001A0071006F03200069008B03260069009503320031005A023A0031005E00400081002A02450081003B014A003100FA036500310045026B0051003C03730069005B017700690065017C0031008301880071006F03A5002E000B0028012E00130031012E001B00500143002300590181002B005901A1002B005901E1002B00590101012B0059014E00540059005E00820094009B00020001000000E20220010000B401240100007700240100001E04200102000100030001000200030002001000050001001100050002001200070001001300070002001400090001001500090004800000000000000000000000000000000076030000040000000000000000000000AC001E000000000001000200010000000000000000005803000000000100000000000000000000000000EC020000000003000200040002000500020015002D0017002D002B008F002B00A00000000047657455496E7436340053657455496E743634003C4D6F64756C653E0053797374656D2E507269766174652E436F72654C69620047657442616C616E63650053657442616C616E636500416C6C6F77616E636500494D657373616765006765745F4D657373616765006765745F4E616D65007365745F4E616D65006E616D650056616C7565547970650049536D617274436F6E74726163745374617465004950657273697374656E745374617465006765745F50657273697374656E7453746174650073746174650044656275676761626C6541747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500496E646578417474726962757465004465706C6F794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465006765745F56616C75650076616C7565005265636569766500417070726F766500476574537472696E6700536574537472696E6700417070726F76616C4C6F67005472616E736665724C6F6700536574417070726F76616C00536D617274436F6E74726163742E646C6C006765745F53796D626F6C007365745F53796D626F6C0073796D626F6C0053797374656D005472616E7366657246726F6D005472616E73666572546F6B656E7346726F6D0066726F6D004469766964656E64546F6B656E00495374616E64617264546F6B656E005472616E73666572546F005472616E73666572546F6B656E73546F00746F006765745F53656E646572005370656E646572007370656E646572005472616E73666572004F776E6572006F776E6572002E63746F720053797374656D2E446961676E6F7374696373006765745F4469766964656E6473007365745F4469766964656E64730043726564697465644469766964656E647300476574576974686472617761626C654469766964656E647300476574546F74616C4469766964656E64730057697468647261776E4469766964656E6473004765744469766964656E647300537472617469732E536D617274436F6E7472616374732E5374616E64617264730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F646573006765745F537563636573730041646472657373006164647265737300537472617469732E536D617274436F6E74726163747300466F726D617400536D617274436F6E7472616374004F626A656374004765745374727563740053657453747275637400495472616E73666572526573756C74005570646174654163636F756E74004765744163636F756E74005365744163636F756E74006163636F756E74004F6C64416D6F756E740063757272656E74416D6F756E7400616D6F756E7400417373657274005769746864726177006765745F546F74616C537570706C79007365745F546F74616C537570706C7900746F74616C537570706C7900000000134400690076006900640065006E006400730000174100630063006F0075006E0074003A007B0030007D00003B54006800650020006100630063006F0075006E007400200068006100730020006E006F0020006400690076006900640065006E00640073002E0000215400720061006E00730066006500720020006600610069006C00650064002E00000D530079006D0062006F006C0000094E0061006D006500001754006F00740061006C0053007500700070006C0079000017420061006C0061006E00630065003A007B0030007D00002341006C006C006F00770061006E00630065003A007B0030007D003A007B0031007D0000002BC74B948E05324A8F56BBF50521E5160004200101080320000105200101111104200012350420010B0E052002010E0B0500020E0E1C063001011E000E040A01110C07300102010E1E00052001011225042000124104200011210320000B050702110C0B0407020B0B040701110C060702110C122905200201020E072002122911210B032000020420010E0E052002010E0E0507020B111006300101011E00040A0111100607030B0B11100407011114040A0111140600030E0E1C1C087CEC85D7BEA7798E02060B03061121042001010B062001110C1121072002011121110C0820040112250B0E0E0620020211210B08200302112111210B0720020B1121110C0520010B11210320000E042001010E0620020111210B0720030211210B0B08200301112111210B0720020B112111210328000B0328000E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010801000200000000000401000000000000000000000000000000000010000000000000000000000000000000F431000000000000000000000E32000000200000000000000000000000000000000000000000000000320000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF25002000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000C000000203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +``` From 2cce6306767e18503132a81fe5fd779504d9e981 Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Tue, 29 Dec 2020 09:50:17 +0300 Subject: [PATCH 02/15] Security fix --- Testnet/DividendToken/DividendToken/DividendToken.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Testnet/DividendToken/DividendToken/DividendToken.cs b/Testnet/DividendToken/DividendToken/DividendToken.cs index 140e8608..8dae8133 100644 --- a/Testnet/DividendToken/DividendToken/DividendToken.cs +++ b/Testnet/DividendToken/DividendToken/DividendToken.cs @@ -119,15 +119,15 @@ public void Withdraw() var remainder = account.DividendBalance % TotalSupply; Assert(balance > 0, "The account has no dividends."); - - var transfer = Transfer(Message.Sender, balance); - - Assert(transfer.Success, "Transfer failed."); - + account.WithdrawnDividends = checked(account.WithdrawnDividends + account.DividendBalance - remainder); account.DividendBalance = remainder; SetAccount(Message.Sender, account); + + var transfer = Transfer(Message.Sender, balance); + + Assert(transfer.Success, "Transfer failed."); } public struct Account From 5f75098e08aea36e9610f6a2a388cb49a15aa259 Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Tue, 29 Dec 2020 13:22:26 +0300 Subject: [PATCH 03/15] Updated readme --- Testnet/DividendToken/DividendToken/DividendToken.cs | 1 - Testnet/DividendToken/README.MD | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Testnet/DividendToken/DividendToken/DividendToken.cs b/Testnet/DividendToken/DividendToken/DividendToken.cs index 8dae8133..3286164a 100644 --- a/Testnet/DividendToken/DividendToken/DividendToken.cs +++ b/Testnet/DividendToken/DividendToken/DividendToken.cs @@ -1,6 +1,5 @@ using Stratis.SmartContracts; using Stratis.SmartContracts.Standards; -using System.Security.Cryptography.X509Certificates; [Deploy] public class DividendToken : SmartContract, IStandardToken diff --git a/Testnet/DividendToken/README.MD b/Testnet/DividendToken/README.MD index 025f17cb..e0a23e6b 100644 --- a/Testnet/DividendToken/README.MD +++ b/Testnet/DividendToken/README.MD @@ -2,10 +2,10 @@ **Contract Hash** ``` -12f8fbab891f6c3ebc5ad369d4dfb68dde1fa83eb7f0e68902fa7df685de65f5 +afb554ad1bb27c85f79f9ed061bd28e4cacbe5fb6fd29231c57f2047ebe00151 ``` **Contract Byte Code** ``` -4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0102004CBCD8E00000000000000000E00022200B0130000014000000020000000000001E320000002000000040000000000010002000000002000004000000000000000400000000000000006000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000CC3100004F000000000000000000000000000000000000000000000000000000004000000C000000B03100001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000024120000002000000014000000020000000000000000000000000000200000602E72656C6F6300000C00000000400000000200000016000000000000000000000000000040000042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000320000000000004800000002000500742500003C0C000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004602280600000A72010000706F0700000A2A4A02280600000A7201000070036F0800000A2A7202280600000A7215000070038C08000001280900000A6F0100002B2A7602280600000A7215000070038C08000001280900000A046F0200002B2AC20203280C00000A0204281500000602052813000006020E0428110000060202280D00000A6F0E00000A0428170000062A660202280100000602280D00000A6F0F00000AD728020000062A8E0202280D00000A6F0E00000A280900000626020328090000062602030428180000062A6A020328090000062602042809000006260203040528190000062A0000133003003900000001000011020328030000060A020306280A0000060B07067B010000042E1D1200077D0100000412000228010000067D030000040203062804000006062A000000133002002800000002000011022801000006047B03000004DB0A0203281600000606D90228140000065C0B047B0100000407D72A4A0202280D00000A6F0E00000A280C0000062A00133003001100000003000011020328030000060A020306280A0000062A4A0202280D00000A6F0E00000A280E0000062A133003001800000003000011020328030000060A020306280A000006067B02000004D72A1330030079000000040000110202280D00000A6F0E00000A28090000060A02067B01000004166AFE03722D000070281000000A0202280D00000A6F0E00000A067B01000004281100000A0B02076F1200000A7269000070281000000A1200067B010000047D020000041200166A7D010000040202280D00000A6F0E00000A0628040000062A4602280600000A728B0000706F1300000A2A4A02280600000A728B000070036F1400000A2A4602280600000A72990000706F1300000A2A4A02280600000A7299000070036F1400000A2A4602280600000A72A30000706F0700000A2A4A02280600000A72A3000070036F0800000A2A7202280600000A72BB000070038C08000001280900000A6F0700000A2A7602280600000A72BB000070038C08000001280900000A046F0800000A2A0013300400A600000005000011042D34021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201166A7D0600000407280300002B172A0202280D00000A6F0E00000A28160000060A06043402162A0202280D00000A6F0E00000A0604DB281700000602030203281600000604D72817000006021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201047D0600000407280300002B172A000013300500AA00000006000011052D2A021202FE15040000021202037D040000041202047D050000041202166A7D0600000408280300002B172A020302280D00000A6F0E00000A281C0000060A020328160000060B0605370407053402162A020302280D00000A6F0E00000A0605DB281B00000602030705DB281700000602040204281600000605D72817000006021202FE15040000021202037D040000041202047D050000041202057D0600000408280300002B172A00001330040065000000070000110202280D00000A6F0E00000A03281C000006042E02162A0202280D00000A6F0E00000A0305281B000006021200FE1505000002120002280D00000A6F0E00000A7D070000041200037D080000041200057D0A0000041200047D0900000406280400002B172A8E02280600000A72D3000070038C08000001048C08000001281600000A056F0800000A2A8A02280600000A72D3000070038C08000001048C08000001281600000A6F0700000A2A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000030050000237E00009C0500003804000023537472696E677300000000D4090000F800000023555300CC0A0000100000002347554944000000DC0A00006001000023426C6F6200000000000000020000015717A201090A000000FA0133001600000100000010000000050000000A0000001C000000250000000100000016000000080000000700000001000000040000000800000001000000030000000300000004000000000093010100000000000600DE000D0306001D010D030600CA0060020F002D0300000A000D0158030A00760358030E00FC01EC020A00480358030A008B0058030A009F03580306008100C2010A00FE0058030A009F00580306006801C20106008403C2010A0055005803000000001500000000000100010001001000EE0100001900010001000A011000CB0300002D0001001D000A0110007B0100002D0004001D000A0110006F0100002D0007001D0006004300B5000600CC02B50006008F02B5000600E401B80006002402B8000600EC03B50006004E02B80006003502B8000600DB03B5000600EC03B500502000000000860873024A00010062200000000081088102BC0001007520000000008600BD03C10002009220000000008100C803C8000300B0200000000086185A02D0000500E12000000000C6004B0106000900FB2000000000E6010B02D90009001F2100000000E601C901E0000B003C21000000008100AF03C1000E008421000000008100A102E9000F00B821000000008600DF024A001100CC21000000008600DF02F1001100E921000000008600BA024A001200FC21000000008600BA02F10012002022000000008600010406001300A522000000008608A501F7001300B722000000008108B001FB001300CA220000000086086A00F7001400DC220000000081087300FB001400EF2200000000E6090A044A00150001230000000081081A04BC001500142300000000E6013500F1001600312300000000810040000001170050230000000081001602D90019000424000000008100D601E0001B00BC2400000000E601530107011E002D2500000000810087010F012100512500000000E6014B001801240000000100450100000100500300000100500300000200D30300000100C400000002002A04000003007C0000000400BB0100000100270200000200F30300000100E90100000200270200000300F30300000100500300000100500300000200D30300000100500300000100500300000100450100000100450100000100450100000100500300000100500300000200450100000100270200000200F30300000100E90100000200270200000300F303000001003D0200000200E50300000300F303000001005402000002003D02000003004501000001005402000002003D0202001D0009005A02010011005A02060019005A020A0029005A02060061005A0206003100B000100069000100150069000B001A0071006F03200069008B03260069009503320031005A023A0031005E00400081002A02450081003B014A003100FA036500310045026B0051003C03730069005B017700690065017C0031008301880071006F03A5002E000B0028012E00130031012E001B00500143002300590181002B005901A1002B005901E1002B00590101012B0059014E00540059005E00820094009B00020001000000E20220010000B401240100007700240100001E04200102000100030001000200030002001000050001001100050002001200070001001300070002001400090001001500090004800000000000000000000000000000000076030000040000000000000000000000AC001E000000000001000200010000000000000000005803000000000100000000000000000000000000EC020000000003000200040002000500020015002D0017002D002B008F002B00A00000000047657455496E7436340053657455496E743634003C4D6F64756C653E0053797374656D2E507269766174652E436F72654C69620047657442616C616E63650053657442616C616E636500416C6C6F77616E636500494D657373616765006765745F4D657373616765006765745F4E616D65007365745F4E616D65006E616D650056616C7565547970650049536D617274436F6E74726163745374617465004950657273697374656E745374617465006765745F50657273697374656E7453746174650073746174650044656275676761626C6541747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500496E646578417474726962757465004465706C6F794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465006765745F56616C75650076616C7565005265636569766500417070726F766500476574537472696E6700536574537472696E6700417070726F76616C4C6F67005472616E736665724C6F6700536574417070726F76616C00536D617274436F6E74726163742E646C6C006765745F53796D626F6C007365745F53796D626F6C0073796D626F6C0053797374656D005472616E7366657246726F6D005472616E73666572546F6B656E7346726F6D0066726F6D004469766964656E64546F6B656E00495374616E64617264546F6B656E005472616E73666572546F005472616E73666572546F6B656E73546F00746F006765745F53656E646572005370656E646572007370656E646572005472616E73666572004F776E6572006F776E6572002E63746F720053797374656D2E446961676E6F7374696373006765745F4469766964656E6473007365745F4469766964656E64730043726564697465644469766964656E647300476574576974686472617761626C654469766964656E647300476574546F74616C4469766964656E64730057697468647261776E4469766964656E6473004765744469766964656E647300537472617469732E536D617274436F6E7472616374732E5374616E64617264730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F646573006765745F537563636573730041646472657373006164647265737300537472617469732E536D617274436F6E74726163747300466F726D617400536D617274436F6E7472616374004F626A656374004765745374727563740053657453747275637400495472616E73666572526573756C74005570646174654163636F756E74004765744163636F756E74005365744163636F756E74006163636F756E74004F6C64416D6F756E740063757272656E74416D6F756E7400616D6F756E7400417373657274005769746864726177006765745F546F74616C537570706C79007365745F546F74616C537570706C7900746F74616C537570706C7900000000134400690076006900640065006E006400730000174100630063006F0075006E0074003A007B0030007D00003B54006800650020006100630063006F0075006E007400200068006100730020006E006F0020006400690076006900640065006E00640073002E0000215400720061006E00730066006500720020006600610069006C00650064002E00000D530079006D0062006F006C0000094E0061006D006500001754006F00740061006C0053007500700070006C0079000017420061006C0061006E00630065003A007B0030007D00002341006C006C006F00770061006E00630065003A007B0030007D003A007B0031007D0000002BC74B948E05324A8F56BBF50521E5160004200101080320000105200101111104200012350420010B0E052002010E0B0500020E0E1C063001011E000E040A01110C07300102010E1E00052001011225042000124104200011210320000B050702110C0B0407020B0B040701110C060702110C122905200201020E072002122911210B032000020420010E0E052002010E0E0507020B111006300101011E00040A0111100607030B0B11100407011114040A0111140600030E0E1C1C087CEC85D7BEA7798E02060B03061121042001010B062001110C1121072002011121110C0820040112250B0E0E0620020211210B08200302112111210B0720020B1121110C0520010B11210320000E042001010E0620020111210B0720030211210B0B08200301112111210B0720020B112111210328000B0328000E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010801000200000000000401000000000000000000000000000000000010000000000000000000000000000000F431000000000000000000000E32000000200000000000000000000000000000000000000000000000320000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF25002000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000C000000203200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0102004E678B9A0000000000000000E00022200B01300000140000000200000000000052320000002000000040000000000010002000000002000004000000000000000400000000000000006000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000003200004F000000000000000000000000000000000000000000000000000000004000000C000000E43100001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000058120000002000000014000000020000000000000000000000000000200000602E72656C6F6300000C00000000400000000200000016000000000000000000000000000040000042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034320000000000004800000002000500982500004C0C000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004602280600000A72010000706F0700000A2A4A02280600000A7201000070036F0800000A2A7202280600000A7215000070038C08000001280900000A6F0100002B2A7602280600000A7215000070038C08000001280900000A046F0200002B2AC20203280C00000A0204281500000602052813000006020E0428110000060202280D00000A6F0E00000A0428170000062A660202280100000602280D00000A6F0F00000AD728020000062A8E0202280D00000A6F0E00000A280900000626020328090000062602030428180000062A6A020328090000062602042809000006260203040528190000062A0000133003003C00000001000011020328030000060A020306280A0000060B07166A36241200067B0100000407D77D0100000412000228010000067D030000040203062804000006062A133002002100000002000011022801000006047B03000004DB0A0203281600000606D90B047B0100000407D72A4A0202280D00000A6F0E00000A280C0000062A133003001800000003000011020328030000060A020306280A0000060228140000065C2A4A0202280D00000A6F0E00000A280E0000062A00133003001F00000003000011020328030000060A020306280A000006067B02000004D70228140000065C2A001330030093000000040000110202280D00000A6F0E00000A28090000060A067B010000040228140000065C0B067B010000040228140000065E0C0207166AFE03722D000070281000000A1200067B02000004067B01000004D708DB7D020000041200087D010000040202280D00000A6F0E00000A0628040000060202280D00000A6F0E00000A07281100000A0D02096F1200000A7269000070281000000A2A4602280600000A728B0000706F1300000A2A4A02280600000A728B000070036F1400000A2A4602280600000A72990000706F1300000A2A4A02280600000A7299000070036F1400000A2A4602280600000A72A30000706F0700000A2A4A02280600000A72A3000070036F0800000A2A7202280600000A72BB000070038C08000001280900000A6F0700000A2A7602280600000A72BB000070038C08000001280900000A046F0800000A2A00000013300400A600000005000011042D34021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201166A7D0600000407280300002B172A0202280D00000A6F0E00000A28160000060A06043402162A0202280D00000A6F0E00000A0604DB281700000602030203281600000604D72817000006021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201047D0600000407280300002B172A000013300500AA00000006000011052D2A021202FE15040000021202037D040000041202047D050000041202166A7D0600000408280300002B172A020302280D00000A6F0E00000A281C0000060A020328160000060B0605370407053402162A020302280D00000A6F0E00000A0605DB281B00000602030705DB281700000602040204281600000605D72817000006021202FE15040000021202037D040000041202047D050000041202057D0600000408280300002B172A00001330040065000000070000110202280D00000A6F0E00000A03281C000006042E02162A0202280D00000A6F0E00000A0305281B000006021200FE1505000002120002280D00000A6F0E00000A7D070000041200037D080000041200057D0A0000041200047D0900000406280400002B172A8E02280600000A72D3000070038C08000001048C08000001281600000A056F0800000A2A8A02280600000A72D3000070038C08000001048C08000001281600000A6F0700000A2A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000030050000237E00009C0500004804000023537472696E677300000000E4090000F800000023555300DC0A0000100000002347554944000000EC0A00006001000023426C6F6200000000000000020000015717A201090A000000FA0133001600000100000010000000050000000A0000001C0000002500000001000000160000000800000007000000010000000400000008000000010000000300000003000000040000000000A3010100000000000600EE001D0306002D011D030600DA0070020F003D0300000A001D0168030A00860368030E000C02FC020A00580368030A009B0068030A00AF03680306009100D2010A000E0168030A00AF00680306007801D20106009403D2010A0065006803000000001500000000000100010001001000FE0100001900010001000A011000DB0300002D0001001D000A0110008B0100002D0004001D000A0110007F0100002D0007001D0006003500B7000600DC02B70006009F02B7000600F401BA0006003402BA000600FC03B70006005E02BA0006004502BA000600EB03B7000600FC03B700502000000000860883024A00010062200000000081089102BE0001007520000000008100CD03C30002009220000000008100D803CA000300B0200000000086186A02D2000500E12000000000C6005B0106000900FB2000000000E6011B02DB0009001F2100000000E601D901E2000B003C21000000008100BF03C3000E008421000000008100B102EB000F00B121000000008600EF024A001100C421000000008600EF02F3001100E821000000008600CA024A001200FC21000000008600CA02F30012002822000000008600110406001300C722000000008608B501F9001300D922000000008108C001FD001300EC220000000086087A00F9001400FE220000000081088300FD001400112300000000E6091A044A00150023230000000081082A04BE001500362300000000E6014500F3001600532300000000810050000201170074230000000081002602DB0019002824000000008100E601E2001B00E02400000000E601630109011E005125000000008100970111012100752500000000E6015B001A01240000000100550100000100600300000100600300000200E30300000100D400000002003A04000003008C0000000400CB0100000100370200000200030400000100F90100000200370200000300030400000100600300000100600300000200E30300000100600300000100600300000100550100000100550100000100550100000100600300000100600300000200550100000100370200000200030400000100F901000002003702000003000304000001004D0200000200F503000003000304000001006402000002004D02000003005501000001006402000002004D0202001D0009006A02010011006A02060019006A020A0029006A02060061006A0206003100C000100069000100150069000B001A0071007F03200069009B0326006900A503320031006A023A0031006E00400081003A02450081004B014A0031000A046700310055026D0051004C03750069006B017900690075017E00310093018A0071007F03A7002E000B002A012E00130033012E001B005201430023005B0181002B005B01A1002B005B01E1002B005B0101012B005B014E00540059005E00840096009D00020001000000F20222010000C401260100008700260100002E04220102000100030001000200030002001000050001001100050002001200070001001300070002001400090001001500090004800000000000000000000000000000000086030000040000000000000000000000AE001E000000000001000200010000000000000000006803000000000100000000000000000000000000FC020000000003000200040002000500020015002D0017002D002B0091002B00A20000000047657455496E7436340053657455496E743634003C4D6F64756C653E0053797374656D2E507269766174652E436F72654C6962004469766964656E6442616C616E63650047657442616C616E63650053657442616C616E636500416C6C6F77616E636500494D657373616765006765745F4D657373616765006765745F4E616D65007365745F4E616D65006E616D650056616C7565547970650049536D617274436F6E74726163745374617465004950657273697374656E745374617465006765745F50657273697374656E7453746174650073746174650044656275676761626C6541747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500496E646578417474726962757465004465706C6F794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465006765745F56616C75650076616C7565005265636569766500417070726F766500476574537472696E6700536574537472696E6700417070726F76616C4C6F67005472616E736665724C6F6700536574417070726F76616C00536D617274436F6E74726163742E646C6C006765745F53796D626F6C007365745F53796D626F6C0073796D626F6C0053797374656D005472616E7366657246726F6D005472616E73666572546F6B656E7346726F6D0066726F6D004469766964656E64546F6B656E00495374616E64617264546F6B656E005472616E73666572546F005472616E73666572546F6B656E73546F00746F006765745F53656E646572005370656E646572007370656E646572005472616E73666572004F776E6572006F776E6572002E63746F720053797374656D2E446961676E6F7374696373006765745F4469766964656E6473007365745F4469766964656E64730043726564697465644469766964656E647300476574576974686472617761626C654469766964656E647300476574546F74616C4469766964656E64730057697468647261776E4469766964656E6473004765744469766964656E647300537472617469732E536D617274436F6E7472616374732E5374616E64617264730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F646573006765745F537563636573730041646472657373006164647265737300537472617469732E536D617274436F6E74726163747300466F726D617400536D617274436F6E7472616374004F626A656374004765745374727563740053657453747275637400495472616E73666572526573756C74005570646174654163636F756E74004765744163636F756E74005365744163636F756E74006163636F756E74004F6C64416D6F756E740063757272656E74416D6F756E7400616D6F756E7400417373657274005769746864726177006765745F546F74616C537570706C79007365745F546F74616C537570706C7900746F74616C537570706C7900000000134400690076006900640065006E006400730000174100630063006F0075006E0074003A007B0030007D00003B54006800650020006100630063006F0075006E007400200068006100730020006E006F0020006400690076006900640065006E00640073002E0000215400720061006E00730066006500720020006600610069006C00650064002E00000D530079006D0062006F006C0000094E0061006D006500001754006F00740061006C0053007500700070006C0079000017420061006C0061006E00630065003A007B0030007D00002341006C006C006F00770061006E00630065003A007B0030007D003A007B0031007D00000031EC77F44ED48A46A24645E9865F8F930004200101080320000105200101111104200012350420010B0E052002010E0B0500020E0E1C063001011E000E040A01110C07300102010E1E00052001011225042000124104200011210320000B050702110C0B0407020B0B040701110C080704110C0B0B122905200201020E072002122911210B032000020420010E0E052002010E0E0507020B111006300101011E00040A0111100607030B0B11100407011114040A0111140600030E0E1C1C087CEC85D7BEA7798E02060B03061121042001010B062001110C1121072002011121110C0820040112250B0E0E0620020211210B08200302112111210B0720020B1121110C0520010B11210320000E042001010E0620020111210B0720030211210B0B08200301112111210B0720020B112111210328000B0328000E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010801000200000000000401000000000000000000000000000000100000000000000000000000000000002832000000000000000000004232000000200000000000000000000000000000000000000000000034320000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF250020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000C000000543200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ``` From 82aee25834188b373b090e742ab16286524bb159 Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Thu, 31 Dec 2020 10:58:00 +0300 Subject: [PATCH 04/15] Moved to mainnet --- .../DividendToken.Tests.csproj | 22 ++ .../DividendToken.Tests/DividendTokenTests.cs | 180 +++++++++++ .../DividendToken.Tests/InMemoryState.cs | 74 +++++ Mainnet/DividendToken/DividendToken.sln | 31 ++ .../DividendToken/DividendToken.cs | 288 ++++++++++++++++++ .../DividendToken/DividendToken.csproj | 12 + Mainnet/DividendToken/README.MD | 11 + 7 files changed, 618 insertions(+) create mode 100644 Mainnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj create mode 100644 Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs create mode 100644 Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs create mode 100644 Mainnet/DividendToken/DividendToken.sln create mode 100644 Mainnet/DividendToken/DividendToken/DividendToken.cs create mode 100644 Mainnet/DividendToken/DividendToken/DividendToken.csproj create mode 100644 Mainnet/DividendToken/README.MD diff --git a/Mainnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj b/Mainnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj new file mode 100644 index 00000000..be593740 --- /dev/null +++ b/Mainnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj @@ -0,0 +1,22 @@ + + + + Exe + netcoreapp3.1 + DividendTokenContract.Tests + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs new file mode 100644 index 00000000..bf9362fb --- /dev/null +++ b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs @@ -0,0 +1,180 @@ +using Moq; +using NBitcoin; +using Stratis.SmartContracts; +using Stratis.SmartContracts.CLR; +using Xunit; + +namespace DividendTokenContract.Tests +{ + public class DividendTokenTests + { + private readonly IPersistentState persistentState; + + private readonly Mock mContractState; + private readonly Mock mContractLogger; + private readonly Mock mTransactionExecutor; + + private readonly Address owner; + private readonly Address tokenHolder; + private readonly Address contract; + + private readonly string name; + private readonly string symbol; + private readonly ulong totalSupply; + + public DividendTokenTests() + { + this.persistentState = new InMemoryState(); + this.mContractState = new Mock(); + this.mContractLogger = new Mock(); + this.mTransactionExecutor = new Mock(); + this.mContractState.Setup(s => s.PersistentState).Returns(this.persistentState); + this.mContractState.Setup(s => s.ContractLogger).Returns(this.mContractLogger.Object); + this.mContractState.Setup(s => s.InternalTransactionExecutor).Returns(this.mTransactionExecutor.Object); + this.owner = "0x0000000000000000000000000000000000000001".HexToAddress(); + this.tokenHolder = "0x0000000000000000000000000000000000000002".HexToAddress(); + this.contract = "0x0000000000000000000000000000000000000003".HexToAddress(); + this.name = "Test Token"; + this.symbol = "TST"; + this.totalSupply = 1_000; + } + + [Fact] + public void Deposited_Dividend_Should_Be_Distributed_Equaly() + { + var dividend = 1000ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + contract.Receive(); + + Assert.Equal(dividend, contract.Dividends); + Assert.Equal(100ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(900ul, contract.GetDividends(this.owner)); + } + + [Fact] + public void Cumulative_Dividends_Should_Be_Distributed_Equaly() + { + var dividend = 1000ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + contract.Receive(); + contract.Receive(); + + Assert.Equal(2 * dividend, contract.Dividends); + Assert.Equal(2 * 100ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(2 * 900ul, contract.GetDividends(this.owner)); + } + + /// + /// In the case of dividend per token is 1.5 satoshi, + /// address that holds 1 token will have 1 dividend at first deposit despite actual earned amount is 1.5 satoshi + /// because satoshi unit doesn't support decimal points. Still 0.5 satoshi is accounted in the account + /// But after second deposit by same rate (0.5 satoshi per token), the user will be able to have 1 satoshi (0.5 + 0.5) + /// + [Fact] + public void Cumulative_Deposits_Should_Be_Distributed_Equaly_When_Dividends_Have_Decimal_Value() + { + var dividend = 500ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 1)); + + contract.Receive(); + + Assert.Equal(dividend, contract.Dividends); + Assert.Equal(0ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(499ul, contract.GetDividends(this.owner)); + + contract.Receive(); + + Assert.Equal(2 * dividend, contract.Dividends); + Assert.Equal(1ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(999ul, contract.GetDividends(this.owner)); + } + + [Fact] + public void Deposited_Dividend_Should_Be_Withdrawable() + { + var dividend = 500ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); + this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 5)).Returns(TransferResult.Transferred(true)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 11)); + + contract.Receive(); + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.tokenHolder, 0)); + + contract.Withdraw(); + + this.mTransactionExecutor.Verify(s => s.Transfer(this.mContractState.Object, this.tokenHolder, 5), Times.Once); + Assert.Equal(0ul, contract.GetDividends()); + var account = this.persistentState.GetStruct($"Account:{this.tokenHolder}"); + Assert.Equal(500ul, account.DividendBalance); + } + + [Fact] + public void GetDividends_Returns_Current_Sender_Dividends() + { + var dividend = 1000ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); + this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferResult.Transferred(true)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.tokenHolder, dividend)); + contract.Receive(); + + Assert.Equal(100ul, contract.GetDividends()); + } + + /// + /// GetTotalDividends should to return Withdrawable + Withdrawn dividends + /// + [Fact] + public void GetTotalDividends_Returns_Current_Sender_TotalDividends() + { + var dividend = 1000ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); + this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferResult.Transferred(true)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + contract.Receive(); + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.tokenHolder, 0)); + + contract.Withdraw(); + + this.mTransactionExecutor.Verify(s => s.Transfer(this.mContractState.Object, this.tokenHolder, 100), Times.Once); + Assert.Equal(0ul, contract.GetDividends()); + Assert.Equal(100ul, contract.GetTotalDividends()); + } + } +} diff --git a/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs b/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs new file mode 100644 index 00000000..5e285e68 --- /dev/null +++ b/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs @@ -0,0 +1,74 @@ +using NBitcoin; +using Stratis.SmartContracts; +using System; +using System.Collections.Generic; + +namespace DividendTokenContract.Tests +{ + public class InMemoryState : IPersistentState + { + private readonly Dictionary storage = new Dictionary(); + + public void Clear(string key) => this.storage.Remove(key); + + public T GetValue(string key) => (T)this.storage.GetValueOrDefault(key, default(T)); + + public Address GetAddress(string key) => this.GetValue
(key); + + public T[] GetArray(string key) => this.GetValue(key); + + public bool GetBool(string key) => this.GetValue(key); + + public byte[] GetBytes(byte[] key) => throw new NotImplementedException(); + + public byte[] GetBytes(string key) => this.GetValue(key); + + public char GetChar(string key) => this.GetValue(key); + + public int GetInt32(string key) => this.GetValue(key); + + public long GetInt64(string key) => this.GetValue(key); + + public string GetString(string key) => this.GetValue(key); + + public T GetStruct(string key) + where T : struct => this.GetValue(key); + + public uint GetUInt32(string key) => this.GetValue(key); + + public ulong GetUInt64(string key) => this.GetValue(key); + + public bool IsContract(Address address) + { + throw new NotImplementedException(); + } + + public void SetAddress(string key, Address value) => this.storage.AddOrReplace(key, value); + + public void SetArray(string key, Array a) => this.storage.AddOrReplace(key, a); + + public void SetBool(string key, bool value) => this.storage.AddOrReplace(key, value); + + public void SetBytes(byte[] key, byte[] value) + { + throw new NotImplementedException(); + } + + public void SetBytes(string key, byte[] value) => this.storage.AddOrReplace(key, value); + + public void SetChar(string key, char value) => this.storage.AddOrReplace(key, value); + + public void SetInt32(string key, int value) => this.storage.AddOrReplace(key, value); + + public void SetInt64(string key, long value) => this.storage.AddOrReplace(key, value); + + public void SetString(string key, string value) => this.storage.AddOrReplace(key, value); + + public void SetStruct(string key, T value) + where T : struct => this.storage.AddOrReplace(key, value); + + public void SetUInt32(string key, uint value) => this.storage.AddOrReplace(key, value); + + public void SetUInt64(string key, ulong value) => this.storage.AddOrReplace(key, value); + } +} diff --git a/Mainnet/DividendToken/DividendToken.sln b/Mainnet/DividendToken/DividendToken.sln new file mode 100644 index 00000000..fff0a409 --- /dev/null +++ b/Mainnet/DividendToken/DividendToken.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30204.135 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DividendToken", "DividendToken\DividendToken.csproj", "{3AD529F2-7163-4BBE-80BB-F2D7D54B2DFA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DividendToken.Tests", "DividendToken.Tests\DividendToken.Tests.csproj", "{3B5AF108-6986-4E17-9A01-EB297D6F0C15}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AD529F2-7163-4BBE-80BB-F2D7D54B2DFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AD529F2-7163-4BBE-80BB-F2D7D54B2DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AD529F2-7163-4BBE-80BB-F2D7D54B2DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AD529F2-7163-4BBE-80BB-F2D7D54B2DFA}.Release|Any CPU.Build.0 = Release|Any CPU + {3B5AF108-6986-4E17-9A01-EB297D6F0C15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B5AF108-6986-4E17-9A01-EB297D6F0C15}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B5AF108-6986-4E17-9A01-EB297D6F0C15}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B5AF108-6986-4E17-9A01-EB297D6F0C15}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BA15305F-3348-4660-BF5B-3D0CD51F0FFD} + EndGlobalSection +EndGlobal diff --git a/Mainnet/DividendToken/DividendToken/DividendToken.cs b/Mainnet/DividendToken/DividendToken/DividendToken.cs new file mode 100644 index 00000000..3286164a --- /dev/null +++ b/Mainnet/DividendToken/DividendToken/DividendToken.cs @@ -0,0 +1,288 @@ +using Stratis.SmartContracts; +using Stratis.SmartContracts.Standards; + +[Deploy] +public class DividendToken : SmartContract, IStandardToken +{ + + public ulong Dividends + { + get => PersistentState.GetUInt64(nameof(this.Dividends)); + private set => PersistentState.SetUInt64(nameof(this.Dividends), value); + } + + private Account GetAccount(Address address) => PersistentState.GetStruct($"Account:{address}"); + + private void SetAccount(Address address, Account account) => PersistentState.SetStruct($"Account:{address}", account); + + + public DividendToken(ISmartContractState state, ulong totalSupply, string name, string symbol) + : base(state) + { + this.TotalSupply = totalSupply; + this.Name = name; + this.Symbol = symbol; + this.SetBalance(Message.Sender, totalSupply); + } + + /// + /// It is advised that deposit amount should to be evenly divided by total supply, + /// otherwise small amount of satoshi may lost(burn) + /// + public override void Receive() + { + Dividends += Message.Value; + } + + public bool TransferTo(Address to, ulong amount) + { + UpdateAccount(Message.Sender); + UpdateAccount(to); + + return TransferTokensTo(to, amount); + } + + public bool TransferFrom(Address from, Address to, ulong amount) + { + UpdateAccount(from); + UpdateAccount(to); + + return TransferTokensFrom(from, to, amount); + } + + Account UpdateAccount(Address address) + { + var account = GetAccount(address); + var newDividends = GetWithdrawableDividends(address, account); + + if (newDividends > 0) + { + account.DividendBalance = checked(account.DividendBalance + newDividends); + account.CreditedDividends = Dividends; + SetAccount(address, account); + } + + return account; + } + + private ulong GetWithdrawableDividends(Address address, Account account) + { + var newDividends = Dividends - account.CreditedDividends; + var notCreditedDividends = checked(GetBalance(address) * newDividends); + + return checked(account.DividendBalance + notCreditedDividends); //Delay divide by TotalSupply to final stage for avoid decimal value loss. + } + + /// + /// Get Withdrawable dividends + /// + /// + public ulong GetDividends() => GetDividends(Message.Sender); + + /// + /// Get Withdrawable dividends + /// + /// + /// + public ulong GetDividends(Address address) + { + var account = GetAccount(address); + + return GetWithdrawableDividends(address, account) / TotalSupply; + } + + /// + /// Get the all divididends since beginning (Withdrawable Dividends + Withdrawn Dividends) + /// + /// + public ulong GetTotalDividends() => GetTotalDividends(Message.Sender); + + /// + /// Get the all divididends since beginning (Withdrawable Dividends + Withdrawn Dividends) + /// + /// + /// + public ulong GetTotalDividends(Address address) + { + var account = GetAccount(address); + return checked(GetWithdrawableDividends(address, account) + account.WithdrawnDividends) / TotalSupply; + } + + /// + /// Withdraws all dividends + /// + public void Withdraw() + { + var account = UpdateAccount(Message.Sender); + var balance = account.DividendBalance / TotalSupply; + var remainder = account.DividendBalance % TotalSupply; + + Assert(balance > 0, "The account has no dividends."); + + account.WithdrawnDividends = checked(account.WithdrawnDividends + account.DividendBalance - remainder); + account.DividendBalance = remainder; + + SetAccount(Message.Sender, account); + + var transfer = Transfer(Message.Sender, balance); + + Assert(transfer.Success, "Transfer failed."); + } + + public struct Account + { + /// + /// Withdrawable Dividend Balance. Exact value should to divided by + /// + public ulong DividendBalance; + + /// + /// + /// + + public ulong WithdrawnDividends; + + /// + /// Dividends computed and added to + /// + + public ulong CreditedDividends; + } + + #region StandardToken code is inlined + + public string Symbol + { + get => PersistentState.GetString(nameof(this.Symbol)); + private set => PersistentState.SetString(nameof(this.Symbol), value); + } + + public string Name + { + get => PersistentState.GetString(nameof(this.Name)); + private set => PersistentState.SetString(nameof(this.Name), value); + } + + /// + public ulong TotalSupply + { + get => PersistentState.GetUInt64(nameof(this.TotalSupply)); + private set => PersistentState.SetUInt64(nameof(this.TotalSupply), value); + } + /// + public ulong GetBalance(Address address) + { + return PersistentState.GetUInt64($"Balance:{address}"); + } + + private void SetBalance(Address address, ulong value) + { + PersistentState.SetUInt64($"Balance:{address}", value); + } + + /// + private bool TransferTokensTo(Address to, ulong amount) + { + if (amount == 0) + { + Log(new TransferLog { From = Message.Sender, To = to, Amount = 0 }); + + return true; + } + + ulong senderBalance = GetBalance(Message.Sender); + + if (senderBalance < amount) + { + return false; + } + + SetBalance(Message.Sender, senderBalance - amount); + + SetBalance(to, checked(GetBalance(to) + amount)); + + Log(new TransferLog { From = Message.Sender, To = to, Amount = amount }); + + return true; + } + + /// + private bool TransferTokensFrom(Address from, Address to, ulong amount) + { + if (amount == 0) + { + Log(new TransferLog { From = from, To = to, Amount = 0 }); + + return true; + } + + ulong senderAllowance = Allowance(from, Message.Sender); + ulong fromBalance = GetBalance(from); + + if (senderAllowance < amount || fromBalance < amount) + { + return false; + } + + SetApproval(from, Message.Sender, senderAllowance - amount); + + SetBalance(from, fromBalance - amount); + + SetBalance(to, checked(GetBalance(to) + amount)); + + Log(new TransferLog { From = from, To = to, Amount = amount }); + + return true; + } + + /// + public bool Approve(Address spender, ulong currentAmount, ulong amount) + { + if (Allowance(Message.Sender, spender) != currentAmount) + { + return false; + } + + SetApproval(Message.Sender, spender, amount); + + Log(new ApprovalLog { Owner = Message.Sender, Spender = spender, Amount = amount, OldAmount = currentAmount }); + + return true; + } + + private void SetApproval(Address owner, Address spender, ulong value) + { + PersistentState.SetUInt64($"Allowance:{owner}:{spender}", value); + } + + /// + public ulong Allowance(Address owner, Address spender) + { + return PersistentState.GetUInt64($"Allowance:{owner}:{spender}"); + } + + public struct TransferLog + { + [Index] + public Address From; + + [Index] + public Address To; + + public ulong Amount; + } + + public struct ApprovalLog + { + [Index] + public Address Owner; + + [Index] + public Address Spender; + + public ulong OldAmount; + + public ulong Amount; + } + #endregion +} \ No newline at end of file diff --git a/Mainnet/DividendToken/DividendToken/DividendToken.csproj b/Mainnet/DividendToken/DividendToken/DividendToken.csproj new file mode 100644 index 00000000..28caaf1a --- /dev/null +++ b/Mainnet/DividendToken/DividendToken/DividendToken.csproj @@ -0,0 +1,12 @@ + + + + netcoreapp2.1 + + 8.0 + + + + + + diff --git a/Mainnet/DividendToken/README.MD b/Mainnet/DividendToken/README.MD new file mode 100644 index 00000000..e0a23e6b --- /dev/null +++ b/Mainnet/DividendToken/README.MD @@ -0,0 +1,11 @@ +# Dividend Token Contract + +**Contract Hash** +``` +afb554ad1bb27c85f79f9ed061bd28e4cacbe5fb6fd29231c57f2047ebe00151 +``` + +**Contract Byte Code** +``` +4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0102004E678B9A0000000000000000E00022200B01300000140000000200000000000052320000002000000040000000000010002000000002000004000000000000000400000000000000006000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000003200004F000000000000000000000000000000000000000000000000000000004000000C000000E43100001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000058120000002000000014000000020000000000000000000000000000200000602E72656C6F6300000C00000000400000000200000016000000000000000000000000000040000042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034320000000000004800000002000500982500004C0C000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004602280600000A72010000706F0700000A2A4A02280600000A7201000070036F0800000A2A7202280600000A7215000070038C08000001280900000A6F0100002B2A7602280600000A7215000070038C08000001280900000A046F0200002B2AC20203280C00000A0204281500000602052813000006020E0428110000060202280D00000A6F0E00000A0428170000062A660202280100000602280D00000A6F0F00000AD728020000062A8E0202280D00000A6F0E00000A280900000626020328090000062602030428180000062A6A020328090000062602042809000006260203040528190000062A0000133003003C00000001000011020328030000060A020306280A0000060B07166A36241200067B0100000407D77D0100000412000228010000067D030000040203062804000006062A133002002100000002000011022801000006047B03000004DB0A0203281600000606D90B047B0100000407D72A4A0202280D00000A6F0E00000A280C0000062A133003001800000003000011020328030000060A020306280A0000060228140000065C2A4A0202280D00000A6F0E00000A280E0000062A00133003001F00000003000011020328030000060A020306280A000006067B02000004D70228140000065C2A001330030093000000040000110202280D00000A6F0E00000A28090000060A067B010000040228140000065C0B067B010000040228140000065E0C0207166AFE03722D000070281000000A1200067B02000004067B01000004D708DB7D020000041200087D010000040202280D00000A6F0E00000A0628040000060202280D00000A6F0E00000A07281100000A0D02096F1200000A7269000070281000000A2A4602280600000A728B0000706F1300000A2A4A02280600000A728B000070036F1400000A2A4602280600000A72990000706F1300000A2A4A02280600000A7299000070036F1400000A2A4602280600000A72A30000706F0700000A2A4A02280600000A72A3000070036F0800000A2A7202280600000A72BB000070038C08000001280900000A6F0700000A2A7602280600000A72BB000070038C08000001280900000A046F0800000A2A00000013300400A600000005000011042D34021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201166A7D0600000407280300002B172A0202280D00000A6F0E00000A28160000060A06043402162A0202280D00000A6F0E00000A0604DB281700000602030203281600000604D72817000006021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201047D0600000407280300002B172A000013300500AA00000006000011052D2A021202FE15040000021202037D040000041202047D050000041202166A7D0600000408280300002B172A020302280D00000A6F0E00000A281C0000060A020328160000060B0605370407053402162A020302280D00000A6F0E00000A0605DB281B00000602030705DB281700000602040204281600000605D72817000006021202FE15040000021202037D040000041202047D050000041202057D0600000408280300002B172A00001330040065000000070000110202280D00000A6F0E00000A03281C000006042E02162A0202280D00000A6F0E00000A0305281B000006021200FE1505000002120002280D00000A6F0E00000A7D070000041200037D080000041200057D0A0000041200047D0900000406280400002B172A8E02280600000A72D3000070038C08000001048C08000001281600000A056F0800000A2A8A02280600000A72D3000070038C08000001048C08000001281600000A6F0700000A2A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000030050000237E00009C0500004804000023537472696E677300000000E4090000F800000023555300DC0A0000100000002347554944000000EC0A00006001000023426C6F6200000000000000020000015717A201090A000000FA0133001600000100000010000000050000000A0000001C0000002500000001000000160000000800000007000000010000000400000008000000010000000300000003000000040000000000A3010100000000000600EE001D0306002D011D030600DA0070020F003D0300000A001D0168030A00860368030E000C02FC020A00580368030A009B0068030A00AF03680306009100D2010A000E0168030A00AF00680306007801D20106009403D2010A0065006803000000001500000000000100010001001000FE0100001900010001000A011000DB0300002D0001001D000A0110008B0100002D0004001D000A0110007F0100002D0007001D0006003500B7000600DC02B70006009F02B7000600F401BA0006003402BA000600FC03B70006005E02BA0006004502BA000600EB03B7000600FC03B700502000000000860883024A00010062200000000081089102BE0001007520000000008100CD03C30002009220000000008100D803CA000300B0200000000086186A02D2000500E12000000000C6005B0106000900FB2000000000E6011B02DB0009001F2100000000E601D901E2000B003C21000000008100BF03C3000E008421000000008100B102EB000F00B121000000008600EF024A001100C421000000008600EF02F3001100E821000000008600CA024A001200FC21000000008600CA02F30012002822000000008600110406001300C722000000008608B501F9001300D922000000008108C001FD001300EC220000000086087A00F9001400FE220000000081088300FD001400112300000000E6091A044A00150023230000000081082A04BE001500362300000000E6014500F3001600532300000000810050000201170074230000000081002602DB0019002824000000008100E601E2001B00E02400000000E601630109011E005125000000008100970111012100752500000000E6015B001A01240000000100550100000100600300000100600300000200E30300000100D400000002003A04000003008C0000000400CB0100000100370200000200030400000100F90100000200370200000300030400000100600300000100600300000200E30300000100600300000100600300000100550100000100550100000100550100000100600300000100600300000200550100000100370200000200030400000100F901000002003702000003000304000001004D0200000200F503000003000304000001006402000002004D02000003005501000001006402000002004D0202001D0009006A02010011006A02060019006A020A0029006A02060061006A0206003100C000100069000100150069000B001A0071007F03200069009B0326006900A503320031006A023A0031006E00400081003A02450081004B014A0031000A046700310055026D0051004C03750069006B017900690075017E00310093018A0071007F03A7002E000B002A012E00130033012E001B005201430023005B0181002B005B01A1002B005B01E1002B005B0101012B005B014E00540059005E00840096009D00020001000000F20222010000C401260100008700260100002E04220102000100030001000200030002001000050001001100050002001200070001001300070002001400090001001500090004800000000000000000000000000000000086030000040000000000000000000000AE001E000000000001000200010000000000000000006803000000000100000000000000000000000000FC020000000003000200040002000500020015002D0017002D002B0091002B00A20000000047657455496E7436340053657455496E743634003C4D6F64756C653E0053797374656D2E507269766174652E436F72654C6962004469766964656E6442616C616E63650047657442616C616E63650053657442616C616E636500416C6C6F77616E636500494D657373616765006765745F4D657373616765006765745F4E616D65007365745F4E616D65006E616D650056616C7565547970650049536D617274436F6E74726163745374617465004950657273697374656E745374617465006765745F50657273697374656E7453746174650073746174650044656275676761626C6541747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500496E646578417474726962757465004465706C6F794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465006765745F56616C75650076616C7565005265636569766500417070726F766500476574537472696E6700536574537472696E6700417070726F76616C4C6F67005472616E736665724C6F6700536574417070726F76616C00536D617274436F6E74726163742E646C6C006765745F53796D626F6C007365745F53796D626F6C0073796D626F6C0053797374656D005472616E7366657246726F6D005472616E73666572546F6B656E7346726F6D0066726F6D004469766964656E64546F6B656E00495374616E64617264546F6B656E005472616E73666572546F005472616E73666572546F6B656E73546F00746F006765745F53656E646572005370656E646572007370656E646572005472616E73666572004F776E6572006F776E6572002E63746F720053797374656D2E446961676E6F7374696373006765745F4469766964656E6473007365745F4469766964656E64730043726564697465644469766964656E647300476574576974686472617761626C654469766964656E647300476574546F74616C4469766964656E64730057697468647261776E4469766964656E6473004765744469766964656E647300537472617469732E536D617274436F6E7472616374732E5374616E64617264730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F646573006765745F537563636573730041646472657373006164647265737300537472617469732E536D617274436F6E74726163747300466F726D617400536D617274436F6E7472616374004F626A656374004765745374727563740053657453747275637400495472616E73666572526573756C74005570646174654163636F756E74004765744163636F756E74005365744163636F756E74006163636F756E74004F6C64416D6F756E740063757272656E74416D6F756E7400616D6F756E7400417373657274005769746864726177006765745F546F74616C537570706C79007365745F546F74616C537570706C7900746F74616C537570706C7900000000134400690076006900640065006E006400730000174100630063006F0075006E0074003A007B0030007D00003B54006800650020006100630063006F0075006E007400200068006100730020006E006F0020006400690076006900640065006E00640073002E0000215400720061006E00730066006500720020006600610069006C00650064002E00000D530079006D0062006F006C0000094E0061006D006500001754006F00740061006C0053007500700070006C0079000017420061006C0061006E00630065003A007B0030007D00002341006C006C006F00770061006E00630065003A007B0030007D003A007B0031007D00000031EC77F44ED48A46A24645E9865F8F930004200101080320000105200101111104200012350420010B0E052002010E0B0500020E0E1C063001011E000E040A01110C07300102010E1E00052001011225042000124104200011210320000B050702110C0B0407020B0B040701110C080704110C0B0B122905200201020E072002122911210B032000020420010E0E052002010E0E0507020B111006300101011E00040A0111100607030B0B11100407011114040A0111140600030E0E1C1C087CEC85D7BEA7798E02060B03061121042001010B062001110C1121072002011121110C0820040112250B0E0E0620020211210B08200302112111210B0720020B1121110C0520010B11210320000E042001010E0620020111210B0720030211210B0B08200301112111210B0720020B112111210328000B0328000E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010801000200000000000401000000000000000000000000000000100000000000000000000000000000002832000000000000000000004232000000200000000000000000000000000000000000000000000034320000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF250020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000C000000543200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +``` From c5ea6e65986ee55b9ffc7ce7ab5bec7caf873bee Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Tue, 5 Jan 2021 22:25:12 +0300 Subject: [PATCH 05/15] Explicitly defined property accessor --- Mainnet/DividendToken/DividendToken/DividendToken.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mainnet/DividendToken/DividendToken/DividendToken.cs b/Mainnet/DividendToken/DividendToken/DividendToken.cs index 3286164a..fd22c60d 100644 --- a/Mainnet/DividendToken/DividendToken/DividendToken.cs +++ b/Mainnet/DividendToken/DividendToken/DividendToken.cs @@ -50,7 +50,7 @@ public bool TransferFrom(Address from, Address to, ulong amount) return TransferTokensFrom(from, to, amount); } - Account UpdateAccount(Address address) + private Account UpdateAccount(Address address) { var account = GetAccount(address); var newDividends = GetWithdrawableDividends(address, account); From aa2672763fc14ff85a0acca7542ccc60899714f9 Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Wed, 6 Jan 2021 16:36:00 +0300 Subject: [PATCH 06/15] Wrong dividend balance calculation fixed --- .../DividendToken.Tests/DividendTokenTests.cs | 27 +++++++++++++++++++ .../DividendToken/DividendToken.cs | 25 ++++++++++++----- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs index bf9362fb..450437d2 100644 --- a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs +++ b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs @@ -54,7 +54,34 @@ public void Deposited_Dividend_Should_Be_Distributed_Equaly() Assert.Equal(dividend, contract.Dividends); Assert.Equal(100ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(100ul, contract.GetTotalDividends(this.tokenHolder)); Assert.Equal(900ul, contract.GetDividends(this.owner)); + Assert.Equal(900ul, contract.GetTotalDividends(this.owner)); + } + + [Fact] + public void Multiple_Deposited_Dividend_Should_Be_Distributed_Equaly() + { + var dividend = 1000ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + contract.Receive(); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + contract.Receive(); + + Assert.Equal(2*dividend, contract.Dividends); + Assert.Equal(300ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(300ul, contract.GetTotalDividends(this.tokenHolder)); + + Assert.Equal(1700ul, contract.GetDividends(this.owner)); + Assert.Equal(1700ul, contract.GetTotalDividends(this.owner)); } [Fact] diff --git a/Mainnet/DividendToken/DividendToken/DividendToken.cs b/Mainnet/DividendToken/DividendToken/DividendToken.cs index fd22c60d..40a6757c 100644 --- a/Mainnet/DividendToken/DividendToken/DividendToken.cs +++ b/Mainnet/DividendToken/DividendToken/DividendToken.cs @@ -25,15 +25,20 @@ public DividendToken(ISmartContractState state, ulong totalSupply, string name, this.SetBalance(Message.Sender, totalSupply); } + + public override void Receive() + { + DistributeDividends(); + } + /// /// It is advised that deposit amount should to be evenly divided by total supply, /// otherwise small amount of satoshi may lost(burn) /// - public override void Receive() + public void DistributeDividends() { Dividends += Message.Value; } - public bool TransferTo(Address to, ulong amount) { UpdateAccount(Message.Sender); @@ -53,7 +58,7 @@ public bool TransferFrom(Address from, Address to, ulong amount) private Account UpdateAccount(Address address) { var account = GetAccount(address); - var newDividends = GetWithdrawableDividends(address, account); + var newDividends = GetNewDividends(address, account); if (newDividends > 0) { @@ -67,10 +72,16 @@ private Account UpdateAccount(Address address) private ulong GetWithdrawableDividends(Address address, Account account) { - var newDividends = Dividends - account.CreditedDividends; - var notCreditedDividends = checked(GetBalance(address) * newDividends); + return checked(account.DividendBalance + GetNewDividends(address, account)); //Delay divide by TotalSupply to final stage for avoid decimal value loss. + } - return checked(account.DividendBalance + notCreditedDividends); //Delay divide by TotalSupply to final stage for avoid decimal value loss. + private ulong GetNewDividends(Address address, Account account) + { + checked + { + var notCreditedDividends = Dividends - account.CreditedDividends; + return GetBalance(address) * notCreditedDividends; + } } /// @@ -118,7 +129,7 @@ public void Withdraw() var remainder = account.DividendBalance % TotalSupply; Assert(balance > 0, "The account has no dividends."); - + account.WithdrawnDividends = checked(account.WithdrawnDividends + account.DividendBalance - remainder); account.DividendBalance = remainder; From 80612a06152f350bf210739394571464e62ab8cc Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Wed, 6 Jan 2021 16:43:50 +0300 Subject: [PATCH 07/15] Fixed test case --- .../DividendToken/DividendToken.Tests/DividendTokenTests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs index 450437d2..7ec36ad2 100644 --- a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs +++ b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs @@ -76,7 +76,9 @@ public void Multiple_Deposited_Dividend_Should_Be_Distributed_Equaly() contract.Receive(); - Assert.Equal(2*dividend, contract.Dividends); + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + Assert.Equal(2 * dividend, contract.Dividends); Assert.Equal(300ul, contract.GetDividends(this.tokenHolder)); Assert.Equal(300ul, contract.GetTotalDividends(this.tokenHolder)); From b0813336de2302f6aaeecf2cbb23a3124fe165c5 Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Wed, 6 Jan 2021 16:50:36 +0300 Subject: [PATCH 08/15] Btye code updated --- Mainnet/DividendToken/README.MD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mainnet/DividendToken/README.MD b/Mainnet/DividendToken/README.MD index e0a23e6b..db698d8e 100644 --- a/Mainnet/DividendToken/README.MD +++ b/Mainnet/DividendToken/README.MD @@ -2,10 +2,10 @@ **Contract Hash** ``` -afb554ad1bb27c85f79f9ed061bd28e4cacbe5fb6fd29231c57f2047ebe00151 +41a37d258e324a6c51ec2099a1a20546c696fecf2a649bd6e6cd8add835d46ce ``` **Contract Byte Code** ``` -4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0102004E678B9A0000000000000000E00022200B01300000140000000200000000000052320000002000000040000000000010002000000002000004000000000000000400000000000000006000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000003200004F000000000000000000000000000000000000000000000000000000004000000C000000E43100001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000058120000002000000014000000020000000000000000000000000000200000602E72656C6F6300000C00000000400000000200000016000000000000000000000000000040000042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034320000000000004800000002000500982500004C0C000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004602280600000A72010000706F0700000A2A4A02280600000A7201000070036F0800000A2A7202280600000A7215000070038C08000001280900000A6F0100002B2A7602280600000A7215000070038C08000001280900000A046F0200002B2AC20203280C00000A0204281500000602052813000006020E0428110000060202280D00000A6F0E00000A0428170000062A660202280100000602280D00000A6F0F00000AD728020000062A8E0202280D00000A6F0E00000A280900000626020328090000062602030428180000062A6A020328090000062602042809000006260203040528190000062A0000133003003C00000001000011020328030000060A020306280A0000060B07166A36241200067B0100000407D77D0100000412000228010000067D030000040203062804000006062A133002002100000002000011022801000006047B03000004DB0A0203281600000606D90B047B0100000407D72A4A0202280D00000A6F0E00000A280C0000062A133003001800000003000011020328030000060A020306280A0000060228140000065C2A4A0202280D00000A6F0E00000A280E0000062A00133003001F00000003000011020328030000060A020306280A000006067B02000004D70228140000065C2A001330030093000000040000110202280D00000A6F0E00000A28090000060A067B010000040228140000065C0B067B010000040228140000065E0C0207166AFE03722D000070281000000A1200067B02000004067B01000004D708DB7D020000041200087D010000040202280D00000A6F0E00000A0628040000060202280D00000A6F0E00000A07281100000A0D02096F1200000A7269000070281000000A2A4602280600000A728B0000706F1300000A2A4A02280600000A728B000070036F1400000A2A4602280600000A72990000706F1300000A2A4A02280600000A7299000070036F1400000A2A4602280600000A72A30000706F0700000A2A4A02280600000A72A3000070036F0800000A2A7202280600000A72BB000070038C08000001280900000A6F0700000A2A7602280600000A72BB000070038C08000001280900000A046F0800000A2A00000013300400A600000005000011042D34021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201166A7D0600000407280300002B172A0202280D00000A6F0E00000A28160000060A06043402162A0202280D00000A6F0E00000A0604DB281700000602030203281600000604D72817000006021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201047D0600000407280300002B172A000013300500AA00000006000011052D2A021202FE15040000021202037D040000041202047D050000041202166A7D0600000408280300002B172A020302280D00000A6F0E00000A281C0000060A020328160000060B0605370407053402162A020302280D00000A6F0E00000A0605DB281B00000602030705DB281700000602040204281600000605D72817000006021202FE15040000021202037D040000041202047D050000041202057D0600000408280300002B172A00001330040065000000070000110202280D00000A6F0E00000A03281C000006042E02162A0202280D00000A6F0E00000A0305281B000006021200FE1505000002120002280D00000A6F0E00000A7D070000041200037D080000041200057D0A0000041200047D0900000406280400002B172A8E02280600000A72D3000070038C08000001048C08000001281600000A056F0800000A2A8A02280600000A72D3000070038C08000001048C08000001281600000A6F0700000A2A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000030050000237E00009C0500004804000023537472696E677300000000E4090000F800000023555300DC0A0000100000002347554944000000EC0A00006001000023426C6F6200000000000000020000015717A201090A000000FA0133001600000100000010000000050000000A0000001C0000002500000001000000160000000800000007000000010000000400000008000000010000000300000003000000040000000000A3010100000000000600EE001D0306002D011D030600DA0070020F003D0300000A001D0168030A00860368030E000C02FC020A00580368030A009B0068030A00AF03680306009100D2010A000E0168030A00AF00680306007801D20106009403D2010A0065006803000000001500000000000100010001001000FE0100001900010001000A011000DB0300002D0001001D000A0110008B0100002D0004001D000A0110007F0100002D0007001D0006003500B7000600DC02B70006009F02B7000600F401BA0006003402BA000600FC03B70006005E02BA0006004502BA000600EB03B7000600FC03B700502000000000860883024A00010062200000000081089102BE0001007520000000008100CD03C30002009220000000008100D803CA000300B0200000000086186A02D2000500E12000000000C6005B0106000900FB2000000000E6011B02DB0009001F2100000000E601D901E2000B003C21000000008100BF03C3000E008421000000008100B102EB000F00B121000000008600EF024A001100C421000000008600EF02F3001100E821000000008600CA024A001200FC21000000008600CA02F30012002822000000008600110406001300C722000000008608B501F9001300D922000000008108C001FD001300EC220000000086087A00F9001400FE220000000081088300FD001400112300000000E6091A044A00150023230000000081082A04BE001500362300000000E6014500F3001600532300000000810050000201170074230000000081002602DB0019002824000000008100E601E2001B00E02400000000E601630109011E005125000000008100970111012100752500000000E6015B001A01240000000100550100000100600300000100600300000200E30300000100D400000002003A04000003008C0000000400CB0100000100370200000200030400000100F90100000200370200000300030400000100600300000100600300000200E30300000100600300000100600300000100550100000100550100000100550100000100600300000100600300000200550100000100370200000200030400000100F901000002003702000003000304000001004D0200000200F503000003000304000001006402000002004D02000003005501000001006402000002004D0202001D0009006A02010011006A02060019006A020A0029006A02060061006A0206003100C000100069000100150069000B001A0071007F03200069009B0326006900A503320031006A023A0031006E00400081003A02450081004B014A0031000A046700310055026D0051004C03750069006B017900690075017E00310093018A0071007F03A7002E000B002A012E00130033012E001B005201430023005B0181002B005B01A1002B005B01E1002B005B0101012B005B014E00540059005E00840096009D00020001000000F20222010000C401260100008700260100002E04220102000100030001000200030002001000050001001100050002001200070001001300070002001400090001001500090004800000000000000000000000000000000086030000040000000000000000000000AE001E000000000001000200010000000000000000006803000000000100000000000000000000000000FC020000000003000200040002000500020015002D0017002D002B0091002B00A20000000047657455496E7436340053657455496E743634003C4D6F64756C653E0053797374656D2E507269766174652E436F72654C6962004469766964656E6442616C616E63650047657442616C616E63650053657442616C616E636500416C6C6F77616E636500494D657373616765006765745F4D657373616765006765745F4E616D65007365745F4E616D65006E616D650056616C7565547970650049536D617274436F6E74726163745374617465004950657273697374656E745374617465006765745F50657273697374656E7453746174650073746174650044656275676761626C6541747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500496E646578417474726962757465004465706C6F794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465006765745F56616C75650076616C7565005265636569766500417070726F766500476574537472696E6700536574537472696E6700417070726F76616C4C6F67005472616E736665724C6F6700536574417070726F76616C00536D617274436F6E74726163742E646C6C006765745F53796D626F6C007365745F53796D626F6C0073796D626F6C0053797374656D005472616E7366657246726F6D005472616E73666572546F6B656E7346726F6D0066726F6D004469766964656E64546F6B656E00495374616E64617264546F6B656E005472616E73666572546F005472616E73666572546F6B656E73546F00746F006765745F53656E646572005370656E646572007370656E646572005472616E73666572004F776E6572006F776E6572002E63746F720053797374656D2E446961676E6F7374696373006765745F4469766964656E6473007365745F4469766964656E64730043726564697465644469766964656E647300476574576974686472617761626C654469766964656E647300476574546F74616C4469766964656E64730057697468647261776E4469766964656E6473004765744469766964656E647300537472617469732E536D617274436F6E7472616374732E5374616E64617264730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F646573006765745F537563636573730041646472657373006164647265737300537472617469732E536D617274436F6E74726163747300466F726D617400536D617274436F6E7472616374004F626A656374004765745374727563740053657453747275637400495472616E73666572526573756C74005570646174654163636F756E74004765744163636F756E74005365744163636F756E74006163636F756E74004F6C64416D6F756E740063757272656E74416D6F756E7400616D6F756E7400417373657274005769746864726177006765745F546F74616C537570706C79007365745F546F74616C537570706C7900746F74616C537570706C7900000000134400690076006900640065006E006400730000174100630063006F0075006E0074003A007B0030007D00003B54006800650020006100630063006F0075006E007400200068006100730020006E006F0020006400690076006900640065006E00640073002E0000215400720061006E00730066006500720020006600610069006C00650064002E00000D530079006D0062006F006C0000094E0061006D006500001754006F00740061006C0053007500700070006C0079000017420061006C0061006E00630065003A007B0030007D00002341006C006C006F00770061006E00630065003A007B0030007D003A007B0031007D00000031EC77F44ED48A46A24645E9865F8F930004200101080320000105200101111104200012350420010B0E052002010E0B0500020E0E1C063001011E000E040A01110C07300102010E1E00052001011225042000124104200011210320000B050702110C0B0407020B0B040701110C080704110C0B0B122905200201020E072002122911210B032000020420010E0E052002010E0E0507020B111006300101011E00040A0111100607030B0B11100407011114040A0111140600030E0E1C1C087CEC85D7BEA7798E02060B03061121042001010B062001110C1121072002011121110C0820040112250B0E0E0620020211210B08200302112111210B0720020B1121110C0520010B11210320000E042001010E0620020111210B0720030211210B0B08200301112111210B0720020B112111210328000B0328000E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010801000200000000000401000000000000000000000000000000100000000000000000000000000000002832000000000000000000004232000000200000000000000000000000000000000000000000000034320000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF250020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000C000000543200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0102001B3479CF0000000000000000E00022200B013000001400000002000000000000B2320000002000000040000000000010002000000002000004000000000000000400000000000000006000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000603200004F000000000000000000000000000000000000000000000000000000004000000C000000443200001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E74657874000000B8120000002000000014000000020000000000000000000000000000200000602E72656C6F6300000C00000000400000000200000016000000000000000000000000000040000042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094320000000000004800000002000500AC250000980C000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004602280600000A72010000706F0700000A2A4A02280600000A7201000070036F0800000A2A7202280600000A7215000070038C08000001280900000A6F0100002B2A7602280600000A7215000070038C08000001280900000A046F0200002B2AC20203280C00000A0204281700000602052815000006020E0428130000060202280D00000A6F0E00000A0428190000062A1E0228070000062A660202280100000602280D00000A6F0F00000AD728020000062A8E0202280D00000A6F0E00000A280A000006260203280A00000626020304281A0000062A6A0203280A000006260204280A0000062602030405281B0000062A0000133003003C00000001000011020328030000060A020306280C0000060B07166A36241200067B0100000407D77D0100000412000228010000067D030000040203062804000006062A42047B01000004020304280C000006D72A000000133002001800000002000011022801000006047B03000004DB0A0203281800000606D92A4A0202280D00000A6F0E00000A280E0000062A00133003001800000003000011020328030000060A020306280B0000060228160000065C2A4A0202280D00000A6F0E00000A28100000062A00133003001F00000003000011020328030000060A020306280B000006067B02000004D70228160000065C2A001330030093000000040000110202280D00000A6F0E00000A280A0000060A067B010000040228160000065C0B067B010000040228160000065E0C0207166AFE03722D000070281000000A1200067B02000004067B01000004D708DB7D020000041200087D010000040202280D00000A6F0E00000A0628040000060202280D00000A6F0E00000A07281100000A0D02096F1200000A7269000070281000000A2A4602280600000A728B0000706F1300000A2A4A02280600000A728B000070036F1400000A2A4602280600000A72990000706F1300000A2A4A02280600000A7299000070036F1400000A2A4602280600000A72A30000706F0700000A2A4A02280600000A72A3000070036F0800000A2A7202280600000A72BB000070038C08000001280900000A6F0700000A2A7602280600000A72BB000070038C08000001280900000A046F0800000A2A00000013300400A600000005000011042D34021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201166A7D0600000407280300002B172A0202280D00000A6F0E00000A28180000060A06043402162A0202280D00000A6F0E00000A0604DB281900000602030203281800000604D72819000006021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201047D0600000407280300002B172A000013300500AA00000006000011052D2A021202FE15040000021202037D040000041202047D050000041202166A7D0600000408280300002B172A020302280D00000A6F0E00000A281E0000060A020328180000060B0605370407053402162A020302280D00000A6F0E00000A0605DB281D00000602030705DB281900000602040204281800000605D72819000006021202FE15040000021202037D040000041202047D050000041202057D0600000408280300002B172A00001330040065000000070000110202280D00000A6F0E00000A03281E000006042E02162A0202280D00000A6F0E00000A0305281D000006021200FE1505000002120002280D00000A6F0E00000A7D070000041200037D080000041200057D0A0000041200047D0900000406280400002B172A8E02280600000A72D3000070038C08000001048C08000001281600000A056F0800000A2A8A02280600000A72D3000070038C08000001048C08000001281600000A6F0700000A2A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000058050000237E0000C40500006C04000023537472696E677300000000300A0000F800000023555300280B0000100000002347554944000000380B00006001000023426C6F6200000000000000020000015717A201090A000000FA0133001600000100000010000000050000000A0000001E0000002700000001000000160000000800000007000000010000000400000008000000010000000300000003000000040000000000A3010100000000000600EE00410306002D0141030600DA0070020F00610300000A001D018C030A00AA038C030E000C0220030A007C038C030A009B008C030A00D3038C0306009100D2010A000E018C030A00AF008C0306007801D2010600B803D2010A0065008C03000000001500000000000100010001001000FE0100001900010001000A011000FF0300002D0001001F000A0110008B0100002D0004001F000A0110007F0100002D0007001F0006003500B6000600F002B60006009F02B6000600F401B90006003402B90006002004B60006005E02B90006004502B90006000F04B60006002004B600502000000000860883024A00010062200000000081089102BD0001007520000000008100F103C20002009220000000008100FC03C9000300B0200000000086186A02D1000500E12000000000C6005B0106000900E920000000008600CA0206000900032100000000E6011B02DA000900272100000000E601D901E1000B004421000000008100E303C2000E008C21000000008100B102EA000F00A0210000000081001003EA001100C42100000000860003034A001300D8210000000086000303F2001300FC21000000008600DE024A0014001022000000008600DE02F20014003C22000000008600350406001500DB22000000008608B501F8001500ED22000000008108C001FC00150000230000000086087A00F800160012230000000081088300FC001600252300000000E6093E044A00170037230000000081084E04BD0017004A2300000000E6014500F2001800672300000000810050000101190088230000000081002602DA001B003C24000000008100E601E1001D00F42400000000E6016301080120006525000000008100970110012300892500000000E6015B001901260000000100550100000100840300000100840300000200070400000100D400000002005E04000003008C0000000400CB0100000100370200000200270400000100F90100000200370200000300270400000100840300000100840300000200070400000100840300000200070400000100840300000100840300000100550100000100550100000100550100000100840300000100840300000200550100000100370200000200270400000100F901000002003702000003002704000001004D02000002001904000003002704000001006402000002004D02000003005501000001006402000002004D0202001D0009006A02010011006A02060019006A020A0029006A02060061006A0206003100C000100069000100150069000B001A007100A30320006900BF0326006900C903320031006A023A0031006E00400081003A02450081004B014A0031002E046600310055026C0051007003740069006B017800690075017D003100930189007100A303A6002E000B0029012E00130032012E001B005101430023005A0181002B005A01A1002B005A01E1002B005A0101012B005A014E00540058005D00830095009C00020001000000160321010000C4012501000087002501000052042101020001000300010002000300020012000500010013000500020014000700010015000700020016000900010017000900048000000000000000000000000000000000AA030000040000000000000000000000AD001E000000000001000200010000000000000000008C0300000000010000000000000000000000000020030000000003000200040002000500020015002D0017002D002B0090002B00A10000000047657455496E7436340053657455496E743634003C4D6F64756C653E0053797374656D2E507269766174652E436F72654C6962004469766964656E6442616C616E63650047657442616C616E63650053657442616C616E636500416C6C6F77616E636500494D657373616765006765745F4D657373616765006765745F4E616D65007365745F4E616D65006E616D650056616C7565547970650049536D617274436F6E74726163745374617465004950657273697374656E745374617465006765745F50657273697374656E7453746174650073746174650044656275676761626C6541747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500496E646578417474726962757465004465706C6F794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465006765745F56616C75650076616C7565005265636569766500417070726F766500476574537472696E6700536574537472696E6700417070726F76616C4C6F67005472616E736665724C6F6700536574417070726F76616C00536D617274436F6E74726163742E646C6C006765745F53796D626F6C007365745F53796D626F6C0073796D626F6C0053797374656D005472616E7366657246726F6D005472616E73666572546F6B656E7346726F6D0066726F6D004469766964656E64546F6B656E00495374616E64617264546F6B656E005472616E73666572546F005472616E73666572546F6B656E73546F00746F006765745F53656E646572005370656E646572007370656E646572005472616E73666572004F776E6572006F776E6572002E63746F720053797374656D2E446961676E6F7374696373006765745F4469766964656E6473007365745F4469766964656E64730043726564697465644469766964656E647300476574576974686472617761626C654469766964656E647300446973747269627574654469766964656E647300476574546F74616C4469766964656E64730057697468647261776E4469766964656E6473004765744469766964656E6473004765744E65774469766964656E647300537472617469732E536D617274436F6E7472616374732E5374616E64617264730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F646573006765745F537563636573730041646472657373006164647265737300537472617469732E536D617274436F6E74726163747300466F726D617400536D617274436F6E7472616374004F626A656374004765745374727563740053657453747275637400495472616E73666572526573756C74005570646174654163636F756E74004765744163636F756E74005365744163636F756E74006163636F756E74004F6C64416D6F756E740063757272656E74416D6F756E7400616D6F756E7400417373657274005769746864726177006765745F546F74616C537570706C79007365745F546F74616C537570706C7900746F74616C537570706C7900000000134400690076006900640065006E006400730000174100630063006F0075006E0074003A007B0030007D00003B54006800650020006100630063006F0075006E007400200068006100730020006E006F0020006400690076006900640065006E00640073002E0000215400720061006E00730066006500720020006600610069006C00650064002E00000D530079006D0062006F006C0000094E0061006D006500001754006F00740061006C0053007500700070006C0079000017420061006C0061006E00630065003A007B0030007D00002341006C006C006F00770061006E00630065003A007B0030007D003A007B0031007D00000043222F817C95CB4498A926937E6400A20004200101080320000105200101111104200012350420010B0E052002010E0B0500020E0E1C063001011E000E040A01110C07300102010E1E00052001011225042000124104200011210320000B050702110C0B0307010B040701110C080704110C0B0B122905200201020E072002122911210B032000020420010E0E052002010E0E0507020B111006300101011E00040A0111100607030B0B11100407011114040A0111140600030E0E1C1C087CEC85D7BEA7798E02060B03061121042001010B062001110C1121072002011121110C0820040112250B0E0E0620020211210B08200302112111210B0720020B1121110C0520010B11210320000E042001010E0620020111210B0720030211210B0B08200301112111210B0720020B112111210328000B0328000E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F77730108010002000000000004010000000000000000000000000000000010000000000000000000000000000000883200000000000000000000A232000000200000000000000000000000000000000000000000000094320000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF250020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000C000000B43200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ``` From 591ab24409ca07dab387d3ca2b4bfccbcbc2d6bd Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Wed, 6 Jan 2021 16:50:53 +0300 Subject: [PATCH 09/15] Applied changes to testnet project --- .../DividendToken.Tests/DividendTokenTests.cs | 29 +++++++++++++++++++ .../DividendToken/DividendToken.cs | 27 ++++++++++++----- Testnet/DividendToken/README.MD | 4 +-- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs b/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs index bf9362fb..7ec36ad2 100644 --- a/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs +++ b/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs @@ -54,7 +54,36 @@ public void Deposited_Dividend_Should_Be_Distributed_Equaly() Assert.Equal(dividend, contract.Dividends); Assert.Equal(100ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(100ul, contract.GetTotalDividends(this.tokenHolder)); Assert.Equal(900ul, contract.GetDividends(this.owner)); + Assert.Equal(900ul, contract.GetTotalDividends(this.owner)); + } + + [Fact] + public void Multiple_Deposited_Dividend_Should_Be_Distributed_Equaly() + { + var dividend = 1000ul; + + this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + contract.Receive(); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + contract.Receive(); + + Assert.True(contract.TransferTo(this.tokenHolder, 100)); + + Assert.Equal(2 * dividend, contract.Dividends); + Assert.Equal(300ul, contract.GetDividends(this.tokenHolder)); + Assert.Equal(300ul, contract.GetTotalDividends(this.tokenHolder)); + + Assert.Equal(1700ul, contract.GetDividends(this.owner)); + Assert.Equal(1700ul, contract.GetTotalDividends(this.owner)); } [Fact] diff --git a/Testnet/DividendToken/DividendToken/DividendToken.cs b/Testnet/DividendToken/DividendToken/DividendToken.cs index 3286164a..40a6757c 100644 --- a/Testnet/DividendToken/DividendToken/DividendToken.cs +++ b/Testnet/DividendToken/DividendToken/DividendToken.cs @@ -25,15 +25,20 @@ public DividendToken(ISmartContractState state, ulong totalSupply, string name, this.SetBalance(Message.Sender, totalSupply); } + + public override void Receive() + { + DistributeDividends(); + } + /// /// It is advised that deposit amount should to be evenly divided by total supply, /// otherwise small amount of satoshi may lost(burn) /// - public override void Receive() + public void DistributeDividends() { Dividends += Message.Value; } - public bool TransferTo(Address to, ulong amount) { UpdateAccount(Message.Sender); @@ -50,10 +55,10 @@ public bool TransferFrom(Address from, Address to, ulong amount) return TransferTokensFrom(from, to, amount); } - Account UpdateAccount(Address address) + private Account UpdateAccount(Address address) { var account = GetAccount(address); - var newDividends = GetWithdrawableDividends(address, account); + var newDividends = GetNewDividends(address, account); if (newDividends > 0) { @@ -67,10 +72,16 @@ Account UpdateAccount(Address address) private ulong GetWithdrawableDividends(Address address, Account account) { - var newDividends = Dividends - account.CreditedDividends; - var notCreditedDividends = checked(GetBalance(address) * newDividends); + return checked(account.DividendBalance + GetNewDividends(address, account)); //Delay divide by TotalSupply to final stage for avoid decimal value loss. + } - return checked(account.DividendBalance + notCreditedDividends); //Delay divide by TotalSupply to final stage for avoid decimal value loss. + private ulong GetNewDividends(Address address, Account account) + { + checked + { + var notCreditedDividends = Dividends - account.CreditedDividends; + return GetBalance(address) * notCreditedDividends; + } } /// @@ -118,7 +129,7 @@ public void Withdraw() var remainder = account.DividendBalance % TotalSupply; Assert(balance > 0, "The account has no dividends."); - + account.WithdrawnDividends = checked(account.WithdrawnDividends + account.DividendBalance - remainder); account.DividendBalance = remainder; diff --git a/Testnet/DividendToken/README.MD b/Testnet/DividendToken/README.MD index e0a23e6b..db698d8e 100644 --- a/Testnet/DividendToken/README.MD +++ b/Testnet/DividendToken/README.MD @@ -2,10 +2,10 @@ **Contract Hash** ``` -afb554ad1bb27c85f79f9ed061bd28e4cacbe5fb6fd29231c57f2047ebe00151 +41a37d258e324a6c51ec2099a1a20546c696fecf2a649bd6e6cd8add835d46ce ``` **Contract Byte Code** ``` -4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0102004E678B9A0000000000000000E00022200B01300000140000000200000000000052320000002000000040000000000010002000000002000004000000000000000400000000000000006000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000003200004F000000000000000000000000000000000000000000000000000000004000000C000000E43100001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000058120000002000000014000000020000000000000000000000000000200000602E72656C6F6300000C00000000400000000200000016000000000000000000000000000040000042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034320000000000004800000002000500982500004C0C000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004602280600000A72010000706F0700000A2A4A02280600000A7201000070036F0800000A2A7202280600000A7215000070038C08000001280900000A6F0100002B2A7602280600000A7215000070038C08000001280900000A046F0200002B2AC20203280C00000A0204281500000602052813000006020E0428110000060202280D00000A6F0E00000A0428170000062A660202280100000602280D00000A6F0F00000AD728020000062A8E0202280D00000A6F0E00000A280900000626020328090000062602030428180000062A6A020328090000062602042809000006260203040528190000062A0000133003003C00000001000011020328030000060A020306280A0000060B07166A36241200067B0100000407D77D0100000412000228010000067D030000040203062804000006062A133002002100000002000011022801000006047B03000004DB0A0203281600000606D90B047B0100000407D72A4A0202280D00000A6F0E00000A280C0000062A133003001800000003000011020328030000060A020306280A0000060228140000065C2A4A0202280D00000A6F0E00000A280E0000062A00133003001F00000003000011020328030000060A020306280A000006067B02000004D70228140000065C2A001330030093000000040000110202280D00000A6F0E00000A28090000060A067B010000040228140000065C0B067B010000040228140000065E0C0207166AFE03722D000070281000000A1200067B02000004067B01000004D708DB7D020000041200087D010000040202280D00000A6F0E00000A0628040000060202280D00000A6F0E00000A07281100000A0D02096F1200000A7269000070281000000A2A4602280600000A728B0000706F1300000A2A4A02280600000A728B000070036F1400000A2A4602280600000A72990000706F1300000A2A4A02280600000A7299000070036F1400000A2A4602280600000A72A30000706F0700000A2A4A02280600000A72A3000070036F0800000A2A7202280600000A72BB000070038C08000001280900000A6F0700000A2A7602280600000A72BB000070038C08000001280900000A046F0800000A2A00000013300400A600000005000011042D34021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201166A7D0600000407280300002B172A0202280D00000A6F0E00000A28160000060A06043402162A0202280D00000A6F0E00000A0604DB281700000602030203281600000604D72817000006021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201047D0600000407280300002B172A000013300500AA00000006000011052D2A021202FE15040000021202037D040000041202047D050000041202166A7D0600000408280300002B172A020302280D00000A6F0E00000A281C0000060A020328160000060B0605370407053402162A020302280D00000A6F0E00000A0605DB281B00000602030705DB281700000602040204281600000605D72817000006021202FE15040000021202037D040000041202047D050000041202057D0600000408280300002B172A00001330040065000000070000110202280D00000A6F0E00000A03281C000006042E02162A0202280D00000A6F0E00000A0305281B000006021200FE1505000002120002280D00000A6F0E00000A7D070000041200037D080000041200057D0A0000041200047D0900000406280400002B172A8E02280600000A72D3000070038C08000001048C08000001281600000A056F0800000A2A8A02280600000A72D3000070038C08000001048C08000001281600000A6F0700000A2A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000030050000237E00009C0500004804000023537472696E677300000000E4090000F800000023555300DC0A0000100000002347554944000000EC0A00006001000023426C6F6200000000000000020000015717A201090A000000FA0133001600000100000010000000050000000A0000001C0000002500000001000000160000000800000007000000010000000400000008000000010000000300000003000000040000000000A3010100000000000600EE001D0306002D011D030600DA0070020F003D0300000A001D0168030A00860368030E000C02FC020A00580368030A009B0068030A00AF03680306009100D2010A000E0168030A00AF00680306007801D20106009403D2010A0065006803000000001500000000000100010001001000FE0100001900010001000A011000DB0300002D0001001D000A0110008B0100002D0004001D000A0110007F0100002D0007001D0006003500B7000600DC02B70006009F02B7000600F401BA0006003402BA000600FC03B70006005E02BA0006004502BA000600EB03B7000600FC03B700502000000000860883024A00010062200000000081089102BE0001007520000000008100CD03C30002009220000000008100D803CA000300B0200000000086186A02D2000500E12000000000C6005B0106000900FB2000000000E6011B02DB0009001F2100000000E601D901E2000B003C21000000008100BF03C3000E008421000000008100B102EB000F00B121000000008600EF024A001100C421000000008600EF02F3001100E821000000008600CA024A001200FC21000000008600CA02F30012002822000000008600110406001300C722000000008608B501F9001300D922000000008108C001FD001300EC220000000086087A00F9001400FE220000000081088300FD001400112300000000E6091A044A00150023230000000081082A04BE001500362300000000E6014500F3001600532300000000810050000201170074230000000081002602DB0019002824000000008100E601E2001B00E02400000000E601630109011E005125000000008100970111012100752500000000E6015B001A01240000000100550100000100600300000100600300000200E30300000100D400000002003A04000003008C0000000400CB0100000100370200000200030400000100F90100000200370200000300030400000100600300000100600300000200E30300000100600300000100600300000100550100000100550100000100550100000100600300000100600300000200550100000100370200000200030400000100F901000002003702000003000304000001004D0200000200F503000003000304000001006402000002004D02000003005501000001006402000002004D0202001D0009006A02010011006A02060019006A020A0029006A02060061006A0206003100C000100069000100150069000B001A0071007F03200069009B0326006900A503320031006A023A0031006E00400081003A02450081004B014A0031000A046700310055026D0051004C03750069006B017900690075017E00310093018A0071007F03A7002E000B002A012E00130033012E001B005201430023005B0181002B005B01A1002B005B01E1002B005B0101012B005B014E00540059005E00840096009D00020001000000F20222010000C401260100008700260100002E04220102000100030001000200030002001000050001001100050002001200070001001300070002001400090001001500090004800000000000000000000000000000000086030000040000000000000000000000AE001E000000000001000200010000000000000000006803000000000100000000000000000000000000FC020000000003000200040002000500020015002D0017002D002B0091002B00A20000000047657455496E7436340053657455496E743634003C4D6F64756C653E0053797374656D2E507269766174652E436F72654C6962004469766964656E6442616C616E63650047657442616C616E63650053657442616C616E636500416C6C6F77616E636500494D657373616765006765745F4D657373616765006765745F4E616D65007365745F4E616D65006E616D650056616C7565547970650049536D617274436F6E74726163745374617465004950657273697374656E745374617465006765745F50657273697374656E7453746174650073746174650044656275676761626C6541747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500496E646578417474726962757465004465706C6F794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465006765745F56616C75650076616C7565005265636569766500417070726F766500476574537472696E6700536574537472696E6700417070726F76616C4C6F67005472616E736665724C6F6700536574417070726F76616C00536D617274436F6E74726163742E646C6C006765745F53796D626F6C007365745F53796D626F6C0073796D626F6C0053797374656D005472616E7366657246726F6D005472616E73666572546F6B656E7346726F6D0066726F6D004469766964656E64546F6B656E00495374616E64617264546F6B656E005472616E73666572546F005472616E73666572546F6B656E73546F00746F006765745F53656E646572005370656E646572007370656E646572005472616E73666572004F776E6572006F776E6572002E63746F720053797374656D2E446961676E6F7374696373006765745F4469766964656E6473007365745F4469766964656E64730043726564697465644469766964656E647300476574576974686472617761626C654469766964656E647300476574546F74616C4469766964656E64730057697468647261776E4469766964656E6473004765744469766964656E647300537472617469732E536D617274436F6E7472616374732E5374616E64617264730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F646573006765745F537563636573730041646472657373006164647265737300537472617469732E536D617274436F6E74726163747300466F726D617400536D617274436F6E7472616374004F626A656374004765745374727563740053657453747275637400495472616E73666572526573756C74005570646174654163636F756E74004765744163636F756E74005365744163636F756E74006163636F756E74004F6C64416D6F756E740063757272656E74416D6F756E7400616D6F756E7400417373657274005769746864726177006765745F546F74616C537570706C79007365745F546F74616C537570706C7900746F74616C537570706C7900000000134400690076006900640065006E006400730000174100630063006F0075006E0074003A007B0030007D00003B54006800650020006100630063006F0075006E007400200068006100730020006E006F0020006400690076006900640065006E00640073002E0000215400720061006E00730066006500720020006600610069006C00650064002E00000D530079006D0062006F006C0000094E0061006D006500001754006F00740061006C0053007500700070006C0079000017420061006C0061006E00630065003A007B0030007D00002341006C006C006F00770061006E00630065003A007B0030007D003A007B0031007D00000031EC77F44ED48A46A24645E9865F8F930004200101080320000105200101111104200012350420010B0E052002010E0B0500020E0E1C063001011E000E040A01110C07300102010E1E00052001011225042000124104200011210320000B050702110C0B0407020B0B040701110C080704110C0B0B122905200201020E072002122911210B032000020420010E0E052002010E0E0507020B111006300101011E00040A0111100607030B0B11100407011114040A0111140600030E0E1C1C087CEC85D7BEA7798E02060B03061121042001010B062001110C1121072002011121110C0820040112250B0E0E0620020211210B08200302112111210B0720020B1121110C0520010B11210320000E042001010E0620020111210B0720030211210B0B08200301112111210B0720020B112111210328000B0328000E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F7773010801000200000000000401000000000000000000000000000000100000000000000000000000000000002832000000000000000000004232000000200000000000000000000000000000000000000000000034320000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF250020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000C000000543200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0102001B3479CF0000000000000000E00022200B013000001400000002000000000000B2320000002000000040000000000010002000000002000004000000000000000400000000000000006000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000603200004F000000000000000000000000000000000000000000000000000000004000000C000000443200001C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E74657874000000B8120000002000000014000000020000000000000000000000000000200000602E72656C6F6300000C00000000400000000200000016000000000000000000000000000040000042000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094320000000000004800000002000500AC250000980C000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004602280600000A72010000706F0700000A2A4A02280600000A7201000070036F0800000A2A7202280600000A7215000070038C08000001280900000A6F0100002B2A7602280600000A7215000070038C08000001280900000A046F0200002B2AC20203280C00000A0204281700000602052815000006020E0428130000060202280D00000A6F0E00000A0428190000062A1E0228070000062A660202280100000602280D00000A6F0F00000AD728020000062A8E0202280D00000A6F0E00000A280A000006260203280A00000626020304281A0000062A6A0203280A000006260204280A0000062602030405281B0000062A0000133003003C00000001000011020328030000060A020306280C0000060B07166A36241200067B0100000407D77D0100000412000228010000067D030000040203062804000006062A42047B01000004020304280C000006D72A000000133002001800000002000011022801000006047B03000004DB0A0203281800000606D92A4A0202280D00000A6F0E00000A280E0000062A00133003001800000003000011020328030000060A020306280B0000060228160000065C2A4A0202280D00000A6F0E00000A28100000062A00133003001F00000003000011020328030000060A020306280B000006067B02000004D70228160000065C2A001330030093000000040000110202280D00000A6F0E00000A280A0000060A067B010000040228160000065C0B067B010000040228160000065E0C0207166AFE03722D000070281000000A1200067B02000004067B01000004D708DB7D020000041200087D010000040202280D00000A6F0E00000A0628040000060202280D00000A6F0E00000A07281100000A0D02096F1200000A7269000070281000000A2A4602280600000A728B0000706F1300000A2A4A02280600000A728B000070036F1400000A2A4602280600000A72990000706F1300000A2A4A02280600000A7299000070036F1400000A2A4602280600000A72A30000706F0700000A2A4A02280600000A72A3000070036F0800000A2A7202280600000A72BB000070038C08000001280900000A6F0700000A2A7602280600000A72BB000070038C08000001280900000A046F0800000A2A00000013300400A600000005000011042D34021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201166A7D0600000407280300002B172A0202280D00000A6F0E00000A28180000060A06043402162A0202280D00000A6F0E00000A0604DB281900000602030203281800000604D72819000006021201FE1504000002120102280D00000A6F0E00000A7D040000041201037D050000041201047D0600000407280300002B172A000013300500AA00000006000011052D2A021202FE15040000021202037D040000041202047D050000041202166A7D0600000408280300002B172A020302280D00000A6F0E00000A281E0000060A020328180000060B0605370407053402162A020302280D00000A6F0E00000A0605DB281D00000602030705DB281900000602040204281800000605D72819000006021202FE15040000021202037D040000041202047D050000041202057D0600000408280300002B172A00001330040065000000070000110202280D00000A6F0E00000A03281E000006042E02162A0202280D00000A6F0E00000A0305281D000006021200FE1505000002120002280D00000A6F0E00000A7D070000041200037D080000041200057D0A0000041200047D0900000406280400002B172A8E02280600000A72D3000070038C08000001048C08000001281600000A056F0800000A2A8A02280600000A72D3000070038C08000001048C08000001281600000A6F0700000A2A42534A4201000100000000000C00000076342E302E33303331390000000005006C00000058050000237E0000C40500006C04000023537472696E677300000000300A0000F800000023555300280B0000100000002347554944000000380B00006001000023426C6F6200000000000000020000015717A201090A000000FA0133001600000100000010000000050000000A0000001E0000002700000001000000160000000800000007000000010000000400000008000000010000000300000003000000040000000000A3010100000000000600EE00410306002D0141030600DA0070020F00610300000A001D018C030A00AA038C030E000C0220030A007C038C030A009B008C030A00D3038C0306009100D2010A000E018C030A00AF008C0306007801D2010600B803D2010A0065008C03000000001500000000000100010001001000FE0100001900010001000A011000FF0300002D0001001F000A0110008B0100002D0004001F000A0110007F0100002D0007001F0006003500B6000600F002B60006009F02B6000600F401B90006003402B90006002004B60006005E02B90006004502B90006000F04B60006002004B600502000000000860883024A00010062200000000081089102BD0001007520000000008100F103C20002009220000000008100FC03C9000300B0200000000086186A02D1000500E12000000000C6005B0106000900E920000000008600CA0206000900032100000000E6011B02DA000900272100000000E601D901E1000B004421000000008100E303C2000E008C21000000008100B102EA000F00A0210000000081001003EA001100C42100000000860003034A001300D8210000000086000303F2001300FC21000000008600DE024A0014001022000000008600DE02F20014003C22000000008600350406001500DB22000000008608B501F8001500ED22000000008108C001FC00150000230000000086087A00F800160012230000000081088300FC001600252300000000E6093E044A00170037230000000081084E04BD0017004A2300000000E6014500F2001800672300000000810050000101190088230000000081002602DA001B003C24000000008100E601E1001D00F42400000000E6016301080120006525000000008100970110012300892500000000E6015B001901260000000100550100000100840300000100840300000200070400000100D400000002005E04000003008C0000000400CB0100000100370200000200270400000100F90100000200370200000300270400000100840300000100840300000200070400000100840300000200070400000100840300000100840300000100550100000100550100000100550100000100840300000100840300000200550100000100370200000200270400000100F901000002003702000003002704000001004D02000002001904000003002704000001006402000002004D02000003005501000001006402000002004D0202001D0009006A02010011006A02060019006A020A0029006A02060061006A0206003100C000100069000100150069000B001A007100A30320006900BF0326006900C903320031006A023A0031006E00400081003A02450081004B014A0031002E046600310055026C0051007003740069006B017800690075017D003100930189007100A303A6002E000B0029012E00130032012E001B005101430023005A0181002B005A01A1002B005A01E1002B005A0101012B005A014E00540058005D00830095009C00020001000000160321010000C4012501000087002501000052042101020001000300010002000300020012000500010013000500020014000700010015000700020016000900010017000900048000000000000000000000000000000000AA030000040000000000000000000000AD001E000000000001000200010000000000000000008C0300000000010000000000000000000000000020030000000003000200040002000500020015002D0017002D002B0090002B00A10000000047657455496E7436340053657455496E743634003C4D6F64756C653E0053797374656D2E507269766174652E436F72654C6962004469766964656E6442616C616E63650047657442616C616E63650053657442616C616E636500416C6C6F77616E636500494D657373616765006765745F4D657373616765006765745F4E616D65007365745F4E616D65006E616D650056616C7565547970650049536D617274436F6E74726163745374617465004950657273697374656E745374617465006765745F50657273697374656E7453746174650073746174650044656275676761626C6541747472696275746500436F6D70696C6174696F6E52656C61786174696F6E7341747472696275746500496E646578417474726962757465004465706C6F794174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465006765745F56616C75650076616C7565005265636569766500417070726F766500476574537472696E6700536574537472696E6700417070726F76616C4C6F67005472616E736665724C6F6700536574417070726F76616C00536D617274436F6E74726163742E646C6C006765745F53796D626F6C007365745F53796D626F6C0073796D626F6C0053797374656D005472616E7366657246726F6D005472616E73666572546F6B656E7346726F6D0066726F6D004469766964656E64546F6B656E00495374616E64617264546F6B656E005472616E73666572546F005472616E73666572546F6B656E73546F00746F006765745F53656E646572005370656E646572007370656E646572005472616E73666572004F776E6572006F776E6572002E63746F720053797374656D2E446961676E6F7374696373006765745F4469766964656E6473007365745F4469766964656E64730043726564697465644469766964656E647300476574576974686472617761626C654469766964656E647300446973747269627574654469766964656E647300476574546F74616C4469766964656E64730057697468647261776E4469766964656E6473004765744469766964656E6473004765744E65774469766964656E647300537472617469732E536D617274436F6E7472616374732E5374616E64617264730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300446562756767696E674D6F646573006765745F537563636573730041646472657373006164647265737300537472617469732E536D617274436F6E74726163747300466F726D617400536D617274436F6E7472616374004F626A656374004765745374727563740053657453747275637400495472616E73666572526573756C74005570646174654163636F756E74004765744163636F756E74005365744163636F756E74006163636F756E74004F6C64416D6F756E740063757272656E74416D6F756E7400616D6F756E7400417373657274005769746864726177006765745F546F74616C537570706C79007365745F546F74616C537570706C7900746F74616C537570706C7900000000134400690076006900640065006E006400730000174100630063006F0075006E0074003A007B0030007D00003B54006800650020006100630063006F0075006E007400200068006100730020006E006F0020006400690076006900640065006E00640073002E0000215400720061006E00730066006500720020006600610069006C00650064002E00000D530079006D0062006F006C0000094E0061006D006500001754006F00740061006C0053007500700070006C0079000017420061006C0061006E00630065003A007B0030007D00002341006C006C006F00770061006E00630065003A007B0030007D003A007B0031007D00000043222F817C95CB4498A926937E6400A20004200101080320000105200101111104200012350420010B0E052002010E0B0500020E0E1C063001011E000E040A01110C07300102010E1E00052001011225042000124104200011210320000B050702110C0B0307010B040701110C080704110C0B0B122905200201020E072002122911210B032000020420010E0E052002010E0E0507020B111006300101011E00040A0111100607030B0B11100407011114040A0111140600030E0E1C1C087CEC85D7BEA7798E02060B03061121042001010B062001110C1121072002011121110C0820040112250B0E0E0620020211210B08200302112111210B0720020B1121110C0520010B11210320000E042001010E0620020111210B0720030211210B0B08200301112111210B0720020B112111210328000B0328000E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F77730108010002000000000004010000000000000000000000000000000010000000000000000000000000000000883200000000000000000000A232000000200000000000000000000000000000000000000000000094320000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF250020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000C000000B43200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ``` From 035289a10e48761de6f528beadc0c7bf2334583a Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Tue, 19 Jan 2021 21:00:29 +0300 Subject: [PATCH 10/15] Types updated to UInt256 --- .../DividendToken/DividendToken.cs | 87 ++++++++++--------- .../DividendToken/DividendToken.csproj | 4 +- 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/Mainnet/DividendToken/DividendToken/DividendToken.cs b/Mainnet/DividendToken/DividendToken/DividendToken.cs index 40a6757c..2592979d 100644 --- a/Mainnet/DividendToken/DividendToken/DividendToken.cs +++ b/Mainnet/DividendToken/DividendToken/DividendToken.cs @@ -16,12 +16,13 @@ public ulong Dividends private void SetAccount(Address address, Account account) => PersistentState.SetStruct($"Account:{address}", account); - public DividendToken(ISmartContractState state, ulong totalSupply, string name, string symbol) + public DividendToken(ISmartContractState state, UInt256 totalSupply, string name, string symbol,uint decimals) : base(state) { this.TotalSupply = totalSupply; this.Name = name; this.Symbol = symbol; + this.Decimals = decimals; this.SetBalance(Message.Sender, totalSupply); } @@ -39,7 +40,8 @@ public void DistributeDividends() { Dividends += Message.Value; } - public bool TransferTo(Address to, ulong amount) + + public bool TransferTo(Address to, UInt256 amount) { UpdateAccount(Message.Sender); UpdateAccount(to); @@ -47,7 +49,7 @@ public bool TransferTo(Address to, ulong amount) return TransferTokensTo(to, amount); } - public bool TransferFrom(Address from, Address to, ulong amount) + public bool TransferFrom(Address from, Address to, UInt256 amount) { UpdateAccount(from); UpdateAccount(to); @@ -62,7 +64,7 @@ private Account UpdateAccount(Address address) if (newDividends > 0) { - account.DividendBalance = checked(account.DividendBalance + newDividends); + account.DividendBalance += newDividends; account.CreditedDividends = Dividends; SetAccount(address, account); } @@ -70,18 +72,15 @@ private Account UpdateAccount(Address address) return account; } - private ulong GetWithdrawableDividends(Address address, Account account) + private UInt256 GetWithdrawableDividends(Address address, Account account) { - return checked(account.DividendBalance + GetNewDividends(address, account)); //Delay divide by TotalSupply to final stage for avoid decimal value loss. + return account.DividendBalance + GetNewDividends(address, account); //Delay divide by TotalSupply to final stage for avoid decimal value loss. } - private ulong GetNewDividends(Address address, Account account) + private UInt256 GetNewDividends(Address address, Account account) { - checked - { - var notCreditedDividends = Dividends - account.CreditedDividends; - return GetBalance(address) * notCreditedDividends; - } + var notCreditedDividends = checked(Dividends - account.CreditedDividends); + return GetBalance(address) * notCreditedDividends; } /// @@ -116,7 +115,8 @@ public ulong GetDividends(Address address) public ulong GetTotalDividends(Address address) { var account = GetAccount(address); - return checked(GetWithdrawableDividends(address, account) + account.WithdrawnDividends) / TotalSupply; + var withdrawable = GetWithdrawableDividends(address, account) / TotalSupply; + return withdrawable + account.WithdrawnDividends; } /// @@ -126,12 +126,12 @@ public void Withdraw() { var account = UpdateAccount(Message.Sender); var balance = account.DividendBalance / TotalSupply; - var remainder = account.DividendBalance % TotalSupply; Assert(balance > 0, "The account has no dividends."); - account.WithdrawnDividends = checked(account.WithdrawnDividends + account.DividendBalance - remainder); - account.DividendBalance = remainder; + account.WithdrawnDividends += balance; + + account.DividendBalance %= TotalSupply; SetAccount(Message.Sender, account); @@ -145,11 +145,7 @@ public struct Account /// /// Withdrawable Dividend Balance. Exact value should to divided by /// - public ulong DividendBalance; - - /// - /// - /// + public UInt256 DividendBalance; public ulong WithdrawnDividends; @@ -162,6 +158,7 @@ public struct Account #region StandardToken code is inlined + public string Symbol { get => PersistentState.GetString(nameof(this.Symbol)); @@ -175,24 +172,32 @@ public string Name } /// - public ulong TotalSupply + public UInt256 TotalSupply + { + get => PersistentState.GetUInt256(nameof(this.TotalSupply)); + private set => PersistentState.SetUInt256(nameof(this.TotalSupply), value); + } + + public uint Decimals { - get => PersistentState.GetUInt64(nameof(this.TotalSupply)); - private set => PersistentState.SetUInt64(nameof(this.TotalSupply), value); + get => PersistentState.GetUInt32(nameof(Decimals)); + private set => PersistentState.SetUInt32(nameof(Decimals), value); } + + /// - public ulong GetBalance(Address address) + public UInt256 GetBalance(Address address) { - return PersistentState.GetUInt64($"Balance:{address}"); + return PersistentState.GetUInt256($"Balance:{address}"); } - private void SetBalance(Address address, ulong value) + private void SetBalance(Address address, UInt256 value) { - PersistentState.SetUInt64($"Balance:{address}", value); + PersistentState.SetUInt256($"Balance:{address}", value); } /// - private bool TransferTokensTo(Address to, ulong amount) + private bool TransferTokensTo(Address to, UInt256 amount) { if (amount == 0) { @@ -201,7 +206,7 @@ private bool TransferTokensTo(Address to, ulong amount) return true; } - ulong senderBalance = GetBalance(Message.Sender); + UInt256 senderBalance = GetBalance(Message.Sender); if (senderBalance < amount) { @@ -218,7 +223,7 @@ private bool TransferTokensTo(Address to, ulong amount) } /// - private bool TransferTokensFrom(Address from, Address to, ulong amount) + private bool TransferTokensFrom(Address from, Address to, UInt256 amount) { if (amount == 0) { @@ -227,8 +232,8 @@ private bool TransferTokensFrom(Address from, Address to, ulong amount) return true; } - ulong senderAllowance = Allowance(from, Message.Sender); - ulong fromBalance = GetBalance(from); + UInt256 senderAllowance = Allowance(from, Message.Sender); + UInt256 fromBalance = GetBalance(from); if (senderAllowance < amount || fromBalance < amount) { @@ -247,7 +252,7 @@ private bool TransferTokensFrom(Address from, Address to, ulong amount) } /// - public bool Approve(Address spender, ulong currentAmount, ulong amount) + public bool Approve(Address spender, UInt256 currentAmount, UInt256 amount) { if (Allowance(Message.Sender, spender) != currentAmount) { @@ -261,15 +266,15 @@ public bool Approve(Address spender, ulong currentAmount, ulong amount) return true; } - private void SetApproval(Address owner, Address spender, ulong value) + private void SetApproval(Address owner, Address spender, UInt256 value) { - PersistentState.SetUInt64($"Allowance:{owner}:{spender}", value); + PersistentState.SetUInt256($"Allowance:{owner}:{spender}", value); } /// - public ulong Allowance(Address owner, Address spender) + public UInt256 Allowance(Address owner, Address spender) { - return PersistentState.GetUInt64($"Allowance:{owner}:{spender}"); + return PersistentState.GetUInt256($"Allowance:{owner}:{spender}"); } public struct TransferLog @@ -280,7 +285,7 @@ public struct TransferLog [Index] public Address To; - public ulong Amount; + public UInt256 Amount; } public struct ApprovalLog @@ -291,9 +296,9 @@ public struct ApprovalLog [Index] public Address Spender; - public ulong OldAmount; + public UInt256 OldAmount; - public ulong Amount; + public UInt256 Amount; } #endregion } \ No newline at end of file diff --git a/Mainnet/DividendToken/DividendToken/DividendToken.csproj b/Mainnet/DividendToken/DividendToken/DividendToken.csproj index 28caaf1a..df2e6cea 100644 --- a/Mainnet/DividendToken/DividendToken/DividendToken.csproj +++ b/Mainnet/DividendToken/DividendToken/DividendToken.csproj @@ -6,7 +6,7 @@ 8.0 - - + + From cd52ab47d70c3b3b280892fb08d1f3aac7588908 Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Sat, 23 Jan 2021 23:22:01 +0300 Subject: [PATCH 11/15] Upgraded to uint256 --- .../DividendToken.Tests/DividendTokenTests.cs | 23 +++++++++++-------- .../DividendToken.Tests/InMemoryState.cs | 8 +++++++ .../DividendToken/DividendToken.csproj | 6 ++--- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs index 7ec36ad2..98b908a2 100644 --- a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs +++ b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs @@ -1,5 +1,4 @@ using Moq; -using NBitcoin; using Stratis.SmartContracts; using Stratis.SmartContracts.CLR; using Xunit; @@ -20,7 +19,8 @@ public class DividendTokenTests private readonly string name; private readonly string symbol; - private readonly ulong totalSupply; + private readonly UInt256 totalSupply; + private readonly uint decimals; public DividendTokenTests() { @@ -37,6 +37,7 @@ public DividendTokenTests() this.name = "Test Token"; this.symbol = "TST"; this.totalSupply = 1_000; + this.decimals = 0; } [Fact] @@ -46,7 +47,7 @@ public void Deposited_Dividend_Should_Be_Distributed_Equaly() this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 100)); @@ -66,7 +67,7 @@ public void Multiple_Deposited_Dividend_Should_Be_Distributed_Equaly() this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 100)); @@ -93,7 +94,7 @@ public void Cumulative_Dividends_Should_Be_Distributed_Equaly() this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 100)); @@ -118,7 +119,7 @@ public void Cumulative_Deposits_Should_Be_Distributed_Equaly_When_Dividends_Have this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 1)); @@ -144,7 +145,7 @@ public void Deposited_Dividend_Should_Be_Withdrawable() this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 5)).Returns(TransferResult.Transferred(true)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 11)); @@ -157,7 +158,9 @@ public void Deposited_Dividend_Should_Be_Withdrawable() this.mTransactionExecutor.Verify(s => s.Transfer(this.mContractState.Object, this.tokenHolder, 5), Times.Once); Assert.Equal(0ul, contract.GetDividends()); var account = this.persistentState.GetStruct($"Account:{this.tokenHolder}"); - Assert.Equal(500ul, account.DividendBalance); + Assert.Equal((UInt256)500, account.DividendBalance); + Assert.Equal(5ul, account.WithdrawnDividends); + Assert.Equal(dividend, account.CreditedDividends); } [Fact] @@ -169,7 +172,7 @@ public void GetDividends_Returns_Current_Sender_Dividends() this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferResult.Transferred(true)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 100)); @@ -191,7 +194,7 @@ public void GetTotalDividends_Returns_Current_Sender_TotalDividends() this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferResult.Transferred(true)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 100)); diff --git a/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs b/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs index 5e285e68..cc1cbffa 100644 --- a/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs +++ b/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs @@ -38,6 +38,10 @@ public T GetStruct(string key) public ulong GetUInt64(string key) => this.GetValue(key); + public UInt128 GetUInt128(string key) => this.GetValue(key); + + public UInt256 GetUInt256(string key) => this.GetValue(key); + public bool IsContract(Address address) { throw new NotImplementedException(); @@ -70,5 +74,9 @@ public void SetStruct(string key, T value) public void SetUInt32(string key, uint value) => this.storage.AddOrReplace(key, value); public void SetUInt64(string key, ulong value) => this.storage.AddOrReplace(key, value); + + public void SetUInt128(string key, UInt128 value) => this.storage.AddOrReplace(key, value); + + public void SetUInt256(string key, UInt256 value) => this.storage.AddOrReplace(key, value); } } diff --git a/Mainnet/DividendToken/DividendToken/DividendToken.csproj b/Mainnet/DividendToken/DividendToken/DividendToken.csproj index df2e6cea..227885dc 100644 --- a/Mainnet/DividendToken/DividendToken/DividendToken.csproj +++ b/Mainnet/DividendToken/DividendToken/DividendToken.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1 @@ -6,7 +6,7 @@ 8.0 - - + + From d305e7dc35850de692a6581d41c04f34d88014e6 Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Sat, 23 Jan 2021 23:29:48 +0300 Subject: [PATCH 12/15] Tesnet files updated --- .../DividendToken.Tests/DividendTokenTests.cs | 23 ++--- .../DividendToken.Tests/InMemoryState.cs | 8 ++ .../DividendToken/DividendToken.cs | 87 ++++++++++--------- .../DividendToken/DividendToken.csproj | 6 +- 4 files changed, 70 insertions(+), 54 deletions(-) diff --git a/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs b/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs index 7ec36ad2..98b908a2 100644 --- a/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs +++ b/Testnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs @@ -1,5 +1,4 @@ using Moq; -using NBitcoin; using Stratis.SmartContracts; using Stratis.SmartContracts.CLR; using Xunit; @@ -20,7 +19,8 @@ public class DividendTokenTests private readonly string name; private readonly string symbol; - private readonly ulong totalSupply; + private readonly UInt256 totalSupply; + private readonly uint decimals; public DividendTokenTests() { @@ -37,6 +37,7 @@ public DividendTokenTests() this.name = "Test Token"; this.symbol = "TST"; this.totalSupply = 1_000; + this.decimals = 0; } [Fact] @@ -46,7 +47,7 @@ public void Deposited_Dividend_Should_Be_Distributed_Equaly() this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 100)); @@ -66,7 +67,7 @@ public void Multiple_Deposited_Dividend_Should_Be_Distributed_Equaly() this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 100)); @@ -93,7 +94,7 @@ public void Cumulative_Dividends_Should_Be_Distributed_Equaly() this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 100)); @@ -118,7 +119,7 @@ public void Cumulative_Deposits_Should_Be_Distributed_Equaly_When_Dividends_Have this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 1)); @@ -144,7 +145,7 @@ public void Deposited_Dividend_Should_Be_Withdrawable() this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 5)).Returns(TransferResult.Transferred(true)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 11)); @@ -157,7 +158,9 @@ public void Deposited_Dividend_Should_Be_Withdrawable() this.mTransactionExecutor.Verify(s => s.Transfer(this.mContractState.Object, this.tokenHolder, 5), Times.Once); Assert.Equal(0ul, contract.GetDividends()); var account = this.persistentState.GetStruct($"Account:{this.tokenHolder}"); - Assert.Equal(500ul, account.DividendBalance); + Assert.Equal((UInt256)500, account.DividendBalance); + Assert.Equal(5ul, account.WithdrawnDividends); + Assert.Equal(dividend, account.CreditedDividends); } [Fact] @@ -169,7 +172,7 @@ public void GetDividends_Returns_Current_Sender_Dividends() this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferResult.Transferred(true)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 100)); @@ -191,7 +194,7 @@ public void GetTotalDividends_Returns_Current_Sender_TotalDividends() this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferResult.Transferred(true)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol); + var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); Assert.True(contract.TransferTo(this.tokenHolder, 100)); diff --git a/Testnet/DividendToken/DividendToken.Tests/InMemoryState.cs b/Testnet/DividendToken/DividendToken.Tests/InMemoryState.cs index 5e285e68..cc1cbffa 100644 --- a/Testnet/DividendToken/DividendToken.Tests/InMemoryState.cs +++ b/Testnet/DividendToken/DividendToken.Tests/InMemoryState.cs @@ -38,6 +38,10 @@ public T GetStruct(string key) public ulong GetUInt64(string key) => this.GetValue(key); + public UInt128 GetUInt128(string key) => this.GetValue(key); + + public UInt256 GetUInt256(string key) => this.GetValue(key); + public bool IsContract(Address address) { throw new NotImplementedException(); @@ -70,5 +74,9 @@ public void SetStruct(string key, T value) public void SetUInt32(string key, uint value) => this.storage.AddOrReplace(key, value); public void SetUInt64(string key, ulong value) => this.storage.AddOrReplace(key, value); + + public void SetUInt128(string key, UInt128 value) => this.storage.AddOrReplace(key, value); + + public void SetUInt256(string key, UInt256 value) => this.storage.AddOrReplace(key, value); } } diff --git a/Testnet/DividendToken/DividendToken/DividendToken.cs b/Testnet/DividendToken/DividendToken/DividendToken.cs index 40a6757c..2592979d 100644 --- a/Testnet/DividendToken/DividendToken/DividendToken.cs +++ b/Testnet/DividendToken/DividendToken/DividendToken.cs @@ -16,12 +16,13 @@ public ulong Dividends private void SetAccount(Address address, Account account) => PersistentState.SetStruct($"Account:{address}", account); - public DividendToken(ISmartContractState state, ulong totalSupply, string name, string symbol) + public DividendToken(ISmartContractState state, UInt256 totalSupply, string name, string symbol,uint decimals) : base(state) { this.TotalSupply = totalSupply; this.Name = name; this.Symbol = symbol; + this.Decimals = decimals; this.SetBalance(Message.Sender, totalSupply); } @@ -39,7 +40,8 @@ public void DistributeDividends() { Dividends += Message.Value; } - public bool TransferTo(Address to, ulong amount) + + public bool TransferTo(Address to, UInt256 amount) { UpdateAccount(Message.Sender); UpdateAccount(to); @@ -47,7 +49,7 @@ public bool TransferTo(Address to, ulong amount) return TransferTokensTo(to, amount); } - public bool TransferFrom(Address from, Address to, ulong amount) + public bool TransferFrom(Address from, Address to, UInt256 amount) { UpdateAccount(from); UpdateAccount(to); @@ -62,7 +64,7 @@ private Account UpdateAccount(Address address) if (newDividends > 0) { - account.DividendBalance = checked(account.DividendBalance + newDividends); + account.DividendBalance += newDividends; account.CreditedDividends = Dividends; SetAccount(address, account); } @@ -70,18 +72,15 @@ private Account UpdateAccount(Address address) return account; } - private ulong GetWithdrawableDividends(Address address, Account account) + private UInt256 GetWithdrawableDividends(Address address, Account account) { - return checked(account.DividendBalance + GetNewDividends(address, account)); //Delay divide by TotalSupply to final stage for avoid decimal value loss. + return account.DividendBalance + GetNewDividends(address, account); //Delay divide by TotalSupply to final stage for avoid decimal value loss. } - private ulong GetNewDividends(Address address, Account account) + private UInt256 GetNewDividends(Address address, Account account) { - checked - { - var notCreditedDividends = Dividends - account.CreditedDividends; - return GetBalance(address) * notCreditedDividends; - } + var notCreditedDividends = checked(Dividends - account.CreditedDividends); + return GetBalance(address) * notCreditedDividends; } /// @@ -116,7 +115,8 @@ public ulong GetDividends(Address address) public ulong GetTotalDividends(Address address) { var account = GetAccount(address); - return checked(GetWithdrawableDividends(address, account) + account.WithdrawnDividends) / TotalSupply; + var withdrawable = GetWithdrawableDividends(address, account) / TotalSupply; + return withdrawable + account.WithdrawnDividends; } /// @@ -126,12 +126,12 @@ public void Withdraw() { var account = UpdateAccount(Message.Sender); var balance = account.DividendBalance / TotalSupply; - var remainder = account.DividendBalance % TotalSupply; Assert(balance > 0, "The account has no dividends."); - account.WithdrawnDividends = checked(account.WithdrawnDividends + account.DividendBalance - remainder); - account.DividendBalance = remainder; + account.WithdrawnDividends += balance; + + account.DividendBalance %= TotalSupply; SetAccount(Message.Sender, account); @@ -145,11 +145,7 @@ public struct Account /// /// Withdrawable Dividend Balance. Exact value should to divided by /// - public ulong DividendBalance; - - /// - /// - /// + public UInt256 DividendBalance; public ulong WithdrawnDividends; @@ -162,6 +158,7 @@ public struct Account #region StandardToken code is inlined + public string Symbol { get => PersistentState.GetString(nameof(this.Symbol)); @@ -175,24 +172,32 @@ public string Name } /// - public ulong TotalSupply + public UInt256 TotalSupply + { + get => PersistentState.GetUInt256(nameof(this.TotalSupply)); + private set => PersistentState.SetUInt256(nameof(this.TotalSupply), value); + } + + public uint Decimals { - get => PersistentState.GetUInt64(nameof(this.TotalSupply)); - private set => PersistentState.SetUInt64(nameof(this.TotalSupply), value); + get => PersistentState.GetUInt32(nameof(Decimals)); + private set => PersistentState.SetUInt32(nameof(Decimals), value); } + + /// - public ulong GetBalance(Address address) + public UInt256 GetBalance(Address address) { - return PersistentState.GetUInt64($"Balance:{address}"); + return PersistentState.GetUInt256($"Balance:{address}"); } - private void SetBalance(Address address, ulong value) + private void SetBalance(Address address, UInt256 value) { - PersistentState.SetUInt64($"Balance:{address}", value); + PersistentState.SetUInt256($"Balance:{address}", value); } /// - private bool TransferTokensTo(Address to, ulong amount) + private bool TransferTokensTo(Address to, UInt256 amount) { if (amount == 0) { @@ -201,7 +206,7 @@ private bool TransferTokensTo(Address to, ulong amount) return true; } - ulong senderBalance = GetBalance(Message.Sender); + UInt256 senderBalance = GetBalance(Message.Sender); if (senderBalance < amount) { @@ -218,7 +223,7 @@ private bool TransferTokensTo(Address to, ulong amount) } /// - private bool TransferTokensFrom(Address from, Address to, ulong amount) + private bool TransferTokensFrom(Address from, Address to, UInt256 amount) { if (amount == 0) { @@ -227,8 +232,8 @@ private bool TransferTokensFrom(Address from, Address to, ulong amount) return true; } - ulong senderAllowance = Allowance(from, Message.Sender); - ulong fromBalance = GetBalance(from); + UInt256 senderAllowance = Allowance(from, Message.Sender); + UInt256 fromBalance = GetBalance(from); if (senderAllowance < amount || fromBalance < amount) { @@ -247,7 +252,7 @@ private bool TransferTokensFrom(Address from, Address to, ulong amount) } /// - public bool Approve(Address spender, ulong currentAmount, ulong amount) + public bool Approve(Address spender, UInt256 currentAmount, UInt256 amount) { if (Allowance(Message.Sender, spender) != currentAmount) { @@ -261,15 +266,15 @@ public bool Approve(Address spender, ulong currentAmount, ulong amount) return true; } - private void SetApproval(Address owner, Address spender, ulong value) + private void SetApproval(Address owner, Address spender, UInt256 value) { - PersistentState.SetUInt64($"Allowance:{owner}:{spender}", value); + PersistentState.SetUInt256($"Allowance:{owner}:{spender}", value); } /// - public ulong Allowance(Address owner, Address spender) + public UInt256 Allowance(Address owner, Address spender) { - return PersistentState.GetUInt64($"Allowance:{owner}:{spender}"); + return PersistentState.GetUInt256($"Allowance:{owner}:{spender}"); } public struct TransferLog @@ -280,7 +285,7 @@ public struct TransferLog [Index] public Address To; - public ulong Amount; + public UInt256 Amount; } public struct ApprovalLog @@ -291,9 +296,9 @@ public struct ApprovalLog [Index] public Address Spender; - public ulong OldAmount; + public UInt256 OldAmount; - public ulong Amount; + public UInt256 Amount; } #endregion } \ No newline at end of file diff --git a/Testnet/DividendToken/DividendToken/DividendToken.csproj b/Testnet/DividendToken/DividendToken/DividendToken.csproj index 28caaf1a..227885dc 100644 --- a/Testnet/DividendToken/DividendToken/DividendToken.csproj +++ b/Testnet/DividendToken/DividendToken/DividendToken.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1 @@ -6,7 +6,7 @@ 8.0 - - + + From cc1607fd9ff64c87b0deec4ee874e2528fb70ec6 Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Wed, 27 Jan 2021 03:44:02 +0300 Subject: [PATCH 13/15] Code cleanup --- .../DividendToken.Tests/AddressExtensions.cs | 42 +++++++++++ .../DividendToken.Tests.csproj | 2 - .../DividendToken.Tests/DividendTokenTests.cs | 28 +++++-- .../DividendToken.Tests/InMemoryState.cs | 73 ++++++++++--------- 4 files changed, 102 insertions(+), 43 deletions(-) create mode 100644 Mainnet/DividendToken/DividendToken.Tests/AddressExtensions.cs diff --git a/Mainnet/DividendToken/DividendToken.Tests/AddressExtensions.cs b/Mainnet/DividendToken/DividendToken.Tests/AddressExtensions.cs new file mode 100644 index 00000000..28365d9f --- /dev/null +++ b/Mainnet/DividendToken/DividendToken.Tests/AddressExtensions.cs @@ -0,0 +1,42 @@ +using Stratis.SmartContracts; +using System; +using System.Collections.Generic; +using System.Text; + +namespace DividendTokenContract.Tests +{ + public static class AddressExtensions + { + private static byte[] HexStringToBytes(string val) + { + if (val.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) + val = val.Substring(2); + + byte[] ret = new byte[val.Length / 2]; + for (int i = 0; i < val.Length; i = i + 2) + { + string hexChars = val.Substring(i, 2); + ret[i / 2] = byte.Parse(hexChars, System.Globalization.NumberStyles.HexNumber); + } + return ret; + } + + public static Address HexToAddress(this string hexString) + { + // uint160 only parses a big-endian hex string + var result = HexStringToBytes(hexString); + return CreateAddress(result); + } + + private static Address CreateAddress(byte[] bytes) + { + uint pn0 = BitConverter.ToUInt32(bytes, 0); + uint pn1 = BitConverter.ToUInt32(bytes, 4); + uint pn2 = BitConverter.ToUInt32(bytes, 8); + uint pn3 = BitConverter.ToUInt32(bytes, 12); + uint pn4 = BitConverter.ToUInt32(bytes, 16); + + return new Address(pn0, pn1, pn2, pn3, pn4); + } + } +} diff --git a/Mainnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj b/Mainnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj index be593740..ffc22b61 100644 --- a/Mainnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj +++ b/Mainnet/DividendToken/DividendToken.Tests/DividendToken.Tests.csproj @@ -8,8 +8,6 @@ - - all diff --git a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs index 98b908a2..6991883d 100644 --- a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs +++ b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs @@ -1,6 +1,5 @@ using Moq; using Stratis.SmartContracts; -using Stratis.SmartContracts.CLR; using Xunit; namespace DividendTokenContract.Tests @@ -40,6 +39,25 @@ public DividendTokenTests() this.decimals = 0; } + private ITransferResult TransferSucceed(object returnValue = null) + { + var mock = new Mock(); + + mock.SetupGet(m => m.Success).Returns(true); + mock.SetupGet(m => m.ReturnValue).Returns(returnValue); + + return mock.Object; + } + + private ITransferResult TransferFailed() + { + var mock = new Mock(); + + mock.SetupGet(m => m.Success).Returns(false); + + return mock.Object; + } + [Fact] public void Deposited_Dividend_Should_Be_Distributed_Equaly() { @@ -65,7 +83,7 @@ public void Multiple_Deposited_Dividend_Should_Be_Distributed_Equaly() { var dividend = 1000ul; - this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); @@ -143,7 +161,7 @@ public void Deposited_Dividend_Should_Be_Withdrawable() this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); - this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 5)).Returns(TransferResult.Transferred(true)); + this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 5)).Returns(TransferSucceed(true)); var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); @@ -170,7 +188,7 @@ public void GetDividends_Returns_Current_Sender_Dividends() this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); - this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferResult.Transferred(true)); + this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferSucceed(true)); var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); @@ -192,7 +210,7 @@ public void GetTotalDividends_Returns_Current_Sender_TotalDividends() this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); - this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferResult.Transferred(true)); + this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferSucceed(true)); var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); diff --git a/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs b/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs index cc1cbffa..53e14132 100644 --- a/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs +++ b/Mainnet/DividendToken/DividendToken.Tests/InMemoryState.cs @@ -1,5 +1,4 @@ -using NBitcoin; -using Stratis.SmartContracts; +using Stratis.SmartContracts; using System; using System.Collections.Generic; @@ -8,75 +7,77 @@ namespace DividendTokenContract.Tests public class InMemoryState : IPersistentState { private readonly Dictionary storage = new Dictionary(); + public bool IsContractResult { get; set; } + public void Clear(string key) => storage.Remove(key); - public void Clear(string key) => this.storage.Remove(key); + public T GetValue(string key) => (T)storage.GetValueOrDefault(key, default(T)); - public T GetValue(string key) => (T)this.storage.GetValueOrDefault(key, default(T)); - - public Address GetAddress(string key) => this.GetValue
(key); + public void AddOrReplace(string key, object value) + { + if (!storage.TryAdd(key, value)) + storage[key] = value; + } + public Address GetAddress(string key) => GetValue
(key); - public T[] GetArray(string key) => this.GetValue(key); + public T[] GetArray(string key) => GetValue(key); - public bool GetBool(string key) => this.GetValue(key); + public bool GetBool(string key) => GetValue(key); public byte[] GetBytes(byte[] key) => throw new NotImplementedException(); - public byte[] GetBytes(string key) => this.GetValue(key); + public byte[] GetBytes(string key) => GetValue(key); - public char GetChar(string key) => this.GetValue(key); + public char GetChar(string key) => GetValue(key); - public int GetInt32(string key) => this.GetValue(key); + public int GetInt32(string key) => GetValue(key); - public long GetInt64(string key) => this.GetValue(key); + public long GetInt64(string key) => GetValue(key); - public string GetString(string key) => this.GetValue(key); + public string GetString(string key) => GetValue(key); public T GetStruct(string key) - where T : struct => this.GetValue(key); + where T : struct => GetValue(key); - public uint GetUInt32(string key) => this.GetValue(key); + public uint GetUInt32(string key) => GetValue(key); - public ulong GetUInt64(string key) => this.GetValue(key); + public ulong GetUInt64(string key) => GetValue(key); - public UInt128 GetUInt128(string key) => this.GetValue(key); + public UInt128 GetUInt128(string key) => GetValue(key); - public UInt256 GetUInt256(string key) => this.GetValue(key); + public UInt256 GetUInt256(string key) => GetValue(key); - public bool IsContract(Address address) - { - throw new NotImplementedException(); - } + public bool IsContract(Address address) => IsContractResult; - public void SetAddress(string key, Address value) => this.storage.AddOrReplace(key, value); + public void SetAddress(string key, Address value) => AddOrReplace(key, value); - public void SetArray(string key, Array a) => this.storage.AddOrReplace(key, a); + public void SetArray(string key, Array a) => AddOrReplace(key, a); - public void SetBool(string key, bool value) => this.storage.AddOrReplace(key, value); + public void SetBool(string key, bool value) => AddOrReplace(key, value); public void SetBytes(byte[] key, byte[] value) { throw new NotImplementedException(); } - public void SetBytes(string key, byte[] value) => this.storage.AddOrReplace(key, value); + public void SetBytes(string key, byte[] value) => AddOrReplace(key, value); - public void SetChar(string key, char value) => this.storage.AddOrReplace(key, value); + public void SetChar(string key, char value) => AddOrReplace(key, value); - public void SetInt32(string key, int value) => this.storage.AddOrReplace(key, value); + public void SetInt32(string key, int value) => AddOrReplace(key, value); - public void SetInt64(string key, long value) => this.storage.AddOrReplace(key, value); + public void SetInt64(string key, long value) => AddOrReplace(key, value); - public void SetString(string key, string value) => this.storage.AddOrReplace(key, value); + public void SetString(string key, string value) => AddOrReplace(key, value); public void SetStruct(string key, T value) - where T : struct => this.storage.AddOrReplace(key, value); + where T : struct => AddOrReplace(key, value); - public void SetUInt32(string key, uint value) => this.storage.AddOrReplace(key, value); + public void SetUInt32(string key, uint value) => AddOrReplace(key, value); - public void SetUInt64(string key, ulong value) => this.storage.AddOrReplace(key, value); + public void SetUInt64(string key, ulong value) => AddOrReplace(key, value); - public void SetUInt128(string key, UInt128 value) => this.storage.AddOrReplace(key, value); + public void SetUInt128(string key, UInt128 value) => AddOrReplace(key, value); - public void SetUInt256(string key, UInt256 value) => this.storage.AddOrReplace(key, value); + public void SetUInt256(string key, UInt256 value) => AddOrReplace(key, value); } -} +} \ No newline at end of file From 1cc2145a87bbadbf3fd42fe08ff401ff08aa18ed Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Wed, 27 Jan 2021 03:55:18 +0300 Subject: [PATCH 14/15] Code cleanup --- .../DividendToken.Tests/DividendTokenTests.cs | 108 +++++++++--------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs index 6991883d..5f388732 100644 --- a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs +++ b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs @@ -14,7 +14,7 @@ public class DividendTokenTests private readonly Address owner; private readonly Address tokenHolder; - private readonly Address contract; + private readonly Address currentContract; private readonly string name; private readonly string symbol; @@ -27,12 +27,12 @@ public DividendTokenTests() this.mContractState = new Mock(); this.mContractLogger = new Mock(); this.mTransactionExecutor = new Mock(); - this.mContractState.Setup(s => s.PersistentState).Returns(this.persistentState); - this.mContractState.Setup(s => s.ContractLogger).Returns(this.mContractLogger.Object); - this.mContractState.Setup(s => s.InternalTransactionExecutor).Returns(this.mTransactionExecutor.Object); + this.mContractState.Setup(s => s.PersistentState).Returns(persistentState); + this.mContractState.Setup(s => s.ContractLogger).Returns(mContractLogger.Object); + this.mContractState.Setup(s => s.InternalTransactionExecutor).Returns(mTransactionExecutor.Object); this.owner = "0x0000000000000000000000000000000000000001".HexToAddress(); this.tokenHolder = "0x0000000000000000000000000000000000000002".HexToAddress(); - this.contract = "0x0000000000000000000000000000000000000003".HexToAddress(); + this.currentContract = "0x0000000000000000000000000000000000000003".HexToAddress(); this.name = "Test Token"; this.symbol = "TST"; this.totalSupply = 1_000; @@ -63,19 +63,19 @@ public void Deposited_Dividend_Should_Be_Distributed_Equaly() { var dividend = 1000ul; - this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + mContractState.Setup(m => m.Message).Returns(new Message(currentContract, owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); + var contract = new DividendToken(mContractState.Object, totalSupply, name, symbol, decimals); - Assert.True(contract.TransferTo(this.tokenHolder, 100)); + Assert.True(contract.TransferTo(tokenHolder, 100)); contract.Receive(); Assert.Equal(dividend, contract.Dividends); - Assert.Equal(100ul, contract.GetDividends(this.tokenHolder)); - Assert.Equal(100ul, contract.GetTotalDividends(this.tokenHolder)); - Assert.Equal(900ul, contract.GetDividends(this.owner)); - Assert.Equal(900ul, contract.GetTotalDividends(this.owner)); + Assert.Equal(100ul, contract.GetDividends(tokenHolder)); + Assert.Equal(100ul, contract.GetTotalDividends(tokenHolder)); + Assert.Equal(900ul, contract.GetDividends(owner)); + Assert.Equal(900ul, contract.GetTotalDividends(owner)); } [Fact] @@ -83,26 +83,26 @@ public void Multiple_Deposited_Dividend_Should_Be_Distributed_Equaly() { var dividend = 1000ul; - mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + mContractState.Setup(m => m.Message).Returns(new Message(currentContract, owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); + var contract = new DividendToken(mContractState.Object, totalSupply, name, symbol, decimals); - Assert.True(contract.TransferTo(this.tokenHolder, 100)); + Assert.True(contract.TransferTo(tokenHolder, 100)); contract.Receive(); - Assert.True(contract.TransferTo(this.tokenHolder, 100)); + Assert.True(contract.TransferTo(tokenHolder, 100)); contract.Receive(); - Assert.True(contract.TransferTo(this.tokenHolder, 100)); + Assert.True(contract.TransferTo(tokenHolder, 100)); Assert.Equal(2 * dividend, contract.Dividends); - Assert.Equal(300ul, contract.GetDividends(this.tokenHolder)); - Assert.Equal(300ul, contract.GetTotalDividends(this.tokenHolder)); + Assert.Equal(300ul, contract.GetDividends(tokenHolder)); + Assert.Equal(300ul, contract.GetTotalDividends(tokenHolder)); - Assert.Equal(1700ul, contract.GetDividends(this.owner)); - Assert.Equal(1700ul, contract.GetTotalDividends(this.owner)); + Assert.Equal(1700ul, contract.GetDividends(owner)); + Assert.Equal(1700ul, contract.GetTotalDividends(owner)); } [Fact] @@ -110,18 +110,18 @@ public void Cumulative_Dividends_Should_Be_Distributed_Equaly() { var dividend = 1000ul; - this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + mContractState.Setup(m => m.Message).Returns(new Message(currentContract, owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); + var contract = new DividendToken(mContractState.Object, totalSupply, name, symbol, decimals); - Assert.True(contract.TransferTo(this.tokenHolder, 100)); + Assert.True(contract.TransferTo(tokenHolder, 100)); contract.Receive(); contract.Receive(); Assert.Equal(2 * dividend, contract.Dividends); - Assert.Equal(2 * 100ul, contract.GetDividends(this.tokenHolder)); - Assert.Equal(2 * 900ul, contract.GetDividends(this.owner)); + Assert.Equal(2 * 100ul, contract.GetDividends(tokenHolder)); + Assert.Equal(2 * 900ul, contract.GetDividends(owner)); } /// @@ -135,23 +135,23 @@ public void Cumulative_Deposits_Should_Be_Distributed_Equaly_When_Dividends_Have { var dividend = 500ul; - this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); + mContractState.Setup(m => m.Message).Returns(new Message(currentContract, owner, dividend)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); + var contract = new DividendToken(mContractState.Object, totalSupply, name, symbol, decimals); - Assert.True(contract.TransferTo(this.tokenHolder, 1)); + Assert.True(contract.TransferTo(tokenHolder, 1)); contract.Receive(); Assert.Equal(dividend, contract.Dividends); - Assert.Equal(0ul, contract.GetDividends(this.tokenHolder)); - Assert.Equal(499ul, contract.GetDividends(this.owner)); + Assert.Equal(0ul, contract.GetDividends(tokenHolder)); + Assert.Equal(499ul, contract.GetDividends(owner)); contract.Receive(); Assert.Equal(2 * dividend, contract.Dividends); - Assert.Equal(1ul, contract.GetDividends(this.tokenHolder)); - Assert.Equal(999ul, contract.GetDividends(this.owner)); + Assert.Equal(1ul, contract.GetDividends(tokenHolder)); + Assert.Equal(999ul, contract.GetDividends(owner)); } [Fact] @@ -159,23 +159,23 @@ public void Deposited_Dividend_Should_Be_Withdrawable() { var dividend = 500ul; - this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); - this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 5)).Returns(TransferSucceed(true)); + mContractState.Setup(m => m.Message).Returns(new Message(currentContract, owner, dividend)); + mContractState.Setup(m => m.GetBalance).Returns(() => dividend); + mTransactionExecutor.Setup(m => m.Transfer(mContractState.Object, tokenHolder, 5)).Returns(TransferSucceed(true)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); + var contract = new DividendToken(mContractState.Object, totalSupply, name, symbol, decimals); - Assert.True(contract.TransferTo(this.tokenHolder, 11)); + Assert.True(contract.TransferTo(tokenHolder, 11)); contract.Receive(); - this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.tokenHolder, 0)); + mContractState.Setup(m => m.Message).Returns(new Message(currentContract, tokenHolder, 0)); contract.Withdraw(); - this.mTransactionExecutor.Verify(s => s.Transfer(this.mContractState.Object, this.tokenHolder, 5), Times.Once); + mTransactionExecutor.Verify(s => s.Transfer(mContractState.Object, tokenHolder, 5), Times.Once); Assert.Equal(0ul, contract.GetDividends()); - var account = this.persistentState.GetStruct($"Account:{this.tokenHolder}"); + var account = persistentState.GetStruct($"Account:{tokenHolder}"); Assert.Equal((UInt256)500, account.DividendBalance); Assert.Equal(5ul, account.WithdrawnDividends); Assert.Equal(dividend, account.CreditedDividends); @@ -186,15 +186,15 @@ public void GetDividends_Returns_Current_Sender_Dividends() { var dividend = 1000ul; - this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); - this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferSucceed(true)); + mContractState.Setup(m => m.Message).Returns(new Message(currentContract, owner, dividend)); + mContractState.Setup(m => m.GetBalance).Returns(() => dividend); + mTransactionExecutor.Setup(m => m.Transfer(mContractState.Object, tokenHolder, 100)).Returns(TransferSucceed(true)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); + var contract = new DividendToken(mContractState.Object, totalSupply, name, symbol, decimals); - Assert.True(contract.TransferTo(this.tokenHolder, 100)); + Assert.True(contract.TransferTo(tokenHolder, 100)); - this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.tokenHolder, dividend)); + mContractState.Setup(m => m.Message).Returns(new Message(currentContract, tokenHolder, dividend)); contract.Receive(); Assert.Equal(100ul, contract.GetDividends()); @@ -208,21 +208,21 @@ public void GetTotalDividends_Returns_Current_Sender_TotalDividends() { var dividend = 1000ul; - this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, dividend)); - this.mContractState.Setup(m => m.GetBalance).Returns(() => dividend); - this.mTransactionExecutor.Setup(m => m.Transfer(this.mContractState.Object, this.tokenHolder, 100)).Returns(TransferSucceed(true)); + mContractState.Setup(m => m.Message).Returns(new Message(currentContract, owner, dividend)); + mContractState.Setup(m => m.GetBalance).Returns(() => dividend); + mTransactionExecutor.Setup(m => m.Transfer(mContractState.Object, tokenHolder, 100)).Returns(TransferSucceed(true)); - var contract = new DividendToken(this.mContractState.Object, this.totalSupply, this.name, this.symbol, this.decimals); + var contract = new DividendToken(mContractState.Object, totalSupply, name, symbol, decimals); - Assert.True(contract.TransferTo(this.tokenHolder, 100)); + Assert.True(contract.TransferTo(tokenHolder, 100)); contract.Receive(); - this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.tokenHolder, 0)); + mContractState.Setup(m => m.Message).Returns(new Message(currentContract, tokenHolder, 0)); contract.Withdraw(); - this.mTransactionExecutor.Verify(s => s.Transfer(this.mContractState.Object, this.tokenHolder, 100), Times.Once); + mTransactionExecutor.Verify(s => s.Transfer(mContractState.Object, tokenHolder, 100), Times.Once); Assert.Equal(0ul, contract.GetDividends()); Assert.Equal(100ul, contract.GetTotalDividends()); } From d7dbe31c9fb9c6e5d1ccc3e12c9fb3a260cfe49f Mon Sep 17 00:00:00 2001 From: YakupIpek Date: Wed, 3 Feb 2021 05:26:20 +0300 Subject: [PATCH 15/15] Updated nuget packages --- .../DividendToken.Tests/DividendTokenTests.cs | 34 ++++---------- .../DividendToken.Tests/TransferResult.cs | 19 ++++++++ .../DividendToken/DividendToken.cs | 47 ++++++++++--------- .../DividendToken/DividendToken.csproj | 5 +- 4 files changed, 53 insertions(+), 52 deletions(-) create mode 100644 Mainnet/DividendToken/DividendToken.Tests/TransferResult.cs diff --git a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs index 5f388732..f56035e6 100644 --- a/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs +++ b/Mainnet/DividendToken/DividendToken.Tests/DividendTokenTests.cs @@ -6,7 +6,7 @@ namespace DividendTokenContract.Tests { public class DividendTokenTests { - private readonly IPersistentState persistentState; + private readonly IPersistentState state; private readonly Mock mContractState; private readonly Mock mContractLogger; @@ -19,15 +19,15 @@ public class DividendTokenTests private readonly string name; private readonly string symbol; private readonly UInt256 totalSupply; - private readonly uint decimals; + private readonly byte decimals; public DividendTokenTests() { - this.persistentState = new InMemoryState(); + this.state = new InMemoryState(); this.mContractState = new Mock(); this.mContractLogger = new Mock(); this.mTransactionExecutor = new Mock(); - this.mContractState.Setup(s => s.PersistentState).Returns(persistentState); + this.mContractState.Setup(s => s.PersistentState).Returns(state); this.mContractState.Setup(s => s.ContractLogger).Returns(mContractLogger.Object); this.mContractState.Setup(s => s.InternalTransactionExecutor).Returns(mTransactionExecutor.Object); this.owner = "0x0000000000000000000000000000000000000001".HexToAddress(); @@ -39,24 +39,6 @@ public DividendTokenTests() this.decimals = 0; } - private ITransferResult TransferSucceed(object returnValue = null) - { - var mock = new Mock(); - - mock.SetupGet(m => m.Success).Returns(true); - mock.SetupGet(m => m.ReturnValue).Returns(returnValue); - - return mock.Object; - } - - private ITransferResult TransferFailed() - { - var mock = new Mock(); - - mock.SetupGet(m => m.Success).Returns(false); - - return mock.Object; - } [Fact] public void Deposited_Dividend_Should_Be_Distributed_Equaly() @@ -161,7 +143,7 @@ public void Deposited_Dividend_Should_Be_Withdrawable() mContractState.Setup(m => m.Message).Returns(new Message(currentContract, owner, dividend)); mContractState.Setup(m => m.GetBalance).Returns(() => dividend); - mTransactionExecutor.Setup(m => m.Transfer(mContractState.Object, tokenHolder, 5)).Returns(TransferSucceed(true)); + mTransactionExecutor.Setup(m => m.Transfer(mContractState.Object, tokenHolder, 5)).Returns(TransferResult.Succeed(true)); var contract = new DividendToken(mContractState.Object, totalSupply, name, symbol, decimals); @@ -175,7 +157,7 @@ public void Deposited_Dividend_Should_Be_Withdrawable() mTransactionExecutor.Verify(s => s.Transfer(mContractState.Object, tokenHolder, 5), Times.Once); Assert.Equal(0ul, contract.GetDividends()); - var account = persistentState.GetStruct($"Account:{tokenHolder}"); + var account = state.GetStruct($"Account:{tokenHolder}"); Assert.Equal((UInt256)500, account.DividendBalance); Assert.Equal(5ul, account.WithdrawnDividends); Assert.Equal(dividend, account.CreditedDividends); @@ -188,7 +170,7 @@ public void GetDividends_Returns_Current_Sender_Dividends() mContractState.Setup(m => m.Message).Returns(new Message(currentContract, owner, dividend)); mContractState.Setup(m => m.GetBalance).Returns(() => dividend); - mTransactionExecutor.Setup(m => m.Transfer(mContractState.Object, tokenHolder, 100)).Returns(TransferSucceed(true)); + mTransactionExecutor.Setup(m => m.Transfer(mContractState.Object, tokenHolder, 100)).Returns(TransferResult.Succeed(true)); var contract = new DividendToken(mContractState.Object, totalSupply, name, symbol, decimals); @@ -210,7 +192,7 @@ public void GetTotalDividends_Returns_Current_Sender_TotalDividends() mContractState.Setup(m => m.Message).Returns(new Message(currentContract, owner, dividend)); mContractState.Setup(m => m.GetBalance).Returns(() => dividend); - mTransactionExecutor.Setup(m => m.Transfer(mContractState.Object, tokenHolder, 100)).Returns(TransferSucceed(true)); + mTransactionExecutor.Setup(m => m.Transfer(mContractState.Object, tokenHolder, 100)).Returns(TransferResult.Succeed(true)); var contract = new DividendToken(mContractState.Object, totalSupply, name, symbol, decimals); diff --git a/Mainnet/DividendToken/DividendToken.Tests/TransferResult.cs b/Mainnet/DividendToken/DividendToken.Tests/TransferResult.cs new file mode 100644 index 00000000..a20cd46f --- /dev/null +++ b/Mainnet/DividendToken/DividendToken.Tests/TransferResult.cs @@ -0,0 +1,19 @@ +using Stratis.SmartContracts; +using System; +using System.Collections.Generic; +using System.Text; + +namespace DividendTokenContract.Tests +{ + public class TransferResult : ITransferResult + { + public object ReturnValue { get; private set; } + + public bool Success { get; private set; } + + public static TransferResult Failed() => new TransferResult { Success = false }; + + + public static TransferResult Succeed(object returnValue) => new TransferResult { Success = true, ReturnValue = returnValue }; + } +} diff --git a/Mainnet/DividendToken/DividendToken/DividendToken.cs b/Mainnet/DividendToken/DividendToken/DividendToken.cs index 2592979d..749760a8 100644 --- a/Mainnet/DividendToken/DividendToken/DividendToken.cs +++ b/Mainnet/DividendToken/DividendToken/DividendToken.cs @@ -2,21 +2,20 @@ using Stratis.SmartContracts.Standards; [Deploy] -public class DividendToken : SmartContract, IStandardToken +public class DividendToken : SmartContract, IStandardToken256 { - public ulong Dividends { - get => PersistentState.GetUInt64(nameof(this.Dividends)); - private set => PersistentState.SetUInt64(nameof(this.Dividends), value); + get => State.GetUInt64(nameof(this.Dividends)); + private set => State.SetUInt64(nameof(this.Dividends), value); } - private Account GetAccount(Address address) => PersistentState.GetStruct($"Account:{address}"); + private Account GetAccount(Address address) => State.GetStruct($"Account:{address}"); - private void SetAccount(Address address, Account account) => PersistentState.SetStruct($"Account:{address}", account); + private void SetAccount(Address address, Account account) => State.SetStruct($"Account:{address}", account); - public DividendToken(ISmartContractState state, UInt256 totalSupply, string name, string symbol,uint decimals) + public DividendToken(ISmartContractState state, UInt256 totalSupply, string name, string symbol, byte decimals) : base(state) { this.TotalSupply = totalSupply; @@ -98,7 +97,9 @@ public ulong GetDividends(Address address) { var account = GetAccount(address); - return GetWithdrawableDividends(address, account) / TotalSupply; + var withdrawable = GetWithdrawableDividends(address, account) / TotalSupply; + + return (ulong)withdrawable; } /// @@ -116,7 +117,7 @@ public ulong GetTotalDividends(Address address) { var account = GetAccount(address); var withdrawable = GetWithdrawableDividends(address, account) / TotalSupply; - return withdrawable + account.WithdrawnDividends; + return (ulong)withdrawable + account.WithdrawnDividends; } /// @@ -125,7 +126,7 @@ public ulong GetTotalDividends(Address address) public void Withdraw() { var account = UpdateAccount(Message.Sender); - var balance = account.DividendBalance / TotalSupply; + var balance = (ulong)(account.DividendBalance / TotalSupply); Assert(balance > 0, "The account has no dividends."); @@ -161,39 +162,39 @@ public struct Account public string Symbol { - get => PersistentState.GetString(nameof(this.Symbol)); - private set => PersistentState.SetString(nameof(this.Symbol), value); + get => State.GetString(nameof(this.Symbol)); + private set => State.SetString(nameof(this.Symbol), value); } public string Name { - get => PersistentState.GetString(nameof(this.Name)); - private set => PersistentState.SetString(nameof(this.Name), value); + get => State.GetString(nameof(this.Name)); + private set => State.SetString(nameof(this.Name), value); } /// public UInt256 TotalSupply { - get => PersistentState.GetUInt256(nameof(this.TotalSupply)); - private set => PersistentState.SetUInt256(nameof(this.TotalSupply), value); + get => State.GetUInt256(nameof(this.TotalSupply)); + private set => State.SetUInt256(nameof(this.TotalSupply), value); } - public uint Decimals + public byte Decimals { - get => PersistentState.GetUInt32(nameof(Decimals)); - private set => PersistentState.SetUInt32(nameof(Decimals), value); + get => State.GetBytes(nameof(Decimals))[0]; + private set => State.SetBytes(nameof(Decimals), new[] { value }); } /// public UInt256 GetBalance(Address address) { - return PersistentState.GetUInt256($"Balance:{address}"); + return State.GetUInt256($"Balance:{address}"); } private void SetBalance(Address address, UInt256 value) { - PersistentState.SetUInt256($"Balance:{address}", value); + State.SetUInt256($"Balance:{address}", value); } /// @@ -268,13 +269,13 @@ public bool Approve(Address spender, UInt256 currentAmount, UInt256 amount) private void SetApproval(Address owner, Address spender, UInt256 value) { - PersistentState.SetUInt256($"Allowance:{owner}:{spender}", value); + State.SetUInt256($"Allowance:{owner}:{spender}", value); } /// public UInt256 Allowance(Address owner, Address spender) { - return PersistentState.GetUInt256($"Allowance:{owner}:{spender}"); + return State.GetUInt256($"Allowance:{owner}:{spender}"); } public struct TransferLog diff --git a/Mainnet/DividendToken/DividendToken/DividendToken.csproj b/Mainnet/DividendToken/DividendToken/DividendToken.csproj index 227885dc..8733aff9 100644 --- a/Mainnet/DividendToken/DividendToken/DividendToken.csproj +++ b/Mainnet/DividendToken/DividendToken/DividendToken.csproj @@ -2,11 +2,10 @@ netcoreapp2.1 - 8.0 - - + +