From b23066737b23404e137a8151268fcaa193563ee2 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Sat, 6 May 2023 13:21:31 +0800 Subject: [PATCH 001/139] feat: Supports parallel of multi-currency transaction fee collection. --- .../TokenContract_ACS1_MethodFeeProvider.cs | 30 ++++++- .../TokenContract_ACS2_StatePathsProvider.cs | 2 +- .../BVT/ACS2_TokenResourceTests.cs | 87 +++++++++++++++++++ 3 files changed, 115 insertions(+), 4 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs index ff15f9a9c6..f729dec518 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using AElf.Sdk.CSharp; using AElf.Standards.ACS1; using AElf.Standards.ACS3; @@ -74,11 +75,34 @@ public override AuthorityInfo GetMethodFeeController(Empty input) #region private methods - private List GetMethodFeeSymbols() + private List GetTransactionFeeSymbols() + { + var transferSymbols = GetTransactionFeeSymbolsByMethod(nameof(Transfer)); + var transferFromSymbols = GetTransactionFeeSymbolsByMethod(nameof(TransferFrom)); + var symbols = transferSymbols.Union(transferFromSymbols).ToList(); + return symbols; + } + + private List GetTransactionFeeSymbolsByMethod(string methodName) { var symbols = new List(); - var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; - if (primaryTokenSymbol != string.Empty) symbols.Add(primaryTokenSymbol); + if (State.TransactionFees[methodName] != null) + { + foreach (var methodFee in State.TransactionFees[methodName].Fees) + { + if (!symbols.Contains(methodFee.Symbol) && methodFee.BasicFee > 0) + symbols.Add(methodFee.Symbol); + } + if (State.TransactionFees[methodName].IsSizeFeeFree) + { + return symbols; + } + } + foreach (var sizeFee in State.SymbolListToPayTxSizeFee.Value.SymbolsToPayTxSizeFee) + { + if (!symbols.Contains(sizeFee.TokenSymbol)) + symbols.Add(sizeFee.TokenSymbol); + } return symbols; } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index bf075eec0c..bce37624a4 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -70,7 +70,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) private void AddPathForTransactionFee(ResourceInfo resourceInfo, String from) { - var symbols = GetMethodFeeSymbols(); + var symbols = GetTransactionFeeSymbols(); var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; if (_primaryTokenSymbol != string.Empty && !symbols.Contains(primaryTokenSymbol)) symbols.Add(primaryTokenSymbol); diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs index 45da7dc586..f17a326f9d 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs @@ -1,4 +1,10 @@ using System.Threading.Tasks; +using AElf.CSharp.Core.Extension; +using AElf.Kernel; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; +using AElf.Types; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; @@ -42,6 +48,87 @@ public async Task ACS2_GetResourceInfo_TransferFrom_Test() result.WritePaths.Count.ShouldBeGreaterThan(0); } + private async Task
GetDefaultParliamentAddressAsync() + { + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + return defaultParliamentAddress; + } + + [Fact] + public async Task ACS2_GetResourceInfo_Transfer_MultiToken_Test() + { + var theDefaultController = await GetDefaultParliamentAddressAsync(); + var newSymbolList = new SymbolListToPayTxSizeFee(); + await CreateNativeTokenAsync(); + await CreateTokenAsync(DefaultAddress, "CPU"); + var methodName = "Transfer"; + var tokenSymbol = NativeTokenInfo.Symbol; + var basicFee = 100; + var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); + var proposalMethodName = nameof(TokenContractStub.SetMethodFee); + var methodFees = new MethodFees + { + MethodName = methodName, + Fees = + { + new MethodFee { Symbol = tokenSymbol, BasicFee = basicFee } + } + }; + var proposalId = await CreateProposalAsync(TokenContractAddress, + methodFeeController.OwnerAddress, proposalMethodName, methodFees); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee + { + TokenSymbol = "ELF", + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }); + newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee + { + TokenSymbol = "CPU", + AddedTokenWeight = 2, + BaseTokenWeight = 1 + }); + var createProposalInput = new CreateProposalInput + { + ToAddress = TokenContractAddress, + Params = newSymbolList.ToByteString(), + OrganizationAddress = theDefaultController, + ContractMethodName = nameof(TokenContractImplContainer.TokenContractImplStub + .SetSymbolsToPayTxSizeFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var parliamentCreateProposal = await ParliamentContractStub.CreateProposal.SendAsync(createProposalInput); + var parliamentProposalId = parliamentCreateProposal.Output; + foreach (var bp in InitialCoreDataCenterKeyPairs) + { + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(parliamentProposalId); + approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); + } + var transactionRelease = ParliamentContractStub.Release.GetTransaction(parliamentProposalId); + await ExecuteTransactionWithMiningAsync(transactionRelease); + var symbolListToPayTxSizeFee = await TokenContractStub.GetSymbolsToPayTxSizeFee.CallAsync(new Empty()); + symbolListToPayTxSizeFee.SymbolsToPayTxSizeFee.Count.ShouldBeGreaterThan(0); + var transaction = GenerateTokenTransaction(Accounts[0].Address, nameof(TokenContractStub.Transfer), + new TransferFromInput + { + Amount = 100, + Symbol = "ELF", + From = Accounts[1].Address, + To = Accounts[2].Address, + Memo = "Test get resource" + }); + + var result1 = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); + result1.NonParallelizable.ShouldBeFalse(); + result1.WritePaths.Count.ShouldBeGreaterThan(0); + } + [Fact] public async Task ACS2_GetResourceInfo_DonateResourceToken_Test() { From 2ee7bd36f9d5dfecca24c83b7d04b8bfe473c2e4 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Sat, 6 May 2023 15:24:40 +0800 Subject: [PATCH 002/139] feat: when symbol list to pay tx size fee is null, return. --- .../TokenContract_ACS1_MethodFeeProvider.cs | 4 ++++ .../BVT/ACS2_TokenResourceTests.cs | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs index f729dec518..7e88e294b1 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs @@ -98,12 +98,16 @@ private List GetTransactionFeeSymbolsByMethod(string methodName) return symbols; } } + + if (State.SymbolListToPayTxSizeFee.Value == null) return symbols; + foreach (var sizeFee in State.SymbolListToPayTxSizeFee.Value.SymbolsToPayTxSizeFee) { if (!symbols.Contains(sizeFee.TokenSymbol)) symbols.Add(sizeFee.TokenSymbol); } return symbols; + } private void RequiredMethodFeeControllerSet() diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs index f17a326f9d..c7dd514896 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs @@ -62,8 +62,9 @@ public async Task ACS2_GetResourceInfo_Transfer_MultiToken_Test() var newSymbolList = new SymbolListToPayTxSizeFee(); await CreateNativeTokenAsync(); await CreateTokenAsync(DefaultAddress, "CPU"); + await CreateTokenAsync(DefaultAddress, "NET"); var methodName = "Transfer"; - var tokenSymbol = NativeTokenInfo.Symbol; + var tokenSymbol = "NET"; var basicFee = 100; var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); var proposalMethodName = nameof(TokenContractStub.SetMethodFee); From aa80a63ea3c161bb5f62169951a2b08c669b4b4d Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Thu, 11 May 2023 15:47:54 +0800 Subject: [PATCH 003/139] feat: refactor charge size fee. --- .../TokenContract_Fees.cs | 248 +++++++++++------- 1 file changed, 147 insertions(+), 101 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index da35910cb8..9ae6db4537 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -120,6 +120,7 @@ private UserContractMethodFees GetActualFee(Address contractAddress, string meth fee.MergeFrom(spec.Value); return fee; } + //If special key is null,get the normal fee set by the configuration contract. //configuration_key:UserContractMethod var value = State.ConfigurationContract.GetConfiguration.Call(new StringValue @@ -130,6 +131,7 @@ private UserContractMethodFees GetActualFee(Address contractAddress, string meth { return new UserContractMethodFees(); } + fee.MergeFrom(value.Value); return fee; } @@ -161,6 +163,43 @@ private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress); break; } + + // if (!chargingResult) + // { + // foreach (var (delegatee, delegations) in State.TransactionFeeDelegateesMap[fromAddress].Delegatees) + // { + // var delegatorAddress = Address.FromBase58(delegatee); + // var delegateeChargingResult = false; + // foreach (var (delegateeSecond, delegationsSecond) in State.TransactionFeeDelegateesMap[delegatorAddress] + // .Delegatees) + // { + // // compare current block height with the block height when the delegatee added + // if (Context.Transaction.RefBlockNumber < delegationsSecond.BlockHeight) continue; + // + // var delegateeBill = new TransactionFeeBill(); + // var delegateeAllowanceBill = new TransactionFreeFeeAllowanceBill(); + // var delegateeAddress = Address.FromBase58(delegateeSecond); + // if (delegateeAddress == fromAddress) continue; + // delegateeChargingResult = ChargeTransactionFeesToBill(input, delegateeAddress, + // ref delegateeBill, ref delegateeAllowanceBill, fee, isSizeFeeFree, delegationsSecond); + // + // if (!delegateeChargingResult) continue; + // + // bill = delegateeBill; + // allowanceBill = delegateeAllowanceBill; + // fromAddress = delegateeAddress; + // chargingResult = true; + // ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress); + // break; + // } + // + // if (delegateeChargingResult) + // { + // break; + // } + // } + // } + return chargingResult; } @@ -239,6 +278,11 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre ChargeBaseFee(fee, fromAddress, ref bill, freeAllowances, ref allowanceBill, delegations); } + if (delegations != null && !successToChargeBaseFee) + { + return false; + } + var successToChargeSizeFee = true; if (!isSizeFeeFree) { @@ -316,16 +360,62 @@ private bool ChargeBaseFee(Dictionary methodFeeMap, Address fromAd return true; } - + private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress, ref TransactionFeeBill bill, MethodFeeFreeAllowances freeAllowances, ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { - string symbolChargedForBaseFee = null; - var amountChargedForBaseFee = 0L; - var amountChargedForBaseAllowance = 0L; // Size Fee is charged in primary token, aelf. var symbolToPayTxFee = State.ChainPrimaryTokenSymbol.Value; + GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, freeAllowances, allowanceBill, + out var symbolChargedForBaseFee, out var amountChargedForBaseFee, out var amountChargedForBaseAllowance, + out var availableBalance, out var availableAllowance); + var txSizeFeeAmount = input.TransactionSizeFee; + + // SymbolsToPayTxSizeFee is set of all available token can be charged, and with the ratio of primary token and another. + if (input.SymbolsToPayTxSizeFee.Any()) + { + var allSymbolToTxFee = input.SymbolsToPayTxSizeFee.ToList(); + // get 1st Balance + Allowance > size fee, else, get 1st > 0 + var availableSymbol = GetAvailableSymbolToPayTxFee(allSymbolToTxFee, fromAddress, txSizeFeeAmount,freeAllowances, + symbolChargedForBaseFee, amountChargedForBaseFee, amountChargedForBaseAllowance, delegations); + + if (availableSymbol != null && availableSymbol.TokenSymbol != symbolToPayTxFee) + { + symbolToPayTxFee = availableSymbol.TokenSymbol; + txSizeFeeAmount = txSizeFeeAmount.Mul(availableSymbol.AddedTokenWeight) + .Div(availableSymbol.BaseTokenWeight); + GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, freeAllowances, allowanceBill, + out symbolChargedForBaseFee, out amountChargedForBaseFee, out amountChargedForBaseAllowance, + out availableBalance, out availableAllowance); + } + } + + var chargeResult = availableBalance.Add(availableAllowance) >= txSizeFeeAmount; + if (delegations != null) + { + chargeResult = chargeResult && IsDelegationEnough(symbolToPayTxFee, symbolChargedForBaseFee, + amountChargedForBaseFee.Add(amountChargedForBaseAllowance), txSizeFeeAmount, delegations); + if (!chargeResult) + { + return false; + } + } + + GenerateBill(txSizeFeeAmount, symbolToPayTxFee, symbolChargedForBaseFee, availableBalance, availableAllowance, + ref bill, ref allowanceBill); + return chargeResult; + } + + private void GetAvailableBalance(string symbolToPayTxFee, Address fromAddress, TransactionFeeBill bill, + MethodFeeFreeAllowances freeAllowances, TransactionFreeFeeAllowanceBill allowanceBill, + out string symbolChargedForBaseFee, out long amountChargedForBaseFee, out long amountChargedForBaseAllowance, + out long availableBalance, out long availableAllowance) + { + symbolChargedForBaseFee = null; + amountChargedForBaseFee = 0L; + amountChargedForBaseAllowance = 0L; + if (bill.FeesMap.Any()) { symbolChargedForBaseFee = bill.FeesMap.First().Key; @@ -333,92 +423,70 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress amountChargedForBaseAllowance = allowanceBill.FreeFeeAllowancesMap[symbolChargedForBaseFee]; } - var availableBalance = symbolChargedForBaseFee == symbolToPayTxFee + availableBalance = symbolChargedForBaseFee == symbolToPayTxFee // Available balance need to deduct amountChargedForBaseFee, if base fee is charged in the same token. ? GetBalance(fromAddress, symbolToPayTxFee).Sub(amountChargedForBaseFee) : GetBalance(fromAddress, symbolToPayTxFee); - var availableAllowance = symbolChargedForBaseFee == symbolToPayTxFee + availableAllowance = symbolChargedForBaseFee == symbolToPayTxFee ? GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) : GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee); - var txSizeFeeAmount = input.TransactionSizeFee; - - - // SymbolsToPayTxSizeFee is set of all available token can be charged, and with the ratio of primary token and another. - if (input.SymbolsToPayTxSizeFee.Any()) + } + + private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List allSymbolToTxFee, + Address fromAddress, long txSizeFeeAmount, MethodFeeFreeAllowances freeAllowances, + string symbolChargedForBaseFee,long amountChargedForBaseFee, long amountChargedForBaseAllowance, + TransactionFeeDelegations delegations = null) + { + SymbolToPayTxSizeFee availableSymbol; + if (delegations == null) { - var allSymbolToTxFee = input.SymbolsToPayTxSizeFee; - // get 1st Balance + Allowance > size fee, else, get 1st > 0 - var availableSymbol = allSymbolToTxFee.FirstOrDefault(x => - GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, symbolChargedForBaseFee, - amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance) >= txSizeFeeAmount && - IsDelegationEnoughBaseOnPrimaryToken(x, symbolChargedForBaseFee, - amountChargedForBaseFee.Add(amountChargedForBaseAllowance), txSizeFeeAmount, delegations)); - - if (delegations != null && availableSymbol == null) - { - return false; - } - - if (delegations == null) + availableSymbol = allSymbolToTxFee.FirstOrDefault(x => { - availableSymbol ??= allSymbolToTxFee.FirstOrDefault(x => - GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, symbolChargedForBaseFee, - amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance) > 0); - } - - if (availableSymbol != null && availableSymbol.TokenSymbol != symbolToPayTxFee) + var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, + symbolChargedForBaseFee, amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance); + return balance >= txSizeFeeAmount || balance > 0; + }); + } + else + { + availableSymbol = allSymbolToTxFee.FirstOrDefault(x => { - symbolToPayTxFee = availableSymbol.TokenSymbol; - txSizeFeeAmount = txSizeFeeAmount.Mul(availableSymbol.AddedTokenWeight) - .Div(availableSymbol.BaseTokenWeight); - availableBalance = symbolChargedForBaseFee == symbolToPayTxFee - ? GetBalance(fromAddress, symbolToPayTxFee).Sub(amountChargedForBaseFee) - : GetBalance(fromAddress, symbolToPayTxFee); - availableAllowance = symbolChargedForBaseFee == symbolToPayTxFee - ? GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) - : GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee); - } + var delegationEnough = IsDelegationEnoughBaseOnPrimaryToken(x, symbolChargedForBaseFee, + amountChargedForBaseFee.Add(amountChargedForBaseAllowance), txSizeFeeAmount, delegations); + var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, + symbolChargedForBaseFee, amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance); + return delegationEnough && balance >= txSizeFeeAmount; + }); } - // Default token is primary token, so if no token can be charged in input.SymbolsToPayTxSizeFee, primary token will be the last one. - // So, we have to take primary token delegation quota into account. + return availableSymbol; + } - // start to charge + private void GenerateBill(long txSizeFeeAmount, string symbolToPayTxFee, string symbolChargedForBaseFee, + long availableBalance, long availableAllowance, ref TransactionFeeBill bill, + ref TransactionFreeFeeAllowanceBill allowanceBill) + { var chargeAmount = 0L; var chargeAllowanceAmount = 0L; - - if (delegations == null - || (delegations.Delegations.Keys.Contains(symbolToPayTxFee) - && (symbolChargedForBaseFee == symbolToPayTxFee - ? delegations.Delegations[symbolToPayTxFee] - .Sub(amountChargedForBaseFee.Add(amountChargedForBaseAllowance)) - : delegations.Delegations[symbolToPayTxFee]) >= txSizeFeeAmount)) + if (availableBalance.Add(availableAllowance) > txSizeFeeAmount) { - // Balance + Allowance > size fee - if (availableBalance.Add(availableAllowance) > txSizeFeeAmount) + // Allowance > size fee, all allowance + if (availableAllowance > txSizeFeeAmount) { - // Allowance > size fee, all allowance - if (availableAllowance > txSizeFeeAmount) - { - chargeAllowanceAmount = txSizeFeeAmount; - } - else - { - // Allowance is not enough - chargeAllowanceAmount = availableAllowance; - chargeAmount = txSizeFeeAmount.Sub(chargeAllowanceAmount); - } + chargeAllowanceAmount = txSizeFeeAmount; } else { + // Allowance is not enough chargeAllowanceAmount = availableAllowance; - chargeAmount = availableBalance; + chargeAmount = txSizeFeeAmount.Sub(chargeAllowanceAmount); } } - - // Warning, currently, if the delegation quato is not enough, we will not charge delegatee bill, so we don't calculate it now. - if (delegations == null && symbolToPayTxFee == null) - return availableBalance.Add(availableAllowance) >= txSizeFeeAmount; + else + { + chargeAllowanceAmount = availableAllowance; + chargeAmount = availableBalance; + } if (symbolChargedForBaseFee == symbolToPayTxFee) { @@ -439,20 +507,6 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress allowanceBill.FreeFeeAllowancesMap.Add(symbolToPayTxFee, chargeAllowanceAmount); } } - - if (delegations == null - || (delegations.Delegations.Keys.Contains(symbolToPayTxFee) - && (symbolChargedForBaseFee == symbolToPayTxFee - ? delegations.Delegations[symbolToPayTxFee] - .Sub(amountChargedForBaseFee.Add(amountChargedForBaseAllowance)) - : delegations.Delegations[symbolToPayTxFee]) >= txSizeFeeAmount)) - { - return availableBalance.Add(availableAllowance) >= txSizeFeeAmount; - } - else - { - return false; - } } public override Empty ChargeResourceToken(ChargeResourceTokenInput input) @@ -1083,29 +1137,21 @@ private long GetAllowanceCalculatedBaseOnPrimaryToken(SymbolToPayTxSizeFee token } private bool IsDelegationEnoughBaseOnPrimaryToken(SymbolToPayTxSizeFee tokenInfo, string baseSymbol, long cost, - long txSizeFeeAmount, TransactionFeeDelegations delegations = null) + long txSizeFeeAmount, TransactionFeeDelegations delegations) { - if (delegations == null) - { - return true; - } - - if (!delegations.Delegations.ContainsKey(tokenInfo.TokenSymbol)) return false; - txSizeFeeAmount = txSizeFeeAmount.Mul(tokenInfo.AddedTokenWeight) .Div(tokenInfo.BaseTokenWeight); - - // If current symbol is base fee symbol, it should be taken into account too. - if (tokenInfo.TokenSymbol != baseSymbol) - { - return delegations.Delegations[tokenInfo.TokenSymbol] >= txSizeFeeAmount; - } - else - { - return delegations.Delegations[tokenInfo.TokenSymbol].Sub(cost) >= txSizeFeeAmount; - } + return IsDelegationEnough(tokenInfo.TokenSymbol, baseSymbol, cost, txSizeFeeAmount, delegations); } + private bool IsDelegationEnough(string txSymbol, string baseSymbol, long cost, + long txSizeFeeAmount, TransactionFeeDelegations delegations) + { + return (baseSymbol == txSymbol + ? delegations.Delegations[txSymbol] + .Sub(cost) + : delegations.Delegations[txSymbol]) >= txSizeFeeAmount; + } private void AssertSymbolToPayTxFeeIsValid(string tokenSymbol, out long totalSupply) { From 3b4fd47740d002722199af10c3b3f005139f77ac Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Fri, 12 May 2023 19:49:23 +0800 Subject: [PATCH 004/139] Update TokenContract_Fees.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat:fix failed unit test. --- .../AElf.Contracts.MultiToken/TokenContract_Fees.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 9ae6db4537..a044205f0b 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -389,6 +389,11 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress out symbolChargedForBaseFee, out amountChargedForBaseFee, out amountChargedForBaseAllowance, out availableBalance, out availableAllowance); } + + if (delegations != null && availableSymbol == null) + { + return false; + } } var chargeResult = availableBalance.Add(availableAllowance) >= txSizeFeeAmount; @@ -1147,9 +1152,8 @@ private bool IsDelegationEnoughBaseOnPrimaryToken(SymbolToPayTxSizeFee tokenInfo private bool IsDelegationEnough(string txSymbol, string baseSymbol, long cost, long txSizeFeeAmount, TransactionFeeDelegations delegations) { - return (baseSymbol == txSymbol - ? delegations.Delegations[txSymbol] - .Sub(cost) + return delegations.Delegations.Keys.Contains(txSymbol) && + (baseSymbol == txSymbol ? delegations.Delegations[txSymbol].Sub(cost) : delegations.Delegations[txSymbol]) >= txSizeFeeAmount; } From 358c7781116e14e60d203a38a4905c8611603bdf Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Mon, 15 May 2023 10:49:15 +0800 Subject: [PATCH 005/139] feat: add methodName when add path for transaction fee. --- .../TokenContract_ACS1_MethodFeeProvider.cs | 12 ++---------- .../TokenContract_ACS2_StatePathsProvider.cs | 8 ++++---- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs index 7e88e294b1..aafbc8ed13 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs @@ -75,15 +75,7 @@ public override AuthorityInfo GetMethodFeeController(Empty input) #region private methods - private List GetTransactionFeeSymbols() - { - var transferSymbols = GetTransactionFeeSymbolsByMethod(nameof(Transfer)); - var transferFromSymbols = GetTransactionFeeSymbolsByMethod(nameof(TransferFrom)); - var symbols = transferSymbols.Union(transferFromSymbols).ToList(); - return symbols; - } - - private List GetTransactionFeeSymbolsByMethod(string methodName) + private List GetTransactionFeeSymbols(string methodName) { var symbols = new List(); if (State.TransactionFees[methodName] != null) @@ -107,9 +99,9 @@ private List GetTransactionFeeSymbolsByMethod(string methodName) symbols.Add(sizeFee.TokenSymbol); } return symbols; - } + private void RequiredMethodFeeControllerSet() { if (State.MethodFeeController.Value != null) return; diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index bce37624a4..b8087da2cd 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -31,7 +31,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesConfig)) } }; - AddPathForTransactionFee(resourceInfo, txn.From.ToString()); + AddPathForTransactionFee(resourceInfo, txn.From.ToString(),txn.MethodName); AddPathForDelegatees(resourceInfo, txn.From); return resourceInfo; } @@ -58,7 +58,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesConfig)) } }; - AddPathForTransactionFee(resourceInfo, txn.From.ToString()); + AddPathForTransactionFee(resourceInfo, txn.From.ToString(),txn.MethodName); AddPathForDelegatees(resourceInfo, txn.From); return resourceInfo; } @@ -68,9 +68,9 @@ public override ResourceInfo GetResourceInfo(Transaction txn) } } - private void AddPathForTransactionFee(ResourceInfo resourceInfo, String from) + private void AddPathForTransactionFee(ResourceInfo resourceInfo, String from,string methodName) { - var symbols = GetTransactionFeeSymbols(); + var symbols = GetTransactionFeeSymbols(methodName); var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; if (_primaryTokenSymbol != string.Empty && !symbols.Contains(primaryTokenSymbol)) symbols.Add(primaryTokenSymbol); From ad84845986c010cead09d245dc23ccfd517800af Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Mon, 15 May 2023 15:14:11 +0800 Subject: [PATCH 006/139] feat: add input params. --- .../TokenContract_ACS2_StatePathsProvider.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index b8087da2cd..c6654c19f3 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -32,7 +32,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) } }; AddPathForTransactionFee(resourceInfo, txn.From.ToString(),txn.MethodName); - AddPathForDelegatees(resourceInfo, txn.From); + AddPathForDelegatees(resourceInfo, txn.From,txn.MethodName); return resourceInfo; } @@ -59,7 +59,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) } }; AddPathForTransactionFee(resourceInfo, txn.From.ToString(),txn.MethodName); - AddPathForDelegatees(resourceInfo, txn.From); + AddPathForDelegatees(resourceInfo, txn.From,txn.MethodName); return resourceInfo; } @@ -97,7 +97,7 @@ private ScopedStatePath GetPath(params string[] parts) }; } - private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from) + private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from,string methodName) { var allDelegatees = State.TransactionFeeDelegateesMap[from]; if (allDelegatees != null) @@ -106,7 +106,7 @@ private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from) { if (delegations == null) return; var add = Address.FromBase58(delegations).ToString(); - AddPathForTransactionFee(resourceInfo, add); + AddPathForTransactionFee(resourceInfo, add,methodName); resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesMap), add)); resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesLastRefreshTimeMap), add)); } From 083501433e5708fc835531a83d93b54536c0faa8 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Wed, 24 May 2023 10:29:54 +0800 Subject: [PATCH 007/139] feat: imporve token contract event --- .../TokenContract_Fees.cs | 24 ++++++++++++--- protobuf/token_contract.proto | 4 +++ protobuf/transaction_fee.proto | 15 ++++++++++ .../ExecutePluginTransactionDirectlyTest.cs | 30 ++++++++++++++++--- 4 files changed, 65 insertions(+), 8 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index da35910cb8..0aa309fe12 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -675,6 +675,12 @@ public override Empty ClaimTransactionFees(TotalTransactionFeesMap input) var amount = bill.Value; ModifyBalance(Context.Self, symbol, amount); TransferTransactionFeesToFeeReceiver(symbol, amount); + Context.Fire(new TransactionFeeClaimed + { + Symbol = symbol, + Amount = amount, + Receiver = Context.Self + }); } Context.LogDebug(() => "Finish claim transaction fee."); @@ -772,11 +778,12 @@ private void PayResourceTokens(TotalResourceTokensMaps billMaps, bool isMainChai if (amount > 0) { ModifyBalance(bill.ContractAddress, symbol, -amount); + var receiver = Context.Self; if (isMainChain) { Context.LogDebug(() => $"Adding {amount} of {symbol}s to dividend pool."); // Main Chain. - ModifyBalance(Context.Self, symbol, amount); + ModifyBalance(receiver, symbol, amount); State.DividendPoolContract.Donate.Send(new DonateInput { Symbol = symbol, @@ -787,10 +794,17 @@ private void PayResourceTokens(TotalResourceTokensMaps billMaps, bool isMainChai { Context.LogDebug(() => $"Adding {amount} of {symbol}s to consensus address account."); // Side Chain - var consensusContractAddress = + receiver = Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName); - ModifyBalance(consensusContractAddress, symbol, amount); + ModifyBalance(receiver, symbol, amount); } + Context.Fire(new ResourceTokenClaimed + { + Symbol = symbol, + Amount = amount, + Payer = bill.ContractAddress, + Receiver = receiver + }); } } } @@ -869,7 +883,9 @@ private void PayRental() Context.Fire(new RentalCharged() { Symbol = symbol, - Amount = donates + Amount = donates, + Payer = creator, + Receiver = consensusContractAddress }); } } diff --git a/protobuf/token_contract.proto b/protobuf/token_contract.proto index 6aea317b43..3d23ee925d 100644 --- a/protobuf/token_contract.proto +++ b/protobuf/token_contract.proto @@ -790,6 +790,10 @@ message RentalCharged { string symbol = 1; // The amount of rental fee charged. int64 amount = 2; + // The payer of rental fee. + aelf.Address payer = 3; + // The receiver of rental fee. + aelf.Address receiver = 4; } message RentalAccountBalanceInsufficient { diff --git a/protobuf/transaction_fee.proto b/protobuf/transaction_fee.proto index 47f9f4af24..57f7c16d04 100644 --- a/protobuf/transaction_fee.proto +++ b/protobuf/transaction_fee.proto @@ -43,4 +43,19 @@ message ResourceTokenOwned { string symbol = 1; int64 amount = 2; aelf.Address contract_address = 3; +} + +message TransactionFeeClaimed { + option (aelf.is_event) = true; + string symbol = 1; + int64 amount = 2; + aelf.Address receiver = 3; +} + +message ResourceTokenClaimed { + option (aelf.is_event) = true; + string symbol = 1; + int64 amount = 2; + aelf.Address payer = 3; + aelf.Address receiver = 4; } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index a72b124533..10f0602ef2 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -222,8 +222,10 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }); } - await TokenContractStub.DonateResourceToken.SendAsync(feeMap); - + var result = await TokenContractStub.DonateResourceToken.SendAsync(feeMap); + var transactionFeeClaimedDic = result.TransactionResult.Logs.Where(o => o.Name == nameof(ResourceTokenClaimed)) + .Select(o => ResourceTokenClaimed.Parser.ParseFrom(o.NonIndexed)).ToDictionary(o => o.Symbol, o => o); + for (var i = 0; i < symbolList.Length; i++) { var balance = await GetBalanceAsync(DefaultSender, symbolList[i]); @@ -233,6 +235,12 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var consensusBalance = await GetBalanceAsync(ConsensusContractAddress, symbolList[i]); consensusBalance.ShouldBe(initialBalances[i] - lastBalances[i]); } + + var transactionFeeClaimed = transactionFeeClaimedDic[symbolList[i]]; + transactionFeeClaimed.Symbol.ShouldBe(symbolList[i]); + transactionFeeClaimed.Amount.ShouldBe(tokenFee[i] > initialBalances[i] ? initialBalances[i] : tokenFee[i]); + transactionFeeClaimed.Payer.ShouldBe(DefaultSender); + transactionFeeClaimed.Receiver.ShouldBe(ConsensusContractAddress); } } @@ -250,7 +258,14 @@ public async Task ClaimTransactionFee_Balance_WithOut_Receiver_Test() { tokenSymbol, feeAmount } } }; - await TokenContractStub.ClaimTransactionFees.SendAsync(claimFeeInput); + var result = await TokenContractStub.ClaimTransactionFees.SendAsync(claimFeeInput); + + var transactionFeeClaimed = TransactionFeeClaimed.Parser.ParseFrom(result.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(TransactionFeeClaimed))).NonIndexed); + transactionFeeClaimed.Symbol.ShouldBe(tokenSymbol); + transactionFeeClaimed.Amount.ShouldBe(feeAmount); + transactionFeeClaimed.Receiver.ShouldBe(TokenContractAddress); + var afterBurned = await GetTokenSupplyAmount(tokenSymbol); (beforeBurned - afterBurned).ShouldBe(feeAmount); } @@ -279,7 +294,14 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { tokenSymbol, feeAmount } } }; - await TokenContractStub.ClaimTransactionFees.SendAsync(claimFeeInput); + var result = await TokenContractStub.ClaimTransactionFees.SendAsync(claimFeeInput); + + var transactionFeeClaimed = TransactionFeeClaimed.Parser.ParseFrom(result.TransactionResult.Logs + .First(l => l.Name.Contains(nameof(TransactionFeeClaimed))).NonIndexed); + transactionFeeClaimed.Symbol.ShouldBe(tokenSymbol); + transactionFeeClaimed.Amount.ShouldBe(feeAmount); + transactionFeeClaimed.Receiver.ShouldBe(TokenContractAddress); + var afterBurned = await GetTokenSupplyAmount(tokenSymbol); var afterBalance = await GetBalanceAsync(receiver, tokenSymbol); var shouldBurned = feeAmount.Div(10); From fdb631f83c601be0684e4bb08ea3d2797669b8ad Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Mon, 29 May 2023 14:54:23 +0800 Subject: [PATCH 008/139] feat: charge fee(unfinished). --- .../TokenContractState.cs | 5 + .../TokenContract_Fees.cs | 228 +++++++++--------- protobuf/token_contract.proto | 2 +- protobuf/token_contract_impl.proto | 105 ++++++++ 4 files changed, 226 insertions(+), 114 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState.cs b/contract/AElf.Contracts.MultiToken/TokenContractState.cs index cac95c40af..53f7c21d29 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState.cs @@ -54,4 +54,9 @@ public partial class TokenContractState : ContractState public MappedState CreateTokenWhiteListMap { get; set; } public MappedState TransactionFeeDelegateesMap { get; set; } + + /// + /// delegator address -> contract address -> method name -> delegatee info + /// + public MappedState TransactionFeeDelegateInfoMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index a044205f0b..1da9b80a2d 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using AElf.CSharp.Core; @@ -25,7 +26,7 @@ public override ChargeTransactionFeesOutput ChargeTransactionFees(ChargeTransact // Primary token not created yet. if (State.ChainPrimaryTokenSymbol.Value == null) { - return new ChargeTransactionFeesOutput {Success = true}; + return new ChargeTransactionFeesOutput { Success = true }; } // Record tx fee bill during current charging process. @@ -33,7 +34,7 @@ public override ChargeTransactionFeesOutput ChargeTransactionFees(ChargeTransact var allowanceBill = new TransactionFreeFeeAllowanceBill(); var fromAddress = Context.Sender; var methodFees = Context.Call(input.ContractAddress, nameof(GetMethodFee), - new StringValue {Value = input.MethodName}); + new StringValue { Value = input.MethodName }); var fee = new Dictionary(); var isSizeFeeFree = false; if (methodFees != null) @@ -86,8 +87,18 @@ private ChargeTransactionFeesOutput TryToChargeTransactionFee(ChargeTransactionF ChargeTransactionFeesToBill(input, fromAddress, ref bill, ref allowanceBill, fee, isSizeFeeFree); if (!chargingResult) { + var delegatorAddress = fromAddress; chargingResult = ChargeFromDelegations(input, ref fromAddress, ref bill, ref allowanceBill, fee, - isSizeFeeFree); + isSizeFeeFree,delegatorAddress); + } + if (!chargingResult) + { + var delegateeAddress = State.TransactionFeeDelegateesMap[fromAddress].Delegatees; + foreach (var (delegatee,_) in delegateeAddress) + { + ChargeFromDelegations(input, ref fromAddress, ref bill, ref allowanceBill, fee, + isSizeFeeFree,Address.FromBase58(delegatee)); + } } ModifyBalance(fromAddress, bill, allowanceBill); @@ -138,68 +149,36 @@ private UserContractMethodFees GetActualFee(Address contractAddress, string meth private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address fromAddress, ref TransactionFeeBill bill, ref TransactionFreeFeeAllowanceBill allowanceBill, - Dictionary fee, bool isSizeFeeFree) + Dictionary fee, bool isSizeFeeFree,Address delegatorAddress) { var chargingResult = false; // Try to charge delegatees - if (State.TransactionFeeDelegateesMap[fromAddress]?.Delegatees == null) return false; - foreach (var (delegatee, delegations) in State.TransactionFeeDelegateesMap[fromAddress].Delegatees) + // Get delegatee list according to the delegator + if (State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees == null) return false; + if (State.TransactionFeeDelegateesMap[delegatorAddress].Delegatees != null) { - // compare current block height with the block height when the delegatee added - if (Context.Transaction.RefBlockNumber < delegations.BlockHeight) continue; - - var delegateeBill = new TransactionFeeBill(); - var delegateeAllowanceBill = new TransactionFreeFeeAllowanceBill(); - var delegateeAddress = Address.FromBase58(delegatee); - var delegateeChargingResult = ChargeTransactionFeesToBill(input, delegateeAddress, - ref delegateeBill, ref delegateeAllowanceBill, fee, isSizeFeeFree, delegations); - - if (!delegateeChargingResult) continue; - - bill = delegateeBill; - allowanceBill = delegateeAllowanceBill; - fromAddress = delegateeAddress; - chargingResult = true; - ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress); - break; + foreach (var (delegatee, delegations) in State.TransactionFeeDelegateesMap[delegatorAddress].Delegatees) + { + // compare current block height with the block height when the delegatee added + if (Context.Transaction.RefBlockNumber < delegations.BlockHeight) continue; + + var delegateeBill = new TransactionFeeBill(); + var delegateeAllowanceBill = new TransactionFreeFeeAllowanceBill(); + var delegateeAddress = Address.FromBase58(delegatee); + var delegateeChargingResult = ChargeTransactionFeesToBill(input, delegateeAddress, + ref delegateeBill, ref delegateeAllowanceBill, fee, isSizeFeeFree, delegations); + + if (!delegateeChargingResult) continue; + + bill = delegateeBill; + allowanceBill = delegateeAllowanceBill; + fromAddress = delegateeAddress; + chargingResult = true; + ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress); + break; + } } - // if (!chargingResult) - // { - // foreach (var (delegatee, delegations) in State.TransactionFeeDelegateesMap[fromAddress].Delegatees) - // { - // var delegatorAddress = Address.FromBase58(delegatee); - // var delegateeChargingResult = false; - // foreach (var (delegateeSecond, delegationsSecond) in State.TransactionFeeDelegateesMap[delegatorAddress] - // .Delegatees) - // { - // // compare current block height with the block height when the delegatee added - // if (Context.Transaction.RefBlockNumber < delegationsSecond.BlockHeight) continue; - // - // var delegateeBill = new TransactionFeeBill(); - // var delegateeAllowanceBill = new TransactionFreeFeeAllowanceBill(); - // var delegateeAddress = Address.FromBase58(delegateeSecond); - // if (delegateeAddress == fromAddress) continue; - // delegateeChargingResult = ChargeTransactionFeesToBill(input, delegateeAddress, - // ref delegateeBill, ref delegateeAllowanceBill, fee, isSizeFeeFree, delegationsSecond); - // - // if (!delegateeChargingResult) continue; - // - // bill = delegateeBill; - // allowanceBill = delegateeAllowanceBill; - // fromAddress = delegateeAddress; - // chargingResult = true; - // ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress); - // break; - // } - // - // if (delegateeChargingResult) - // { - // break; - // } - // } - // } - return chargingResult; } @@ -277,7 +256,7 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre successToChargeBaseFee = ChargeBaseFee(fee, fromAddress, ref bill, freeAllowances, ref allowanceBill, delegations); } - + //For delegation, if the base fee fails to be charged, the size fee will not be charged if (delegations != null && !successToChargeBaseFee) { return false; @@ -360,13 +339,14 @@ private bool ChargeBaseFee(Dictionary methodFeeMap, Address fromAd return true; } - + private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress, ref TransactionFeeBill bill, MethodFeeFreeAllowances freeAllowances, ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { - // Size Fee is charged in primary token, aelf. + // Size Fee is charged in primary token, elf. var symbolToPayTxFee = State.ChainPrimaryTokenSymbol.Value; + //Get primary token balance GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, freeAllowances, allowanceBill, out var symbolChargedForBaseFee, out var amountChargedForBaseFee, out var amountChargedForBaseAllowance, out var availableBalance, out var availableAllowance); @@ -376,9 +356,8 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress if (input.SymbolsToPayTxSizeFee.Any()) { var allSymbolToTxFee = input.SymbolsToPayTxSizeFee.ToList(); - // get 1st Balance + Allowance > size fee, else, get 1st > 0 - var availableSymbol = GetAvailableSymbolToPayTxFee(allSymbolToTxFee, fromAddress, txSizeFeeAmount,freeAllowances, - symbolChargedForBaseFee, amountChargedForBaseFee, amountChargedForBaseAllowance, delegations); + var availableSymbol = GetAvailableSymbolToPayTxFee(allSymbolToTxFee, fromAddress, txSizeFeeAmount, + freeAllowances, symbolChargedForBaseFee, amountChargedForBaseFee, amountChargedForBaseAllowance, delegations); if (availableSymbol != null && availableSymbol.TokenSymbol != symbolToPayTxFee) { @@ -389,7 +368,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress out symbolChargedForBaseFee, out amountChargedForBaseFee, out amountChargedForBaseAllowance, out availableBalance, out availableAllowance); } - + //For delegation,if there is no available token,return false,no need to generate bill if (delegations != null && availableSymbol == null) { return false; @@ -436,21 +415,27 @@ private void GetAvailableBalance(string symbolToPayTxFee, Address fromAddress, T ? GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) : GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee); } - + private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List allSymbolToTxFee, Address fromAddress, long txSizeFeeAmount, MethodFeeFreeAllowances freeAllowances, - string symbolChargedForBaseFee,long amountChargedForBaseFee, long amountChargedForBaseAllowance, + string symbolChargedForBaseFee, long amountChargedForBaseFee, long amountChargedForBaseAllowance, TransactionFeeDelegations delegations = null) { SymbolToPayTxSizeFee availableSymbol; if (delegations == null) { + // get 1st Balance + Allowance > size fee, else, get 1st > 0 availableSymbol = allSymbolToTxFee.FirstOrDefault(x => { var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, symbolChargedForBaseFee, amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance); - return balance >= txSizeFeeAmount || balance > 0; - }); + return balance >= txSizeFeeAmount; + }) ?? allSymbolToTxFee.FirstOrDefault(x => + { + var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, + symbolChargedForBaseFee, amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance); + return balance > 0; + }); } else { @@ -654,34 +639,58 @@ public override Empty SetSymbolsToPayTxSizeFee(SymbolListToPayTxSizeFee input) /// /// private bool ChargeFirstSufficientToken(Dictionary symbolToAmountMap, Address fromAddress, - out string symbol, - out long amount, out long existingBalance, out long existingAllowance, MethodFeeFreeAllowances freeAllowances, + out string symbol, out long amount, out long existingBalance, out long existingAllowance, MethodFeeFreeAllowances freeAllowances, TransactionFeeDelegations delegations = null) { symbol = null; amount = 0L; existingBalance = 0L; existingAllowance = 0L; + + symbol = GetAvailableSymbolToPayBaseFee(symbolToAmountMap, fromAddress, freeAllowances, out amount, delegations); + //Whether or not delegation exists, there is no token that can be used for payment + if (symbol == null) return false; + + //For delegation, There is enough token balance and delegation to pay + //For user, There is enough token balance to pay or there is a token balance greater than 0 + existingBalance = GetBalance(fromAddress, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + //For delegation, return true + //For user,if balance enough return true + if (delegations != null || existingBalance.Add(existingAllowance) >= amount) + { + return true; + } - //var fromAddress = Context.Sender; - string symbolOfValidBalance = null; + //For user, else priority charge primary token + var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; + if (symbolToAmountMap.ContainsKey(primaryTokenSymbol)) + { + symbol = primaryTokenSymbol; + existingBalance = GetBalance(fromAddress, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + } + return false; + } + + private string GetAvailableSymbolToPayBaseFee(Dictionary symbolToAmountMap, Address fromAddress, + MethodFeeFreeAllowances freeAllowances, out long amount, TransactionFeeDelegations delegations = null) + { + string symbolOfValidBalance = null; + amount = 0; // Traverse available token symbols, check balance one by one // until there's balance of one certain token is enough to pay the fee. - foreach (var symbolToAmount in symbolToAmountMap) + //For user + //Find the token that satisfies the balance of the fee,if there is no token that satisfies the balance of the fee, find the token that balance > 0 + if (delegations == null) { - // current token symbol - existingBalance = GetBalance(fromAddress, symbolToAmount.Key); - symbol = symbolToAmount.Key; - amount = symbolToAmount.Value; - - // free allowance in current token symbol - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); - - // if delegations is null, that means no delegation is involved. - if (delegations == null - || (delegations.Delegations.ContainsKey(symbol) && delegations.Delegations[symbol] >= amount)) + foreach (var (symbol, value) in symbolToAmountMap) { + // current token symbol + amount = value; + var existingBalance = GetBalance(fromAddress, symbol); + var existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); if (existingBalance.Add(existingAllowance) > 0) { symbolOfValidBalance = symbol; @@ -690,32 +699,24 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM if (existingBalance.Add(existingAllowance) >= amount) break; } } - - if (delegations == null - || (symbolOfValidBalance != null && delegations.Delegations.ContainsKey(symbolOfValidBalance) && - delegations.Delegations[symbolOfValidBalance] >= amount)) - { - if (existingBalance.Add(existingAllowance) >= amount) return true; - } - - var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; - if (symbolToAmountMap.Keys.Contains(primaryTokenSymbol) && delegations == null) - { - symbol = primaryTokenSymbol; - existingBalance = GetBalance(fromAddress, primaryTokenSymbol); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); - } + //For delegation else { - symbol = symbolOfValidBalance; - if (symbol != null) + //Find the token that satisfies the delegate limit and satisfies the balance of the fee + foreach (var (symbol, value) in symbolToAmountMap) { - existingBalance = GetBalance(fromAddress, symbolOfValidBalance); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + // current token symbol + amount = value; + var existingBalance = GetBalance(fromAddress, symbol); + var existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + if (!delegations.Delegations.ContainsKey(symbol) || delegations.Delegations[symbol] < amount || + existingBalance.Add(existingAllowance) < amount) continue; + symbolOfValidBalance = symbol; + break; } } - - return false; + + return symbolOfValidBalance; } public override Empty ClaimTransactionFees(TotalTransactionFeesMap input) @@ -874,7 +875,7 @@ private void PayRental() } // Update LastPayRentTime if it is ready to charge rental. - State.LastPayRentTime.Value += new Duration {Seconds = duration.Mul(60)}; + State.LastPayRentTime.Value += new Duration { Seconds = duration.Mul(60) }; foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName)) { @@ -1095,7 +1096,7 @@ private MethodFeeFreeAllowances CalculateMethodFeeFreeAllowances(Address input) { if (balance >= config.Threshold) { - return new MethodFeeFreeAllowances {Value = {config.FreeAllowances.Value}}; + return new MethodFeeFreeAllowances { Value = { config.FreeAllowances.Value } }; } } @@ -1105,7 +1106,7 @@ private MethodFeeFreeAllowances CalculateMethodFeeFreeAllowances(Address input) } return (Context.CurrentBlockTime - lastRefreshTime).Seconds > config.RefreshSeconds - ? new MethodFeeFreeAllowances {Value = {config.FreeAllowances.Value}} + ? new MethodFeeFreeAllowances { Value = { config.FreeAllowances.Value } } : freeAllowances; } @@ -1152,9 +1153,10 @@ private bool IsDelegationEnoughBaseOnPrimaryToken(SymbolToPayTxSizeFee tokenInfo private bool IsDelegationEnough(string txSymbol, string baseSymbol, long cost, long txSizeFeeAmount, TransactionFeeDelegations delegations) { - return delegations.Delegations.Keys.Contains(txSymbol) && - (baseSymbol == txSymbol ? delegations.Delegations[txSymbol].Sub(cost) - : delegations.Delegations[txSymbol]) >= txSizeFeeAmount; + return delegations.Delegations.Keys.Contains(txSymbol) && + (baseSymbol == txSymbol + ? delegations.Delegations[txSymbol].Sub(cost) + : delegations.Delegations[txSymbol]) >= txSizeFeeAmount; } private void AssertSymbolToPayTxFeeIsValid(string tokenSymbol, out long totalSupply) diff --git a/protobuf/token_contract.proto b/protobuf/token_contract.proto index 6aea317b43..b3c13d254b 100644 --- a/protobuf/token_contract.proto +++ b/protobuf/token_contract.proto @@ -240,7 +240,7 @@ service TokenContract { } rpc GetTransactionFeeDelegationsOfADelegatee(GetTransactionFeeDelegationsOfADelegateeInput) returns(TransactionFeeDelegations){ - option (aelf.is_view) = true; + option (aelf.is_view) = true; } } diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index 939c15344f..b0f292dd38 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -77,6 +77,18 @@ service TokenContractImpl { rpc ChangeDeveloperController (AuthorityInfo) returns (google.protobuf.Empty) { } + // Delegatee sets the delegation and related information of the delegator based on a transaction. + rpc SetTransactionFeeDelegateInfos (SetTransactionFeeDelegateInfosInput) returns (google.protobuf.Empty){ + } + + // Delegatee remove delegator info based on a transaction. + rpc RemoveTransactionFeeDelegatorInfos (RemoveTransactionFeeDelegatorInfosInput) returns (google.protobuf.Empty){ + } + + // Delegator remove delegatee info based on a transaction. + rpc RemoveTransactionFeeDelegateeInfos (RemoveTransactionFeeDelegateeInfosInput) returns (google.protobuf.Empty){ + } + // Get the address of fee receiver. rpc GetFeeReceiver (google.protobuf.Empty) returns (aelf.Address){ option (aelf.is_view) = true; @@ -128,6 +140,15 @@ service TokenContractImpl { rpc GetOwningRentalUnitValue (google.protobuf.Empty) returns (OwningRentalUnitValue) { option (aelf.is_view) = true; } + + // Get delegation according to the delegator,transaction and delegatee. + rpc GetTransactionFeeDelegateInfos (GetTransactionFeeDelegateInfosInput) returns (TransactionFeeDelegateInfo) { + option (aelf.is_view) = true; + } + // Get delegatee info list according to the delegator and transaction. + rpc GetTransactionFeeDelegateInfosOfADelegatee(GetTransactionFeeDelegateInfosOfADelegateeInput) returns (TransactionFeeDelegatee){ + option (aelf.is_view) = true; + } } message AdvanceResourceTokenInput { @@ -244,3 +265,87 @@ enum SymbolType { NFT = 1; NFT_COLLECTION = 2; } + +message TransactionFeeDelegateInfo{ + // delegation, symbols and its' amount + map delegations = 1; + // height when added + int64 block_height = 2; + //Whether to pay transaction fee continuously + bool isUnlimitedDelegate = 3; +} + +message TransactionFeeDelegatee{ + //delegatee -> delegate info + map delegatees = 1; +} + + +message SetTransactionFeeDelegateInfosInput{ + // the delegator address + aelf.Address delegator_address = 1; + //delegate info list (support batch) + repeated delegateInfo delegate_info_list = 2; +} +message delegateInfo{ + //symbol->amount + map delegations = 1; + aelf.Address contract_address = 2; + string method_name = 3; + //Whether to pay transaction fee continuously + bool isUnlimitedDelegate = 4; +} + +message RemoveTransactionFeeDelegatorInfosInput{ + // the delegator address + aelf.Address delegator_address = 1; + // delegate transaction info (support batch) + repeated delegateTransaction delegate_transaction_list = 2; +} +message delegateTransaction{ + aelf.Address contract_address = 1; + string method_name = 2; +} +message delegateTransactionList{ + repeated delegateTransaction value = 1; +} + +message RemoveTransactionFeeDelegateeInfosInput { + // the delegatee address + aelf.Address delegatee_address = 1; + // delegate transaction info (support batch) + repeated delegateTransaction delegate_transaction_list = 2; +} + +message GetTransactionFeeDelegateInfosOfADelegateeInput { + aelf.Address delegator_address = 1; + aelf.Address delegatee_address = 2; + aelf.Address contract_address = 3; + string method_name = 4; +} +message GetTransactionFeeDelegateInfosInput { + aelf.Address delegator_address = 1; + aelf.Address contract_address = 2; + string method_name = 3; +} +message TransactionFeeDelegateInfoAdded { + option (aelf.is_event) = true; + aelf.Address delegator = 1; + aelf.Address delegatee = 2; + aelf.Address caller = 3; + delegateTransactionList delegate_transaction_list = 4; +} +message TransactionFeeDelegateInfoUpdated { + option (aelf.is_event) = true; + aelf.Address delegator = 1 ; + aelf.Address delegatee = 2 ; + aelf.Address caller = 3 ; + delegateTransactionList delegate_transaction_list = 4; +} + +message TransactionFeeDelegateInfoCancelled { + option (aelf.is_event) = true; + aelf.Address delegator = 1 ; + aelf.Address delegatee = 2 ; + aelf.Address caller = 3 ; +} From 42e46cfa55f1ba8c049cee51dfd78f1d988fd11a Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Tue, 30 May 2023 18:45:34 +0800 Subject: [PATCH 009/139] feat: finished charge transaction fee with secondary delegate and add unit test. --- .../TokenContractState.cs | 2 +- .../TokenContract_Delegation.cs | 257 ++++++ .../TokenContract_Fees.cs | 157 ++-- protobuf/token_contract.proto | 4 +- protobuf/token_contract_impl.proto | 47 +- .../BVT/TokenDelegationTest.cs | 618 ++++++++++++++ .../MultiTokenContractTestBase.cs | 4 + ...t.ExecutionPluginForMethodFee.Tests.csproj | 3 + .../ExecutePluginTransactionDirectlyTest.cs | 762 ++++++++++++++++++ .../ExecutionPluginForMethodFeeTestBase.cs | 9 + 10 files changed, 1764 insertions(+), 99 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState.cs b/contract/AElf.Contracts.MultiToken/TokenContractState.cs index 53f7c21d29..4e5dddc488 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState.cs @@ -58,5 +58,5 @@ public partial class TokenContractState : ContractState /// /// delegator address -> contract address -> method name -> delegatee info /// - public MappedState TransactionFeeDelegateInfoMap { get; set; } + public MappedState TransactionFeeDelegateInfoMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs index b38acad74a..fea03f9016 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs @@ -192,4 +192,261 @@ public override GetTransactionFeeDelegateesOutput GetTransactionFeeDelegatees( DelegateeAddresses = { allDelegatees.Delegatees.Keys.Select(Address.FromBase58) } }; } + + public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateInfosInput input) + { + Assert(input.DelegatorAddress.Value.Any() && input.DelegateInfoList.Count > 0, + "Delegator address and delegate info cannot be null."); + var toAddTransactionList = new DelegateTransactionList(); + var toUpdateTransactionList = new DelegateTransactionList(); + var toCancelTransactionList = new DelegateTransactionList(); + var delegatorAddress = input.DelegatorAddress; + foreach (var delegateInfo in input.DelegateInfoList) + { + //If isUnlimitedDelegate is false,delegate info list should > 0. + Assert(delegateInfo.IsUnlimitedDelegate || delegateInfo.Delegations.Count > 0, + "Delegation cannot be null."); + var existDelegateeInfoList = + State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateInfo.ContractAddress] + [delegateInfo.MethodName] ?? new TransactionFeeDelegatees(); + var delegateeAddress = Context.Sender.ToBase58(); + var existDelegateeList = existDelegateeInfoList.Delegatees; + //If the transaction contains delegatee,update delegate info. + if (existDelegateeList.TryGetValue(delegateeAddress, out var value)) + { + UpdateDelegateInfo(ref value, ref toUpdateTransactionList,delegateInfo); + existDelegateeList[delegateeAddress] = value; + } //else,add new delegate info. + else + { + Assert(existDelegateeList.Count <= TokenContractConstants.DELEGATEE_MAX_COUNT, + "The quantity of delegatee has reached its limit"); + existDelegateeList.Add(delegateeAddress, new TransactionFeeDelegations()); + var transactionFeeDelegations = existDelegateeList[delegateeAddress]; + AddDelegateInfo(ref transactionFeeDelegations,ref toAddTransactionList,delegateInfo); + } + + if (existDelegateeInfoList.Delegatees[delegateeAddress].Delegations.Count == 0 && + !existDelegateeInfoList.Delegatees[delegateeAddress].IsUnlimitedDelegate) + { + existDelegateeInfoList.Delegatees.Remove(delegateeAddress); + toCancelTransactionList.Value.Add(new DelegateTransaction + { + ContractAddress = delegateInfo.ContractAddress, + MethodName = delegateInfo.MethodName + }); + } + + State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateInfo.ContractAddress] + [delegateInfo.MethodName] = existDelegateeInfoList; + } + + FireLogEvent(toAddTransactionList, toUpdateTransactionList, toCancelTransactionList, delegatorAddress); + + return new Empty(); + } + + private void AddDelegateInfo(ref TransactionFeeDelegations existDelegateeList,ref DelegateTransactionList toAddTransactionList,DelegateInfo delegateInfo) + { + if (!delegateInfo.IsUnlimitedDelegate) + { + foreach (var (symbol, amount) in delegateInfo.Delegations) + { + AssertValidToken(symbol, amount); + existDelegateeList.Delegations[symbol] = amount; + } + } + + existDelegateeList.BlockHeight = Context.CurrentHeight; + existDelegateeList.IsUnlimitedDelegate = delegateInfo.IsUnlimitedDelegate; + toAddTransactionList.Value.Add(new DelegateTransaction + { + ContractAddress = delegateInfo.ContractAddress, + MethodName = delegateInfo.MethodName + }); + } + private void UpdateDelegateInfo(ref TransactionFeeDelegations existDelegateInfo,ref DelegateTransactionList toUpdateTransactionList,DelegateInfo delegateInfo) + { + var existDelegation = existDelegateInfo.Delegations; + if (delegateInfo.IsUnlimitedDelegate) + { + existDelegation.Clear(); + } + else + { + var delegation = delegateInfo.Delegations; + foreach (var (symbol, amount) in delegation) + { + if (existDelegation.ContainsKey(symbol)) + { + if (amount < 0) + { + existDelegation.Remove(symbol); + } + else + { + AssertValidToken(symbol, amount); + existDelegation[symbol] = amount; + } + } + else + { + AssertValidToken(symbol, amount); + existDelegation[symbol] = amount; + } + } + } + + existDelegateInfo.BlockHeight = Context.CurrentHeight; + existDelegateInfo.IsUnlimitedDelegate = delegateInfo.IsUnlimitedDelegate; + toUpdateTransactionList.Value.Add(new DelegateTransaction + { + ContractAddress = delegateInfo.ContractAddress, + MethodName = delegateInfo.MethodName + }); + } + private void FireLogEvent(DelegateTransactionList toAddTransactionList, + DelegateTransactionList toUpdateTransactionList, DelegateTransactionList toCancelTransactionList, + Address delegatorAddress) + { + if (toAddTransactionList.Value.Count > 0) + { + Context.Fire(new TransactionFeeDelegateInfoAdded + { + Caller = Context.Sender, + Delegatee = Context.Sender, + Delegator = delegatorAddress, + DelegateTransactionList = toAddTransactionList + }); + } + + if (toUpdateTransactionList.Value.Count > 0) + { + Context.Fire(new TransactionFeeDelegateInfoUpdated + { + Caller = Context.Sender, + Delegatee = Context.Sender, + Delegator = delegatorAddress, + DelegateTransactionList = toUpdateTransactionList + }); + } + + if (toCancelTransactionList.Value.Count > 0) + { + Context.Fire(new TransactionFeeDelegateInfoCancelled + { + Caller = Context.Sender, + Delegatee = Context.Sender, + Delegator = delegatorAddress, + DelegateTransactionList = toCancelTransactionList + }); + } + } + + public override Empty RemoveTransactionFeeDelegateeInfos(RemoveTransactionFeeDelegateeInfosInput input) + { + Assert(input.DelegateeAddress != null, "Delegatee address cannot be null."); + Assert(input.DelegateTransactionList.Count > 0, "Delegate transaction list should not be null."); + var delegateTransactionList = input.DelegateTransactionList; + var delegatorAddress = Context.Sender; + var delegateeAddress = input.DelegateeAddress.ToBase58(); + var toCancelTransactionList = new DelegateTransactionList(); + foreach (var delegateTransaction in delegateTransactionList.ToList().Distinct()) + { + var delegateeInfo = + State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ + delegateTransaction.MethodName]; + if (delegateeInfo != null && delegateeInfo.Delegatees.ContainsKey(delegateeAddress)) + { + delegateeInfo.Delegatees.Remove(delegateeAddress); + toCancelTransactionList.Value.Add(delegateTransaction); + } + + State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ + delegateTransaction.MethodName] = delegateeInfo; + } + + if (toCancelTransactionList.Value.Count > 0) + { + Context.Fire(new TransactionFeeDelegateInfoCancelled + { + Caller = Context.Sender, + Delegatee = input.DelegateeAddress, + Delegator = Context.Sender, + DelegateTransactionList = toCancelTransactionList + }); + } + + return new Empty(); + } + + public override Empty RemoveTransactionFeeDelegatorInfos(RemoveTransactionFeeDelegatorInfosInput input) + { + Assert(input.DelegatorAddress != null, "Delegator address cannot be null."); + Assert(input.DelegateTransactionList.Count > 0, "Delegate transaction list should not be null."); + var delegateTransactionList = input.DelegateTransactionList; + var delegateeAddress = Context.Sender.ToBase58(); + var delegatorAddress = input.DelegatorAddress; + var toCancelTransactionList = new DelegateTransactionList(); + foreach (var delegateTransaction in delegateTransactionList.ToList().Distinct()) + { + var delegateeInfo = + State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ + delegateTransaction.MethodName]; + if (delegateeInfo != null && delegateeInfo.Delegatees.ContainsKey(delegateeAddress)) + { + delegateeInfo.Delegatees.Remove(delegateeAddress); + toCancelTransactionList.Value.Add(delegateTransaction); + } + + State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ + delegateTransaction.MethodName] = delegateeInfo; + } + + if (toCancelTransactionList.Value.Count > 0) + { + Context.Fire(new TransactionFeeDelegateInfoCancelled + { + Caller = Context.Sender, + Delegatee = input.DelegatorAddress, + Delegator = Context.Sender, + DelegateTransactionList = toCancelTransactionList + }); + } + + return new Empty(); + } + + public override GetTransactionFeeDelegateeListOutput GetTransactionFeeDelegateeList( + GetTransactionFeeDelegateeListInput input) + { + Assert(input.DelegatorAddress != null && input.ContractAddress != null && input.MethodName != null, + "invalid input"); + var allDelegatees = + State.TransactionFeeDelegateInfoMap[input.DelegatorAddress][input.ContractAddress][input.MethodName]; + + if (allDelegatees == null || allDelegatees.Delegatees == null || allDelegatees.Delegatees.Count == 0) + { + return new GetTransactionFeeDelegateeListOutput(); + } + + return new GetTransactionFeeDelegateeListOutput + { + DelegateeAddresses = { allDelegatees.Delegatees.Keys.Select(Address.FromBase58) } + }; + } + + public override TransactionFeeDelegations GetTransactionFeeDelegateInfosOfADelegatee( + GetTransactionFeeDelegateInfosOfADelegateeInput input) + { + var allDelegatees = + State.TransactionFeeDelegateInfoMap[input.DelegatorAddress][input.ContractAddress][input.MethodName]; + var delegateeAddress = input.DelegateeAddress.ToBase58(); + // According to protoBuf, return an empty object, but null. + if (allDelegatees == null) return new TransactionFeeDelegations(); + + var allDelegateesMap = allDelegatees.Delegatees; + var result = allDelegateesMap.TryGetValue(delegateeAddress, out var value); + return result ? value : new TransactionFeeDelegations(); + } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 1da9b80a2d..a4ff9056a6 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -56,7 +56,7 @@ public override ChargeTransactionFeesOutput ChargeUserContractTransactionFees(Ch // Primary token not created yet. if (State.ChainPrimaryTokenSymbol.Value == null) { - return new ChargeTransactionFeesOutput {Success = true}; + return new ChargeTransactionFeesOutput { Success = true }; } // Record tx fee bill during current charging process. @@ -89,20 +89,26 @@ private ChargeTransactionFeesOutput TryToChargeTransactionFee(ChargeTransactionF { var delegatorAddress = fromAddress; chargingResult = ChargeFromDelegations(input, ref fromAddress, ref bill, ref allowanceBill, fee, - isSizeFeeFree,delegatorAddress); + isSizeFeeFree, delegatorAddress); } + if (!chargingResult) { - var delegateeAddress = State.TransactionFeeDelegateesMap[fromAddress].Delegatees; - foreach (var (delegatee,_) in delegateeAddress) + var transactionFeeDelegatees = State.TransactionFeeDelegateesMap[fromAddress] ?? + State.TransactionFeeDelegateInfoMap[fromAddress][input.ContractAddress][input.MethodName]; + if (transactionFeeDelegatees != null) { - ChargeFromDelegations(input, ref fromAddress, ref bill, ref allowanceBill, fee, - isSizeFeeFree,Address.FromBase58(delegatee)); + var delegateeAddress = transactionFeeDelegatees.Delegatees; + foreach (var (delegatee, _) in delegateeAddress) + { + chargingResult = ChargeFromDelegations(input, ref fromAddress, ref bill, ref allowanceBill, fee, + isSizeFeeFree, Address.FromBase58(delegatee)); + } } } ModifyBalance(fromAddress, bill, allowanceBill); - var chargingOutput = new ChargeTransactionFeesOutput {Success = chargingResult}; + var chargingOutput = new ChargeTransactionFeesOutput { Success = chargingResult }; if (!chargingResult) chargingOutput.ChargingInformation = "Transaction fee not enough."; return chargingOutput; @@ -149,64 +155,64 @@ private UserContractMethodFees GetActualFee(Address contractAddress, string meth private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address fromAddress, ref TransactionFeeBill bill, ref TransactionFreeFeeAllowanceBill allowanceBill, - Dictionary fee, bool isSizeFeeFree,Address delegatorAddress) + Dictionary fee, bool isSizeFeeFree, Address delegatorAddress) { var chargingResult = false; // Try to charge delegatees // Get delegatee list according to the delegator - if (State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees == null) return false; - if (State.TransactionFeeDelegateesMap[delegatorAddress].Delegatees != null) + if ((State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees == null) && + (State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][input.MethodName]?.Delegatees == null)) { - foreach (var (delegatee, delegations) in State.TransactionFeeDelegateesMap[delegatorAddress].Delegatees) - { - // compare current block height with the block height when the delegatee added - if (Context.Transaction.RefBlockNumber < delegations.BlockHeight) continue; - - var delegateeBill = new TransactionFeeBill(); - var delegateeAllowanceBill = new TransactionFreeFeeAllowanceBill(); - var delegateeAddress = Address.FromBase58(delegatee); - var delegateeChargingResult = ChargeTransactionFeesToBill(input, delegateeAddress, - ref delegateeBill, ref delegateeAllowanceBill, fee, isSizeFeeFree, delegations); - - if (!delegateeChargingResult) continue; - - bill = delegateeBill; - allowanceBill = delegateeAllowanceBill; - fromAddress = delegateeAddress; - chargingResult = true; - ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress); - break; - } + return false; } + var delegationInfo = State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees ?? + State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][ + input.MethodName]?.Delegatees; + foreach (var (delegatee, delegations) in delegationInfo) + { + // compare current block height with the block height when the delegatee added + if (Context.Transaction.RefBlockNumber < delegations.BlockHeight) continue; + + var delegateeBill = new TransactionFeeBill(); + var delegateeAllowanceBill = new TransactionFreeFeeAllowanceBill(); + var delegateeAddress = Address.FromBase58(delegatee); + var delegateeChargingResult = ChargeTransactionFeesToBill(input, delegateeAddress, + ref delegateeBill, ref delegateeAllowanceBill, fee, isSizeFeeFree, delegations); + + if (!delegateeChargingResult) continue; + + bill = delegateeBill; + allowanceBill = delegateeAllowanceBill; + fromAddress = delegateeAddress; + chargingResult = true; + ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress, input.ContractAddress, input.MethodName,delegatorAddress); + break; + } + + return chargingResult; } private void ModifyDelegation(TransactionFeeBill bill, TransactionFreeFeeAllowanceBill allowanceBill, - Address delegateeAddress) + Address delegateeAddress,Address contractAddress,string methodName,Address delegatorAddress) { foreach (var (symbol, amount) in bill.FeesMap) { - if (amount > 0) - { - State.TransactionFeeDelegateesMap[Context.Sender].Delegatees[delegateeAddress.ToBase58()] - .Delegations[symbol] = - State.TransactionFeeDelegateesMap[Context.Sender].Delegatees[delegateeAddress.ToBase58()] - .Delegations[symbol] - .Sub(amount); - } + if (amount <= 0) continue; + var delegateInfo = State.TransactionFeeDelegateesMap[delegatorAddress] ?? + State.TransactionFeeDelegateInfoMap[delegatorAddress][contractAddress][methodName]; + delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol] = + delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol].Sub(amount); } - + foreach (var (symbol, amount) in allowanceBill.FreeFeeAllowancesMap) { - if (amount > 0) - { - State.TransactionFeeDelegateesMap[Context.Sender].Delegatees[delegateeAddress.ToBase58()] - .Delegations[symbol] = - State.TransactionFeeDelegateesMap[Context.Sender].Delegatees[delegateeAddress.ToBase58()] - .Delegations[symbol] - .Sub(amount); - } + if (amount <= 0) continue; + var delegateInfo = State.TransactionFeeDelegateesMap[Context.Sender] ?? + State.TransactionFeeDelegateInfoMap[Context.Sender][contractAddress][methodName]; + delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol] = + delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol].Sub(amount); } } @@ -256,6 +262,7 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre successToChargeBaseFee = ChargeBaseFee(fee, fromAddress, ref bill, freeAllowances, ref allowanceBill, delegations); } + //For delegation, if the base fee fails to be charged, the size fee will not be charged if (delegations != null && !successToChargeBaseFee) { @@ -357,7 +364,8 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress { var allSymbolToTxFee = input.SymbolsToPayTxSizeFee.ToList(); var availableSymbol = GetAvailableSymbolToPayTxFee(allSymbolToTxFee, fromAddress, txSizeFeeAmount, - freeAllowances, symbolChargedForBaseFee, amountChargedForBaseFee, amountChargedForBaseAllowance, delegations); + freeAllowances, symbolChargedForBaseFee, amountChargedForBaseFee, amountChargedForBaseAllowance, + delegations); if (availableSymbol != null && availableSymbol.TokenSymbol != symbolToPayTxFee) { @@ -368,6 +376,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress out symbolChargedForBaseFee, out amountChargedForBaseFee, out amountChargedForBaseAllowance, out availableBalance, out availableAllowance); } + //For delegation,if there is no available token,return false,no need to generate bill if (delegations != null && availableSymbol == null) { @@ -431,11 +440,11 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List= txSizeFeeAmount; }) ?? allSymbolToTxFee.FirstOrDefault(x => - { - var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, - symbolChargedForBaseFee, amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance); - return balance > 0; - }); + { + var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, + symbolChargedForBaseFee, amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance); + return balance > 0; + }); } else { @@ -639,18 +648,20 @@ public override Empty SetSymbolsToPayTxSizeFee(SymbolListToPayTxSizeFee input) /// /// private bool ChargeFirstSufficientToken(Dictionary symbolToAmountMap, Address fromAddress, - out string symbol, out long amount, out long existingBalance, out long existingAllowance, MethodFeeFreeAllowances freeAllowances, + out string symbol, out long amount, out long existingBalance, out long existingAllowance, + MethodFeeFreeAllowances freeAllowances, TransactionFeeDelegations delegations = null) { symbol = null; amount = 0L; existingBalance = 0L; existingAllowance = 0L; - - symbol = GetAvailableSymbolToPayBaseFee(symbolToAmountMap, fromAddress, freeAllowances, out amount, delegations); + + symbol = GetAvailableSymbolToPayBaseFee(symbolToAmountMap, fromAddress, freeAllowances, out amount, + delegations); //Whether or not delegation exists, there is no token that can be used for payment if (symbol == null) return false; - + //For delegation, There is enough token balance and delegation to pay //For user, There is enough token balance to pay or there is a token balance greater than 0 existingBalance = GetBalance(fromAddress, symbol); @@ -673,7 +684,7 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM return false; } - + private string GetAvailableSymbolToPayBaseFee(Dictionary symbolToAmountMap, Address fromAddress, MethodFeeFreeAllowances freeAllowances, out long amount, TransactionFeeDelegations delegations = null) { @@ -709,13 +720,19 @@ private string GetAvailableSymbolToPayBaseFee(Dictionary symbolToA amount = value; var existingBalance = GetBalance(fromAddress, symbol); var existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); - if (!delegations.Delegations.ContainsKey(symbol) || delegations.Delegations[symbol] < amount || - existingBalance.Add(existingAllowance) < amount) continue; - symbolOfValidBalance = symbol; - break; + // is unlimited delegate is true && balance enough + // is unlimited delegate is false && delegation enough && balance enough + if ((delegations.IsUnlimitedDelegate && existingBalance.Add(existingAllowance) >= amount) || + (!delegations.IsUnlimitedDelegate && delegations.Delegations.ContainsKey(symbol) && + delegations.Delegations[symbol] > amount && + existingBalance.Add(existingAllowance) >= amount)) + { + symbolOfValidBalance = symbol; + break; + } } } - + return symbolOfValidBalance; } @@ -1153,10 +1170,14 @@ private bool IsDelegationEnoughBaseOnPrimaryToken(SymbolToPayTxSizeFee tokenInfo private bool IsDelegationEnough(string txSymbol, string baseSymbol, long cost, long txSizeFeeAmount, TransactionFeeDelegations delegations) { - return delegations.Delegations.Keys.Contains(txSymbol) && - (baseSymbol == txSymbol - ? delegations.Delegations[txSymbol].Sub(cost) - : delegations.Delegations[txSymbol]) >= txSizeFeeAmount; + if (!delegations.IsUnlimitedDelegate) + { + return delegations.Delegations.Keys.Contains(txSymbol) && (baseSymbol == txSymbol + ? delegations.Delegations[txSymbol].Sub(cost) + : delegations.Delegations[txSymbol]) >= txSizeFeeAmount; + } + + return true; } private void AssertSymbolToPayTxFeeIsValid(string tokenSymbol, out long totalSupply) diff --git a/protobuf/token_contract.proto b/protobuf/token_contract.proto index b3c13d254b..78849c4583 100644 --- a/protobuf/token_contract.proto +++ b/protobuf/token_contract.proto @@ -153,7 +153,7 @@ service TokenContract { // Get all delegatees' address of delegator from input rpc GetTransactionFeeDelegatees (GetTransactionFeeDelegateesInput) returns (GetTransactionFeeDelegateesOutput) { - + option (aelf.is_view) = true; } // Query token information. @@ -681,6 +681,8 @@ message TransactionFeeDelegations{ map delegations = 1; // height when added int64 block_height = 2; + //Whether to pay transaction fee continuously + bool isUnlimitedDelegate = 3; } message TransactionFeeDelegatees{ diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index b0f292dd38..ce5346b9b3 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -141,12 +141,12 @@ service TokenContractImpl { option (aelf.is_view) = true; } - // Get delegation according to the delegator,transaction and delegatee. - rpc GetTransactionFeeDelegateInfos (GetTransactionFeeDelegateInfosInput) returns (TransactionFeeDelegateInfo) { + // Get delegatee info list according to the delegator and transaction. + rpc GetTransactionFeeDelegateeList (GetTransactionFeeDelegateeListInput) returns (GetTransactionFeeDelegateeListOutput) { option (aelf.is_view) = true; } - // Get delegatee info list according to the delegator and transaction. - rpc GetTransactionFeeDelegateInfosOfADelegatee(GetTransactionFeeDelegateInfosOfADelegateeInput) returns (TransactionFeeDelegatee){ + // Get delegation according to the delegator,transaction and delegatee. + rpc GetTransactionFeeDelegateInfosOfADelegatee(GetTransactionFeeDelegateInfosOfADelegateeInput) returns (token.TransactionFeeDelegations){ option (aelf.is_view) = true; } } @@ -266,28 +266,13 @@ enum SymbolType { NFT_COLLECTION = 2; } -message TransactionFeeDelegateInfo{ - // delegation, symbols and its' amount - map delegations = 1; - // height when added - int64 block_height = 2; - //Whether to pay transaction fee continuously - bool isUnlimitedDelegate = 3; -} - -message TransactionFeeDelegatee{ - //delegatee -> delegate info - map delegatees = 1; -} - - message SetTransactionFeeDelegateInfosInput{ // the delegator address aelf.Address delegator_address = 1; //delegate info list (support batch) - repeated delegateInfo delegate_info_list = 2; + repeated DelegateInfo delegate_info_list = 2; } -message delegateInfo{ +message DelegateInfo{ //symbol->amount map delegations = 1; aelf.Address contract_address = 2; @@ -300,21 +285,21 @@ message RemoveTransactionFeeDelegatorInfosInput{ // the delegator address aelf.Address delegator_address = 1; // delegate transaction info (support batch) - repeated delegateTransaction delegate_transaction_list = 2; + repeated DelegateTransaction delegate_transaction_list = 2; } -message delegateTransaction{ +message DelegateTransaction{ aelf.Address contract_address = 1; string method_name = 2; } -message delegateTransactionList{ - repeated delegateTransaction value = 1; +message DelegateTransactionList{ + repeated DelegateTransaction value = 1; } message RemoveTransactionFeeDelegateeInfosInput { // the delegatee address aelf.Address delegatee_address = 1; // delegate transaction info (support batch) - repeated delegateTransaction delegate_transaction_list = 2; + repeated DelegateTransaction delegate_transaction_list = 2; } message GetTransactionFeeDelegateInfosOfADelegateeInput { @@ -323,24 +308,27 @@ message GetTransactionFeeDelegateInfosOfADelegateeInput { aelf.Address contract_address = 3; string method_name = 4; } -message GetTransactionFeeDelegateInfosInput { +message GetTransactionFeeDelegateeListInput { aelf.Address delegator_address = 1; aelf.Address contract_address = 2; string method_name = 3; } +message GetTransactionFeeDelegateeListOutput { + repeated aelf.Address delegatee_addresses = 1; +} message TransactionFeeDelegateInfoAdded { option (aelf.is_event) = true; aelf.Address delegator = 1; aelf.Address delegatee = 2; aelf.Address caller = 3; - delegateTransactionList delegate_transaction_list = 4; + DelegateTransactionList delegate_transaction_list = 4; } message TransactionFeeDelegateInfoUpdated { option (aelf.is_event) = true; aelf.Address delegator = 1 ; aelf.Address delegatee = 2 ; aelf.Address caller = 3 ; - delegateTransactionList delegate_transaction_list = 4; + DelegateTransactionList delegate_transaction_list = 4; } message TransactionFeeDelegateInfoCancelled { @@ -348,4 +336,5 @@ message TransactionFeeDelegateInfoCancelled { aelf.Address delegator = 1 ; aelf.Address delegatee = 2 ; aelf.Address caller = 3 ; + DelegateTransactionList delegate_transaction_list = 4; } diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs index ad8baa382d..fd66f9aee6 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs @@ -2,7 +2,9 @@ using System.Linq; using System.Threading.Tasks; using AElf.Types; +using Google.Protobuf.Collections; using Shouldly; +using Volo.Abp; using Xunit; namespace AElf.Contracts.MultiToken; @@ -307,4 +309,620 @@ await TokenContractStubUser.SetTransactionFeeDelegations.SendAsync(new SetTransa output.DelegateeAddresses[0].ShouldBe(DefaultAddress); output.DelegateeAddresses[1].ShouldBe(User1Address); } + + [Fact] + public async Task SetDelegateInfos_NewDelegate_Success_Test() + { + await Initialize(); + var delegations1 = new Dictionary + { + [NativeToken] = 1000, + [BasicFeeSymbol] = 500, + [SizeFeeSymbol] = 100 + }; + var delegations2 = new Dictionary + { + [NativeToken] = 100 + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + Delegations = + { + delegations1 + }, + IsUnlimitedDelegate = false + }; + var delegateInfo2 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test2", + Delegations = + { + delegations2 + }, + IsUnlimitedDelegate = false + }; + var delegateInfo3 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test3", + Delegations = + { + delegations2 + }, + IsUnlimitedDelegate = true + }; + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo3 } + }); + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(1000); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(500); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test2" + }); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(100); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test3" + }); + delegateInfoOfADelegatee.Delegations.ShouldBeEmpty(); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeTrue(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var log = TransactionFeeDelegateInfoAdded.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoAdded))?.NonIndexed); + log.Delegator.ShouldBe(User1Address); + log.Delegatee.ShouldBe(DefaultAddress); + log.DelegateTransactionList.Value.Count.ShouldBe(3); + log.DelegateTransactionList.Value[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); + log.DelegateTransactionList.Value[0].MethodName.ShouldBe("test1"); + log.DelegateTransactionList.Value[1].ContractAddress.ShouldBe(BasicFunctionContractAddress); + log.DelegateTransactionList.Value[1].MethodName.ShouldBe("test2"); + log.DelegateTransactionList.Value[2].ContractAddress.ShouldBe(BasicFunctionContractAddress); + log.DelegateTransactionList.Value[2].MethodName.ShouldBe("test3"); + } + + } + [Fact] + public async Task SetDelegateInfos_NewOrUpdateDelegate_Success_Test() + { + await SetDelegateInfos_NewDelegate_Success_Test(); + var newDelegations = new Dictionary + { + [NativeToken] = 10, + [BasicFeeSymbol] = 20 + }; + var delegations2 = new Dictionary + { + [NativeToken] = 100, + [SizeFeeSymbol] = 30 + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicContractZeroAddress, + MethodName = "test1", + Delegations = + { + newDelegations + }, + IsUnlimitedDelegate = false + }; + var delegateInfo2 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test2", + Delegations = + { + delegations2 + }, + IsUnlimitedDelegate = false + }; + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1,delegateInfo2 } + }); + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicContractZeroAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(10); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(20); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test2" + }); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(100); + delegateInfoOfADelegatee.Delegations[SizeFeeSymbol].ShouldBe(30); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var log = TransactionFeeDelegateInfoAdded.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoAdded))?.NonIndexed); + log.Delegator.ShouldBe(User1Address); + log.Delegatee.ShouldBe(DefaultAddress); + log.DelegateTransactionList.Value.Count.ShouldBe(1); + log.DelegateTransactionList.Value[0].ContractAddress.ShouldBe(BasicContractZeroAddress); + log.DelegateTransactionList.Value[0].MethodName.ShouldBe("test1"); + } + { + var log = TransactionFeeDelegateInfoUpdated.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoUpdated))?.NonIndexed); + log.Delegator.ShouldBe(User1Address); + log.Delegatee.ShouldBe(DefaultAddress); + log.DelegateTransactionList.Value.Count.ShouldBe(1); + log.DelegateTransactionList.Value[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); + log.DelegateTransactionList.Value[0].MethodName.ShouldBe("test2"); + } + + } + [Fact] + public async Task SetDelegateInfos_UpdateDelegate_Success_Test() + { + await SetDelegateInfos_NewDelegate_Success_Test(); + var delegations1 = new Dictionary + { + [NativeToken] = 300, + [BasicFeeSymbol] = 200, + [SizeFeeSymbol] = 100 + }; + var delegations3 = new Dictionary + { + [NativeToken] = 100, + [BasicFeeSymbol] = 200, + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + Delegations = + { + delegations1 + }, + IsUnlimitedDelegate = false + }; + var delegateInfo2 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test2", + IsUnlimitedDelegate = true + }; + var delegateInfo3 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test3", + Delegations = + { + delegations3 + }, + IsUnlimitedDelegate = false + }; + await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo3 } + }); + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(300); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(200); + delegateInfoOfADelegatee.Delegations[SizeFeeSymbol].ShouldBe(100); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test2" + }); + delegateInfoOfADelegatee.Delegations.ShouldBeEmpty(); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeTrue(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test3" + }); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(100); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(200); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + + } + [Fact] + public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test() + { + await SetDelegateInfos_NewDelegate_Success_Test(); + var delegations1 = new Dictionary + { + [NativeToken] = 300, + [BasicFeeSymbol] = 200, + [SizeFeeSymbol] = -1 + }; + var delegations2 = new Dictionary + { + [NativeToken] = -1, + [BasicFeeSymbol] = 200, + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + Delegations = + { + delegations1 + }, + IsUnlimitedDelegate = false + }; + var delegateInfo2 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test2", + Delegations = + { + delegations2 + }, + IsUnlimitedDelegate = false + }; + await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1,delegateInfo2 } + }); + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.Delegations.Count.ShouldBe(2); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(300); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(200); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test2" + }); + delegateInfoOfADelegatee.Delegations.Count.ShouldBe(1); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(200); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + } + [Fact] + public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegateInfo_Success_Test() + { + await SetDelegateInfos_NewDelegate_Success_Test(); + var delegations1 = new Dictionary + { + [NativeToken] = -1, + [BasicFeeSymbol] = -1, + [SizeFeeSymbol] = -1 + }; + var delegations2 = new Dictionary + { + [NativeToken] = -1, + [BasicFeeSymbol] = 200, + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + Delegations = + { + delegations1 + }, + IsUnlimitedDelegate = false + }; + var delegateInfo2 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test2", + Delegations = + { + delegations2 + }, + IsUnlimitedDelegate = false + }; + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1,delegateInfo2 } + }); + { + var delegateeAddress = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + MethodName = "test1" + }); + delegateeAddress.DelegateeAddresses.Count.ShouldBe(0); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateeAddress = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + MethodName = "test2" + }); + delegateeAddress.DelegateeAddresses.Count.ShouldBe(1); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test2" + }); + delegateInfoOfADelegatee.Delegations.Count.ShouldBe(1); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(200); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var log = TransactionFeeDelegateInfoCancelled.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoCancelled))?.NonIndexed); + log.Delegator.ShouldBe(User1Address); + log.Delegatee.ShouldBe(DefaultAddress); + log.DelegateTransactionList.Value.Count.ShouldBe(1); + log.DelegateTransactionList.Value[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); + log.DelegateTransactionList.Value[0].MethodName.ShouldBe("test1"); + } + } + + [Fact] + public async Task RemoveTransactionFeeDelegateeInfos_Success_Test() + { + await SetDelegateInfos_NewDelegate_Success_Test(); + var delegations1 = new Dictionary + { + [NativeToken] = 300, + [BasicFeeSymbol] = 200 + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + Delegations = + { + delegations1 + }, + IsUnlimitedDelegate = false + }; + await TokenContractStubDelegate.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1 } + }); + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(1000); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(500); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1" + }, + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test3" + } + }; + await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new RemoveTransactionFeeDelegateeInfosInput + { + DelegateeAddress = DefaultAddress, + DelegateTransactionList = { delegationTransactionList } + }); + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test2" + }); + delegateInfoOfADelegatee.Delegations[NativeToken] = 100; + delegateInfoOfADelegatee.IsUnlimitedDelegate = false; + } + { + var delegateeAddress = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + MethodName = "test1" + }); + delegateeAddress.DelegateeAddresses.Count.ShouldBe(1); + delegateeAddress.DelegateeAddresses[0].ShouldBe(User2Address); + } + } + [Fact] + public async Task RemoveTransactionFeeDelegatorInfos_Success_Test() + { + await SetDelegateInfos_NewDelegate_Success_Test(); + var delegations1 = new Dictionary + { + [NativeToken] = 300, + [BasicFeeSymbol] = 200 + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + Delegations = + { + delegations1 + }, + IsUnlimitedDelegate = false + }; + await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User2Address, + DelegateInfoList = { delegateInfo1 } + }); + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1" + }, + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test3" + } + }; + await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendAsync(new RemoveTransactionFeeDelegatorInfosInput + { + DelegatorAddress = User1Address, + DelegateTransactionList = { delegationTransactionList } + }); + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test2" + }); + delegateInfoOfADelegatee.Delegations[NativeToken] = 100; + delegateInfoOfADelegatee.IsUnlimitedDelegate = false; + } + { + var delegateeAddress = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User2Address, + MethodName = "test1" + }); + delegateeAddress.DelegateeAddresses.Count.ShouldBe(1); + delegateeAddress.DelegateeAddresses[0].ShouldBe(DefaultAddress); + } + } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs index 819e5f825d..427167bfef 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs @@ -24,6 +24,7 @@ public class MultiTokenContractTestBase : ContractTestBase(TokenContractAddress, DefaultKeyPair); TokenContractStubUser = GetTester(TokenContractAddress, User1KeyPair); + TokenContractStubDelegate = + GetTester(TokenContractAddress, User2KeyPair); Acs2BaseStub = GetTester(TokenContractAddress, DefaultKeyPair); TreasuryContractStub = GetTester( @@ -62,6 +65,7 @@ public MultiTokenContractTestBase() protected Address DefaultAddress => Accounts[0].Address; protected ECKeyPair User1KeyPair => Accounts[10].KeyPair; protected Address User1Address => Accounts[10].Address; + protected ECKeyPair User2KeyPair => Accounts[11].KeyPair; protected Address User2Address => Accounts[11].Address; protected List InitialCoreDataCenterKeyPairs => diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj index 17473c3736..8d091828d7 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj @@ -107,6 +107,9 @@ Protobuf\Proto\token_contract.proto + + Protobuf\Proto\token_contract_impl.proto + Protobuf\Proto\acs1_plugin_test_contract.proto diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index a72b124533..3bcceb1275 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -988,6 +988,768 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } + [Theory] + [InlineData(1000, 1000, 1000, 1000, 1000, 1000, 1000, 50, 50, 100, 100, 50, 50, 10, 10, 80, 80, 50, 30, 920)] + public async Task ChargeTransactionFee_DelegateNew_First( + long threshold, long initialBalance, long initialDelegateeBalance, long initialUserBalance, + long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, + long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, + long baseFeeUserBalance, long sizeFeeUserBalance, long baseFeeFreeAmount, long sizeFeeFreeAmount, + long basicFee, long sizeFee, long afterBalanceDefault, long afterBalanceDelegatee, long afterDelegateeAmount + ) + { + var basicFeeSymbol = "BASIC"; + var sizeFeeSymbol = "SIZE"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, basicFeeSymbol); + await CreateTokenAsync(DefaultSender, sizeFeeSymbol); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialUserBalance, userAddress); + + var delegations = new Dictionary + { + [NativeTokenSymbol] = delegateeAmountNativeToken, + [basicFeeSymbol] = delegateeAmountBasic, + [sizeFeeSymbol] = delegateeAmountSize + }; + var delegateInfo1 = new DelegateInfo + { + Delegations = { delegations }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; + var transactionResult = await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DefaultSender, + DelegateInfoList = { delegateInfo1 } + }); + // Test Case 11 + { + var result = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + result.BlockHeight.ShouldBe(transactionResult.TransactionResult.BlockNumber); + result.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); + } + + if (baseFeeBalance != 0 && sizeFeeBalance != 0 && + baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && + baseFeeUserBalance != 0 && sizeFeeUserBalance != 0) + { + await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); + await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeUserBalance, userAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeUserBalance, userAddress); + } + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + { + FreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = basicFeeSymbol, + Amount = baseFeeFreeAmount + }, + new MethodFeeFreeAllowance + { + Symbol = sizeFeeSymbol, + Amount = sizeFeeFreeAmount + } + } + }, + RefreshSeconds = 100, + Threshold = threshold + }); + { + var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(userAddress); + if (threshold <= initialBalance) + { + freeAllowances.Value.First().Symbol.ShouldBe(basicFeeSymbol); + freeAllowances.Value.First().Amount.ShouldBe(baseFeeFreeAmount); + freeAllowances.Value.Last().Symbol.ShouldBe(sizeFeeSymbol); + freeAllowances.Value.Last().Amount.ShouldBe(sizeFeeFreeAmount); + } + else + { + freeAllowances.Value.ShouldBeEmpty(); + } + } + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = basicFeeSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = sizeFeeSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + { + var chargeFeeRetUser = await TokenContractStub3.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRetUser.Output.Success.ShouldBe(false); + chargeFeeRetUser.Output.ChargingInformation.ShouldBe("Transaction fee not enough."); + + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = userAddress + }); + afterBalance.Balance.ShouldBe(0); + } + // Test Case 12 + { + var delegationResult = + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + var chargeFeeRetDefault = + await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2) + { + chargeFeeRetDefault.Output.Success.ShouldBe(true); + + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = DefaultSender + }); + afterBalance.Balance.ShouldBe(afterBalanceDefault); + + var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = delegateeAddress + }); + afterDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); + } + else + { + chargeFeeRetDefault.Output.Success.ShouldBe(false); + + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); + } + } + } + + [Theory] + [InlineData( 10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] + public async Task ChargeTransactionFee_DelegationNew_Second_Success( + long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, + long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, + long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, + long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, + long basicFee, long sizeFee, long afterBalanceDelegatee, long afterDelegateeAmount) + { + var basicFeeSymbol = "BASIC"; + var sizeFeeSymbol = "SIZE"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, basicFeeSymbol); + await CreateTokenAsync(DefaultSender, sizeFeeSymbol); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); + if (baseFeeBalance != 0 && sizeFeeBalance != 0 && + baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && + baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) + { + await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); + await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); + } + + var delegations = new Dictionary + { + [NativeTokenSymbol] = 5, + }; + var delegations2 = new Dictionary + { + [NativeTokenSymbol] = delegateeAmountNativeToken, + [basicFeeSymbol] = delegateeAmountBasic, + [sizeFeeSymbol] = delegateeAmountSize + }; + var delegateInfo1 = new DelegateInfo + { + Delegations = { delegations }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; + var delegateInfo2 = new DelegateInfo + { + Delegations = { delegations2 }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; + await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DefaultSender, + DelegateInfoList = { delegateInfo1 } + }); + await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = delegateeAddress, + DelegateInfoList = { delegateInfo2 } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = basicFeeSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = sizeFeeSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + var delegationResult = + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + var delegationResult2 = + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = delegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + { + chargeFeeRetDefault.Output.Success.ShouldBe(true); + + //no change + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = DefaultSender + }); + afterBalance.Balance.ShouldBe(10); + + //no change + var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = delegateeAddress + }); + afterDelegateeBalance.Balance.ShouldBe(20); + + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = Delegatee2Address + }); + afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = delegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); + } + else + { + chargeFeeRetDefault.Output.Success.ShouldBe(false); + + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation.Delegations[NativeTokenSymbol].ShouldBe(5); + var delegation2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = delegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation2.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); + } + } + [Theory] + [InlineData( 10, 20, 70, 1000, 1000, 1000, 10, 10, 20, 20, 70, 70, 80, 80, 70, 1000)] + public async Task ChargeTransactionFee_DelegationNew_Second_Failed( + long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, + long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, + long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, + long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, + long basicFee, long sizeFee, long afterBalanceDelegatee, long afterDelegateeAmount) + { + var basicFeeSymbol = "BASIC"; + var sizeFeeSymbol = "SIZE"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, basicFeeSymbol); + await CreateTokenAsync(DefaultSender, sizeFeeSymbol); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); + if (baseFeeBalance != 0 && sizeFeeBalance != 0 && + baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && + baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) + { + await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); + await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); + } + + var delegations = new Dictionary + { + [NativeTokenSymbol] = 5, + }; + var delegations2 = new Dictionary + { + [NativeTokenSymbol] = delegateeAmountNativeToken, + [basicFeeSymbol] = delegateeAmountBasic, + [sizeFeeSymbol] = delegateeAmountSize + }; + var delegateInfo1 = new DelegateInfo + { + Delegations = { delegations }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; + var delegateInfo2 = new DelegateInfo + { + Delegations = { delegations2 }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; + await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DefaultSender, + DelegateInfoList = { delegateInfo1 } + }); + await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = delegateeAddress, + DelegateInfoList = { delegateInfo2 } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = basicFeeSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = sizeFeeSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + var delegationResult = + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + var delegationResult2 = + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = delegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + { + chargeFeeRetDefault.Output.Success.ShouldBe(false); + chargeFeeRetDefault.Output.ChargingInformation.ShouldBe("Transaction fee not enough."); + + //all in + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = DefaultSender + }); + afterBalance.Balance.ShouldBe(0); + + //no change + var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = delegateeAddress + }); + afterDelegateeBalance.Balance.ShouldBe(20); + + //no change + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = Delegatee2Address + }); + afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = delegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); + } + else + { + chargeFeeRetDefault.Output.Success.ShouldBe(false); + } + } + [Theory] + [InlineData( 10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] + public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( + long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, + long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, + long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, + long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, + long basicFee, long sizeFee, long afterBalanceDelegatee, long afterDelegateeAmount) + { + var basicFeeSymbol = "BASIC"; + var sizeFeeSymbol = "SIZE"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, basicFeeSymbol); + await CreateTokenAsync(DefaultSender, sizeFeeSymbol); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); + if (baseFeeBalance != 0 && sizeFeeBalance != 0 && + baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && + baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) + { + await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); + await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); + } + + var delegations = new Dictionary + { + [NativeTokenSymbol] = 5, + }; + var delegations2 = new Dictionary + { + [NativeTokenSymbol] = delegateeAmountNativeToken, + [basicFeeSymbol] = delegateeAmountBasic, + [sizeFeeSymbol] = delegateeAmountSize + }; + var delegateInfo2 = new DelegateInfo + { + Delegations = { delegations2 }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; + await TokenContractStubDelegate1.SetTransactionFeeDelegations.SendAsync( + new SetTransactionFeeDelegationsInput + { + DelegatorAddress = DefaultSender, + Delegations = { delegations } + }); + await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = delegateeAddress, + DelegateInfoList = { delegateInfo2 } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = basicFeeSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = sizeFeeSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + var delegationResult = + await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( + new GetTransactionFeeDelegationsOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender + }); + var delegationResult2 = + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = delegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + { + chargeFeeRetDefault.Output.Success.ShouldBe(true); + + //no change + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = DefaultSender + }); + afterBalance.Balance.ShouldBe(10); + + //no change + var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = delegateeAddress + }); + afterDelegateeBalance.Balance.ShouldBe(20); + + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = Delegatee2Address + }); + afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = delegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); + } + else + { + chargeFeeRetDefault.Output.Success.ShouldBe(false); + + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( + new GetTransactionFeeDelegationsOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender + }); + delegation.Delegations[NativeTokenSymbol].ShouldBe(5); + var delegation2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = delegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation2.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); + } + } + private async Task GetTokenSupplyAmount(string tokenSymbol) { var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index 33fff08c64..bf9daa50ba 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -295,10 +295,14 @@ protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub2 { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub3 { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStubDelegate1 { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStubDelegate2 { get; set; } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; internal ECKeyPair DelegateeKeyPair => Accounts[1].KeyPair; + internal ECKeyPair Delegatee2KeyPair => Accounts[3].KeyPair; internal ECKeyPair UserKeyPair => Accounts[2].KeyPair; internal ECKeyPair UserAKeyPair => Accounts[3].KeyPair; @@ -309,6 +313,7 @@ protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() internal Address DefaultSender => Accounts[0].Address; internal Address delegateeAddress => Accounts[1].Address; + internal Address Delegatee2Address => Accounts[3].Address; internal Address userAddress => Accounts[2].Address; internal TokenContractContainer.TokenContractStub TokenContractStubA { get; set; } @@ -349,6 +354,10 @@ private async Task DeployContractsAsync() GetTester(TokenContractAddress, UserKeyPair); TokenContractStubA = GetTester(TokenContractAddress, UserKeyPair); + TokenContractStubDelegate1 = + GetTester(TokenContractAddress, DelegateeKeyPair); + TokenContractStubDelegate2 = + GetTester(TokenContractAddress, Delegatee2KeyPair); } // Parliament From 9eae9cd66b6a2790cacc0199b0b9f819f1195245 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Tue, 30 May 2023 18:54:37 +0800 Subject: [PATCH 010/139] feat: Add if isUnlimitedDelegate is true,not modify delegation. --- .../TokenContract_Fees.cs | 5 +- .../ExecutePluginTransactionDirectlyTest.cs | 157 +++++++++++++++++- 2 files changed, 160 insertions(+), 2 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index a4ff9056a6..46884bc404 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -186,7 +186,10 @@ private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address allowanceBill = delegateeAllowanceBill; fromAddress = delegateeAddress; chargingResult = true; - ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress, input.ContractAddress, input.MethodName,delegatorAddress); + if (!delegations.IsUnlimitedDelegate) + { + ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress, input.ContractAddress, input.MethodName,delegatorAddress); + } break; } diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 3bcceb1275..61fc563335 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -1569,7 +1569,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call chargeFeeRetDefault.Output.Success.ShouldBe(false); } } - [Theory] + [Theory] [InlineData( 10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, @@ -1750,6 +1750,161 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call } } + [Theory] + [InlineData( 10, 20, 100, 10, 10, 20, 20, 100, 100, 80, 80, 20)] + public async Task ChargeTransactionFee_DelegationNew_UnlimitedDelegate_Success( + long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, + long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, + long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, + long basicFee, long sizeFee, long afterBalanceDelegatee) + { + var basicFeeSymbol = "BASIC"; + var sizeFeeSymbol = "SIZE"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, basicFeeSymbol); + await CreateTokenAsync(DefaultSender, sizeFeeSymbol); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); + if (baseFeeBalance != 0 && sizeFeeBalance != 0 && + baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && + baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) + { + await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); + await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); + } + + var delegations = new Dictionary + { + [NativeTokenSymbol] = 5, + }; + var delegateInfo2 = new DelegateInfo + { + IsUnlimitedDelegate = true, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; + await TokenContractStubDelegate1.SetTransactionFeeDelegations.SendAsync( + new SetTransactionFeeDelegationsInput + { + DelegatorAddress = DefaultSender, + Delegations = { delegations } + }); + await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = delegateeAddress, + DelegateInfoList = { delegateInfo2 } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = basicFeeSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = sizeFeeSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + var delegationResult = + await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( + new GetTransactionFeeDelegationsOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender + }); + var delegationResult2 = + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = delegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + { + chargeFeeRetDefault.Output.Success.ShouldBe(true); + + //no change + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = DefaultSender + }); + afterBalance.Balance.ShouldBe(10); + + //no change + var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = delegateeAddress + }); + afterDelegateeBalance.Balance.ShouldBe(20); + + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = Delegatee2Address + }); + afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); + } + else + { + chargeFeeRetDefault.Output.Success.ShouldBe(false); + + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( + new GetTransactionFeeDelegationsOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = DefaultSender + }); + delegation.Delegations[NativeTokenSymbol].ShouldBe(5); + } + } + private async Task GetTokenSupplyAmount(string tokenSymbol) { var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput From 82c31232b43b747154565c044e08ab4745a84959 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Wed, 31 May 2023 10:25:19 +0800 Subject: [PATCH 011/139] feat: add break when charge from secondary delegation. --- .../TokenContract_Fees.cs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 46884bc404..e6bbb80616 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -103,6 +103,10 @@ private ChargeTransactionFeesOutput TryToChargeTransactionFee(ChargeTransactionF { chargingResult = ChargeFromDelegations(input, ref fromAddress, ref bill, ref allowanceBill, fee, isSizeFeeFree, Address.FromBase58(delegatee)); + if (chargingResult) + { + break; + } } } } @@ -160,15 +164,14 @@ private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address var chargingResult = false; // Try to charge delegatees // Get delegatee list according to the delegator - if ((State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees == null) && - (State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][input.MethodName]?.Delegatees == null)) + var delegationInfo = State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees ?? + State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][input.MethodName]?.Delegatees; + + if (delegationInfo == null) { return false; } - var delegationInfo = State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees ?? - State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][ - input.MethodName]?.Delegatees; foreach (var (delegatee, delegations) in delegationInfo) { // compare current block height with the block height when the delegatee added @@ -188,8 +191,10 @@ private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address chargingResult = true; if (!delegations.IsUnlimitedDelegate) { - ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress, input.ContractAddress, input.MethodName,delegatorAddress); + ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress, input.ContractAddress, + input.MethodName, delegatorAddress); } + break; } @@ -367,8 +372,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress { var allSymbolToTxFee = input.SymbolsToPayTxSizeFee.ToList(); var availableSymbol = GetAvailableSymbolToPayTxFee(allSymbolToTxFee, fromAddress, txSizeFeeAmount, - freeAllowances, symbolChargedForBaseFee, amountChargedForBaseFee, amountChargedForBaseAllowance, - delegations); + freeAllowances, symbolChargedForBaseFee, amountChargedForBaseFee, amountChargedForBaseAllowance, delegations); if (availableSymbol != null && availableSymbol.TokenSymbol != symbolToPayTxFee) { @@ -727,8 +731,7 @@ private string GetAvailableSymbolToPayBaseFee(Dictionary symbolToA // is unlimited delegate is false && delegation enough && balance enough if ((delegations.IsUnlimitedDelegate && existingBalance.Add(existingAllowance) >= amount) || (!delegations.IsUnlimitedDelegate && delegations.Delegations.ContainsKey(symbol) && - delegations.Delegations[symbol] > amount && - existingBalance.Add(existingAllowance) >= amount)) + delegations.Delegations[symbol] > amount && existingBalance.Add(existingAllowance) >= amount)) { symbolOfValidBalance = symbol; break; @@ -1175,7 +1178,7 @@ private bool IsDelegationEnough(string txSymbol, string baseSymbol, long cost, { if (!delegations.IsUnlimitedDelegate) { - return delegations.Delegations.Keys.Contains(txSymbol) && (baseSymbol == txSymbol + return delegations.Delegations.ContainsKey(txSymbol) && (baseSymbol == txSymbol ? delegations.Delegations[txSymbol].Sub(cost) : delegations.Delegations[txSymbol]) >= txSizeFeeAmount; } From 89e936e82d2975d4762bc4cb7e3f87e1b0223019 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Thu, 1 Jun 2023 11:38:46 +0800 Subject: [PATCH 012/139] feat: Add delegate unit test. --- .../TokenContract_Delegation.cs | 55 +- .../TokenContract_Helper.cs | 5 + .../BVT/TokenDelegationTest.cs | 988 ++++++++++++++++-- 3 files changed, 959 insertions(+), 89 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs index fea03f9016..6756c4dd2a 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs @@ -195,7 +195,7 @@ public override GetTransactionFeeDelegateesOutput GetTransactionFeeDelegatees( public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateInfosInput input) { - Assert(input.DelegatorAddress.Value.Any() && input.DelegateInfoList.Count > 0, + Assert(input.DelegatorAddress != null && input.DelegateInfoList.Count > 0, "Delegator address and delegate info cannot be null."); var toAddTransactionList = new DelegateTransactionList(); var toUpdateTransactionList = new DelegateTransactionList(); @@ -206,6 +206,8 @@ public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateIn //If isUnlimitedDelegate is false,delegate info list should > 0. Assert(delegateInfo.IsUnlimitedDelegate || delegateInfo.Delegations.Count > 0, "Delegation cannot be null."); + Assert(delegateInfo.ContractAddress != null && !string.IsNullOrEmpty(delegateInfo.MethodName) && + delegateInfo.MethodName.All(IsValidMethodNameChar), "Invalid contract address and method name."); var existDelegateeInfoList = State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateInfo.ContractAddress] [delegateInfo.MethodName] ?? new TransactionFeeDelegatees(); @@ -214,7 +216,7 @@ public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateIn //If the transaction contains delegatee,update delegate info. if (existDelegateeList.TryGetValue(delegateeAddress, out var value)) { - UpdateDelegateInfo(ref value, ref toUpdateTransactionList,delegateInfo); + UpdateDelegateInfo(ref value, ref toUpdateTransactionList, delegateInfo); existDelegateeList[delegateeAddress] = value; } //else,add new delegate info. else @@ -223,9 +225,9 @@ public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateIn "The quantity of delegatee has reached its limit"); existDelegateeList.Add(delegateeAddress, new TransactionFeeDelegations()); var transactionFeeDelegations = existDelegateeList[delegateeAddress]; - AddDelegateInfo(ref transactionFeeDelegations,ref toAddTransactionList,delegateInfo); + AddDelegateInfo(ref transactionFeeDelegations, ref toAddTransactionList, delegateInfo); } - + if (existDelegateeInfoList.Delegatees[delegateeAddress].Delegations.Count == 0 && !existDelegateeInfoList.Delegatees[delegateeAddress].IsUnlimitedDelegate) { @@ -236,7 +238,7 @@ public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateIn MethodName = delegateInfo.MethodName }); } - + State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateInfo.ContractAddress] [delegateInfo.MethodName] = existDelegateeInfoList; } @@ -246,7 +248,8 @@ public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateIn return new Empty(); } - private void AddDelegateInfo(ref TransactionFeeDelegations existDelegateeList,ref DelegateTransactionList toAddTransactionList,DelegateInfo delegateInfo) + private void AddDelegateInfo(ref TransactionFeeDelegations existDelegateeList, + ref DelegateTransactionList toAddTransactionList, DelegateInfo delegateInfo) { if (!delegateInfo.IsUnlimitedDelegate) { @@ -256,7 +259,6 @@ private void AddDelegateInfo(ref TransactionFeeDelegations existDelegateeList,re existDelegateeList.Delegations[symbol] = amount; } } - existDelegateeList.BlockHeight = Context.CurrentHeight; existDelegateeList.IsUnlimitedDelegate = delegateInfo.IsUnlimitedDelegate; toAddTransactionList.Value.Add(new DelegateTransaction @@ -265,7 +267,9 @@ private void AddDelegateInfo(ref TransactionFeeDelegations existDelegateeList,re MethodName = delegateInfo.MethodName }); } - private void UpdateDelegateInfo(ref TransactionFeeDelegations existDelegateInfo,ref DelegateTransactionList toUpdateTransactionList,DelegateInfo delegateInfo) + + private void UpdateDelegateInfo(ref TransactionFeeDelegations existDelegateInfo, + ref DelegateTransactionList toUpdateTransactionList, DelegateInfo delegateInfo) { var existDelegation = existDelegateInfo.Delegations; if (delegateInfo.IsUnlimitedDelegate) @@ -279,7 +283,7 @@ private void UpdateDelegateInfo(ref TransactionFeeDelegations existDelegateInfo, { if (existDelegation.ContainsKey(symbol)) { - if (amount < 0) + if (amount <= 0) { existDelegation.Remove(symbol); } @@ -296,7 +300,7 @@ private void UpdateDelegateInfo(ref TransactionFeeDelegations existDelegateInfo, } } } - + existDelegateInfo.BlockHeight = Context.CurrentHeight; existDelegateInfo.IsUnlimitedDelegate = delegateInfo.IsUnlimitedDelegate; toUpdateTransactionList.Value.Add(new DelegateTransaction @@ -305,6 +309,7 @@ private void UpdateDelegateInfo(ref TransactionFeeDelegations existDelegateInfo, MethodName = delegateInfo.MethodName }); } + private void FireLogEvent(DelegateTransactionList toAddTransactionList, DelegateTransactionList toUpdateTransactionList, DelegateTransactionList toCancelTransactionList, Address delegatorAddress) @@ -353,15 +358,14 @@ public override Empty RemoveTransactionFeeDelegateeInfos(RemoveTransactionFeeDel var toCancelTransactionList = new DelegateTransactionList(); foreach (var delegateTransaction in delegateTransactionList.ToList().Distinct()) { + Assert(delegateTransaction.ContractAddress != null && !string.IsNullOrEmpty(delegateTransaction.MethodName) && + delegateTransaction.MethodName.All(IsValidMethodNameChar), "Invalid contract address and method name."); var delegateeInfo = State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ delegateTransaction.MethodName]; - if (delegateeInfo != null && delegateeInfo.Delegatees.ContainsKey(delegateeAddress)) - { - delegateeInfo.Delegatees.Remove(delegateeAddress); - toCancelTransactionList.Value.Add(delegateTransaction); - } - + if (delegateeInfo == null || !delegateeInfo.Delegatees.ContainsKey(delegateeAddress)) continue; + delegateeInfo.Delegatees.Remove(delegateeAddress); + toCancelTransactionList.Value.Add(delegateTransaction); State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ delegateTransaction.MethodName] = delegateeInfo; } @@ -390,15 +394,14 @@ public override Empty RemoveTransactionFeeDelegatorInfos(RemoveTransactionFeeDel var toCancelTransactionList = new DelegateTransactionList(); foreach (var delegateTransaction in delegateTransactionList.ToList().Distinct()) { + Assert(delegateTransaction.ContractAddress != null && !string.IsNullOrEmpty(delegateTransaction.MethodName) && + delegateTransaction.MethodName.All(IsValidMethodNameChar), "Invalid contract address and method name."); var delegateeInfo = State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ delegateTransaction.MethodName]; - if (delegateeInfo != null && delegateeInfo.Delegatees.ContainsKey(delegateeAddress)) - { - delegateeInfo.Delegatees.Remove(delegateeAddress); - toCancelTransactionList.Value.Add(delegateTransaction); - } - + if (delegateeInfo == null || !delegateeInfo.Delegatees.ContainsKey(delegateeAddress)) continue; + delegateeInfo.Delegatees.Remove(delegateeAddress); + toCancelTransactionList.Value.Add(delegateTransaction); State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ delegateTransaction.MethodName] = delegateeInfo; } @@ -408,8 +411,8 @@ public override Empty RemoveTransactionFeeDelegatorInfos(RemoveTransactionFeeDel Context.Fire(new TransactionFeeDelegateInfoCancelled { Caller = Context.Sender, - Delegatee = input.DelegatorAddress, - Delegator = Context.Sender, + Delegator = input.DelegatorAddress, + Delegatee = Context.Sender, DelegateTransactionList = toCancelTransactionList }); } @@ -421,11 +424,11 @@ public override GetTransactionFeeDelegateeListOutput GetTransactionFeeDelegateeL GetTransactionFeeDelegateeListInput input) { Assert(input.DelegatorAddress != null && input.ContractAddress != null && input.MethodName != null, - "invalid input"); + "Invalid input."); var allDelegatees = State.TransactionFeeDelegateInfoMap[input.DelegatorAddress][input.ContractAddress][input.MethodName]; - if (allDelegatees == null || allDelegatees.Delegatees == null || allDelegatees.Delegatees.Count == 0) + if (allDelegatees?.Delegatees == null || allDelegatees.Delegatees.Count == 0) { return new GetTransactionFeeDelegateeListOutput(); } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index d11e25b7de..ad6f8d5fb1 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -27,6 +27,11 @@ private bool IsValidCreateSymbolChar(char character) { return character >= 'A' && character <= 'Z'; } + + private bool IsValidMethodNameChar(char character) + { + return (character >= 'A' && character <= 'Z') || (character >= 'a' && character <= 'z') || (character >= '0' && character <= '9'); + } private TokenInfo AssertValidToken(string symbol, long amount) { diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs index fd66f9aee6..97815f3bb8 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs @@ -603,7 +603,7 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test( }; var delegations2 = new Dictionary { - [NativeToken] = -1, + [NativeToken] = 0, [BasicFeeSymbol] = 200, }; var delegateInfo1 = new DelegateInfo @@ -626,7 +626,7 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test( }, IsUnlimitedDelegate = false }; - await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput { DelegatorAddress = User1Address, DelegateInfoList = { delegateInfo1,delegateInfo2 } @@ -660,6 +660,17 @@ await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransact delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } + { + var log = TransactionFeeDelegateInfoUpdated.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoUpdated))?.NonIndexed); + log.Delegator.ShouldBe(User1Address); + log.Delegatee.ShouldBe(DefaultAddress); + log.DelegateTransactionList.Value.Count.ShouldBe(2); + log.DelegateTransactionList.Value[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); + log.DelegateTransactionList.Value[0].MethodName.ShouldBe("test1"); + log.DelegateTransactionList.Value[1].ContractAddress.ShouldBe(BasicFunctionContractAddress); + log.DelegateTransactionList.Value[1].MethodName.ShouldBe("test2"); + } } [Fact] public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegateInfo_Success_Test() @@ -756,15 +767,20 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegateInfo_Success_Tes log.DelegateTransactionList.Value[0].MethodName.ShouldBe("test1"); } } - + [Fact] - public async Task RemoveTransactionFeeDelegateeInfos_Success_Test() + public async Task SetDelegateInfos_AddOrUpdateOrRemoveDelegate_Success_Test() { - await SetDelegateInfos_NewDelegate_Success_Test(); + await SetDelegateInfos_NewOrUpdateDelegate_Success_Test(); var delegations1 = new Dictionary { [NativeToken] = 300, - [BasicFeeSymbol] = 200 + [BasicFeeSymbol] = 200, + [SizeFeeSymbol] = 0 + }; + var delegations4 = new Dictionary + { + [NativeToken] = 60, }; var delegateInfo1 = new DelegateInfo { @@ -776,10 +792,26 @@ public async Task RemoveTransactionFeeDelegateeInfos_Success_Test() }, IsUnlimitedDelegate = false }; - await TokenContractStubDelegate.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + var delegateInfo2 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test2", + IsUnlimitedDelegate = true + }; + var delegateInfo4 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test4", + Delegations = + { + delegations4 + }, + IsUnlimitedDelegate = false + }; + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput { DelegatorAddress = User1Address, - DelegateInfoList = { delegateInfo1 } + DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo4 } }); { var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( @@ -790,28 +822,93 @@ await TokenContractStubDelegate.SetTransactionFeeDelegateInfos.SendAsync(new Set DelegateeAddress = DefaultAddress, MethodName = "test1" }); - delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(1000); - delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(500); + delegateInfoOfADelegatee.Delegations.Count.ShouldBe(2); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(300); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(200); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test2" + }); + delegateInfoOfADelegatee.Delegations.ShouldBeEmpty(); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeTrue(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test4" + }); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(60); delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } - var delegationTransactionList = new RepeatedField { - new DelegateTransaction { - ContractAddress = BasicFunctionContractAddress, - MethodName = "test1" - }, - new DelegateTransaction + var log = TransactionFeeDelegateInfoAdded.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoAdded))?.NonIndexed); + log.Delegator.ShouldBe(User1Address); + log.Delegatee.ShouldBe(DefaultAddress); + log.DelegateTransactionList.Value.Count.ShouldBe(1); + log.DelegateTransactionList.Value[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); + log.DelegateTransactionList.Value[0].MethodName.ShouldBe("test4"); + } { - ContractAddress = BasicFunctionContractAddress, - MethodName = "test3" + var log = TransactionFeeDelegateInfoUpdated.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoUpdated))?.NonIndexed); + log.Delegator.ShouldBe(User1Address); + log.Delegatee.ShouldBe(DefaultAddress); + log.DelegateTransactionList.Value.Count.ShouldBe(2); + log.DelegateTransactionList.Value[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); + log.DelegateTransactionList.Value[0].MethodName.ShouldBe("test1"); + log.DelegateTransactionList.Value[1].ContractAddress.ShouldBe(BasicFunctionContractAddress); + log.DelegateTransactionList.Value[1].MethodName.ShouldBe("test2"); } + } + } + + [Fact] + public async Task SetDelegateInfos_MultiDelegateeAndSameTransaction_Success_Test() + { + await Initialize(); + var delegations1 = new Dictionary + { + [NativeToken] = 1000, + [BasicFeeSymbol] = 500, + [SizeFeeSymbol] = 100 }; - await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new RemoveTransactionFeeDelegateeInfosInput + var delegateInfo1 = new DelegateInfo { - DelegateeAddress = DefaultAddress, - DelegateTransactionList = { delegationTransactionList } + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + Delegations = + { + delegations1 + }, + IsUnlimitedDelegate = false + }; + //Default -> User1 + await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1 } + }); + //User2 -> User1 + await TokenContractStubDelegate.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1 } }); { var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( @@ -822,7 +919,10 @@ await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new Rem DelegateeAddress = DefaultAddress, MethodName = "test1" }); - delegateInfoOfADelegatee.ShouldBe(new TransactionFeeDelegations()); + delegateInfoOfADelegatee.Delegations.Count.ShouldBe(3); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(1000); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( @@ -830,32 +930,37 @@ await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new Rem { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, - DelegateeAddress = DefaultAddress, - MethodName = "test2" + DelegateeAddress = User2Address, + MethodName = "test1" }); - delegateInfoOfADelegatee.Delegations[NativeToken] = 100; - delegateInfoOfADelegatee.IsUnlimitedDelegate = false; + delegateInfoOfADelegatee.Delegations.Count.ShouldBe(3); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(1000); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateeAddress = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( new GetTransactionFeeDelegateeListInput { ContractAddress = BasicFunctionContractAddress, - DelegatorAddress = User1Address, - MethodName = "test1" + MethodName = "test1", + DelegatorAddress = User1Address }); - delegateeAddress.DelegateeAddresses.Count.ShouldBe(1); - delegateeAddress.DelegateeAddresses[0].ShouldBe(User2Address); + delegateeList.DelegateeAddresses.Count.ShouldBe(2); + delegateeList.DelegateeAddresses[0].ShouldBe(DefaultAddress); + delegateeList.DelegateeAddresses[1].ShouldBe(User2Address); } } - [Fact] - public async Task RemoveTransactionFeeDelegatorInfos_Success_Test() + + [Fact] + public async Task SetDelegateInfos_MultiDelegatorAndSameTransaction_Success_Test() { - await SetDelegateInfos_NewDelegate_Success_Test(); + await Initialize(); var delegations1 = new Dictionary { - [NativeToken] = 300, - [BasicFeeSymbol] = 200 + [NativeToken] = 1000, + [BasicFeeSymbol] = 500, + [SizeFeeSymbol] = 100 }; var delegateInfo1 = new DelegateInfo { @@ -867,28 +972,17 @@ public async Task RemoveTransactionFeeDelegatorInfos_Success_Test() }, IsUnlimitedDelegate = false }; + //Default -> User1 await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput { - DelegatorAddress = User2Address, + DelegatorAddress = User1Address, DelegateInfoList = { delegateInfo1 } }); - var delegationTransactionList = new RepeatedField - { - new DelegateTransaction - { - ContractAddress = BasicFunctionContractAddress, - MethodName = "test1" - }, - new DelegateTransaction - { - ContractAddress = BasicFunctionContractAddress, - MethodName = "test3" - } - }; - await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendAsync(new RemoveTransactionFeeDelegatorInfosInput + //Default -> User2 + await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput { - DelegatorAddress = User1Address, - DelegateTransactionList = { delegationTransactionList } + DelegatorAddress = User2Address, + DelegateInfoList = { delegateInfo1 } }); { var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( @@ -899,30 +993,798 @@ await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendAsync(new RemoveT DelegateeAddress = DefaultAddress, MethodName = "test1" }); - delegateInfoOfADelegatee.ShouldBe(new TransactionFeeDelegations()); + delegateInfoOfADelegatee.Delegations.Count.ShouldBe(3); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(1000); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( new GetTransactionFeeDelegateInfosOfADelegateeInput { ContractAddress = BasicFunctionContractAddress, - DelegatorAddress = User1Address, + DelegatorAddress = User2Address, DelegateeAddress = DefaultAddress, - MethodName = "test2" + MethodName = "test1" }); - delegateInfoOfADelegatee.Delegations[NativeToken] = 100; - delegateInfoOfADelegatee.IsUnlimitedDelegate = false; + delegateInfoOfADelegatee.Delegations.Count.ShouldBe(3); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(1000); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateeAddress = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( new GetTransactionFeeDelegateeListInput { ContractAddress = BasicFunctionContractAddress, - DelegatorAddress = User2Address, - MethodName = "test1" + MethodName = "test1", + DelegatorAddress = User1Address }); - delegateeAddress.DelegateeAddresses.Count.ShouldBe(1); - delegateeAddress.DelegateeAddresses[0].ShouldBe(DefaultAddress); + delegateeList.DelegateeAddresses.Count.ShouldBe(1); + delegateeList.DelegateeAddresses[0].ShouldBe(DefaultAddress); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + DelegatorAddress = User2Address + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(1); + delegateeList.DelegateeAddresses[0].ShouldBe(DefaultAddress); + } + } + [Fact] + public async Task SetDelegateInfos_InvalidInput_Failed_Test() + { + await Initialize(); + var delegations1 = new Dictionary + { + [NativeToken] = 1000, + [BasicFeeSymbol] = 500, + [SizeFeeSymbol] = 100 + }; + var delegateInfo = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + Delegations = { delegations1 } + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + IsUnlimitedDelegate = false + }; + var delegateInfo2 = new DelegateInfo + { + MethodName = "test1", + Delegations = { delegations1 }, + IsUnlimitedDelegate = false + }; + var delegateInfo3 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + Delegations = { delegations1 }, + IsUnlimitedDelegate = false + }; + { + await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo } + }); + } + { + var transactionFeeDelegation = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress + }); + transactionFeeDelegation.IsUnlimitedDelegate.ShouldBeFalse(); + transactionFeeDelegation.Delegations.Count.ShouldBe(3); + transactionFeeDelegation.Delegations[NativeToken].ShouldBe(1000); } + { + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1 } + }); + executionResult.TransactionResult.Error.ShouldContain("Delegation cannot be null."); + } + { + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo2 } + }); + executionResult.TransactionResult.Error.ShouldContain("Invalid contract address and method name."); + } + { + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo3 } + }); + executionResult.TransactionResult.Error.ShouldContain("Invalid contract address and method name."); + } + { + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput + { + DelegateInfoList = { delegateInfo } + }); + executionResult.TransactionResult.Error.ShouldContain("Delegator address and delegate info cannot be null."); + } + { + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + }); + executionResult.TransactionResult.Error.ShouldContain("Delegator address and delegate info cannot be null."); + } + } + + [Fact] + public async Task SetDelegateInfos_InvalidMethodName_Failed_Test() + { + await Initialize(); + var delegations1 = new Dictionary + { + [NativeToken] = 1000, + [BasicFeeSymbol] = 500, + [SizeFeeSymbol] = 100 + }; + var delegateInfo = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1-0", + Delegations = { delegations1 }, + IsUnlimitedDelegate = false + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1@0", + Delegations = { delegations1 }, + IsUnlimitedDelegate = false + }; + var delegateInfo2 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "@#¥%Z……", + Delegations = { delegations1 }, + IsUnlimitedDelegate = false + }; + { + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo } + }); + executionResult.TransactionResult.Error.ShouldContain("Invalid contract address and method name."); + } + { + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1 } + }); + executionResult.TransactionResult.Error.ShouldContain("Invalid contract address and method name."); + } + { + var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo2 } + }); + executionResult.TransactionResult.Error.ShouldContain("Invalid contract address and method name."); + } + + } + [Fact] + public async Task RemoveTransactionFeeDelegateeInfos_Success_Test() + { + await SetDelegateInfos_NewDelegate_Success_Test(); + var delegations1 = new Dictionary + { + [NativeToken] = 300, + [BasicFeeSymbol] = 200 + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + Delegations = + { + delegations1 + }, + IsUnlimitedDelegate = false + }; + await TokenContractStubDelegate.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1 } + }); + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(1000); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(500); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1" + }, + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test3" + } + }; + await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new RemoveTransactionFeeDelegateeInfosInput + { + DelegateeAddress = DefaultAddress, + DelegateTransactionList = { delegationTransactionList } + }); + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test2" + }); + delegateInfoOfADelegatee.Delegations[NativeToken] = 100; + delegateInfoOfADelegatee.IsUnlimitedDelegate = false; + } + { + var delegateeAddress = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + MethodName = "test1" + }); + delegateeAddress.DelegateeAddresses.Count.ShouldBe(1); + delegateeAddress.DelegateeAddresses[0].ShouldBe(User2Address); + } + } + + [Fact] + public async Task RemoveTransactionFeeDelegateeInfos_SingleTransaction_Success_Test() + { + await SetDelegateInfos_NewDelegate_Success_Test(); + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1" + } + }; + var executionResult = await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new RemoveTransactionFeeDelegateeInfosInput + { + DelegateeAddress = DefaultAddress, + DelegateTransactionList = { delegationTransactionList } + }); + { + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress + }); + transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(0); + } + { + var log = TransactionFeeDelegateInfoCancelled.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoCancelled))?.NonIndexed); + log.Delegatee.ShouldBe(DefaultAddress); + log.Delegator.ShouldBe(User1Address); + delegationTransactionList.Count.ShouldBe(1); + delegationTransactionList[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); + delegationTransactionList[0].MethodName.ShouldBe("test1"); + } + } + [Fact] + public async Task RemoveTransactionFeeDelegateeInfos_MultiTransaction_Success_Test() + { + await SetDelegateInfos_NewOrUpdateDelegate_Success_Test(); + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1" + }, + new DelegateTransaction + { + ContractAddress = BasicContractZeroAddress, + MethodName = "test1" + } + }; + var executionResult = await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new RemoveTransactionFeeDelegateeInfosInput + { + DelegateeAddress = DefaultAddress, + DelegateTransactionList = { delegationTransactionList } + }); + { + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress + }); + transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicContractZeroAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress + }); + transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(0); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicContractZeroAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(0); + } + { + var log = TransactionFeeDelegateInfoCancelled.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoCancelled))?.NonIndexed); + log.Delegatee.ShouldBe(DefaultAddress); + log.Delegator.ShouldBe(User1Address); + delegationTransactionList.Count.ShouldBe(2); + delegationTransactionList[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); + delegationTransactionList[0].MethodName.ShouldBe("test1"); + delegationTransactionList[1].ContractAddress.ShouldBe(BasicContractZeroAddress); + delegationTransactionList[1].MethodName.ShouldBe("test1"); + } + } + [Fact] + public async Task RemoveTransactionFeeDelegateeInfos_NotExistTransaction_Success_Test() + { + await SetDelegateInfos_NewOrUpdateDelegate_Success_Test(); + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = TokenContractAddress, + MethodName = "transfer" + } + }; + var executionResult = await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new RemoveTransactionFeeDelegateeInfosInput + { + DelegateeAddress = DefaultAddress, + DelegateTransactionList = { delegationTransactionList } + }); + var executionResult1 = await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new RemoveTransactionFeeDelegateeInfosInput + { + DelegateeAddress = User2Address, + DelegateTransactionList = { delegationTransactionList } + }); + { + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = TokenContractAddress, + MethodName = "transfer", + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress + }); + transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = TokenContractAddress, + MethodName = "transfer", + DelegatorAddress = User1Address, + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(0); + } + { + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = TokenContractAddress, + MethodName = "transfer", + DelegatorAddress = User1Address, + DelegateeAddress = User2Address + }); + transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = TokenContractAddress, + MethodName = "transfer", + DelegatorAddress = User1Address, + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(0); + } + } + + [Fact] + public async Task RemoveTransactionFeeDelegateeInfos_InvalidInput_Failed_Test() + { + await SetDelegateInfos_NewOrUpdateDelegate_Success_Test(); + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = BasicContractZeroAddress + }, + new DelegateTransaction + { + MethodName = "jsh&&&" + }, + new DelegateTransaction + { + + } + }; + var executionResult = await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendWithExceptionAsync(new RemoveTransactionFeeDelegateeInfosInput + { + DelegateeAddress = DefaultAddress, + DelegateTransactionList = { delegationTransactionList } + }); + executionResult.TransactionResult.Error.ShouldContain("Invalid contract address and method name."); + } + [Fact] + public async Task RemoveTransactionFeeDelegatorInfos_Success_Test() + { + await SetDelegateInfos_NewDelegate_Success_Test(); + var delegations1 = new Dictionary + { + [NativeToken] = 300, + [BasicFeeSymbol] = 200 + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + Delegations = + { + delegations1 + }, + IsUnlimitedDelegate = false + }; + await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User2Address, + DelegateInfoList = { delegateInfo1 } + }); + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1" + }, + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test3" + } + }; + await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendAsync(new RemoveTransactionFeeDelegatorInfosInput + { + DelegatorAddress = User1Address, + DelegateTransactionList = { delegationTransactionList } + }); + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test2" + }); + delegateInfoOfADelegatee.Delegations[NativeToken] = 100; + delegateInfoOfADelegatee.IsUnlimitedDelegate = false; + } + { + var delegateeAddress = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + DelegatorAddress = User2Address, + MethodName = "test1" + }); + delegateeAddress.DelegateeAddresses.Count.ShouldBe(1); + delegateeAddress.DelegateeAddresses[0].ShouldBe(DefaultAddress); + } + } + [Fact] + public async Task RemoveTransactionFeeDelegatorInfos_SingleTransaction_Success_Test() + { + await SetDelegateInfos_NewDelegate_Success_Test(); + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1" + } + }; + var executionResult = await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendAsync(new RemoveTransactionFeeDelegatorInfosInput + { + DelegatorAddress = User1Address, + DelegateTransactionList = { delegationTransactionList } + }); + { + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress + }); + transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(0); + } + { + var log = TransactionFeeDelegateInfoCancelled.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoCancelled))?.NonIndexed); + log.Delegatee.ShouldBe(DefaultAddress); + log.Delegator.ShouldBe(User1Address); + delegationTransactionList.Count.ShouldBe(1); + delegationTransactionList[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); + delegationTransactionList[0].MethodName.ShouldBe("test1"); + } + } + [Fact] + public async Task RemoveTransactionFeeDelegatorInfos_MultiTransaction_Success_Test() + { + await SetDelegateInfos_NewOrUpdateDelegate_Success_Test(); + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1" + }, + new DelegateTransaction + { + ContractAddress = BasicContractZeroAddress, + MethodName = "test1" + } + }; + var executionResult = await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendAsync(new RemoveTransactionFeeDelegatorInfosInput + { + DelegatorAddress = User1Address, + DelegateTransactionList = { delegationTransactionList } + }); + { + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress + }); + transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicContractZeroAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress + }); + transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicFunctionContractAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(0); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = BasicContractZeroAddress, + MethodName = "test1", + DelegatorAddress = User1Address, + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(0); + } + { + var log = TransactionFeeDelegateInfoCancelled.Parser.ParseFrom(executionResult.TransactionResult.Logs + .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoCancelled))?.NonIndexed); + log.Delegatee.ShouldBe(DefaultAddress); + log.Delegator.ShouldBe(User1Address); + delegationTransactionList.Count.ShouldBe(2); + delegationTransactionList[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); + delegationTransactionList[0].MethodName.ShouldBe("test1"); + delegationTransactionList[1].ContractAddress.ShouldBe(BasicContractZeroAddress); + delegationTransactionList[1].MethodName.ShouldBe("test1"); + } + } + [Fact] + public async Task RemoveTransactionFeeDelegatorInfos_NotExistTransaction_Success_Test() + { + await SetDelegateInfos_NewOrUpdateDelegate_Success_Test(); + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = TokenContractAddress, + MethodName = "transfer" + } + }; + var executionResult = await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendAsync(new RemoveTransactionFeeDelegatorInfosInput + { + DelegatorAddress = User1Address, + DelegateTransactionList = { delegationTransactionList } + }); + var executionResult1 = await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendAsync(new RemoveTransactionFeeDelegatorInfosInput + { + DelegatorAddress = User2Address, + DelegateTransactionList = { delegationTransactionList } + }); + { + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = TokenContractAddress, + MethodName = "transfer", + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress + }); + transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = TokenContractAddress, + MethodName = "transfer", + DelegatorAddress = User1Address, + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(0); + } + { + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = TokenContractAddress, + MethodName = "transfer", + DelegatorAddress = User2Address, + DelegateeAddress = DefaultAddress + }); + transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); + } + { + var delegateeList = await TokenContractStub.GetTransactionFeeDelegateeList.CallAsync( + new GetTransactionFeeDelegateeListInput + { + ContractAddress = TokenContractAddress, + MethodName = "transfer", + DelegatorAddress = User2Address, + }); + delegateeList.DelegateeAddresses.Count.ShouldBe(0); + } + } + + [Fact] + public async Task RemoveTransactionFeeDelegatorInfos_InvalidInput_Failed_Test() + { + await SetDelegateInfos_NewOrUpdateDelegate_Success_Test(); + var delegationTransactionList = new RepeatedField + { + new DelegateTransaction + { + ContractAddress = BasicContractZeroAddress + }, + new DelegateTransaction + { + MethodName = "jsh&&&" + }, + new DelegateTransaction + { + + } + }; + var executionResult = await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendWithExceptionAsync(new RemoveTransactionFeeDelegatorInfosInput + { + DelegatorAddress = User1Address, + DelegateTransactionList = { delegationTransactionList } + }); + executionResult.TransactionResult.Error.ShouldContain("Invalid contract address and method name."); } } \ No newline at end of file From 980c85980f1294f99b39ac31a9c46c2cb240932f Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 1 Jun 2023 15:54:54 +0800 Subject: [PATCH 013/139] feat: adjust code structure and support multiple tokens with multiple free allowances --- .../TokenContractState_ChargeFee.cs | 5 +- .../TokenContract_Fees.cs | 194 ++++++++++++------ .../TokenContract_Helper.cs | 67 ++++-- protobuf/token_contract.proto | 112 ++++------ protobuf/token_contract_impl.proto | 56 +++++ 5 files changed, 283 insertions(+), 151 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs index 9fdf6cbe0c..bccf5edbbe 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs @@ -36,6 +36,7 @@ public partial class TokenContractState public MappedState OwningRental { get; set; } public SingletonState MethodFeeFreeAllowancesConfig { get; set; } - public MappedState MethodFeeFreeAllowancesMap { get; set; } - public MappedState MethodFeeFreeAllowancesLastRefreshTimeMap { get; set; } + public MappedState MethodFeeFreeAllowancesConfigMap { get; set; } + public MappedState MethodFeeFreeAllowancesMap { get; set; } + public MappedState MethodFeeFreeAllowancesLastRefreshTimeMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index da35910cb8..8d4fd87d41 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -25,7 +25,7 @@ public override ChargeTransactionFeesOutput ChargeTransactionFees(ChargeTransact // Primary token not created yet. if (State.ChainPrimaryTokenSymbol.Value == null) { - return new ChargeTransactionFeesOutput {Success = true}; + return new ChargeTransactionFeesOutput { Success = true }; } // Record tx fee bill during current charging process. @@ -33,7 +33,7 @@ public override ChargeTransactionFeesOutput ChargeTransactionFees(ChargeTransact var allowanceBill = new TransactionFreeFeeAllowanceBill(); var fromAddress = Context.Sender; var methodFees = Context.Call(input.ContractAddress, nameof(GetMethodFee), - new StringValue {Value = input.MethodName}); + new StringValue { Value = input.MethodName }); var fee = new Dictionary(); var isSizeFeeFree = false; if (methodFees != null) @@ -55,7 +55,7 @@ public override ChargeTransactionFeesOutput ChargeUserContractTransactionFees(Ch // Primary token not created yet. if (State.ChainPrimaryTokenSymbol.Value == null) { - return new ChargeTransactionFeesOutput {Success = true}; + return new ChargeTransactionFeesOutput { Success = true }; } // Record tx fee bill during current charging process. @@ -91,7 +91,7 @@ private ChargeTransactionFeesOutput TryToChargeTransactionFee(ChargeTransactionF } ModifyBalance(fromAddress, bill, allowanceBill); - var chargingOutput = new ChargeTransactionFeesOutput {Success = chargingResult}; + var chargingOutput = new ChargeTransactionFeesOutput { Success = chargingResult }; if (!chargingResult) chargingOutput.ChargingInformation = "Transaction fee not enough."; return chargingOutput; @@ -120,6 +120,7 @@ private UserContractMethodFees GetActualFee(Address contractAddress, string meth fee.MergeFrom(spec.Value); return fee; } + //If special key is null,get the normal fee set by the configuration contract. //configuration_key:UserContractMethod var value = State.ConfigurationContract.GetConfiguration.Call(new StringValue @@ -130,6 +131,7 @@ private UserContractMethodFees GetActualFee(Address contractAddress, string meth { return new UserContractMethodFees(); } + fee.MergeFrom(value.Value); return fee; } @@ -161,6 +163,7 @@ private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address ModifyDelegation(delegateeBill, delegateeAllowanceBill, fromAddress); break; } + return chargingResult; } @@ -196,7 +199,7 @@ private void ModifyBalance(Address fromAddress, TransactionFeeBill bill, TransactionFreeFeeAllowanceBill allowanceBill) { SetOrRefreshMethodFeeFreeAllowances(fromAddress); - var freeAllowances = CalculateMethodFeeFreeAllowances(fromAddress)?.Clone(); + var freeAllowancesMap = CalculateMethodFeeFreeAllowances(fromAddress); // Update balances and allowances foreach (var (symbol, amount) in bill.FeesMap) @@ -211,15 +214,20 @@ private void ModifyBalance(Address fromAddress, TransactionFeeBill bill, }); } + if (freeAllowancesMap?.Map == null || freeAllowancesMap.Map.Count == 0) return; + foreach (var (symbol, amount) in allowanceBill.FreeFeeAllowancesMap) { if (amount > 0) { - ModifyFreeFeeAllowanceAmount(freeAllowances, symbol, -amount); + ModifyFreeFeeAllowanceAmount(fromAddress, freeAllowancesMap, symbol, -amount); } } - State.MethodFeeFreeAllowancesMap[fromAddress] = freeAllowances; + foreach (var (symbol, freeAllowances) in freeAllowancesMap.Map) + { + State.MethodFeeFreeAllowancesMap[fromAddress][symbol] = freeAllowances; + } } private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Address fromAddress, @@ -230,13 +238,13 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre var successToChargeBaseFee = true; SetOrRefreshMethodFeeFreeAllowances(fromAddress); - var freeAllowances = CalculateMethodFeeFreeAllowances(fromAddress)?.Clone(); + var freeAllowancesMap = CalculateMethodFeeFreeAllowances(fromAddress)?.Clone(); if (fee.Count != 0) { // If base fee is set before, charge base fee. successToChargeBaseFee = - ChargeBaseFee(fee, fromAddress, ref bill, freeAllowances, ref allowanceBill, delegations); + ChargeBaseFee(fee, fromAddress, ref bill, freeAllowancesMap, ref allowanceBill, delegations); } var successToChargeSizeFee = true; @@ -244,7 +252,7 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre { // If IsSizeFeeFree == true, do not charge size fee. successToChargeSizeFee = - ChargeSizeFee(input, fromAddress, ref bill, freeAllowances, ref allowanceBill, delegations); + ChargeSizeFee(input, fromAddress, ref bill, freeAllowancesMap, ref allowanceBill, delegations); } return successToChargeBaseFee && successToChargeSizeFee; @@ -253,19 +261,20 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre private void SetOrRefreshMethodFeeFreeAllowances(Address address) { var config = State.MethodFeeFreeAllowancesConfig.Value; - if (config == null || State.Balances[address][Context.Variables.NativeSymbol] < config.Threshold) - { - return; - } + if (config == null) return; - var lastRefreshTime = State.MethodFeeFreeAllowancesLastRefreshTimeMap[address]; - if (lastRefreshTime != null && config.RefreshSeconds > (Context.CurrentBlockTime - lastRefreshTime).Seconds) + foreach (var symbol in config.Symbols) { - return; - } + if (State.Balances[address][symbol] < State.MethodFeeFreeAllowancesConfigMap[symbol].Threshold) continue; + var lastRefreshTime = State.MethodFeeFreeAllowancesLastRefreshTimeMap[address][symbol]; + + if (lastRefreshTime != null && State.MethodFeeFreeAllowancesConfigMap[symbol].RefreshSeconds > + (Context.CurrentBlockTime - lastRefreshTime).Seconds) continue; - State.MethodFeeFreeAllowancesLastRefreshTimeMap[address] = Context.CurrentBlockTime; - State.MethodFeeFreeAllowancesMap[address] = config.FreeAllowances; + State.MethodFeeFreeAllowancesLastRefreshTimeMap[address][symbol] = Context.CurrentBlockTime; + State.MethodFeeFreeAllowancesMap[address][symbol] = + State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances; + } } private Dictionary GetBaseFeeDictionary(MethodFees methodFees) @@ -283,12 +292,12 @@ private Dictionary GetUserContractFeeDictionary(UserContractMethod } private bool ChargeBaseFee(Dictionary methodFeeMap, Address fromAddress, ref TransactionFeeBill bill, - MethodFeeFreeAllowances freeAllowances, ref TransactionFreeFeeAllowanceBill allowanceBill, + MethodFeeFreeAllowancesMap freeAllowancesMap, ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { // Fail to charge if (!ChargeFirstSufficientToken(methodFeeMap, fromAddress, out var symbolToChargeBaseFee, - out var amountToChargeBaseFee, out var existingBalance, out var existingAllowance, freeAllowances, + out var amountToChargeBaseFee, out var existingBalance, out var existingAllowance, freeAllowancesMap, delegations)) { Context.LogDebug(() => "Failed to charge first sufficient token."); @@ -318,7 +327,7 @@ private bool ChargeBaseFee(Dictionary methodFeeMap, Address fromAd } private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress, ref TransactionFeeBill bill, - MethodFeeFreeAllowances freeAllowances, ref TransactionFreeFeeAllowanceBill allowanceBill, + MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { string symbolChargedForBaseFee = null; @@ -338,8 +347,8 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress ? GetBalance(fromAddress, symbolToPayTxFee).Sub(amountChargedForBaseFee) : GetBalance(fromAddress, symbolToPayTxFee); var availableAllowance = symbolChargedForBaseFee == symbolToPayTxFee - ? GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) - : GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee); + ? GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) + : GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbolToPayTxFee); var txSizeFeeAmount = input.TransactionSizeFee; @@ -350,7 +359,8 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress // get 1st Balance + Allowance > size fee, else, get 1st > 0 var availableSymbol = allSymbolToTxFee.FirstOrDefault(x => GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, symbolChargedForBaseFee, - amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance) >= txSizeFeeAmount && + amountChargedForBaseFee, methodFeeFreeAllowancesMap, amountChargedForBaseAllowance) >= + txSizeFeeAmount && IsDelegationEnoughBaseOnPrimaryToken(x, symbolChargedForBaseFee, amountChargedForBaseFee.Add(amountChargedForBaseAllowance), txSizeFeeAmount, delegations)); @@ -363,7 +373,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress { availableSymbol ??= allSymbolToTxFee.FirstOrDefault(x => GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, symbolChargedForBaseFee, - amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance) > 0); + amountChargedForBaseFee, methodFeeFreeAllowancesMap, amountChargedForBaseAllowance) > 0); } if (availableSymbol != null && availableSymbol.TokenSymbol != symbolToPayTxFee) @@ -375,8 +385,9 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress ? GetBalance(fromAddress, symbolToPayTxFee).Sub(amountChargedForBaseFee) : GetBalance(fromAddress, symbolToPayTxFee); availableAllowance = symbolChargedForBaseFee == symbolToPayTxFee - ? GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) - : GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee); + ? GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbolToPayTxFee) + .Sub(amountChargedForBaseAllowance) + : GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbolToPayTxFee); } } @@ -591,12 +602,13 @@ public override Empty SetSymbolsToPayTxSizeFee(SymbolListToPayTxSizeFee input) /// /// /// - /// + /// /// /// private bool ChargeFirstSufficientToken(Dictionary symbolToAmountMap, Address fromAddress, out string symbol, - out long amount, out long existingBalance, out long existingAllowance, MethodFeeFreeAllowances freeAllowances, + out long amount, out long existingBalance, out long existingAllowance, + MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, TransactionFeeDelegations delegations = null) { symbol = null; @@ -617,7 +629,7 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM amount = symbolToAmount.Value; // free allowance in current token symbol - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); // if delegations is null, that means no delegation is involved. if (delegations == null @@ -644,7 +656,7 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM { symbol = primaryTokenSymbol; existingBalance = GetBalance(fromAddress, primaryTokenSymbol); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); } else { @@ -652,7 +664,7 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM if (symbol != null) { existingBalance = GetBalance(fromAddress, symbolOfValidBalance); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); } } @@ -815,7 +827,7 @@ private void PayRental() } // Update LastPayRentTime if it is ready to charge rental. - State.LastPayRentTime.Value += new Duration {Seconds = duration.Mul(60)}; + State.LastPayRentTime.Value += new Duration { Seconds = duration.Mul(60) }; foreach (var symbol in Context.Variables.GetStringArray(TokenContractConstants.PayRentalSymbolListName)) { @@ -999,55 +1011,115 @@ public override Address GetFeeReceiver(Empty input) return State.FeeReceiver.Value; } - public override Empty ConfigMethodFeeFreeAllowances(MethodFeeFreeAllowancesConfig input) + public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowancesInput input) + { + AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); + Assert(string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol"); + Assert(input.MethodFeeFreeAllowances?.Value != null && input.MethodFeeFreeAllowances.Value.Count > 0, + "Invalid input allowances"); + Assert(input.Threshold > 0, "Invalid input threshold"); + Assert(input.RefreshSeconds > 0, "Invalid input refresh seconds"); + + State.MethodFeeFreeAllowancesConfigMap[input.Symbol].Threshold = input.Threshold; + State.MethodFeeFreeAllowancesConfigMap[input.Symbol].RefreshSeconds = input.RefreshSeconds; + State.MethodFeeFreeAllowancesConfigMap[input.Symbol].FreeAllowances = new MethodFeeFreeAllowanceMap(); + foreach (var allowance in input.MethodFeeFreeAllowances!.Value!) + { + State.MethodFeeFreeAllowancesConfigMap[input.Symbol].FreeAllowances.Map.Add(allowance.Symbol, allowance); + } + + if (!State.MethodFeeFreeAllowancesConfig.Value.Symbols.Contains(input.Symbol)) + { + State.MethodFeeFreeAllowancesConfig.Value.Symbols.Add(input.Symbol); + } + + return new Empty(); + } + + public override Empty RemoveMethodFeeFreeAllowancesConfig(RemoveMethodFeeFreeAllowancesConfigInput input) { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); - State.MethodFeeFreeAllowancesConfig.Value = input; + Assert(input.Symbols != null && input.Symbols.Count > 0, "Invalid input"); + Assert(State.MethodFeeFreeAllowancesConfig.Value != null, "Method fee free allowances config not set"); + + var symbols = input.Symbols!.Distinct(); + + foreach (var symbol in symbols) + { + if (State.MethodFeeFreeAllowancesConfig.Value!.Symbols.Contains(symbol)) + { + State.MethodFeeFreeAllowancesConfig.Value.Symbols.Remove(symbol); + } + } + return new Empty(); } - public override MethodFeeFreeAllowancesConfig GetMethodFeeFreeAllowancesConfig(Empty input) + public override GetMethodFeeFreeAllowancesConfigOutput GetMethodFeeFreeAllowancesConfig(Empty input) { - return State.MethodFeeFreeAllowancesConfig.Value; + var symbols = State.MethodFeeFreeAllowancesConfig.Value.Symbols; + var output = new GetMethodFeeFreeAllowancesConfigOutput(); + + foreach (var symbol in symbols) + { + output.Value.Add(State.MethodFeeFreeAllowancesConfigMap[symbol]); + } + + return output; } - public override MethodFeeFreeAllowances GetMethodFeeFreeAllowances(Address input) + public override MethodFeeFreeAllowancesMap GetMethodFeeFreeAllowances(Address input) { return CalculateMethodFeeFreeAllowances(input); } - private MethodFeeFreeAllowances CalculateMethodFeeFreeAllowances(Address input) + private MethodFeeFreeAllowancesMap CalculateMethodFeeFreeAllowances(Address input) { - var freeAllowances = State.MethodFeeFreeAllowancesMap[input]; + var freeAllowanceMap = State.MethodFeeFreeAllowancesMap[input]; + var freeAllowancesConfig = State.MethodFeeFreeAllowancesConfig.Value; if (freeAllowancesConfig == null) { - return new MethodFeeFreeAllowances(); + return new MethodFeeFreeAllowancesMap(); } var config = freeAllowancesConfig.Clone(); + var methodFeeFreeAllowancesMap = new MethodFeeFreeAllowancesMap(); - var balance = State.Balances[input][Context.Variables.NativeSymbol]; - if (balance < config.Threshold) return new MethodFeeFreeAllowances(); + foreach (var symbol in config.Symbols) + { + var balance = State.Balances[input][symbol]; + if (balance < State.MethodFeeFreeAllowancesConfigMap[symbol].Threshold) continue; - var lastRefreshTime = State.MethodFeeFreeAllowancesLastRefreshTimeMap[input]; + var lastRefreshTime = State.MethodFeeFreeAllowancesLastRefreshTimeMap[input][symbol]; - if (freeAllowances == null) - { - if (balance >= config.Threshold) + var freeAllowances = freeAllowanceMap[symbol]; + + if (freeAllowances == null) { - return new MethodFeeFreeAllowances {Value = {config.FreeAllowances.Value}}; + if (balance >= State.MethodFeeFreeAllowancesConfigMap[symbol].Threshold) + { + methodFeeFreeAllowancesMap.Map.Add(symbol, + State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances); + continue; + } } - } - if (lastRefreshTime == null) - { - return freeAllowances; + if (lastRefreshTime == null) + { + methodFeeFreeAllowancesMap.Map.Add(symbol, freeAllowances); + } + else + { + methodFeeFreeAllowancesMap.Map.Add(symbol, + (Context.CurrentBlockTime - lastRefreshTime).Seconds > + State.MethodFeeFreeAllowancesConfigMap[symbol].RefreshSeconds + ? State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances + : freeAllowances); + } } - return (Context.CurrentBlockTime - lastRefreshTime).Seconds > config.RefreshSeconds - ? new MethodFeeFreeAllowances {Value = {config.FreeAllowances.Value}} - : freeAllowances; + return methodFeeFreeAllowancesMap; } private long GetBalanceCalculatedBaseOnPrimaryToken(Address fromAddress, SymbolToPayTxSizeFee tokenInfo, @@ -1063,18 +1135,18 @@ private long GetBalanceCalculatedBaseOnPrimaryToken(Address fromAddress, SymbolT private long GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(Address fromAddress, SymbolToPayTxSizeFee tokenInfo, string baseSymbol, - long cost, MethodFeeFreeAllowances freeAllowances, long allowanceCost) + long cost, MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, long allowanceCost) { return GetBalanceCalculatedBaseOnPrimaryToken(fromAddress, tokenInfo, baseSymbol, cost).Add( - GetAllowanceCalculatedBaseOnPrimaryToken(tokenInfo, freeAllowances, baseSymbol, allowanceCost)); + GetAllowanceCalculatedBaseOnPrimaryToken(tokenInfo, methodFeeFreeAllowancesMap, baseSymbol, allowanceCost)); } private long GetAllowanceCalculatedBaseOnPrimaryToken(SymbolToPayTxSizeFee tokenInfo, - MethodFeeFreeAllowances freeAllowances, string baseSymbol, + MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, string baseSymbol, long allowanceCost) { var availableAllowance = - GetFreeFeeAllowanceAmount(freeAllowances, + GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, tokenInfo.TokenSymbol); //GetBalance(Context.Sender, tokenInfo.TokenSymbol); if (tokenInfo.TokenSymbol == baseSymbol) availableAllowance = availableAllowance.Sub(allowanceCost); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index d11e25b7de..70865a8550 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Linq; using System.Text; using AElf.Contracts.Parliament; @@ -15,7 +16,8 @@ public partial class TokenContract { private static bool IsValidSymbolChar(char character) { - return (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9') || character == TokenContractConstants.NFTSymbolSeparator; + return (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9') || + character == TokenContractConstants.NFTSymbolSeparator; } private bool IsValidItemIdChar(char character) @@ -76,41 +78,66 @@ private void ModifyBalance(Address address, string symbol, long addAmount) State.Balances[address][symbol] = target; } - private void ModifyFreeFeeAllowanceAmount(MethodFeeFreeAllowances freeAllowances, string symbol, long addAmount) + private void ModifyFreeFeeAllowanceAmount(Address fromAddress, + MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, string symbol, + long addAmount) { - var freeAllowance = GetFreeFeeAllowance(freeAllowances, symbol); - if (freeAllowance != null) + var freeAllowanceAmount = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); + if (addAmount < 0 && freeAllowanceAmount < -addAmount) { - var before = freeAllowance.Amount; - if (addAmount < 0 && before < -addAmount) - Assert(false, - $"Insufficient amount of {symbol} for free fee allowance. Need amount: {-addAmount}; Current amount: {before}"); + Assert(false, + $"Insufficient amount of {symbol} for free fee allowance. Need amount: {-addAmount}; Current amount: {freeAllowanceAmount}"); + } + + // var symbolList = methodFeeFreeAllowancesMap.Map.Keys; + var symbolList = GetSymbolListSortedByExpirationTime(methodFeeFreeAllowancesMap, fromAddress); + + foreach (var s in symbolList) + { + if (addAmount == 0) break; - var target = before.Add(addAmount); - freeAllowance.Amount = target; + var currentAllowance = methodFeeFreeAllowancesMap.Map[s].Map[symbol].Amount; + + addAmount += currentAllowance; + + methodFeeFreeAllowancesMap.Map[s].Map[symbol].Amount = addAmount >= 0 ? addAmount : 0; } } - private long GetBalance(Address address, string symbol) + private List GetSymbolListSortedByExpirationTime(MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, Address fromAddress) { - return State.Balances[address][symbol]; + return methodFeeFreeAllowancesMap.Map.Keys.OrderBy(t => + State.MethodFeeFreeAllowancesConfigMap[t].RefreshSeconds - (Context.CurrentBlockTime - + State.MethodFeeFreeAllowancesLastRefreshTimeMap[ + fromAddress][t]).Seconds).ToList(); } - private MethodFeeFreeAllowance GetFreeFeeAllowance(MethodFeeFreeAllowances freeAllowances, string symbol) + + private long GetBalance(Address address, string symbol) { - return freeAllowances?.Value.FirstOrDefault(a => a.Symbol == symbol); + return State.Balances[address][symbol]; } - private long GetFreeFeeAllowanceAmount(MethodFeeFreeAllowances freeAllowances, string symbol) + // private MethodFeeFreeAllowance GetFreeFeeAllowance(MethodFeeFreeAllowances freeAllowances, string symbol) + // { + // return freeAllowances?.Value.FirstOrDefault(a => a.Symbol == symbol); + // } + + private long GetFreeFeeAllowanceAmount(MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, string symbol) { - var existingAllowance = 0L; - var freeAllowance = GetFreeFeeAllowance(freeAllowances, symbol); - if (freeAllowance != null) + var allowance = 0L; + var map = methodFeeFreeAllowancesMap?.Map; + + if (map == null) return allowance; + + foreach (var freeAllowances in map.Values) { - existingAllowance = freeAllowance.Amount; + var freeAllowance = freeAllowances.Map.Values.FirstOrDefault(t => t.Symbol == symbol); + + allowance.Add(freeAllowance?.Amount ?? 0L); } - return existingAllowance; + return allowance; } private void AssertSystemContractOrLockWhiteListAddress(string symbol) diff --git a/protobuf/token_contract.proto b/protobuf/token_contract.proto index 6aea317b43..7c5582df0a 100644 --- a/protobuf/token_contract.proto +++ b/protobuf/token_contract.proto @@ -16,20 +16,20 @@ service TokenContract { // Create a new token. rpc Create (CreateInput) returns (google.protobuf.Empty) { } - + // Issuing some amount of tokens to an address is the action of increasing that addresses balance // for the given token. The total amount of issued tokens must not exceed the total supply of the token // and only the issuer (creator) of the token can issue tokens. // Issuing tokens effectively increases the circulating supply. rpc Issue (IssueInput) returns (google.protobuf.Empty) { } - + // Transferring tokens simply is the action of transferring a given amount of tokens from one address to another. // The origin or source address is the signer of the transaction. // The balance of the sender must be higher than the amount that is transferred. rpc Transfer (TransferInput) returns (google.protobuf.Empty) { } - + // The TransferFrom action will transfer a specified amount of tokens from one address to another. // For this operation to succeed the from address needs to have approved (see allowances) enough tokens // to Sender of this transaction. If successful the amount will be removed from the allowance. @@ -40,23 +40,23 @@ service TokenContract { // enabling the Spender to call TransferFrom. rpc Approve (ApproveInput) returns (google.protobuf.Empty) { } - + // This is the reverse operation for Approve, it will decrease the allowance. rpc UnApprove (UnApproveInput) returns (google.protobuf.Empty) { } - + // This method can be used to lock tokens. rpc Lock (LockInput) returns (google.protobuf.Empty) { } - + // This is the reverse operation of locking, it un-locks some previously locked tokens. rpc Unlock (UnlockInput) returns (google.protobuf.Empty) { } - + // This action will burn the specified amount of tokens, removing them from the token’s Supply. rpc Burn (BurnInput) returns (google.protobuf.Empty) { } - + // Change the issuer of the specified token. Only the original issuer can change it. rpc ChangeTokenIssuer (ChangeTokenIssuerInput) returns (google.protobuf.Empty) { } @@ -64,19 +64,19 @@ service TokenContract { // Set the primary token of side chain. rpc SetPrimaryTokenSymbol (SetPrimaryTokenSymbolInput) returns (google.protobuf.Empty) { } - + // This interface is used for cross-chain transfer. rpc CrossChainTransfer (CrossChainTransferInput) returns (google.protobuf.Empty) { } - + // This method is used to receive cross-chain transfers. rpc CrossChainReceiveToken (CrossChainReceiveTokenInput) returns (google.protobuf.Empty) { } - + // The side chain creates tokens. - rpc CrossChainCreateToken(CrossChainCreateTokenInput) returns (google.protobuf.Empty) { + rpc CrossChainCreateToken(CrossChainCreateTokenInput) returns (google.protobuf.Empty) { } - + // When the side chain is started, the side chain is initialized with the parent chain information. rpc InitializeFromParentChain (InitializeFromParentChainInput) returns (google.protobuf.Empty) { } @@ -84,13 +84,13 @@ service TokenContract { // Handle the transaction fees charged by ChargeTransactionFees. rpc ClaimTransactionFees (TotalTransactionFeesMap) returns (google.protobuf.Empty) { } - + // Used to collect transaction fees. rpc ChargeTransactionFees (ChargeTransactionFeesInput) returns (ChargeTransactionFeesOutput) { } - + rpc ChargeUserContractTransactionFees(ChargeTransactionFeesInput) returns(ChargeTransactionFeesOutput){ - + } // Check the token threshold. @@ -100,31 +100,31 @@ service TokenContract { // Initialize coefficients of every type of tokens supporting charging fee. rpc InitialCoefficients (google.protobuf.Empty) returns (google.protobuf.Empty){ } - + // Processing resource token received. rpc DonateResourceToken (TotalResourceTokensMaps) returns (google.protobuf.Empty) { } - + // A transaction resource fee is charged to implement the ACS8 standards. rpc ChargeResourceToken (ChargeResourceTokenInput) returns (google.protobuf.Empty) { } - + // Verify that the resource token are sufficient. rpc CheckResourceToken (google.protobuf.Empty) returns (google.protobuf.Empty) { } - + // Set the list of tokens to pay transaction fees. rpc SetSymbolsToPayTxSizeFee (SymbolListToPayTxSizeFee) returns (google.protobuf.Empty){ } - + // Update the coefficient of the transaction fee calculation formula. rpc UpdateCoefficientsForSender (UpdateCoefficientsInput) returns (google.protobuf.Empty) { } - + // Update the coefficient of the transaction fee calculation formula. rpc UpdateCoefficientsForContract (UpdateCoefficientsInput) returns (google.protobuf.Empty) { } - + // This method is used to initialize the governance organization for some functions, // including: the coefficient of the user transaction fee calculation formula, // the coefficient of the contract developer resource fee calculation formula, and the side chain rental fee. @@ -133,75 +133,72 @@ service TokenContract { rpc ResetExternalInfo (ResetExternalInfoInput) returns (google.protobuf.Empty){ } - + rpc AddAddressToCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) { } rpc RemoveAddressFromCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) { } - - rpc ConfigMethodFeeFreeAllowances (MethodFeeFreeAllowancesConfig) returns (google.protobuf.Empty) { - } - + rpc SetTransactionFeeDelegations (SetTransactionFeeDelegationsInput) returns (SetTransactionFeeDelegationsOutput){ } - + rpc RemoveTransactionFeeDelegator (RemoveTransactionFeeDelegatorInput) returns (google.protobuf.Empty){ } rpc RemoveTransactionFeeDelegatee (RemoveTransactionFeeDelegateeInput) returns (google.protobuf.Empty){ } - + // Get all delegatees' address of delegator from input rpc GetTransactionFeeDelegatees (GetTransactionFeeDelegateesInput) returns (GetTransactionFeeDelegateesOutput) { - + } // Query token information. rpc GetTokenInfo (GetTokenInfoInput) returns (TokenInfo) { option (aelf.is_view) = true; } - + // Query native token information. rpc GetNativeTokenInfo (google.protobuf.Empty) returns (TokenInfo) { option (aelf.is_view) = true; } - + // Query resource token information. rpc GetResourceTokenInfo (google.protobuf.Empty) returns (TokenInfoList) { option (aelf.is_view) = true; } - + // Query the balance at the specified address. rpc GetBalance (GetBalanceInput) returns (GetBalanceOutput) { option (aelf.is_view) = true; } - + // Query the account's allowance for other addresses rpc GetAllowance (GetAllowanceInput) returns (GetAllowanceOutput) { option (aelf.is_view) = true; } - + // Check whether the token is in the whitelist of an address, // which can be called TransferFrom to transfer the token under the condition of not being credited. rpc IsInWhiteList (IsInWhiteListInput) returns (google.protobuf.BoolValue) { option (aelf.is_view) = true; } - + // Query the information for a lock. rpc GetLockedAmount (GetLockedAmountInput) returns (GetLockedAmountOutput) { option (aelf.is_view) = true; } - + // Query the address of receiving token in cross-chain transfer. rpc GetCrossChainTransferTokenContractAddress (GetCrossChainTransferTokenContractAddressInput) returns (aelf.Address) { option (aelf.is_view) = true; } - + // Query the name of the primary Token. rpc GetPrimaryTokenSymbol (google.protobuf.Empty) returns (google.protobuf.StringValue) { option (aelf.is_view) = true; } - + // Query the coefficient of the transaction fee calculation formula. rpc GetCalculateFeeCoefficientsForContract (google.protobuf.Int32Value) returns (CalculateFeeCoefficients) { option (aelf.is_view) = true; @@ -211,17 +208,17 @@ service TokenContract { rpc GetCalculateFeeCoefficientsForSender (google.protobuf.Empty) returns (CalculateFeeCoefficients) { option (aelf.is_view) = true; } - + // Query tokens that can pay transaction fees. rpc GetSymbolsToPayTxSizeFee (google.protobuf.Empty) returns (SymbolListToPayTxSizeFee){ option (aelf.is_view) = true; } - + // Query the hash of the last input of ClaimTransactionFees. rpc GetLatestTotalTransactionFeesMapHash (google.protobuf.Empty) returns (aelf.Hash){ option (aelf.is_view) = true; } - + // Query the hash of the last input of DonateResourceToken. rpc GetLatestTotalResourceTokensMapsHash (google.protobuf.Empty) returns (aelf.Hash){ option (aelf.is_view) = true; @@ -232,15 +229,9 @@ service TokenContract { rpc GetReservedExternalInfoKeyList (google.protobuf.Empty) returns (StringList) { option (aelf.is_view) = true; } - rpc GetMethodFeeFreeAllowances (aelf.Address) returns (MethodFeeFreeAllowances) { - option (aelf.is_view) = true; - } - rpc GetMethodFeeFreeAllowancesConfig (google.protobuf.Empty) returns (MethodFeeFreeAllowancesConfig) { - option (aelf.is_view) = true; - } - + rpc GetTransactionFeeDelegationsOfADelegatee(GetTransactionFeeDelegationsOfADelegateeInput) returns(TransactionFeeDelegations){ - option (aelf.is_view) = true; + option (aelf.is_view) = true; } } @@ -321,7 +312,7 @@ message TransferInput { message LockInput { // The one want to lock his token. - aelf.Address address = 1; + aelf.Address address = 1; // Id of the lock. aelf.Hash lock_id = 2; // The symbol of the token to lock. @@ -661,21 +652,6 @@ message StringList { repeated string value = 1; } -message MethodFeeFreeAllowancesConfig { - MethodFeeFreeAllowances free_allowances = 1; - int64 refresh_seconds = 2; - int64 threshold = 3; -} - -message MethodFeeFreeAllowances { - repeated MethodFeeFreeAllowance value = 1; -} - -message MethodFeeFreeAllowance { - string symbol = 1; - int64 amount = 2; -} - message TransactionFeeDelegations{ // delegation, symbols and its' amount map delegations = 1; @@ -687,7 +663,7 @@ message TransactionFeeDelegatees{ map delegatees = 1; } -message SetTransactionFeeDelegationsInput { +message SetTransactionFeeDelegationsInput { // the delegator address aelf.Address delegator_address = 1; // delegation, symbols and its' amount diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index 939c15344f..88e7eb5da9 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -77,6 +77,12 @@ service TokenContractImpl { rpc ChangeDeveloperController (AuthorityInfo) returns (google.protobuf.Empty) { } + rpc ConfigMethodFeeFreeAllowances (ConfigMethodFeeFreeAllowancesInput) returns (google.protobuf.Empty) { + } + + rpc RemoveMethodFeeFreeAllowancesConfig (RemoveMethodFeeFreeAllowancesConfigInput) returns (google.protobuf.Empty) { + } + // Get the address of fee receiver. rpc GetFeeReceiver (google.protobuf.Empty) returns (aelf.Address){ option (aelf.is_view) = true; @@ -128,6 +134,14 @@ service TokenContractImpl { rpc GetOwningRentalUnitValue (google.protobuf.Empty) returns (OwningRentalUnitValue) { option (aelf.is_view) = true; } + + // Query + rpc GetMethodFeeFreeAllowances (aelf.Address) returns (MethodFeeFreeAllowancesMap) { + option (aelf.is_view) = true; + } + rpc GetMethodFeeFreeAllowancesConfig (google.protobuf.Empty) returns (GetMethodFeeFreeAllowancesConfigOutput) { + option (aelf.is_view) = true; + } } message AdvanceResourceTokenInput { @@ -244,3 +258,45 @@ enum SymbolType { NFT = 1; NFT_COLLECTION = 2; } + +message MethodFeeFreeAllowancesConfig { + repeated string symbols = 1; +} + +message ConfigMethodFeeFreeAllowancesInput { + string symbol = 1; + MethodFeeFreeAllowances method_fee_free_allowances = 2; + int64 refresh_seconds = 3; + int64 threshold = 4; +} + +message RemoveMethodFeeFreeAllowancesConfigInput { + repeated string symbols = 1; +} + +message GetMethodFeeFreeAllowancesConfigOutput { + repeated FreeAllowanceConfig value = 1; +} + +message FreeAllowanceConfig { + MethodFeeFreeAllowanceMap free_allowances = 1; + int64 refresh_seconds = 2; + int64 threshold = 3; +} + +message MethodFeeFreeAllowanceMap { + map map = 1; +} + +message MethodFeeFreeAllowancesMap { + map map = 1; +} + +message MethodFeeFreeAllowances{ + repeated MethodFeeFreeAllowance value = 1; +} + +message MethodFeeFreeAllowance { + string symbol = 1; + int64 amount = 2; +} \ No newline at end of file From d1119c37cbb67803ad327af88bef825194f03eda Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Thu, 1 Jun 2023 18:13:13 +0800 Subject: [PATCH 014/139] feat: add charge transaction fee unit test. --- .../ExecutePluginTransactionDirectlyTest.cs | 1011 ++++++++++++----- .../ExecutionPluginForMethodFeeTestBase.cs | 57 +- 2 files changed, 790 insertions(+), 278 deletions(-) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 61fc563335..04b3d8c760 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -559,7 +559,7 @@ public async Task ChargeTransactionFee_Delegate( await CreateTokenAsync(DefaultSender, sizeFeeSymbol); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); await IssueTokenToUserAsync(NativeTokenSymbol, initialUserBalance, userAddress); var delegations = new Dictionary @@ -568,20 +568,21 @@ public async Task ChargeTransactionFee_Delegate( [basicFeeSymbol] = delegateeAmountBasic, [sizeFeeSymbol] = delegateeAmountSize }; - var transactionResult = await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransactionFeeDelegationsInput - { - DelegatorAddress = DefaultSender, - Delegations = + var transactionResult = await TokenContractStub2.SetTransactionFeeDelegations.SendAsync( + new SetTransactionFeeDelegationsInput { - delegations - } - }); + DelegatorAddress = DefaultSender, + Delegations = + { + delegations + } + }); // Test Case 11 { var result = await TokenContractStubA.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); result.BlockHeight.ShouldBe(transactionResult.TransactionResult.BlockNumber); @@ -590,7 +591,7 @@ public async Task ChargeTransactionFee_Delegate( var result = await TokenContractStub.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); result.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); @@ -602,8 +603,8 @@ public async Task ChargeTransactionFee_Delegate( { await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); await IssueTokenToUserAsync(basicFeeSymbol, baseFeeUserBalance, userAddress); await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeUserBalance, userAddress); } @@ -706,7 +707,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var delegationResult = await TokenContractStub.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); var chargeFeeRetDefault = @@ -714,7 +715,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2) { chargeFeeRetDefault.Output.Success.ShouldBe(true); - + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, @@ -725,13 +726,13 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, - Owner = delegateeAddress + Owner = DelegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); var delegation = await TokenContractStub.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); @@ -739,11 +740,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, else { chargeFeeRetDefault.Output.Success.ShouldBe(false); - + var delegation = await TokenContractStub.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); delegation.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); @@ -771,7 +772,7 @@ public async Task ChargeTransactionFee_Delegate_Failed( await CreateTokenAsync(DefaultSender, sizeFeeSymbol); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); var delegations = new Dictionary { @@ -791,7 +792,7 @@ await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransacti var result = await TokenContractStub.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); result.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); @@ -802,8 +803,8 @@ await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransacti { await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, @@ -890,13 +891,13 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, - Owner = delegateeAddress + Owner = DelegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); var delegation = await TokenContractStub.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); delegation.Delegations[sizeFeeSymbol].ShouldBe(afterDelegateeAmount); @@ -913,8 +914,8 @@ public async Task ChargeTransactionFee_Delegate_DefaultSizeFee( await SetPrimaryTokenSymbolAsync(); await CreateTokenAsync(DefaultSender, basicFeeSymbol); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); - await IssueTokenToUserAsync(basicFeeSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, initialDelegateeBalance, DelegateeAddress); var delegations = new Dictionary { @@ -933,7 +934,7 @@ await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransacti var result = await TokenContractStub.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = userAddress }); result.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); @@ -975,14 +976,14 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, - Owner = delegateeAddress + Owner = DelegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(exceptDelegateeBalance); var afterDelegateeElfBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = NativeTokenSymbol, - Owner = delegateeAddress + Owner = DelegateeAddress }); afterDelegateeElfBalance.Balance.ShouldBe(exceptDelegateeElfBalance); } @@ -1006,8 +1007,22 @@ public async Task ChargeTransactionFee_DelegateNew_First( await CreateTokenAsync(DefaultSender, sizeFeeSymbol); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); await IssueTokenToUserAsync(NativeTokenSymbol, initialUserBalance, userAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialUserBalance, UserTomSender); + if (baseFeeBalance != 0 && sizeFeeBalance != 0 && + baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && + baseFeeUserBalance != 0 && sizeFeeUserBalance != 0) + { + await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); + await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeUserBalance, userAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeUserBalance, userAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeUserBalance, UserTomSender); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeUserBalance, UserTomSender); + } var delegations = new Dictionary { @@ -1015,6 +1030,10 @@ public async Task ChargeTransactionFee_DelegateNew_First( [basicFeeSymbol] = delegateeAmountBasic, [sizeFeeSymbol] = delegateeAmountSize }; + var delegations1 = new Dictionary + { + [NativeTokenSymbol] = 5, + }; var delegateInfo1 = new DelegateInfo { Delegations = { delegations }, @@ -1022,18 +1041,58 @@ public async Task ChargeTransactionFee_DelegateNew_First( MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), ContractAddress = TokenContractAddress, }; + var delegateInfo2 = new DelegateInfo + { + Delegations = { delegations }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.TransferFrom), + ContractAddress = TokenContractAddress, + }; + var delegateInfo3 = new DelegateInfo + { + Delegations = { delegations }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.TransferFrom), + ContractAddress = ConsensusContractAddress, + }; + var delegateInfo4 = new DelegateInfo + { + Delegations = { delegations1 }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; var transactionResult = await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( new SetTransactionFeeDelegateInfosInput { DelegatorAddress = DefaultSender, DelegateInfoList = { delegateInfo1 } }); - // Test Case 11 + //delegate User transferFrom method + var transactionResult1 = await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = userAddress, + DelegateInfoList = { delegateInfo2 } + }); + //delegate User ConsensusContract + var transactionResult2 = await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = userAddress, + DelegateInfoList = { delegateInfo3 } + }); + var transactionResult3 = await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = UserTomSender, + DelegateInfoList = { delegateInfo4 } + }); { var result = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( new GetTransactionFeeDelegateInfosOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) @@ -1042,16 +1101,40 @@ public async Task ChargeTransactionFee_DelegateNew_First( result.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); } - if (baseFeeBalance != 0 && sizeFeeBalance != 0 && - baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && - baseFeeUserBalance != 0 && sizeFeeUserBalance != 0) + var delegationsBefore = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = DelegateeAddress, + DelegatorAddress = userAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.TransferFrom) + }); + delegationsBefore.BlockHeight.ShouldBe(transactionResult1.TransactionResult.BlockNumber); + delegationsBefore.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); + + + var delegationBefore2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = DelegateeAddress, + DelegatorAddress = userAddress, + ContractAddress = ConsensusContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.TransferFrom) + }); + delegationBefore2.BlockHeight.ShouldBe(transactionResult2.TransactionResult.BlockNumber); + delegationBefore2.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); + { - await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); - await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeUserBalance, userAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeUserBalance, userAddress); + var result = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = DelegateeAddress, + DelegatorAddress = UserTomSender, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + result.BlockHeight.ShouldBe(transactionResult3.TransactionResult.BlockNumber); + result.Delegations[NativeTokenSymbol].ShouldBe(5); } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, @@ -1090,53 +1173,18 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Value.ShouldBeEmpty(); } } - - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = basicFeeSymbol, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = sizeFeeSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - - + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); + var chargeTransactionFeesInput = new ChargeTransactionFeesInput { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), ContractAddress = TokenContractAddress, TransactionSizeFee = sizeFee, }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); { - var chargeFeeRetUser = await TokenContractStub3.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + var chargeFeeRetUser = await TokenContractStubA.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRetUser.Output.Success.ShouldBe(false); chargeFeeRetUser.Output.ChargingInformation.ShouldBe("Transaction fee not enough."); @@ -1147,13 +1195,47 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }); afterBalance.Balance.ShouldBe(0); } - // Test Case 12 + { + var chargeFeeRetUser = + await TokenContractStubDelegator.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRetUser.Output.Success.ShouldBe(false); + chargeFeeRetUser.Output.ChargingInformation.ShouldBe("Transaction fee not enough."); + + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = UserTomSender + }); + afterBalance.Balance.ShouldBe(0); + } + var delegationsAfter = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = DelegateeAddress, + DelegatorAddress = userAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.TransferFrom) + }); + delegationsAfter.BlockHeight.ShouldBe(transactionResult1.TransactionResult.BlockNumber); + delegationsAfter.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); + + + var delegationAfter2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = DelegateeAddress, + DelegatorAddress = DefaultSender, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegationAfter2.BlockHeight.ShouldBe(transactionResult.TransactionResult.BlockNumber); + delegationAfter2.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); { var delegationResult = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( new GetTransactionFeeDelegateInfosOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) @@ -1174,13 +1256,13 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, - Owner = delegateeAddress + Owner = DelegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( new GetTransactionFeeDelegateInfosOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) @@ -1194,7 +1276,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( new GetTransactionFeeDelegateInfosOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) @@ -1205,7 +1287,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call } [Theory] - [InlineData( 10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] + [InlineData(10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] public async Task ChargeTransactionFee_DelegationNew_Second_Success( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, @@ -1221,7 +1303,7 @@ public async Task ChargeTransactionFee_DelegationNew_Second_Success( await CreateTokenAsync(DefaultSender, sizeFeeSymbol); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); if (baseFeeBalance != 0 && sizeFeeBalance != 0 && baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && @@ -1229,8 +1311,8 @@ public async Task ChargeTransactionFee_DelegationNew_Second_Success( { await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); } @@ -1268,46 +1350,11 @@ await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( new SetTransactionFeeDelegateInfosInput { - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, DelegateInfoList = { delegateInfo2 } }); - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = basicFeeSymbol, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = sizeFeeSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -1320,7 +1367,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( new GetTransactionFeeDelegateInfosOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) @@ -1330,12 +1377,13 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call new GetTransactionFeeDelegateInfosOfADelegateeInput { DelegateeAddress = Delegatee2Address, - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && + chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) { chargeFeeRetDefault.Output.Success.ShouldBe(true); @@ -1351,10 +1399,10 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, - Owner = delegateeAddress + Owner = DelegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(20); - + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, @@ -1365,7 +1413,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call new GetTransactionFeeDelegateInfosOfADelegateeInput { DelegateeAddress = Delegatee2Address, - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); @@ -1378,7 +1426,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( new GetTransactionFeeDelegateInfosOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) @@ -1388,16 +1436,17 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call new GetTransactionFeeDelegateInfosOfADelegateeInput { DelegateeAddress = Delegatee2Address, - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); delegation2.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); } } + [Theory] - [InlineData( 10, 20, 70, 1000, 1000, 1000, 10, 10, 20, 20, 70, 70, 80, 80, 70, 1000)] - public async Task ChargeTransactionFee_DelegationNew_Second_Failed( + [InlineData(10, 20, 70, 1000, 1000, 1000, 10, 10, 20, 20, 70, 70, 80, 80, 70, 1000)] + public async Task ChargeTransactionFee_DelegationNew_Second_Failed_DelegateeBalanceIsNotEnough( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, @@ -1412,7 +1461,7 @@ public async Task ChargeTransactionFee_DelegationNew_Second_Failed( await CreateTokenAsync(DefaultSender, sizeFeeSymbol); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); if (baseFeeBalance != 0 && sizeFeeBalance != 0 && baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && @@ -1420,8 +1469,8 @@ public async Task ChargeTransactionFee_DelegationNew_Second_Failed( { await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); } @@ -1459,46 +1508,11 @@ await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( new SetTransactionFeeDelegateInfosInput { - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, DelegateInfoList = { delegateInfo2 } }); - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = basicFeeSymbol, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = sizeFeeSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -1511,7 +1525,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( new GetTransactionFeeDelegateInfosOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) @@ -1521,12 +1535,13 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call new GetTransactionFeeDelegateInfosOfADelegateeInput { DelegateeAddress = Delegatee2Address, - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && + chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) { chargeFeeRetDefault.Output.Success.ShouldBe(false); chargeFeeRetDefault.Output.ChargingInformation.ShouldBe("Transaction fee not enough."); @@ -1543,10 +1558,10 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, - Owner = delegateeAddress + Owner = DelegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(20); - + //no change var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { @@ -1558,7 +1573,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call new GetTransactionFeeDelegateInfosOfADelegateeInput { DelegateeAddress = Delegatee2Address, - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); @@ -1569,9 +1584,10 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call chargeFeeRetDefault.Output.Success.ShouldBe(false); } } + [Theory] - [InlineData( 10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] - public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( + [InlineData(10, 20, 100, 30, 30, 30, 10, 10, 20, 20, 100, 100, 80, 80, 100, 30)] + public async Task ChargeTransactionFee_DelegationNew_Second_Failed_DelegationIsNotEnough( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, @@ -1586,7 +1602,7 @@ public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( await CreateTokenAsync(DefaultSender, sizeFeeSymbol); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); if (baseFeeBalance != 0 && sizeFeeBalance != 0 && baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && @@ -1594,8 +1610,8 @@ public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( { await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); } @@ -1610,6 +1626,13 @@ public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( [basicFeeSymbol] = delegateeAmountBasic, [sizeFeeSymbol] = delegateeAmountSize }; + var delegateInfo1 = new DelegateInfo + { + Delegations = { delegations }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; var delegateInfo2 = new DelegateInfo { Delegations = { delegations2 }, @@ -1617,56 +1640,240 @@ public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), ContractAddress = TokenContractAddress, }; - await TokenContractStubDelegate1.SetTransactionFeeDelegations.SendAsync( - new SetTransactionFeeDelegationsInput + await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput { DelegatorAddress = DefaultSender, - Delegations = { delegations } + DelegateInfoList = { delegateInfo1 } }); await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( new SetTransactionFeeDelegateInfosInput { - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, DelegateInfoList = { delegateInfo2 } }); - var methodFee = new MethodFees + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = basicFeeSymbol, - BasicFee = basicFee - } - } + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRetDefault.Output.Success.ShouldBe(false); - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = + //no change + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { - new SymbolToPayTxSizeFee - { - TokenSymbol = sizeFeeSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } + Symbol = basicFeeSymbol, + Owner = DefaultSender + }); + afterBalance.Balance.ShouldBe(0); + + //no change + var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = DelegateeAddress + }); + afterDelegateeBalance.Balance.ShouldBe(20); + + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = Delegatee2Address + }); + afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = DelegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); + } + + [Theory] + [InlineData(10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 100, 1000)] + public async Task ChargeTransactionFee_DelegationNew_Second_Failed_DelegateIsNotExist( + long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, + long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, + long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, + long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, + long basicFee, long sizeFee, long afterBalanceDelegatee, long afterDelegateeAmount) + { + var basicFeeSymbol = "BASIC"; + var sizeFeeSymbol = "SIZE"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, basicFeeSymbol); + await CreateTokenAsync(DefaultSender, sizeFeeSymbol); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); + if (baseFeeBalance != 0 && sizeFeeBalance != 0 && + baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && + baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) + { + await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); + await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); + } + + var delegations = new Dictionary + { + [NativeTokenSymbol] = 5, }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + var delegations2 = new Dictionary + { + [NativeTokenSymbol] = delegateeAmountNativeToken, + [basicFeeSymbol] = delegateeAmountBasic, + [sizeFeeSymbol] = delegateeAmountSize + }; + var delegateInfo1 = new DelegateInfo + { + Delegations = { delegations }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; + var delegateInfo2 = new DelegateInfo + { + Delegations = { delegations2 }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = ConsensusContractAddress, + }; + await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DefaultSender, + DelegateInfoList = { delegateInfo1 } + }); + await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DelegateeAddress, + DelegateInfoList = { delegateInfo2 } + }); + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,basicFee); + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRetDefault.Output.Success.ShouldBe(false); + + //no change + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = DefaultSender + }); + afterBalance.Balance.ShouldBe(0); + + //no change + var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = DelegateeAddress + }); + afterDelegateeBalance.Balance.ShouldBe(20); + + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = Delegatee2Address + }); + afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = Delegatee2Address, + DelegatorAddress = DelegateeAddress, + ContractAddress = ConsensusContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); + } + + [Theory] + [InlineData(10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] + public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( + long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, + long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, + long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, + long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, + long basicFee, long sizeFee, long afterBalanceDelegatee, long afterDelegateeAmount) + { + var basicFeeSymbol = "BASIC"; + var sizeFeeSymbol = "SIZE"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, basicFeeSymbol); + await CreateTokenAsync(DefaultSender, sizeFeeSymbol); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); + if (baseFeeBalance != 0 && sizeFeeBalance != 0 && + baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && + baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) + { + await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); + await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); + } + + var delegations = new Dictionary + { + [NativeTokenSymbol] = 5, + }; + var delegations2 = new Dictionary + { + [NativeTokenSymbol] = delegateeAmountNativeToken, + [basicFeeSymbol] = delegateeAmountBasic, + [sizeFeeSymbol] = delegateeAmountSize + }; + var delegateInfo2 = new DelegateInfo + { + Delegations = { delegations2 }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; + await TokenContractStubDelegate1.SetTransactionFeeDelegations.SendAsync( + new SetTransactionFeeDelegationsInput + { + DelegatorAddress = DefaultSender, + Delegations = { delegations } + }); + await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DelegateeAddress, + DelegateInfoList = { delegateInfo2 } + }); + + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,basicFee); + var chargeTransactionFeesInput = new ChargeTransactionFeesInput { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), @@ -1678,7 +1885,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); var delegationResult2 = @@ -1686,12 +1893,13 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call new GetTransactionFeeDelegateInfosOfADelegateeInput { DelegateeAddress = Delegatee2Address, - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && + chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) { chargeFeeRetDefault.Output.Success.ShouldBe(true); @@ -1707,10 +1915,10 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, - Owner = delegateeAddress + Owner = DelegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(20); - + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, @@ -1721,7 +1929,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call new GetTransactionFeeDelegateInfosOfADelegateeInput { DelegateeAddress = Delegatee2Address, - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); @@ -1734,7 +1942,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); delegation.Delegations[NativeTokenSymbol].ShouldBe(5); @@ -1742,16 +1950,16 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call new GetTransactionFeeDelegateInfosOfADelegateeInput { DelegateeAddress = Delegatee2Address, - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); delegation2.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); } } - + [Theory] - [InlineData( 10, 20, 100, 10, 10, 20, 20, 100, 100, 80, 80, 20)] + [InlineData(10, 20, 100, 10, 10, 20, 20, 100, 100, 80, 80, 20)] public async Task ChargeTransactionFee_DelegationNew_UnlimitedDelegate_Success( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, @@ -1766,7 +1974,7 @@ public async Task ChargeTransactionFee_DelegationNew_UnlimitedDelegate_Success( await CreateTokenAsync(DefaultSender, sizeFeeSymbol); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, delegateeAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); if (baseFeeBalance != 0 && sizeFeeBalance != 0 && baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && @@ -1774,8 +1982,8 @@ public async Task ChargeTransactionFee_DelegationNew_UnlimitedDelegate_Success( { await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); + await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); + await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); } @@ -1799,46 +2007,11 @@ await TokenContractStubDelegate1.SetTransactionFeeDelegations.SendAsync( await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( new SetTransactionFeeDelegateInfosInput { - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, DelegateInfoList = { delegateInfo2 } }); - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = basicFeeSymbol, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = sizeFeeSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,basicFee); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -1851,7 +2024,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); var delegationResult2 = @@ -1859,12 +2032,13 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call new GetTransactionFeeDelegateInfosOfADelegateeInput { DelegateeAddress = Delegatee2Address, - DelegatorAddress = delegateeAddress, + DelegatorAddress = DelegateeAddress, ContractAddress = TokenContractAddress, MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && + chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) { chargeFeeRetDefault.Output.Success.ShouldBe(true); @@ -1880,10 +2054,10 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, - Owner = delegateeAddress + Owner = DelegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(20); - + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, @@ -1898,13 +2072,296 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { - DelegateeAddress = delegateeAddress, + DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender }); delegation.Delegations[NativeTokenSymbol].ShouldBe(5); } } + + [Fact] + public async Task ChargeTransactionFee_DelegationNew_MultiDelegate_Success() + { + var basicFeeSymbol = "BASIC"; + var sizeFeeSymbol = "SIZE"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, basicFeeSymbol); + await CreateTokenAsync(DefaultSender, sizeFeeSymbol); + + var tokenList = new List { NativeTokenSymbol, basicFeeSymbol, sizeFeeSymbol }; + await IssueTokenListToUserAsync(tokenList, 10, DefaultSender); + await IssueTokenListToUserAsync(tokenList, 20, DelegateeAddress); + await IssueTokenListToUserAsync(tokenList, 100, Delegatee2Address); + await IssueTokenListToUserAsync(tokenList, 20, Delegatee3Address); + await IssueTokenListToUserAsync(tokenList, 20, SecondaryDelegatee1Address); + await IssueTokenListToUserAsync(tokenList, 100, SecondaryDelegatee2Address); + await IssueTokenListToUserAsync(tokenList, 20, SecondaryDelegatee3Address); + await IssueTokenListToUserAsync(tokenList, 20, SecondaryDelegatee4Address); + await IssueTokenListToUserAsync(tokenList, 200, SecondaryDelegatee5Address); + await IssueTokenListToUserAsync(tokenList, 100, SecondaryDelegatee6Address); + + //first delegate + //delegatee1 -> default sender, balance is not enough + //delegatee2 -> default sender, delegation is not enough + //delegatee3 -> default sender, balance and delegation is not enough + var delegations1 = new Dictionary + { + [NativeTokenSymbol] = 100, + [basicFeeSymbol] = 100, + [sizeFeeSymbol] = 100, + }; + var delegations2 = new Dictionary + { + [NativeTokenSymbol] = 10 + }; + var delegations3 = new Dictionary + { + [NativeTokenSymbol] = 30, + [basicFeeSymbol] = 100 + }; + var delegateInfo1 = new DelegateInfo + { + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + Delegations = { delegations1 } + }; + var delegateInfo2 = new DelegateInfo + { + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + Delegations = { delegations2 } + }; + var delegateInfo3 = new DelegateInfo + { + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + Delegations = { delegations3 } + }; + await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DefaultSender, + DelegateInfoList = { delegateInfo1 }, + }); + await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DefaultSender, + DelegateInfoList = { delegateInfo2 } + }); + await TokenContractStubDelegate3.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DefaultSender, + DelegateInfoList = { delegateInfo3 } + }); + //second delegate + //secondary delegatee1 -> delegatee1, balance is not enough + //secondary delegatee2 -> delegatee1, delegation is not enough + //secondary delegatee3 -> delegatee1, balance and delegation is not enough + //secondary delegatee4 -> delegatee2, balance is not enough + //secondary delegatee5 -> delegatee2, success + //secondary delegatee6 -> delegatee3 + await TokenContractStubSecondaryDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DelegateeAddress, + DelegateInfoList = { delegateInfo1 } + }); + await TokenContractStubSecondaryDelegate2.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DelegateeAddress, + DelegateInfoList = { delegateInfo2 } + }); + await TokenContractStubSecondaryDelegate3.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DelegateeAddress, + DelegateInfoList = { delegateInfo3 } + }); + await TokenContractStubSecondaryDelegate4.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = Delegatee2Address, + DelegateInfoList = { delegateInfo1 } + }); + await TokenContractStubSecondaryDelegate5.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = Delegatee2Address, + DelegateInfoList = { delegateInfo1 } + }); + await TokenContractStubSecondaryDelegate6.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = Delegatee3Address, + DelegateInfoList = { delegateInfo3 } + }); + + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol, sizeFeeSymbol, 80); + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = 80, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var delegateList = new List<(Address, Address)> + { + (DelegateeAddress, DefaultSender), + (Delegatee2Address, DefaultSender), + (Delegatee3Address, DefaultSender), + (SecondaryDelegatee1Address, DelegateeAddress), + (SecondaryDelegatee2Address, DelegateeAddress), + (SecondaryDelegatee3Address, DelegateeAddress), + (SecondaryDelegatee4Address, Delegatee2Address), + (SecondaryDelegatee5Address, Delegatee2Address), + (SecondaryDelegatee6Address, Delegatee3Address), + (DelegateeAddress, DefaultSender), + (DelegateeAddress, DefaultSender), + (DelegateeAddress, DefaultSender) + }; + + var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + var result = await GetSetDelegationResultAsync(delegateList, chargeFeeRetDefault.Transaction.RefBlockNumber); + if (result) + { + chargeFeeRetDefault.Output.Success.ShouldBe(true); + await CheckUserBalanceAsync(NativeTokenSymbol, DefaultSender, 10); + await CheckUserBalanceAsync(basicFeeSymbol, DelegateeAddress, 20); + await CheckUserBalanceAsync(basicFeeSymbol, Delegatee2Address, 100); + await CheckUserBalanceAsync(NativeTokenSymbol, Delegatee3Address, 20); + await CheckUserBalanceAsync(basicFeeSymbol, SecondaryDelegatee1Address, 20); + await CheckUserBalanceAsync(basicFeeSymbol, SecondaryDelegatee2Address, 100); + await CheckUserBalanceAsync(NativeTokenSymbol, SecondaryDelegatee3Address, 20); + await CheckUserBalanceAsync(NativeTokenSymbol, SecondaryDelegatee4Address, 20); + //change + await CheckUserBalanceAsync(basicFeeSymbol, SecondaryDelegatee5Address, 120); + await CheckUserBalanceAsync(NativeTokenSymbol, SecondaryDelegatee6Address, 100); + var delegateInfo = + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = SecondaryDelegatee5Address, + DelegatorAddress = Delegatee2Address, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegateInfo.Delegations[basicFeeSymbol].ShouldBe(20); + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = SecondaryDelegatee3Address, + DelegatorAddress = DelegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegation.Delegations[NativeTokenSymbol].ShouldBe(30); + delegation.Delegations[basicFeeSymbol].ShouldBe(100); + } + else + { + chargeFeeRetDefault.Output.Success.ShouldBe(false); + var delegateInfo = + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = SecondaryDelegatee5Address, + DelegatorAddress = Delegatee2Address, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + delegateInfo.Delegations[basicFeeSymbol].ShouldBe(100); + } + } + + private async Task IssueTokenListToUserAsync(List symbols, long amount, Address address) + { + foreach (var symbol in symbols) + { + await IssueTokenToUserAsync(symbol, amount, address); + } + } + private async Task GetSetDelegationResultAsync(List<(Address, Address)> delegateAddressList, + long refBlockHeight) + { + var result = true; + foreach (var (delegateeAddress, delegatorAddress) in delegateAddressList) + { + var delegateInfo = + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + DelegateeAddress = delegateeAddress, + DelegatorAddress = delegatorAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) + }); + result = result && refBlockHeight >= delegateInfo.BlockHeight + 2; + } + + return result; + } + + private async Task CheckUserBalanceAsync(string symbol, Address owner, long balance) + { + var userBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = symbol, + Owner = owner + }); + userBalance.Balance.ShouldBe(balance); + } + + private async Task SetMethodOrSizeFeeAsync(string basicFeeSymbol, string sizeFeeSymbol, + long basicFee) + { + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = basicFeeSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = sizeFeeSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + return sizeFeeSymbolList; + } + + private async Task GetTokenSupplyAmount(string tokenSymbol) { var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput @@ -1956,7 +2413,7 @@ private async Task IssueTokenToUserAsync(string tokenSymbol, long amount, Addres issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - // single node +// single node private async Task SubmitAndPassProposalOfDefaultParliamentAsync(Address contractAddress, string methodName, IMessage input) { diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index bf9daa50ba..42ec94932e 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -295,14 +295,38 @@ protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub2 { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub3 { get; set; } + internal TokenContractContainer.TokenContractStub TokenContractStubDelegator { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStubDelegate1 { get; set; } internal TokenContractImplContainer.TokenContractImplStub TokenContractStubDelegate2 { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStubDelegate3 { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStubSecondaryDelegate1 { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStubSecondaryDelegate2 { get; set; } + + internal TokenContractImplContainer.TokenContractImplStub TokenContractStubSecondaryDelegate3 { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStubSecondaryDelegate4 { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStubSecondaryDelegate5 { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractStubSecondaryDelegate6 { get; set; } + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; internal ECKeyPair DelegateeKeyPair => Accounts[1].KeyPair; internal ECKeyPair Delegatee2KeyPair => Accounts[3].KeyPair; + internal ECKeyPair Delegatee3KeyPair => Accounts[5].KeyPair; + internal ECKeyPair SecondaryDelegatee1KeyPair => Accounts[6].KeyPair; + internal ECKeyPair SecondaryDelegatee2KeyPair => Accounts[7].KeyPair; + + internal ECKeyPair SecondaryDelegatee3KeyPair => Accounts[8].KeyPair; + + internal ECKeyPair SecondaryDelegatee4KeyPair => Accounts[9].KeyPair; + + internal ECKeyPair SecondaryDelegatee5KeyPair => Accounts[11].KeyPair; + + internal ECKeyPair SecondaryDelegatee6KeyPair => Accounts[12].KeyPair; + + internal ECKeyPair UserKeyPair => Accounts[2].KeyPair; internal ECKeyPair UserAKeyPair => Accounts[3].KeyPair; @@ -312,8 +336,22 @@ protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() Accounts.Take(1).Select(a => a.KeyPair).ToList(); internal Address DefaultSender => Accounts[0].Address; - internal Address delegateeAddress => Accounts[1].Address; + internal Address DelegateeAddress => Accounts[1].Address; internal Address Delegatee2Address => Accounts[3].Address; + internal Address Delegatee3Address => Accounts[5].Address; + internal Address SecondaryDelegatee1Address => Accounts[6].Address; + internal Address SecondaryDelegatee2Address => Accounts[7].Address; + + internal Address SecondaryDelegatee3Address => Accounts[8].Address; + + internal Address SecondaryDelegatee4Address => Accounts[9].Address; + + internal Address SecondaryDelegatee5Address => Accounts[11].Address; + + internal Address SecondaryDelegatee6Address => Accounts[12].Address; + + + internal Address userAddress => Accounts[2].Address; internal TokenContractContainer.TokenContractStub TokenContractStubA { get; set; } @@ -354,10 +392,27 @@ private async Task DeployContractsAsync() GetTester(TokenContractAddress, UserKeyPair); TokenContractStubA = GetTester(TokenContractAddress, UserKeyPair); + TokenContractStubDelegator = + GetTester(TokenContractAddress, UserTomSenderKeyPair); TokenContractStubDelegate1 = GetTester(TokenContractAddress, DelegateeKeyPair); TokenContractStubDelegate2 = GetTester(TokenContractAddress, Delegatee2KeyPair); + TokenContractStubDelegate3 = + GetTester(TokenContractAddress, Delegatee3KeyPair); + TokenContractStubSecondaryDelegate1 = + GetTester(TokenContractAddress, SecondaryDelegatee1KeyPair); + TokenContractStubSecondaryDelegate2 = + GetTester(TokenContractAddress, SecondaryDelegatee2KeyPair); + TokenContractStubSecondaryDelegate3 = + GetTester(TokenContractAddress, SecondaryDelegatee3KeyPair); + TokenContractStubSecondaryDelegate4 = + GetTester(TokenContractAddress, SecondaryDelegatee4KeyPair); + TokenContractStubSecondaryDelegate5 = + GetTester(TokenContractAddress, SecondaryDelegatee5KeyPair); + TokenContractStubSecondaryDelegate6 = + GetTester(TokenContractAddress, SecondaryDelegatee6KeyPair); + } // Parliament From 9de053d9cb7ceb153089285d517d7e6be388e783 Mon Sep 17 00:00:00 2001 From: kevin Date: Fri, 2 Jun 2023 14:25:26 +0800 Subject: [PATCH 015/139] fix: pass ut --- .../TokenContract_Fees.cs | 43 ++++--- .../TokenContract_Helper.cs | 10 +- ...t.ExecutionPluginForMethodFee.Tests.csproj | 3 + .../ExecutePluginTransactionDirectlyTest.cs | 116 ++++++++++-------- .../ExecutionPluginForMethodFeeTestBase.cs | 3 + 5 files changed, 102 insertions(+), 73 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 8d4fd87d41..0ca3cb76b8 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -7,6 +7,7 @@ using AElf.Standards.ACS12; using AElf.Types; using Google.Protobuf; +using Google.Protobuf.Collections; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.MultiToken; @@ -214,7 +215,7 @@ private void ModifyBalance(Address fromAddress, TransactionFeeBill bill, }); } - if (freeAllowancesMap?.Map == null || freeAllowancesMap.Map.Count == 0) return; + if (freeAllowancesMap.Map == null || freeAllowancesMap.Map.Count == 0) return; foreach (var (symbol, amount) in allowanceBill.FreeFeeAllowancesMap) { @@ -223,11 +224,6 @@ private void ModifyBalance(Address fromAddress, TransactionFeeBill bill, ModifyFreeFeeAllowanceAmount(fromAddress, freeAllowancesMap, symbol, -amount); } } - - foreach (var (symbol, freeAllowances) in freeAllowancesMap.Map) - { - State.MethodFeeFreeAllowancesMap[fromAddress][symbol] = freeAllowances; - } } private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Address fromAddress, @@ -238,7 +234,7 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre var successToChargeBaseFee = true; SetOrRefreshMethodFeeFreeAllowances(fromAddress); - var freeAllowancesMap = CalculateMethodFeeFreeAllowances(fromAddress)?.Clone(); + var freeAllowancesMap = CalculateMethodFeeFreeAllowances(fromAddress); if (fee.Count != 0) { @@ -273,7 +269,7 @@ private void SetOrRefreshMethodFeeFreeAllowances(Address address) State.MethodFeeFreeAllowancesLastRefreshTimeMap[address][symbol] = Context.CurrentBlockTime; State.MethodFeeFreeAllowancesMap[address][symbol] = - State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances; + State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone(); } } @@ -1014,20 +1010,30 @@ public override Address GetFeeReceiver(Empty input) public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowancesInput input) { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); - Assert(string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol"); + Assert(!string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol"); Assert(input.MethodFeeFreeAllowances?.Value != null && input.MethodFeeFreeAllowances.Value.Count > 0, "Invalid input allowances"); - Assert(input.Threshold > 0, "Invalid input threshold"); - Assert(input.RefreshSeconds > 0, "Invalid input refresh seconds"); + Assert(input.Threshold >= 0, "Invalid input threshold"); + Assert(input.RefreshSeconds >= 0, "Invalid input refresh seconds"); - State.MethodFeeFreeAllowancesConfigMap[input.Symbol].Threshold = input.Threshold; - State.MethodFeeFreeAllowancesConfigMap[input.Symbol].RefreshSeconds = input.RefreshSeconds; - State.MethodFeeFreeAllowancesConfigMap[input.Symbol].FreeAllowances = new MethodFeeFreeAllowanceMap(); + var config = new FreeAllowanceConfig + { + Threshold = input.Threshold, + RefreshSeconds = input.RefreshSeconds, + FreeAllowances = new MethodFeeFreeAllowanceMap() + }; foreach (var allowance in input.MethodFeeFreeAllowances!.Value!) { - State.MethodFeeFreeAllowancesConfigMap[input.Symbol].FreeAllowances.Map.Add(allowance.Symbol, allowance); + config.FreeAllowances.Map.Add(allowance.Symbol, allowance); } + State.MethodFeeFreeAllowancesConfigMap[input.Symbol] = config; + + State.MethodFeeFreeAllowancesConfig.Value ??= new MethodFeeFreeAllowancesConfig + { + Symbols = { new RepeatedField() } + }; + if (!State.MethodFeeFreeAllowancesConfig.Value.Symbols.Contains(input.Symbol)) { State.MethodFeeFreeAllowancesConfig.Value.Symbols.Add(input.Symbol); @@ -1083,10 +1089,9 @@ private MethodFeeFreeAllowancesMap CalculateMethodFeeFreeAllowances(Address inpu return new MethodFeeFreeAllowancesMap(); } - var config = freeAllowancesConfig.Clone(); var methodFeeFreeAllowancesMap = new MethodFeeFreeAllowancesMap(); - foreach (var symbol in config.Symbols) + foreach (var symbol in freeAllowancesConfig.Symbols) { var balance = State.Balances[input][symbol]; if (balance < State.MethodFeeFreeAllowancesConfigMap[symbol].Threshold) continue; @@ -1100,7 +1105,7 @@ private MethodFeeFreeAllowancesMap CalculateMethodFeeFreeAllowances(Address inpu if (balance >= State.MethodFeeFreeAllowancesConfigMap[symbol].Threshold) { methodFeeFreeAllowancesMap.Map.Add(symbol, - State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances); + State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone()); continue; } } @@ -1114,7 +1119,7 @@ private MethodFeeFreeAllowancesMap CalculateMethodFeeFreeAllowances(Address inpu methodFeeFreeAllowancesMap.Map.Add(symbol, (Context.CurrentBlockTime - lastRefreshTime).Seconds > State.MethodFeeFreeAllowancesConfigMap[symbol].RefreshSeconds - ? State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances + ? State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone() : freeAllowances); } } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 70865a8550..8b288131c6 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -88,8 +88,7 @@ private void ModifyFreeFeeAllowanceAmount(Address fromAddress, Assert(false, $"Insufficient amount of {symbol} for free fee allowance. Need amount: {-addAmount}; Current amount: {freeAllowanceAmount}"); } - - // var symbolList = methodFeeFreeAllowancesMap.Map.Keys; + var symbolList = GetSymbolListSortedByExpirationTime(methodFeeFreeAllowancesMap, fromAddress); foreach (var s in symbolList) @@ -98,13 +97,16 @@ private void ModifyFreeFeeAllowanceAmount(Address fromAddress, var currentAllowance = methodFeeFreeAllowancesMap.Map[s].Map[symbol].Amount; + if (currentAllowance == 0) continue; + addAmount += currentAllowance; methodFeeFreeAllowancesMap.Map[s].Map[symbol].Amount = addAmount >= 0 ? addAmount : 0; } } - private List GetSymbolListSortedByExpirationTime(MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, Address fromAddress) + private List GetSymbolListSortedByExpirationTime(MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, + Address fromAddress) { return methodFeeFreeAllowancesMap.Map.Keys.OrderBy(t => State.MethodFeeFreeAllowancesConfigMap[t].RefreshSeconds - (Context.CurrentBlockTime - @@ -134,7 +136,7 @@ private long GetFreeFeeAllowanceAmount(MethodFeeFreeAllowancesMap methodFeeFreeA { var freeAllowance = freeAllowances.Map.Values.FirstOrDefault(t => t.Symbol == symbol); - allowance.Add(freeAllowance?.Amount ?? 0L); + allowance = allowance.Add(freeAllowance?.Amount ?? 0L); } return allowance; diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj index 17473c3736..8d091828d7 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj @@ -107,6 +107,9 @@ Protobuf\Proto\token_contract.proto + + Protobuf\Proto\token_contract_impl.proto + Protobuf\Proto\acs1_plugin_test_contract.proto diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index a72b124533..01d3b6a722 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -1,13 +1,11 @@ -using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices; using System.Threading.Tasks; -using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Contracts.MultiToken; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; +using AElf.Standards.ACS1; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -302,9 +300,10 @@ public async Task FreeAllowancesTest(long threshold, long initialBalance, long f await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput { - FreeAllowances = new MethodFeeFreeAllowances + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = { @@ -335,15 +334,17 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); { - var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); if (threshold <= initialBalance) { - freeAllowances.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Value.First().Amount.ShouldBe(freeAmount); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmount); } else { - freeAllowances.Value.ShouldBeEmpty(); + freeAllowances.Map.ShouldBeEmpty(); } } @@ -377,15 +378,17 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, chargeFeeRet.Output.Success.ShouldBe(true); { - var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); if (threshold <= initialBalance) { - freeAllowances.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Value.First().Amount.ShouldBe(newFreeAllowance); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAllowance); } else { - freeAllowances.Value.ShouldBeEmpty(); + freeAllowances.Map.ShouldBeEmpty(); } } @@ -426,9 +429,9 @@ public async Task FreeAllowances_MultToken_Test( } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput { - FreeAllowances = new MethodFeeFreeAllowances + MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = { @@ -445,7 +448,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } }, RefreshSeconds = 100, - Threshold = threshold + Threshold = threshold, + Symbol = NativeTokenSymbol }); @@ -486,17 +490,20 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); { - var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); if (threshold <= initialBalance) { - freeAllowances.Value.First().Symbol.ShouldBe(basicFeeSymbol); - freeAllowances.Value.First().Amount.ShouldBe(baseFeeFreeAmount); - freeAllowances.Value.Last().Symbol.ShouldBe(sizeFeeSymbol); - freeAllowances.Value.Last().Amount.ShouldBe(sizeFeeFreeAmount); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(basicFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(basicFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(baseFeeFreeAmount); + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(sizeFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(sizeFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(sizeFeeFreeAmount); } else { - freeAllowances.Value.ShouldBeEmpty(); + freeAllowances.Map.ShouldBeEmpty(); } } @@ -512,17 +519,20 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, chargeFeeRet.Output.Success.ShouldBe(true); { - var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); if (threshold <= initialBalance) { - freeAllowances.Value.First().Symbol.ShouldBe(basicFeeSymbol); - freeAllowances.Value.First().Amount.ShouldBe(newBaseFreeAllowance); - freeAllowances.Value.Last().Symbol.ShouldBe(sizeFeeSymbol); - freeAllowances.Value.Last().Amount.ShouldBe(newSizeFreeAllowance); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(basicFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(basicFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newBaseFreeAllowance); + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(sizeFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(sizeFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(newSizeFreeAllowance); } else { - freeAllowances.Value.ShouldBeEmpty(); + freeAllowances.Map.ShouldBeEmpty(); } } @@ -568,14 +578,15 @@ public async Task ChargeTransactionFee_Delegate( [basicFeeSymbol] = delegateeAmountBasic, [sizeFeeSymbol] = delegateeAmountSize }; - var transactionResult = await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransactionFeeDelegationsInput - { - DelegatorAddress = DefaultSender, - Delegations = + var transactionResult = await TokenContractStub2.SetTransactionFeeDelegations.SendAsync( + new SetTransactionFeeDelegationsInput { - delegations - } - }); + DelegatorAddress = DefaultSender, + Delegations = + { + delegations + } + }); // Test Case 11 { var result = await TokenContractStubA.GetTransactionFeeDelegationsOfADelegatee.CallAsync( @@ -609,9 +620,9 @@ public async Task ChargeTransactionFee_Delegate( } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput { - FreeAllowances = new MethodFeeFreeAllowances + MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = { @@ -628,20 +639,24 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } }, RefreshSeconds = 100, - Threshold = threshold + Threshold = threshold, + Symbol = NativeTokenSymbol }); { - var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(userAddress); + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(userAddress); if (threshold <= initialBalance) { - freeAllowances.Value.First().Symbol.ShouldBe(basicFeeSymbol); - freeAllowances.Value.First().Amount.ShouldBe(baseFeeFreeAmount); - freeAllowances.Value.Last().Symbol.ShouldBe(sizeFeeSymbol); - freeAllowances.Value.Last().Amount.ShouldBe(sizeFeeFreeAmount); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(basicFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(basicFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(baseFeeFreeAmount); + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(sizeFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(sizeFeeSymbol); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(sizeFeeFreeAmount); } else { - freeAllowances.Value.ShouldBeEmpty(); + freeAllowances.Map.ShouldBeEmpty(); } } @@ -714,7 +729,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2) { chargeFeeRetDefault.Output.Success.ShouldBe(true); - + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, @@ -739,7 +754,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, else { chargeFeeRetDefault.Output.Success.ShouldBe(false); - + var delegation = await TokenContractStub.GetTransactionFeeDelegationsOfADelegatee.CallAsync( new GetTransactionFeeDelegationsOfADelegateeInput { @@ -807,9 +822,9 @@ await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransacti } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput { - FreeAllowances = new MethodFeeFreeAllowances + MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = { @@ -826,7 +841,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } }, RefreshSeconds = 100, - Threshold = threshold + Threshold = threshold, + Symbol = NativeTokenSymbol }); var methodFee = new MethodFees diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index 33fff08c64..63243ee4b3 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -293,6 +293,7 @@ protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() internal Address TreasuryContractAddress { get; set; } internal Address ConsensusContractAddress { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractImplStub { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub2 { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub3 { get; set; } internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } @@ -349,6 +350,8 @@ private async Task DeployContractsAsync() GetTester(TokenContractAddress, UserKeyPair); TokenContractStubA = GetTester(TokenContractAddress, UserKeyPair); + TokenContractImplStub = + GetTester(TokenContractAddress, DefaultSenderKeyPair); } // Parliament From 96b030aac8eadeea194307c04f31ec11038e8a99 Mon Sep 17 00:00:00 2001 From: kevin Date: Fri, 2 Jun 2023 14:48:09 +0800 Subject: [PATCH 016/139] fix: ut --- test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs index 05cdb0efab..c169957480 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs @@ -169,7 +169,7 @@ public async Task InitializeAuthorizedController_Test() public async Task ConfigMethodFeeFreeAllowances_Without_Authorization_Test() { var configMethodFeeFreeAllowancesRet = - await TokenContractStub.ConfigMethodFeeFreeAllowances.SendWithExceptionAsync(new MethodFeeFreeAllowancesConfig()); + await TokenContractStub.ConfigMethodFeeFreeAllowances.SendWithExceptionAsync(new ConfigMethodFeeFreeAllowancesInput()); configMethodFeeFreeAllowancesRet.TransactionResult.Error.ShouldContain("Unauthorized behavior."); } From c97d1569e6286b2a3736cdd6a050c0314a8bf7f8 Mon Sep 17 00:00:00 2001 From: kevin Date: Fri, 2 Jun 2023 15:42:25 +0800 Subject: [PATCH 017/139] feat: rename structures and adjust GetResourceInfo --- .../TokenContractState_ChargeFee.cs | 8 ++++-- .../TokenContract_ACS2_StatePathsProvider.cs | 23 +++++++-------- .../TokenContract_Fees.cs | 28 +++++++++---------- .../TokenContract_Helper.cs | 2 +- protobuf/token_contract_impl.proto | 24 ++++++++++------ 5 files changed, 48 insertions(+), 37 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs index bccf5edbbe..0ee95e67f9 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs @@ -36,7 +36,11 @@ public partial class TokenContractState public MappedState OwningRental { get; set; } public SingletonState MethodFeeFreeAllowancesConfig { get; set; } + public MappedState MethodFeeFreeAllowancesMap { get; set; } + public MappedState MethodFeeFreeAllowancesLastRefreshTimeMap { get; set; } + + public SingletonState MethodFeeFreeAllowancesSymbolList { get; set; } public MappedState MethodFeeFreeAllowancesConfigMap { get; set; } - public MappedState MethodFeeFreeAllowancesMap { get; set; } - public MappedState MethodFeeFreeAllowancesLastRefreshTimeMap { get; set; } + public MappedState MethodFeeFreeAllowances { get; set; } + public MappedState MethodFeeFreeAllowancesLastRefreshTimes { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index bf075eec0c..5d2a01a48a 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Data.SqlTypes; using System.Linq; using AElf.Standards.ACS2; using AElf.Types; @@ -21,18 +22,18 @@ public override ResourceInfo GetResourceInfo(Transaction txn) { GetPath(nameof(TokenContractState.Balances), txn.From.ToString(), args.Symbol), GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesMap), txn.From.ToString()), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesLastRefreshTimeMap), txn.From.ToString()) + GetPath(nameof(TokenContractState.MethodFeeFreeAllowances), txn.From.ToString(), args.Symbol), + GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesLastRefreshTimes), txn.From.ToString(), args.Symbol) }, ReadPaths = { GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesConfig)) + GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesSymbolList)) } }; AddPathForTransactionFee(resourceInfo, txn.From.ToString()); - AddPathForDelegatees(resourceInfo, txn.From); + AddPathForDelegatees(resourceInfo, txn.From, args.Symbol); return resourceInfo; } @@ -48,18 +49,18 @@ public override ResourceInfo GetResourceInfo(Transaction txn) GetPath(nameof(TokenContractState.Balances), args.From.ToString(), args.Symbol), GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol), GetPath(nameof(TokenContractState.LockWhiteLists), args.Symbol, txn.From.ToString()), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesMap), txn.From.ToString()), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesLastRefreshTimeMap), txn.From.ToString()) + GetPath(nameof(TokenContractState.MethodFeeFreeAllowances), txn.From.ToString(), args.Symbol), + GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesLastRefreshTimes), txn.From.ToString(), args.Symbol) }, ReadPaths = { GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesConfig)) + GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesSymbolList)) } }; AddPathForTransactionFee(resourceInfo, txn.From.ToString()); - AddPathForDelegatees(resourceInfo, txn.From); + AddPathForDelegatees(resourceInfo, txn.From, args.Symbol); return resourceInfo; } @@ -97,7 +98,7 @@ private ScopedStatePath GetPath(params string[] parts) }; } - private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from) + private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from, string symbol) { var allDelegatees = State.TransactionFeeDelegateesMap[from]; if (allDelegatees != null) @@ -107,8 +108,8 @@ private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from) if (delegations == null) return; var add = Address.FromBase58(delegations).ToString(); AddPathForTransactionFee(resourceInfo, add); - resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesMap), add)); - resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesLastRefreshTimeMap), add)); + resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.MethodFeeFreeAllowances), add, symbol)); + resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesLastRefreshTimes), add, symbol)); } } } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 0ca3cb76b8..755c1ad3ac 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -256,19 +256,19 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre private void SetOrRefreshMethodFeeFreeAllowances(Address address) { - var config = State.MethodFeeFreeAllowancesConfig.Value; + var config = State.MethodFeeFreeAllowancesSymbolList.Value; if (config == null) return; foreach (var symbol in config.Symbols) { if (State.Balances[address][symbol] < State.MethodFeeFreeAllowancesConfigMap[symbol].Threshold) continue; - var lastRefreshTime = State.MethodFeeFreeAllowancesLastRefreshTimeMap[address][symbol]; + var lastRefreshTime = State.MethodFeeFreeAllowancesLastRefreshTimes[address][symbol]; if (lastRefreshTime != null && State.MethodFeeFreeAllowancesConfigMap[symbol].RefreshSeconds > (Context.CurrentBlockTime - lastRefreshTime).Seconds) continue; - State.MethodFeeFreeAllowancesLastRefreshTimeMap[address][symbol] = Context.CurrentBlockTime; - State.MethodFeeFreeAllowancesMap[address][symbol] = + State.MethodFeeFreeAllowancesLastRefreshTimes[address][symbol] = Context.CurrentBlockTime; + State.MethodFeeFreeAllowances[address][symbol] = State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone(); } } @@ -1029,14 +1029,14 @@ public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowance State.MethodFeeFreeAllowancesConfigMap[input.Symbol] = config; - State.MethodFeeFreeAllowancesConfig.Value ??= new MethodFeeFreeAllowancesConfig + State.MethodFeeFreeAllowancesSymbolList.Value ??= new MethodFeeFreeAllowancesSymbolList { Symbols = { new RepeatedField() } }; - if (!State.MethodFeeFreeAllowancesConfig.Value.Symbols.Contains(input.Symbol)) + if (!State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Contains(input.Symbol)) { - State.MethodFeeFreeAllowancesConfig.Value.Symbols.Add(input.Symbol); + State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Add(input.Symbol); } return new Empty(); @@ -1046,15 +1046,15 @@ public override Empty RemoveMethodFeeFreeAllowancesConfig(RemoveMethodFeeFreeAll { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); Assert(input.Symbols != null && input.Symbols.Count > 0, "Invalid input"); - Assert(State.MethodFeeFreeAllowancesConfig.Value != null, "Method fee free allowances config not set"); + Assert(State.MethodFeeFreeAllowancesSymbolList.Value != null, "Method fee free allowances config not set"); var symbols = input.Symbols!.Distinct(); foreach (var symbol in symbols) { - if (State.MethodFeeFreeAllowancesConfig.Value!.Symbols.Contains(symbol)) + if (State.MethodFeeFreeAllowancesSymbolList.Value!.Symbols.Contains(symbol)) { - State.MethodFeeFreeAllowancesConfig.Value.Symbols.Remove(symbol); + State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Remove(symbol); } } @@ -1063,7 +1063,7 @@ public override Empty RemoveMethodFeeFreeAllowancesConfig(RemoveMethodFeeFreeAll public override GetMethodFeeFreeAllowancesConfigOutput GetMethodFeeFreeAllowancesConfig(Empty input) { - var symbols = State.MethodFeeFreeAllowancesConfig.Value.Symbols; + var symbols = State.MethodFeeFreeAllowancesSymbolList.Value.Symbols; var output = new GetMethodFeeFreeAllowancesConfigOutput(); foreach (var symbol in symbols) @@ -1081,9 +1081,9 @@ public override MethodFeeFreeAllowancesMap GetMethodFeeFreeAllowances(Address in private MethodFeeFreeAllowancesMap CalculateMethodFeeFreeAllowances(Address input) { - var freeAllowanceMap = State.MethodFeeFreeAllowancesMap[input]; + var freeAllowanceMap = State.MethodFeeFreeAllowances[input]; - var freeAllowancesConfig = State.MethodFeeFreeAllowancesConfig.Value; + var freeAllowancesConfig = State.MethodFeeFreeAllowancesSymbolList.Value; if (freeAllowancesConfig == null) { return new MethodFeeFreeAllowancesMap(); @@ -1096,7 +1096,7 @@ private MethodFeeFreeAllowancesMap CalculateMethodFeeFreeAllowances(Address inpu var balance = State.Balances[input][symbol]; if (balance < State.MethodFeeFreeAllowancesConfigMap[symbol].Threshold) continue; - var lastRefreshTime = State.MethodFeeFreeAllowancesLastRefreshTimeMap[input][symbol]; + var lastRefreshTime = State.MethodFeeFreeAllowancesLastRefreshTimes[input][symbol]; var freeAllowances = freeAllowanceMap[symbol]; diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 8b288131c6..79da391111 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -110,7 +110,7 @@ private List GetSymbolListSortedByExpirationTime(MethodFeeFreeAllowances { return methodFeeFreeAllowancesMap.Map.Keys.OrderBy(t => State.MethodFeeFreeAllowancesConfigMap[t].RefreshSeconds - (Context.CurrentBlockTime - - State.MethodFeeFreeAllowancesLastRefreshTimeMap[ + State.MethodFeeFreeAllowancesLastRefreshTimes[ fromAddress][t]).Seconds).ToList(); } diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index 88e7eb5da9..620f87d016 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -260,6 +260,21 @@ enum SymbolType { } message MethodFeeFreeAllowancesConfig { + MethodFeeFreeAllowances free_allowances = 1; + int64 refresh_seconds = 2; + int64 threshold = 3; +} + +message MethodFeeFreeAllowances{ + repeated MethodFeeFreeAllowance value = 1; +} + +message MethodFeeFreeAllowance { + string symbol = 1; + int64 amount = 2; +} + +message MethodFeeFreeAllowancesSymbolList { repeated string symbols = 1; } @@ -290,13 +305,4 @@ message MethodFeeFreeAllowanceMap { message MethodFeeFreeAllowancesMap { map map = 1; -} - -message MethodFeeFreeAllowances{ - repeated MethodFeeFreeAllowance value = 1; -} - -message MethodFeeFreeAllowance { - string symbol = 1; - int64 amount = 2; } \ No newline at end of file From d9a75ad149a97cc0eda68ecaa8aeb2f66a895ea0 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Mon, 5 Jun 2023 11:00:11 +0800 Subject: [PATCH 018/139] feat: fix cr. --- .../TokenContract_Delegation.cs | 46 +++++-------------- .../TokenContract_Fees.cs | 5 +- 2 files changed, 15 insertions(+), 36 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs index 6756c4dd2a..de1951daec 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Linq; using AElf.Sdk.CSharp; using AElf.Types; @@ -352,35 +353,9 @@ public override Empty RemoveTransactionFeeDelegateeInfos(RemoveTransactionFeeDel { Assert(input.DelegateeAddress != null, "Delegatee address cannot be null."); Assert(input.DelegateTransactionList.Count > 0, "Delegate transaction list should not be null."); - var delegateTransactionList = input.DelegateTransactionList; var delegatorAddress = Context.Sender; - var delegateeAddress = input.DelegateeAddress.ToBase58(); - var toCancelTransactionList = new DelegateTransactionList(); - foreach (var delegateTransaction in delegateTransactionList.ToList().Distinct()) - { - Assert(delegateTransaction.ContractAddress != null && !string.IsNullOrEmpty(delegateTransaction.MethodName) && - delegateTransaction.MethodName.All(IsValidMethodNameChar), "Invalid contract address and method name."); - var delegateeInfo = - State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ - delegateTransaction.MethodName]; - if (delegateeInfo == null || !delegateeInfo.Delegatees.ContainsKey(delegateeAddress)) continue; - delegateeInfo.Delegatees.Remove(delegateeAddress); - toCancelTransactionList.Value.Add(delegateTransaction); - State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ - delegateTransaction.MethodName] = delegateeInfo; - } - - if (toCancelTransactionList.Value.Count > 0) - { - Context.Fire(new TransactionFeeDelegateInfoCancelled - { - Caller = Context.Sender, - Delegatee = input.DelegateeAddress, - Delegator = Context.Sender, - DelegateTransactionList = toCancelTransactionList - }); - } - + var delegateeAddress = input.DelegateeAddress?.ToBase58(); + RemoveTransactionFeeDelegateInfo(input.DelegateTransactionList.ToList(), delegatorAddress, delegateeAddress); return new Empty(); } @@ -388,11 +363,16 @@ public override Empty RemoveTransactionFeeDelegatorInfos(RemoveTransactionFeeDel { Assert(input.DelegatorAddress != null, "Delegator address cannot be null."); Assert(input.DelegateTransactionList.Count > 0, "Delegate transaction list should not be null."); - var delegateTransactionList = input.DelegateTransactionList; var delegateeAddress = Context.Sender.ToBase58(); var delegatorAddress = input.DelegatorAddress; + RemoveTransactionFeeDelegateInfo(input.DelegateTransactionList.ToList(), delegatorAddress, delegateeAddress); + return new Empty(); + } + + private void RemoveTransactionFeeDelegateInfo(List delegateTransactionList,Address delegatorAddress,string delegateeAddress) + { var toCancelTransactionList = new DelegateTransactionList(); - foreach (var delegateTransaction in delegateTransactionList.ToList().Distinct()) + foreach (var delegateTransaction in delegateTransactionList.Distinct()) { Assert(delegateTransaction.ContractAddress != null && !string.IsNullOrEmpty(delegateTransaction.MethodName) && delegateTransaction.MethodName.All(IsValidMethodNameChar), "Invalid contract address and method name."); @@ -411,13 +391,11 @@ public override Empty RemoveTransactionFeeDelegatorInfos(RemoveTransactionFeeDel Context.Fire(new TransactionFeeDelegateInfoCancelled { Caller = Context.Sender, - Delegator = input.DelegatorAddress, - Delegatee = Context.Sender, + Delegator = delegatorAddress, + Delegatee = Address.FromBase58(delegateeAddress), DelegateTransactionList = toCancelTransactionList }); } - - return new Empty(); } public override GetTransactionFeeDelegateeListOutput GetTransactionFeeDelegateeList( diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index e6bbb80616..4844056d16 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -217,8 +217,8 @@ private void ModifyDelegation(TransactionFeeBill bill, TransactionFreeFeeAllowan foreach (var (symbol, amount) in allowanceBill.FreeFeeAllowancesMap) { if (amount <= 0) continue; - var delegateInfo = State.TransactionFeeDelegateesMap[Context.Sender] ?? - State.TransactionFeeDelegateInfoMap[Context.Sender][contractAddress][methodName]; + var delegateInfo = State.TransactionFeeDelegateesMap[delegatorAddress] ?? + State.TransactionFeeDelegateInfoMap[delegatorAddress][contractAddress][methodName]; delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol] = delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol].Sub(amount); } @@ -359,6 +359,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress MethodFeeFreeAllowances freeAllowances, ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { + //If delegation != null,from address->delegateeAddress // Size Fee is charged in primary token, elf. var symbolToPayTxFee = State.ChainPrimaryTokenSymbol.Value; //Get primary token balance From 9e25667c920d2b6c495a59b310af045b96b67f45 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 5 Jun 2023 15:19:35 +0800 Subject: [PATCH 019/139] feat: adjust GetMethodFeeFreeAllowancesConfigOutput --- .../TokenContractState_ChargeFee.cs | 15 +++++++++++++++ .../TokenContract_Fees.cs | 1 + protobuf/token_contract_impl.proto | 7 ++++--- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs index 0ee95e67f9..5776abb8a1 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs @@ -39,8 +39,23 @@ public partial class TokenContractState public MappedState MethodFeeFreeAllowancesMap { get; set; } public MappedState MethodFeeFreeAllowancesLastRefreshTimeMap { get; set; } + /// + /// Symbol List + /// public SingletonState MethodFeeFreeAllowancesSymbolList { get; set; } + + /// + /// Symbol -> FreeAllowanceConfig + /// public MappedState MethodFeeFreeAllowancesConfigMap { get; set; } + + /// + /// Address -> Symbol -> MethodFeeFreeAllowanceMap + /// public MappedState MethodFeeFreeAllowances { get; set; } + + /// + /// Address -> Symbol -> LastRefreshTime + /// public MappedState MethodFeeFreeAllowancesLastRefreshTimes { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 755c1ad3ac..8863ef28ca 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -1018,6 +1018,7 @@ public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowance var config = new FreeAllowanceConfig { + Symbol = input.Symbol, Threshold = input.Threshold, RefreshSeconds = input.RefreshSeconds, FreeAllowances = new MethodFeeFreeAllowanceMap() diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index 620f87d016..0e1b1c2098 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -294,9 +294,10 @@ message GetMethodFeeFreeAllowancesConfigOutput { } message FreeAllowanceConfig { - MethodFeeFreeAllowanceMap free_allowances = 1; - int64 refresh_seconds = 2; - int64 threshold = 3; + string symbol = 1; + MethodFeeFreeAllowanceMap free_allowances = 2; + int64 refresh_seconds = 3; + int64 threshold = 4; } message MethodFeeFreeAllowanceMap { From 79a8d8d752f6eb01f3f927bd3d57f2791cda1684 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 5 Jun 2023 16:42:09 +0800 Subject: [PATCH 020/139] feat: adjust ConfigMethodFeeFreeAllowances for multiple configs and ut --- .../TokenContract_Fees.cs | 52 +++---- protobuf/token_contract_impl.proto | 4 + .../ExecutePluginTransactionDirectlyTest.cs | 128 +++++++++++------- 3 files changed, 109 insertions(+), 75 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 8863ef28ca..45e7c59809 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -1010,34 +1010,40 @@ public override Address GetFeeReceiver(Empty input) public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowancesInput input) { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); - Assert(!string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol"); - Assert(input.MethodFeeFreeAllowances?.Value != null && input.MethodFeeFreeAllowances.Value.Count > 0, - "Invalid input allowances"); - Assert(input.Threshold >= 0, "Invalid input threshold"); - Assert(input.RefreshSeconds >= 0, "Invalid input refresh seconds"); - - var config = new FreeAllowanceConfig - { - Symbol = input.Symbol, - Threshold = input.Threshold, - RefreshSeconds = input.RefreshSeconds, - FreeAllowances = new MethodFeeFreeAllowanceMap() - }; - foreach (var allowance in input.MethodFeeFreeAllowances!.Value!) - { - config.FreeAllowances.Map.Add(allowance.Symbol, allowance); - } - - State.MethodFeeFreeAllowancesConfigMap[input.Symbol] = config; + Assert(input.Value != null && input.Value.Count > 0, "Invalid input"); State.MethodFeeFreeAllowancesSymbolList.Value ??= new MethodFeeFreeAllowancesSymbolList { Symbols = { new RepeatedField() } }; - - if (!State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Contains(input.Symbol)) - { - State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Add(input.Symbol); + + foreach (var allowances in input.Value!) + { + Assert(!string.IsNullOrWhiteSpace(allowances.Symbol), "Invalid input symbol"); + Assert(allowances.MethodFeeFreeAllowances?.Value != null && allowances.MethodFeeFreeAllowances.Value.Count > 0, + "Invalid input allowances"); + Assert(allowances.Threshold >= 0, "Invalid input threshold"); + Assert(allowances.RefreshSeconds >= 0, "Invalid input refresh seconds"); + + var config = new FreeAllowanceConfig + { + Symbol = allowances.Symbol, + Threshold = allowances.Threshold, + RefreshSeconds = allowances.RefreshSeconds, + FreeAllowances = new MethodFeeFreeAllowanceMap() + }; + + foreach (var allowance in allowances.MethodFeeFreeAllowances!.Value!) + { + config.FreeAllowances.Map.Add(allowance.Symbol, allowance); + } + + State.MethodFeeFreeAllowancesConfigMap[allowances.Symbol] = config; + + if (!State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Contains(allowances.Symbol)) + { + State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Add(allowances.Symbol); + } } return new Empty(); diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index 0e1b1c2098..b6bc0d7be9 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -279,6 +279,10 @@ message MethodFeeFreeAllowancesSymbolList { } message ConfigMethodFeeFreeAllowancesInput { + repeated ConfigMethodFeeFreeAllowance value = 1; +} + +message ConfigMethodFeeFreeAllowance { string symbol = 1; MethodFeeFreeAllowances method_fee_free_allowances = 2; int64 refresh_seconds = 3; diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 01d3b6a722..449dd5768c 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -302,20 +302,26 @@ public async Task FreeAllowancesTest(long threshold, long initialBalance, long f await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + Value = { - Value = + new ConfigMethodFeeFreeAllowance { - new MethodFeeFreeAllowance + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances { - Symbol = NativeTokenSymbol, - Amount = freeAmount - } + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = freeAmount + } + } + }, + RefreshSeconds = refreshSeconds, + Threshold = threshold } - }, - RefreshSeconds = refreshSeconds, - Threshold = threshold + } }); var methodFee = new MethodFees @@ -431,25 +437,31 @@ public async Task FreeAllowances_MultToken_Test( await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput { - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + Value = { - Value = + new ConfigMethodFeeFreeAllowance { - new MethodFeeFreeAllowance + MethodFeeFreeAllowances = new MethodFeeFreeAllowances { - Symbol = basicFeeSymbol, - Amount = baseFeeFreeAmount + Value = + { + new MethodFeeFreeAllowance + { + Symbol = basicFeeSymbol, + Amount = baseFeeFreeAmount + }, + new MethodFeeFreeAllowance + { + Symbol = sizeFeeSymbol, + Amount = sizeFeeFreeAmount + } + } }, - new MethodFeeFreeAllowance - { - Symbol = sizeFeeSymbol, - Amount = sizeFeeFreeAmount - } + RefreshSeconds = 100, + Threshold = threshold, + Symbol = NativeTokenSymbol } - }, - RefreshSeconds = 100, - Threshold = threshold, - Symbol = NativeTokenSymbol + } }); @@ -622,25 +634,31 @@ public async Task ChargeTransactionFee_Delegate( await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput { - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + Value = { - Value = + new ConfigMethodFeeFreeAllowance { - new MethodFeeFreeAllowance + MethodFeeFreeAllowances = new MethodFeeFreeAllowances { - Symbol = basicFeeSymbol, - Amount = baseFeeFreeAmount + Value = + { + new MethodFeeFreeAllowance + { + Symbol = basicFeeSymbol, + Amount = baseFeeFreeAmount + }, + new MethodFeeFreeAllowance + { + Symbol = sizeFeeSymbol, + Amount = sizeFeeFreeAmount + } + } }, - new MethodFeeFreeAllowance - { - Symbol = sizeFeeSymbol, - Amount = sizeFeeFreeAmount - } + RefreshSeconds = 100, + Threshold = threshold, + Symbol = NativeTokenSymbol } - }, - RefreshSeconds = 100, - Threshold = threshold, - Symbol = NativeTokenSymbol + } }); { var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(userAddress); @@ -824,25 +842,31 @@ await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransacti await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput { - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + Value = { - Value = + new ConfigMethodFeeFreeAllowance { - new MethodFeeFreeAllowance + MethodFeeFreeAllowances = new MethodFeeFreeAllowances { - Symbol = basicFeeSymbol, - Amount = baseFeeFreeAmount + Value = + { + new MethodFeeFreeAllowance + { + Symbol = basicFeeSymbol, + Amount = baseFeeFreeAmount + }, + new MethodFeeFreeAllowance + { + Symbol = sizeFeeSymbol, + Amount = sizeFeeFreeAmount + } + } }, - new MethodFeeFreeAllowance - { - Symbol = sizeFeeSymbol, - Amount = sizeFeeFreeAmount - } + RefreshSeconds = 100, + Threshold = threshold, + Symbol = NativeTokenSymbol } - }, - RefreshSeconds = 100, - Threshold = threshold, - Symbol = NativeTokenSymbol + } }); var methodFee = new MethodFees From 885efd08376376150991262048b9ca0b20184807 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Tue, 6 Jun 2023 14:30:39 +0800 Subject: [PATCH 021/139] feat: modify code after cr and add unit test. --- .../TokenContract_Delegation.cs | 19 ++- .../TokenContract_Fees.cs | 120 +++++++++--------- .../BVT/TokenDelegationTest.cs | 99 +++++++++++++-- 3 files changed, 159 insertions(+), 79 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs index de1951daec..6f9cae0ae9 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs @@ -217,8 +217,7 @@ public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateIn //If the transaction contains delegatee,update delegate info. if (existDelegateeList.TryGetValue(delegateeAddress, out var value)) { - UpdateDelegateInfo(ref value, ref toUpdateTransactionList, delegateInfo); - existDelegateeList[delegateeAddress] = value; + toUpdateTransactionList.Value.Add(UpdateDelegateInfo(value, delegateInfo)); } //else,add new delegate info. else { @@ -226,7 +225,7 @@ public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateIn "The quantity of delegatee has reached its limit"); existDelegateeList.Add(delegateeAddress, new TransactionFeeDelegations()); var transactionFeeDelegations = existDelegateeList[delegateeAddress]; - AddDelegateInfo(ref transactionFeeDelegations, ref toAddTransactionList, delegateInfo); + toAddTransactionList.Value.Add(AddDelegateInfo(transactionFeeDelegations, delegateInfo)); } if (existDelegateeInfoList.Delegatees[delegateeAddress].Delegations.Count == 0 && @@ -249,8 +248,7 @@ public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateIn return new Empty(); } - private void AddDelegateInfo(ref TransactionFeeDelegations existDelegateeList, - ref DelegateTransactionList toAddTransactionList, DelegateInfo delegateInfo) + private DelegateTransaction AddDelegateInfo(TransactionFeeDelegations existDelegateeList, DelegateInfo delegateInfo) { if (!delegateInfo.IsUnlimitedDelegate) { @@ -262,15 +260,14 @@ private void AddDelegateInfo(ref TransactionFeeDelegations existDelegateeList, } existDelegateeList.BlockHeight = Context.CurrentHeight; existDelegateeList.IsUnlimitedDelegate = delegateInfo.IsUnlimitedDelegate; - toAddTransactionList.Value.Add(new DelegateTransaction + return new DelegateTransaction { ContractAddress = delegateInfo.ContractAddress, MethodName = delegateInfo.MethodName - }); + }; } - private void UpdateDelegateInfo(ref TransactionFeeDelegations existDelegateInfo, - ref DelegateTransactionList toUpdateTransactionList, DelegateInfo delegateInfo) + private DelegateTransaction UpdateDelegateInfo(TransactionFeeDelegations existDelegateInfo, DelegateInfo delegateInfo) { var existDelegation = existDelegateInfo.Delegations; if (delegateInfo.IsUnlimitedDelegate) @@ -304,11 +301,11 @@ private void UpdateDelegateInfo(ref TransactionFeeDelegations existDelegateInfo, existDelegateInfo.BlockHeight = Context.CurrentHeight; existDelegateInfo.IsUnlimitedDelegate = delegateInfo.IsUnlimitedDelegate; - toUpdateTransactionList.Value.Add(new DelegateTransaction + return new DelegateTransaction { ContractAddress = delegateInfo.ContractAddress, MethodName = delegateInfo.MethodName - }); + }; } private void FireLogEvent(DelegateTransactionList toAddTransactionList, diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 4844056d16..9f04ffdd96 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -657,90 +657,94 @@ public override Empty SetSymbolsToPayTxSizeFee(SymbolListToPayTxSizeFee input) /// private bool ChargeFirstSufficientToken(Dictionary symbolToAmountMap, Address fromAddress, out string symbol, out long amount, out long existingBalance, out long existingAllowance, - MethodFeeFreeAllowances freeAllowances, - TransactionFeeDelegations delegations = null) + MethodFeeFreeAllowances freeAllowances, TransactionFeeDelegations delegations = null) { symbol = null; amount = 0L; existingBalance = 0L; existingAllowance = 0L; + bool chargeResult; - symbol = GetAvailableSymbolToPayBaseFee(symbolToAmountMap, fromAddress, freeAllowances, out amount, - delegations); - //Whether or not delegation exists, there is no token that can be used for payment - if (symbol == null) return false; - - //For delegation, There is enough token balance and delegation to pay - //For user, There is enough token balance to pay or there is a token balance greater than 0 - existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); - //For delegation, return true - //For user,if balance enough return true - if (delegations != null || existingBalance.Add(existingAllowance) >= amount) + if (delegations != null) { - return true; + //from address -> delegatee + chargeResult = TryToChargeDelegateBaseFee(symbolToAmountMap, fromAddress, freeAllowances, delegations, + out amount, out symbol, out existingBalance, out existingAllowance); + return chargeResult; } - //For user, else priority charge primary token - var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; - if (symbolToAmountMap.ContainsKey(primaryTokenSymbol)) + chargeResult = TryToChargeUserBaseFee(symbolToAmountMap, fromAddress, freeAllowances, + out amount, out symbol, out existingBalance, out existingAllowance); + + //For user, if charge failed and delegation is null, priority charge primary token + if (!chargeResult) { - symbol = primaryTokenSymbol; - existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; + if (symbolToAmountMap.ContainsKey(primaryTokenSymbol)) + { + symbol = primaryTokenSymbol; + existingBalance = GetBalance(fromAddress, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + } } - return false; + return chargeResult; } - private string GetAvailableSymbolToPayBaseFee(Dictionary symbolToAmountMap, Address fromAddress, - MethodFeeFreeAllowances freeAllowances, out long amount, TransactionFeeDelegations delegations = null) + private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, Address fromAddress, + MethodFeeFreeAllowances freeAllowances, out long amount, out string symbolOfValidBalance, + out long existingBalance, out long existingAllowance) { - string symbolOfValidBalance = null; + symbolOfValidBalance = null; amount = 0; - // Traverse available token symbols, check balance one by one - // until there's balance of one certain token is enough to pay the fee. + existingBalance = 0; + existingAllowance = 0; //For user //Find the token that satisfies the balance of the fee,if there is no token that satisfies the balance of the fee, find the token that balance > 0 - if (delegations == null) + foreach (var (symbol, value) in symbolToAmountMap) { - foreach (var (symbol, value) in symbolToAmountMap) + // current token symbol + amount = value; + existingBalance = GetBalance(fromAddress, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + if (existingBalance.Add(existingAllowance) > 0) { - // current token symbol - amount = value; - var existingBalance = GetBalance(fromAddress, symbol); - var existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); - if (existingBalance.Add(existingAllowance) > 0) - { - symbolOfValidBalance = symbol; - } - - if (existingBalance.Add(existingAllowance) >= amount) break; + symbolOfValidBalance = symbol; } + + if (existingBalance.Add(existingAllowance) >= amount) + return true; } - //For delegation - else + + return false; + } + + private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountMap, Address fromAddress, + MethodFeeFreeAllowances freeAllowances, TransactionFeeDelegations delegations, + out long amount, out string symbolOfValidBalance, out long existingBalance, out long existingAllowance) + { + symbolOfValidBalance = null; + amount = 0; + existingBalance = 0; + existingAllowance = 0; + //Find the token that satisfies the delegate limit and satisfies the balance of the fee + foreach (var (symbol, value) in symbolToAmountMap) { - //Find the token that satisfies the delegate limit and satisfies the balance of the fee - foreach (var (symbol, value) in symbolToAmountMap) + // current token symbol + amount = value; + existingBalance = GetBalance(fromAddress, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + // is unlimited delegate is true && balance enough + // is unlimited delegate is false && delegation enough && balance enough + if (existingBalance.Add(existingAllowance) < amount) continue; + if (delegations.IsUnlimitedDelegate || (!delegations.IsUnlimitedDelegate && delegations.Delegations.ContainsKey(symbol) + && delegations.Delegations[symbol] >= amount)) { - // current token symbol - amount = value; - var existingBalance = GetBalance(fromAddress, symbol); - var existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); - // is unlimited delegate is true && balance enough - // is unlimited delegate is false && delegation enough && balance enough - if ((delegations.IsUnlimitedDelegate && existingBalance.Add(existingAllowance) >= amount) || - (!delegations.IsUnlimitedDelegate && delegations.Delegations.ContainsKey(symbol) && - delegations.Delegations[symbol] > amount && existingBalance.Add(existingAllowance) >= amount)) - { - symbolOfValidBalance = symbol; - break; - } + symbolOfValidBalance = symbol; + return true; } } - - return symbolOfValidBalance; + return false; } public override Empty ClaimTransactionFees(TotalTransactionFeesMap input) diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs index 97815f3bb8..a257a763ed 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs @@ -504,7 +504,7 @@ public async Task SetDelegateInfos_NewOrUpdateDelegate_Success_Test() [Fact] public async Task SetDelegateInfos_UpdateDelegate_Success_Test() { - await SetDelegateInfos_NewDelegate_Success_Test(); + await SetDelegateInfos_NewOrUpdateDelegate_Success_Test(); var delegations1 = new Dictionary { [NativeToken] = 300, @@ -542,10 +542,16 @@ public async Task SetDelegateInfos_UpdateDelegate_Success_Test() }, IsUnlimitedDelegate = false }; + var delegateInfo4 = new DelegateInfo + { + ContractAddress = BasicContractZeroAddress, + MethodName = "test1", + IsUnlimitedDelegate = true + }; await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput { DelegatorAddress = User1Address, - DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo3 } + DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo3,delegateInfo4 } }); { var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( @@ -589,12 +595,24 @@ await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransact delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } - + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicContractZeroAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.Delegations.ShouldBeEmpty(); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeTrue(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } } [Fact] public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test() { - await SetDelegateInfos_NewDelegate_Success_Test(); + await SetDelegateInfos_NewOrUpdateDelegate_Success_Test(); var delegations1 = new Dictionary { [NativeToken] = 300, @@ -604,7 +622,12 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test( var delegations2 = new Dictionary { [NativeToken] = 0, - [BasicFeeSymbol] = 200, + [SizeFeeSymbol] = 200, + }; + var delegations3 = new Dictionary + { + [NativeToken] = 5, + [BasicFeeSymbol] = 0 }; var delegateInfo1 = new DelegateInfo { @@ -626,10 +649,20 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test( }, IsUnlimitedDelegate = false }; + var delegateInfo3 = new DelegateInfo + { + ContractAddress = BasicContractZeroAddress, + MethodName = "test1", + Delegations = + { + delegations3 + }, + IsUnlimitedDelegate = false + }; var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput { DelegatorAddress = User1Address, - DelegateInfoList = { delegateInfo1,delegateInfo2 } + DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo3 } }); { var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( @@ -656,7 +689,21 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test( MethodName = "test2" }); delegateInfoOfADelegatee.Delegations.Count.ShouldBe(1); - delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(200); + delegateInfoOfADelegatee.Delegations[SizeFeeSymbol].ShouldBe(200); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicContractZeroAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.Delegations.Count.ShouldBe(1); + delegateInfoOfADelegatee.Delegations[NativeToken].ShouldBe(5); delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } @@ -665,11 +712,13 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test( .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoUpdated))?.NonIndexed); log.Delegator.ShouldBe(User1Address); log.Delegatee.ShouldBe(DefaultAddress); - log.DelegateTransactionList.Value.Count.ShouldBe(2); + log.DelegateTransactionList.Value.Count.ShouldBe(3); log.DelegateTransactionList.Value[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); log.DelegateTransactionList.Value[0].MethodName.ShouldBe("test1"); log.DelegateTransactionList.Value[1].ContractAddress.ShouldBe(BasicFunctionContractAddress); log.DelegateTransactionList.Value[1].MethodName.ShouldBe("test2"); + log.DelegateTransactionList.Value[2].ContractAddress.ShouldBe(BasicContractZeroAddress); + log.DelegateTransactionList.Value[2].MethodName.ShouldBe("test1"); } } [Fact] @@ -782,6 +831,10 @@ public async Task SetDelegateInfos_AddOrUpdateOrRemoveDelegate_Success_Test() { [NativeToken] = 60, }; + var delegations5 = new Dictionary + { + [NativeToken] = 0, + }; var delegateInfo1 = new DelegateInfo { ContractAddress = BasicFunctionContractAddress, @@ -808,10 +861,20 @@ public async Task SetDelegateInfos_AddOrUpdateOrRemoveDelegate_Success_Test() }, IsUnlimitedDelegate = false }; + var delegateInfo5 = new DelegateInfo + { + ContractAddress = BasicContractZeroAddress, + MethodName = "test1", + Delegations = + { + delegations5 + }, + IsUnlimitedDelegate = false + }; var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput { DelegatorAddress = User1Address, - DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo4 } + DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo4,delegateInfo5 } }); { var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( @@ -854,6 +917,20 @@ public async Task SetDelegateInfos_AddOrUpdateOrRemoveDelegate_Success_Test() delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } + { + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( + new GetTransactionFeeDelegateInfosOfADelegateeInput + { + ContractAddress = BasicContractZeroAddress, + DelegatorAddress = User1Address, + DelegateeAddress = DefaultAddress, + MethodName = "test1" + }); + delegateInfoOfADelegatee.Delegations.Count.ShouldBe(1); + delegateInfoOfADelegatee.Delegations[BasicFeeSymbol].ShouldBe(20); + delegateInfoOfADelegatee.IsUnlimitedDelegate.ShouldBeFalse(); + delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); + } { { var log = TransactionFeeDelegateInfoAdded.Parser.ParseFrom(executionResult.TransactionResult.Logs @@ -869,11 +946,13 @@ public async Task SetDelegateInfos_AddOrUpdateOrRemoveDelegate_Success_Test() .FirstOrDefault(i => i.Name == nameof(TransactionFeeDelegateInfoUpdated))?.NonIndexed); log.Delegator.ShouldBe(User1Address); log.Delegatee.ShouldBe(DefaultAddress); - log.DelegateTransactionList.Value.Count.ShouldBe(2); + log.DelegateTransactionList.Value.Count.ShouldBe(3); log.DelegateTransactionList.Value[0].ContractAddress.ShouldBe(BasicFunctionContractAddress); log.DelegateTransactionList.Value[0].MethodName.ShouldBe("test1"); log.DelegateTransactionList.Value[1].ContractAddress.ShouldBe(BasicFunctionContractAddress); log.DelegateTransactionList.Value[1].MethodName.ShouldBe("test2"); + log.DelegateTransactionList.Value[2].ContractAddress.ShouldBe(BasicContractZeroAddress); + log.DelegateTransactionList.Value[2].MethodName.ShouldBe("test1"); } } } From 18f8a2b3ac5af22b3ad01c8488cd85982ec8347b Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 6 Jun 2023 17:26:49 +0800 Subject: [PATCH 022/139] feat: validate symbol in ConfigMethodFeeFreeAllowances --- contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 45e7c59809..3583c2da3b 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -1019,7 +1019,7 @@ public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowance foreach (var allowances in input.Value!) { - Assert(!string.IsNullOrWhiteSpace(allowances.Symbol), "Invalid input symbol"); + ValidateToken(allowances.Symbol); Assert(allowances.MethodFeeFreeAllowances?.Value != null && allowances.MethodFeeFreeAllowances.Value.Count > 0, "Invalid input allowances"); Assert(allowances.Threshold >= 0, "Invalid input threshold"); @@ -1049,6 +1049,12 @@ public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowance return new Empty(); } + private void ValidateToken(string symbol) + { + Assert(!string.IsNullOrWhiteSpace(symbol), "Invalid input symbol"); + Assert(State.TokenInfos[symbol] != null, $"Symbol {symbol} not exist"); + } + public override Empty RemoveMethodFeeFreeAllowancesConfig(RemoveMethodFeeFreeAllowancesConfigInput input) { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); From 643cc069fd5cf85330120030ff22a91763f446d7 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 7 Jun 2023 21:25:55 +0800 Subject: [PATCH 023/139] test: add ut --- .../TokenContract_Fees.cs | 17 +- .../TokenContract_Helper.cs | 6 +- .../ExecutePluginTransactionDirectlyTest.cs | 1581 ++++++++++++++++- .../ExecutionPluginForMethodFeeTestBase.cs | 36 +- .../ExecutionPluginForMethodFeeTestModule.cs | 7 +- 5 files changed, 1547 insertions(+), 100 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 3583c2da3b..20f10a0383 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -1016,15 +1016,16 @@ public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowance { Symbols = { new RepeatedField() } }; - + foreach (var allowances in input.Value!) { ValidateToken(allowances.Symbol); - Assert(allowances.MethodFeeFreeAllowances?.Value != null && allowances.MethodFeeFreeAllowances.Value.Count > 0, + Assert( + allowances.MethodFeeFreeAllowances?.Value != null && allowances.MethodFeeFreeAllowances.Value.Count > 0, "Invalid input allowances"); Assert(allowances.Threshold >= 0, "Invalid input threshold"); Assert(allowances.RefreshSeconds >= 0, "Invalid input refresh seconds"); - + var config = new FreeAllowanceConfig { Symbol = allowances.Symbol, @@ -1032,14 +1033,14 @@ public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowance RefreshSeconds = allowances.RefreshSeconds, FreeAllowances = new MethodFeeFreeAllowanceMap() }; - + foreach (var allowance in allowances.MethodFeeFreeAllowances!.Value!) { config.FreeAllowances.Map.Add(allowance.Symbol, allowance); } - + State.MethodFeeFreeAllowancesConfigMap[allowances.Symbol] = config; - + if (!State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Contains(allowances.Symbol)) { State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Add(allowances.Symbol); @@ -1129,11 +1130,11 @@ private MethodFeeFreeAllowancesMap CalculateMethodFeeFreeAllowances(Address inpu } else { - methodFeeFreeAllowancesMap.Map.Add(symbol, + methodFeeFreeAllowancesMap.Map[symbol] = (Context.CurrentBlockTime - lastRefreshTime).Seconds > State.MethodFeeFreeAllowancesConfigMap[symbol].RefreshSeconds ? State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone() - : freeAllowances); + : freeAllowances; } } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 79da391111..1835864da8 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -93,8 +93,10 @@ private void ModifyFreeFeeAllowanceAmount(Address fromAddress, foreach (var s in symbolList) { - if (addAmount == 0) break; - + if (addAmount >= 0) break; + + if (!methodFeeFreeAllowancesMap.Map[s].Map.ContainsKey(symbol)) continue; + var currentAllowance = methodFeeFreeAllowancesMap.Map[s].Map[symbol].Amount; if (currentAllowance == 0) continue; diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 449dd5768c..bafdd0235a 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.MultiToken; +using AElf.ContractTestBase.ContractTestKit; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; using AElf.Standards.ACS1; @@ -398,14 +399,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = NativeTokenSymbol, - Owner = DefaultSender - }); - balance.Balance.ShouldBe(afterBalance); - } + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterBalance); } [Theory] @@ -548,19 +542,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } - var baseFeeSymbolBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DefaultSender - }); - baseFeeSymbolBalance.Balance.ShouldBe(afterBaseFeeBalance); - - var sizeFeeSymbolBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = sizeFeeSymbol, - Owner = DefaultSender - }); - sizeFeeSymbolBalance.Balance.ShouldBe(afterSizeFeeBalance); + await CheckDefaultSenderTokenAsync(basicFeeSymbol, afterBaseFeeBalance); + await CheckDefaultSenderTokenAsync(sizeFeeSymbol, afterSizeFeeBalance); } [Theory] @@ -1028,76 +1011,1528 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } - private async Task GetTokenSupplyAmount(string tokenSymbol) + [Fact] + public async Task ConfigMethodFeeFreeAllowances_Test() { - var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + await SetPrimaryTokenSymbolAsync(); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 0 + } + } + }, + RefreshSeconds = 600, + Threshold = 0 + } + } + }); + { - Symbol = tokenSymbol - }); - return tokenInfo.Supply; + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(1); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(0); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(0); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); + } + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 2_00000000); + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + RefreshSeconds = 600, + Threshold = 1_00000000 + } + } + }); + + { + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(1); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(1_00000000); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + } } - private async Task> GetDefaultBalancesAsync(string[] tokenSymbolList) + [Fact] + public async Task ConfigMethodFeeFreeAllowances_Unauthorized_Test() { - var balances = new List(); - foreach (var symbol in tokenSymbolList) - balances.Add(await GetBalanceAsync(DefaultSender, symbol)); - return balances; + var result = + await TokenContractImplStub.ConfigMethodFeeFreeAllowances.SendWithExceptionAsync( + new ConfigMethodFeeFreeAllowancesInput()); + result.TransactionResult.Error.ShouldContain("Unauthorized behavior."); } - private async Task CreateTokenAsync(Address creator, string tokenSymbol, bool isBurned = true) + [Fact] + public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_OneByOne_Test() { - await TokenContractStub.Create.SendAsync(new CreateInput + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAndIssueAsync(); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + RefreshSeconds = 600, + Threshold = 1_00000000 + } + } + }); + { - Symbol = tokenSymbol, - TokenName = tokenSymbol + " name", - TotalSupply = 1000_00000000, - IsBurnable = isBurned, - Issuer = creator, - }); + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(1); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(1_00000000); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + userBFreeAllowances.Result.Map.Count.ShouldBe(0); + var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); + } + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + RefreshSeconds = 300, + Threshold = 1_000000 + } + } + }); + + { + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(2); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(1_00000000); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + config.Value.Last().Symbol.ShouldBe("USDT"); + config.Value.Last().Threshold.ShouldBe(1_000000); + config.Value.Last().RefreshSeconds.ShouldBe(300); + config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(1); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + userBFreeAllowances.Result.Map.Count.ShouldBe(1); + userBFreeAllowances.Result.Map.Keys.First().ShouldBe("USDT"); + userBFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + userAFreeAllowances.Result.Map.Add("USDT", userBFreeAllowances.Result.Map.Values.First()); + userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); + } } - private async Task IssueTokenToDefaultSenderAsync(string tokenSymbol, long amount) + [Fact] + public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test() { - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = tokenSymbol, - Amount = amount, - To = DefaultSender, - }); - issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAndIssueAsync(); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + RefreshSeconds = 600, + Threshold = 1_00000000 + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + RefreshSeconds = 300, + Threshold = 1_000000 + } + } + }); + + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(2); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(1_00000000); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + config.Value.Last().Symbol.ShouldBe("USDT"); + config.Value.Last().Threshold.ShouldBe(1_000000); + config.Value.Last().RefreshSeconds.ShouldBe(300); + config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(1); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + userBFreeAllowances.Result.Map.Count.ShouldBe(1); + userBFreeAllowances.Result.Map.Keys.First().ShouldBe("USDT"); + userBFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + userAFreeAllowances.Result.Map.Add("USDT", userBFreeAllowances.Result.Map.Values.First()); + userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); } - private async Task IssueTokenToUserAsync(string tokenSymbol, long amount, Address to) + [Fact] + public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_Modify_Test() { - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() - { - Symbol = tokenSymbol, - Amount = amount, - To = to, - }); - issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + await CreateTokenAsync(DefaultSender, "ABC"); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 2_00000000 + }, + new MethodFeeFreeAllowance + { + Symbol = "ABC", + Amount = 2_00000000 + } + } + }, + RefreshSeconds = 1200, + Threshold = 2_000000 + } + } + }); + + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(2); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(1_00000000); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + config.Value.Last().Symbol.ShouldBe("USDT"); + config.Value.Last().Threshold.ShouldBe(2_000000); + config.Value.Last().RefreshSeconds.ShouldBe(1200); + config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(2_00000000); + config.Value.Last().FreeAllowances.Map.Keys.Last().ShouldBe("ABC"); + config.Value.Last().FreeAllowances.Map.Values.Last().Symbol.ShouldBe("ABC"); + config.Value.Last().FreeAllowances.Map.Values.Last().Amount.ShouldBe(2_00000000); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(1); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + userBFreeAllowances.Result.Map.Count.ShouldBe(0); + var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); } - // single node - private async Task SubmitAndPassProposalOfDefaultParliamentAsync(Address contractAddress, string methodName, - IMessage input) + [Fact] + public async Task ConfigMethodFeeFreeAllowances_InvalidInput_Test() { - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = new CreateProposalInput - { - OrganizationAddress = defaultParliament, - ToAddress = contractAddress, - Params = input.ToByteString(), - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var createProposalRet = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - createProposalRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = createProposalRet.Output; - await ParliamentContractStub.Approve.SendAsync(proposalId); - var releaseRet = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance() + } + }); + message.ShouldContain("Invalid input symbol"); + + message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = "TEST" + } + } + }); + message.ShouldContain("Symbol TEST not exist"); + + message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol + } + } + }); + message.ShouldContain("Invalid input allowances"); + + message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + Threshold = -1 + } + } + }); + message.ShouldContain("Invalid input threshold"); + + message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + Threshold = 1_00000000, + RefreshSeconds = -1 + } + } + }); + message.ShouldContain("Invalid input refresh seconds"); + } + + [Fact] + public async Task RemoveMethodFeeFreeAllowancesConfig_Unauthorized_Test() + { + var result = + await TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig.SendWithExceptionAsync( + new RemoveMethodFeeFreeAllowancesConfigInput()); + result.TransactionResult.Error.ShouldContain("Unauthorized behavior."); + } + + [Fact] + public async Task RemoveMethodFeeFreeAllowancesConfig_Test() + { + await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + await IssueTokenToUserAsync("USDT", 1_000000, UserAAddress); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(2); + var config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Result.Value.Count.ShouldBe(2); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput + { + Symbols = { "USDT" } + }); + config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Result.Value.Count.ShouldBe(1); + config.Result.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(1); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + + // symbol not exist + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput + { + Symbols = { "USDT" } + }); + config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Result.Value.Count.ShouldBe(1); + config.Result.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(1); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + + // Duplicate symbols + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput + { + Symbols = { "ELF", "ELF" } + }); + config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Result.Value.Count.ShouldBe(0); + userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(0); + } + + [Fact] + public async Task RemoveMethodFeeFreeAllowancesConfig_MultipleTokens_AtOnce_Test() + { + await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + await IssueTokenToUserAsync("USDT", 1_000000, UserAAddress); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(2); + var config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Result.Value.Count.ShouldBe(2); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput + { + Symbols = { "ELF", "USDT" } + }); + userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(0); + } + + [Fact] + public async Task RemoveMethodFeeFreeAllowancesConfig_InvalidInput_Test() + { + var message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput + { + Symbols = { "USDT" } + }); + message.ShouldContain("Method fee free allowances config not set"); + + await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput()); + message.ShouldContain("Invalid input"); + } + + [Theory] + [InlineData(1000, 0, 1000, 0, 100, 0, 0, 0, 800, 0, 1000, 200)] + [InlineData(1000, 0, 100, 0, 100, 0, 0, 0, 0, 0, 900, 200)] + [InlineData(1000, 1000, 500, 10, 100, 500, 20, 100, 300, 500, 1000, 200)] + [InlineData(1000, 1000, 150, 10, 100, 150, 20, 100, 0, 100, 1000, 200)] + public async Task ChargeTransactionFee_Test(long initialELFBalance, long initialUSDTBalance, + long freeAmountELF, long refreshSecondsELF, long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, + long thresholdUSDT, long newFreeAmountELF, long newFreeAmountUSDT, long afterBalance, long basicFee) + { + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, "USDT"); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); + await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = freeAmountELF + } + } + }, + RefreshSeconds = refreshSecondsELF, + Threshold = thresholdELF + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = freeAmountUSDT + } + } + }, + RefreshSeconds = refreshSecondsUSDT, + Threshold = thresholdUSDT + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress + }; + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountELF); + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterBalance); + } + + [Theory] + [InlineData(1000, 1000, 1000, 1000, 1000, 10, 100, 1000, 20, 100, 700, 500, 1000, 1000, 1000, 1000, 300, 500)] + [InlineData(1000, 1000, 1000, 1000, 100, 10, 100, 1000, 20, 100, 0, 500, 800, 1000, 1000, 1000, 300, 500)] + [InlineData(1000, 1000, 1000, 1000, 500, 10, 10000, 500, 20, 1000, 0, 300, 800, 1000, 1000, 1000, 200, 200)] + [InlineData(1000, 1000, 1000, 1000, 1000, 10, 1000, 1000, 20, 1000, 0, 0, 0, 0, 1000, 1000, 10000, 5000)] + public async Task ChargeTransactionFee_MultipleTokens_Test(long initialELFBalance, long initialUSDTBalance, + long initialTokenABalance, long initialTokenBBalance, long freeAmountELF, long refreshSecondsELF, + long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFreeAmountELF, + long newFreeAmountUSDT, long afterTokenABalance, long afterTokenBBalance, long afterELFBalance, + long afterUSDTBalance, long sizeFee, long basicFee) + { + const string TokenForELF = "TOKENA"; + const string TokenForUSDT = "TOKENB"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, "USDT"); + + await CreateTokenAsync(DefaultSender, TokenForELF); + await CreateTokenAsync(DefaultSender, TokenForUSDT); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); + await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); + await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); + await IssueTokenToDefaultSenderAsync(TokenForUSDT, initialTokenBBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForELF, + Amount = freeAmountELF + } + } + }, + RefreshSeconds = refreshSecondsELF, + Threshold = thresholdELF + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForUSDT, + Amount = freeAmountUSDT + } + } + }, + RefreshSeconds = refreshSecondsUSDT, + Threshold = thresholdUSDT + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = TokenForUSDT, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = TokenForELF, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + if (initialELFBalance >= thresholdELF) + { + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); + } + + if (initialUSDTBalance >= thresholdUSDT) + { + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); + } + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(initialTokenABalance + freeAmountELF >= sizeFee); + + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + if (initialELFBalance >= thresholdELF) + { + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountELF); + } + + if (initialUSDTBalance >= thresholdUSDT) + { + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); + } + + await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); + await CheckDefaultSenderTokenAsync(TokenForUSDT, afterTokenBBalance); + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); + await CheckDefaultSenderTokenAsync("USDT", afterUSDTBalance); + } + + [Theory] + [InlineData(1000, 600, 200, 200)] + public async Task ChargeTransactionFee_NoFreeAllowance_Test(long initialBalance, long afterBalance, long sizeFee, + long basicFee) + { + await SetPrimaryTokenSymbolAsync(); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterBalance); + } + + [Theory] + [InlineData(1000, 1000, 1000, 2000, 2000, 0, 1000, 1000, 500, 1000, 1000, 1000, 1500)] + public async Task ChargeTransactionFee_SingleThreshold_Test(long initialBalance, long initialTokenABalance, + long initialTokenBBalance, long freeAmountTokenA, long freeAmountTokenB, long refreshSeconds, + long threshold, long newFreeAmountTokenA, long newFreeAmountTokenB, long afterTokenABalance, + long afterTokenBBalance, long sizeFee, long basicFee) + { + const string TokenA = "TOKENA"; + const string TokenB = "TOKENB"; + + await SetPrimaryTokenSymbolAsync(); + + await CreateTokenAsync(DefaultSender, TokenA); + await CreateTokenAsync(DefaultSender, TokenB); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + await IssueTokenToDefaultSenderAsync(TokenA, initialTokenABalance); + await IssueTokenToDefaultSenderAsync(TokenB, initialTokenBBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenA, + Amount = freeAmountTokenA + }, + new MethodFeeFreeAllowance + { + Symbol = TokenB, + Amount = freeAmountTokenB + } + } + }, + RefreshSeconds = refreshSeconds, + Threshold = threshold + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = TokenB, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = TokenA, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenA); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenA); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountTokenA); + + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(TokenB); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(TokenB); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(freeAmountTokenB); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenA); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenA); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountTokenA); + + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(TokenB); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(TokenB); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(newFreeAmountTokenB); + + await CheckDefaultSenderTokenAsync(TokenA, afterTokenABalance); + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterTokenBBalance); + } + + [Theory] + [InlineData(1000, 1000, 1000, 1000, 1000, 10, 100, 1000, 20, 100, 0, 1000, 0, 1000, 3000, 5000)] + public async Task ChargeTransactionFee_NotEnough_Test(long initialELFBalance, long initialUSDTBalance, + long initialTokenABalance, long initialTokenBBalance, long freeAmountELF, long refreshSecondsELF, + long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFreeAmountELF, + long newFreeAmountUSDT, long afterTokenABalance, long afterTokenBBalance, long sizeFee, long basicFee) + { + const string TokenForELF = "TOKENA"; + const string TokenForUSDT = "TOKENB"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, "USDT"); + + await CreateTokenAsync(DefaultSender, TokenForELF); + await CreateTokenAsync(DefaultSender, TokenForUSDT); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); + await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); + await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); + await IssueTokenToDefaultSenderAsync(TokenForUSDT, initialTokenBBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForELF, + Amount = freeAmountELF + } + } + }, + RefreshSeconds = refreshSecondsELF, + Threshold = thresholdELF + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForUSDT, + Amount = freeAmountUSDT + } + } + }, + RefreshSeconds = refreshSecondsUSDT, + Threshold = thresholdUSDT + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = TokenForELF, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = TokenForELF, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(false); + + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); + + await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); + await CheckDefaultSenderTokenAsync(TokenForUSDT, afterTokenBBalance); + } + + [Theory] + [InlineData(10000, 500, 50, 10000, 300, 100, 100, 100, 2000, 10000, 7800, 10000)] + public async Task ChargeTransactionFee_ClearFreeAllowance_Test(long initialBalance, long freeAmount, + long refreshSeconds, long threshold, long firstFreeAmount, long secondFreeAmount, long sizeFee, long basicFee, + long transferAmount, long firstBalance, long secondBalance, long thirdBalance) + { + await SetPrimaryTokenSymbolAsync(); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = freeAmount + } + } + }, + RefreshSeconds = refreshSeconds, + Threshold = threshold + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmount); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(firstFreeAmount); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, firstBalance); + + await TokenContractStub.Transfer.SendAsync(new TransferInput + { + Amount = transferAmount, + Symbol = NativeTokenSymbol, + To = UserCAddress, + Memo = "test" + }); + + chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, secondBalance); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.ShouldBeEmpty(); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, transferAmount + sizeFee + basicFee); + + chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, thirdBalance); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(secondFreeAmount); + } + + [Fact] + public async Task ChargeTransactionFee_RefreshTime_Test() + { + const string TokenForELF = "TOKENA"; + const string TokenForUSDT = "TOKENB"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, "USDT"); + + await CreateTokenAsync(DefaultSender, TokenForELF); + await CreateTokenAsync(DefaultSender, TokenForUSDT); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 10000); + await IssueTokenToDefaultSenderAsync("USDT", 10000); + await IssueTokenToDefaultSenderAsync(TokenForELF, 10000); + await IssueTokenToDefaultSenderAsync(TokenForUSDT, 10000); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForELF, + Amount = 1000 + } + } + }, + RefreshSeconds = 2, + Threshold = 100 + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForUSDT, + Amount = 1000 + } + } + }, + RefreshSeconds = 1, + Threshold = 100 + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = TokenForUSDT, + BasicFee = 500 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = TokenForELF, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(1000); + + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(1000); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = 1000 + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); + + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(500); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); + await CheckDefaultSenderTokenAsync("USDT", 10000); + await CheckDefaultSenderTokenAsync(TokenForELF, 10000); + await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); + + chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); + + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(0); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); + await CheckDefaultSenderTokenAsync("USDT", 10000); + await CheckDefaultSenderTokenAsync(TokenForELF, 9000); + await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); + + _blockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddSeconds(1)); + + chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); + + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(500); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); + await CheckDefaultSenderTokenAsync("USDT", 10000); + await CheckDefaultSenderTokenAsync(TokenForELF, 8000); + await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); + } + + private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultSender, + Symbol = symbol + }); + + balance.Balance.ShouldBe(amount); + } + + private async Task CreateTokenAndIssueAsync() + { + await CreateTokenAsync(DefaultSender, "USDT"); + await IssueTokenToUserAsync(NativeTokenSymbol, 1_00000000, UserAAddress); + await IssueTokenToUserAsync("USDT", 1_000000, UserBAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, 1_00000000, UserCAddress); + await IssueTokenToUserAsync("USDT", 1_000000, UserCAddress); + } + + private async Task GetTokenSupplyAmount(string tokenSymbol) + { + var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = tokenSymbol + }); + return tokenInfo.Supply; + } + + private async Task> GetDefaultBalancesAsync(string[] tokenSymbolList) + { + var balances = new List(); + foreach (var symbol in tokenSymbolList) + balances.Add(await GetBalanceAsync(DefaultSender, symbol)); + return balances; + } + + private async Task CreateTokenAsync(Address creator, string tokenSymbol, bool isBurned = true) + { + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = tokenSymbol, + TokenName = tokenSymbol + " name", + TotalSupply = 1000_00000000, + IsBurnable = isBurned, + Issuer = creator, + }); + } + + private async Task IssueTokenToDefaultSenderAsync(string tokenSymbol, long amount) + { + if (amount <= 0) return; + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() + { + Symbol = tokenSymbol, + Amount = amount, + To = DefaultSender, + }); + issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + private async Task IssueTokenToUserAsync(string tokenSymbol, long amount, Address to) + { + var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput() + { + Symbol = tokenSymbol, + Amount = amount, + To = to, + }); + issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + // single node + private async Task SubmitAndPassProposalOfDefaultParliamentAsync(Address contractAddress, string methodName, + IMessage input) + { + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposal = new CreateProposalInput + { + OrganizationAddress = defaultParliament, + ToAddress = contractAddress, + Params = input.ToByteString(), + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var createProposalRet = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + createProposalRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = createProposalRet.Output; + await ParliamentContractStub.Approve.SendAsync(proposalId); + var releaseRet = await ParliamentContractStub.Release.SendAsync(proposalId); + releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + private async Task SubmitProposalOfDefaultParliamentAsync(Address contractAddress, string methodName, + IMessage input) + { + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposal = new CreateProposalInput + { + OrganizationAddress = defaultParliament, + ToAddress = contractAddress, + Params = input.ToByteString(), + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) + }; + var createProposalRet = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + createProposalRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var proposalId = createProposalRet.Output; + await ParliamentContractStub.Approve.SendAsync(proposalId); + var releaseRet = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + return releaseRet.TransactionResult.Error; } private async Task GetBalanceAsync(Address address, string tokenSymbol) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index 63243ee4b3..ba428b37d5 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -10,7 +10,6 @@ using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.Kernel.Blockchain.Application; -using AElf.Kernel.Blockchain.Domain; using AElf.Kernel.Configuration; using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract.Application; @@ -23,7 +22,6 @@ using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.Threading; -using Xunit; namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; @@ -31,10 +29,12 @@ public class ExecutionPluginForMethodFeeTestBase : ContractTestBase +public class + ExecutionPluginForUserContractMethodFeeTestBase : ContractTestBase< + ExecutionPluginForUserContractMethodFeeTestModule> { protected const string NativeTokenSymbol = "ELF"; - + internal Address ConfigurationAddress; internal Address ParliamentAddress; internal Address ConsensusContractAddress; @@ -46,12 +46,13 @@ public class ExecutionPluginForUserContractMethodFeeTestBase : ContractTestBase< internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } protected new ISmartContractAddressService ContractAddressService => Application.ServiceProvider.GetRequiredService(); + protected IBlockchainService BlockChainService => Application.ServiceProvider.GetRequiredService(); - + protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; protected Address DefaultAddress => Accounts[0].Address; - + protected List InitialCoreDataCenterKeyPairs => Accounts.Take(1).Select(a => a.KeyPair).ToList(); @@ -59,17 +60,19 @@ protected ExecutionPluginForUserContractMethodFeeTestBase() { AsyncHelper.RunSync(InitializeContracts); } + private async Task InitializeContracts() { await DeployContractsAsync(); - AuthorizationContractStub= + AuthorizationContractStub = GetTester(ParliamentAddress, DefaultSenderKeyPair); await InitializeAElfConsensus(); - await InitializedParliament(); + await InitializedParliament(); TokenContractStub = await GetTokenContractStubAsync(); await SetPrimaryTokenSymbolAsync(); } + private async Task
GetTokenContractAddressAsync() { var preBlockHeader = await BlockChainService.GetBestChainLastBlockHeaderAsync(); @@ -83,6 +86,7 @@ private async Task
GetTokenContractAddressAsync() return contractMapping[TokenSmartContractAddressNameProvider.Name]; } + private async Task GetTokenContractStubAsync() { TokenContractAddress = await GetTokenContractAddressAsync(); @@ -121,7 +125,6 @@ private async Task DeployContractsAsync() ParliamentContractStub = GetTester(ParliamentAddress, DefaultSenderKeyPair); - } //Consensus { @@ -133,6 +136,7 @@ private async Task DeployContractsAsync() DefaultSenderKeyPair); } } + private async Task InitializeAElfConsensus() { { @@ -180,6 +184,7 @@ private Round GenerateFirstRoundOfNewTerm(MinerList minerList, int miningInterva return round; } + private async Task SetPrimaryTokenSymbolAsync() { await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput @@ -284,8 +289,11 @@ public class ExecutePluginTransactionDirectlyForMethodFeeTestBase : ContractTest { protected const string NativeTokenSymbol = "ELF"; + protected readonly IBlockTimeProvider _blockTimeProvider; + protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() { + _blockTimeProvider = GetRequiredService(); AsyncHelper.RunSync(InitializeContracts); } @@ -305,6 +313,7 @@ protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() internal ECKeyPair UserTomSenderKeyPair => Accounts[10].KeyPair; internal Address UserTomSender => Accounts[10].Address; + protected List InitialCoreDataCenterKeyPairs => Accounts.Take(1).Select(a => a.KeyPair).ToList(); @@ -314,9 +323,10 @@ protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() internal TokenContractContainer.TokenContractStub TokenContractStubA { get; set; } internal Address UserAAddress => Accounts[3].Address; - internal Address UserCAddress => Accounts[4].Address; + internal Address UserBAddress => Accounts[4].Address; + internal Address UserCAddress => Accounts[5].Address; + - private async Task InitializeContracts() { await DeployContractsAsync(); @@ -346,9 +356,9 @@ private async Task DeployContractsAsync() GetTester(TokenContractAddress, DefaultSenderKeyPair); TokenContractStub2 = GetTester(TokenContractAddress, DelegateeKeyPair); - TokenContractStub3 = + TokenContractStub3 = GetTester(TokenContractAddress, UserKeyPair); - TokenContractStubA = + TokenContractStubA = GetTester(TokenContractAddress, UserKeyPair); TokenContractImplStub = GetTester(TokenContractAddress, DefaultSenderKeyPair); diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestModule.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestModule.cs index b05c11846f..874d7b8049 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestModule.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestModule.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using AElf.Blockchains.MainChain; using AElf.Contracts.TestBase; using AElf.ContractTestKit; using AElf.Cryptography; @@ -11,7 +10,6 @@ using AElf.Kernel.Miner.Application; using AElf.Kernel.SmartContract.Application; using AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.Service; -using AElf.Kernel.Token; using AElf.OS.Node.Application; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -47,8 +45,8 @@ public override void ConfigureServices(ServiceConfigurationContext context) [DependsOn( typeof(ContractTestModule), -typeof(ExecutionPluginForMethodFeeModule), -typeof(FeeCalculationModule))] + typeof(ExecutionPluginForMethodFeeModule), + typeof(FeeCalculationModule))] public class ExecutionPluginForUserContractMethodFeeTestModule : ContractTestModule { public override void ConfigureServices(ServiceConfigurationContext context) @@ -95,6 +93,7 @@ public class ExecutionPluginTransactionDirectlyForMethodFeeTestModule : Contract public override void ConfigureServices(ServiceConfigurationContext context) { Configure(o => o.ContractDeploymentAuthorityRequired = false); + context.Services.AddSingleton(); context.Services.RemoveAll(); context.Services.RemoveAll(); context.Services.RemoveAll(); From 04ee3ce171d5caa811e175a54575ea45a20c1f82 Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 8 Jun 2023 14:09:31 +0800 Subject: [PATCH 024/139] fix: ut --- .../TokenContract_Fees.cs | 38 +- .../ExecutePluginTransactionDirectlyTest.cs | 1515 +---------------- ...inTransactionDirectlyTest_FreeAllowance.cs | 1444 ++++++++++++++++ 3 files changed, 1513 insertions(+), 1484 deletions(-) create mode 100644 test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 125085667f..11ddb5242b 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -365,7 +365,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress // Size Fee is charged in primary token, elf. var symbolToPayTxFee = State.ChainPrimaryTokenSymbol.Value; //Get primary token balance - GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, freeAllowances, allowanceBill, + GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, methodFeeFreeAllowancesMap, allowanceBill, out var symbolChargedForBaseFee, out var amountChargedForBaseFee, out var amountChargedForBaseAllowance, out var availableBalance, out var availableAllowance); var txSizeFeeAmount = input.TransactionSizeFee; @@ -375,15 +375,15 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress { var allSymbolToTxFee = input.SymbolsToPayTxSizeFee.ToList(); var availableSymbol = GetAvailableSymbolToPayTxFee(allSymbolToTxFee, fromAddress, txSizeFeeAmount, - freeAllowances, symbolChargedForBaseFee, amountChargedForBaseFee, amountChargedForBaseAllowance, - delegations); + methodFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseFee, + amountChargedForBaseAllowance, delegations); if (availableSymbol != null && availableSymbol.TokenSymbol != symbolToPayTxFee) { symbolToPayTxFee = availableSymbol.TokenSymbol; txSizeFeeAmount = txSizeFeeAmount.Mul(availableSymbol.AddedTokenWeight) .Div(availableSymbol.BaseTokenWeight); - GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, freeAllowances, allowanceBill, + GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, methodFeeFreeAllowancesMap, allowanceBill, out symbolChargedForBaseFee, out amountChargedForBaseFee, out amountChargedForBaseAllowance, out availableBalance, out availableAllowance); } @@ -412,7 +412,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress } private void GetAvailableBalance(string symbolToPayTxFee, Address fromAddress, TransactionFeeBill bill, - MethodFeeFreeAllowances freeAllowances, TransactionFreeFeeAllowanceBill allowanceBill, + MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, TransactionFreeFeeAllowanceBill allowanceBill, out string symbolChargedForBaseFee, out long amountChargedForBaseFee, out long amountChargedForBaseAllowance, out long availableBalance, out long availableAllowance) { @@ -432,12 +432,12 @@ private void GetAvailableBalance(string symbolToPayTxFee, Address fromAddress, T ? GetBalance(fromAddress, symbolToPayTxFee).Sub(amountChargedForBaseFee) : GetBalance(fromAddress, symbolToPayTxFee); availableAllowance = symbolChargedForBaseFee == symbolToPayTxFee - ? GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) - : GetFreeFeeAllowanceAmount(freeAllowances, symbolToPayTxFee); + ? GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) + : GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbolToPayTxFee); } private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List allSymbolToTxFee, - Address fromAddress, long txSizeFeeAmount, MethodFeeFreeAllowances freeAllowances, + Address fromAddress, long txSizeFeeAmount, MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, string symbolChargedForBaseFee, long amountChargedForBaseFee, long amountChargedForBaseAllowance, TransactionFeeDelegations delegations = null) { @@ -448,12 +448,14 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List { var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, - symbolChargedForBaseFee, amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance); + symbolChargedForBaseFee, amountChargedForBaseFee, methodFeeFreeAllowancesMap, + amountChargedForBaseAllowance); return balance >= txSizeFeeAmount; }) ?? allSymbolToTxFee.FirstOrDefault(x => { var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, - symbolChargedForBaseFee, amountChargedForBaseFee, freeAllowances, amountChargedForBaseAllowance); + symbolChargedForBaseFee, amountChargedForBaseFee, methodFeeFreeAllowancesMap, + amountChargedForBaseAllowance); return balance > 0; }); } @@ -464,7 +466,8 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List= txSizeFeeAmount; }); } @@ -667,7 +670,7 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM existingBalance = 0L; existingAllowance = 0L; - symbol = GetAvailableSymbolToPayBaseFee(symbolToAmountMap, fromAddress, freeAllowances, out amount, + symbol = GetAvailableSymbolToPayBaseFee(symbolToAmountMap, fromAddress, methodFeeFreeAllowancesMap, out amount, delegations); //Whether or not delegation exists, there is no token that can be used for payment if (symbol == null) return false; @@ -675,7 +678,7 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM //For delegation, There is enough token balance and delegation to pay //For user, There is enough token balance to pay or there is a token balance greater than 0 existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); //For delegation, return true //For user,if balance enough return true if (delegations != null || existingBalance.Add(existingAllowance) >= amount) @@ -689,14 +692,15 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM { symbol = primaryTokenSymbol; existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); } return false; } private string GetAvailableSymbolToPayBaseFee(Dictionary symbolToAmountMap, Address fromAddress, - MethodFeeFreeAllowances freeAllowances, out long amount, TransactionFeeDelegations delegations = null) + MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, out long amount, + TransactionFeeDelegations delegations = null) { string symbolOfValidBalance = null; amount = 0; @@ -711,7 +715,7 @@ private string GetAvailableSymbolToPayBaseFee(Dictionary symbolToA // current token symbol amount = value; var existingBalance = GetBalance(fromAddress, symbol); - var existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + var existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); if (existingBalance.Add(existingAllowance) > 0) { symbolOfValidBalance = symbol; @@ -729,7 +733,7 @@ private string GetAvailableSymbolToPayBaseFee(Dictionary symbolToA // current token symbol amount = value; var existingBalance = GetBalance(fromAddress, symbol); - var existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + var existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); // is unlimited delegate is true && balance enough // is unlimited delegate is false && delegation enough && balance enough if ((delegations.IsUnlimitedDelegate && existingBalance.Add(existingAllowance) >= amount) || diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 47dac2e6f1..bfbcce9832 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.MultiToken; -using AElf.ContractTestBase.ContractTestKit; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; using AElf.Standards.ACS1; @@ -15,7 +14,7 @@ namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; -public class ExecutePluginTransactionDirectlyTest : ExecutePluginTransactionDirectlyForMethodFeeTestBase +public partial class ExecutePluginTransactionDirectlyTest : ExecutePluginTransactionDirectlyForMethodFeeTestBase { [Fact] public async Task ChargeTransactionFees_Invalid_Input_Test() @@ -1011,1437 +1010,6 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } - [Fact] - public async Task ConfigMethodFeeFreeAllowances_Test() - { - await SetPrimaryTokenSymbolAsync(); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = 0 - } - } - }, - RefreshSeconds = 600, - Threshold = 0 - } - } - }); - - { - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Value.Count.ShouldBe(1); - config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().Threshold.ShouldBe(0); - config.Value.First().RefreshSeconds.ShouldBe(600); - config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(0); - - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); - } - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 2_00000000); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = 1_00000000 - } - } - }, - RefreshSeconds = 600, - Threshold = 1_00000000 - } - } - }); - - { - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Value.Count.ShouldBe(1); - config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().Threshold.ShouldBe(1_00000000); - config.Value.First().RefreshSeconds.ShouldBe(600); - config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - } - } - - [Fact] - public async Task ConfigMethodFeeFreeAllowances_Unauthorized_Test() - { - var result = - await TokenContractImplStub.ConfigMethodFeeFreeAllowances.SendWithExceptionAsync( - new ConfigMethodFeeFreeAllowancesInput()); - result.TransactionResult.Error.ShouldContain("Unauthorized behavior."); - } - - [Fact] - public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_OneByOne_Test() - { - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAndIssueAsync(); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = 1_00000000 - } - } - }, - RefreshSeconds = 600, - Threshold = 1_00000000 - } - } - }); - - { - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Value.Count.ShouldBe(1); - config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().Threshold.ShouldBe(1_00000000); - config.Value.First().RefreshSeconds.ShouldBe(600); - config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); - userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); - userBFreeAllowances.Result.Map.Count.ShouldBe(0); - var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); - userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); - } - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = "USDT", - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = 1_00000000 - } - } - }, - RefreshSeconds = 300, - Threshold = 1_000000 - } - } - }); - - { - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Value.Count.ShouldBe(2); - config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().Threshold.ShouldBe(1_00000000); - config.Value.First().RefreshSeconds.ShouldBe(600); - config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - - config.Value.Last().Symbol.ShouldBe("USDT"); - config.Value.Last().Threshold.ShouldBe(1_000000); - config.Value.Last().RefreshSeconds.ShouldBe(300); - config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); - userAFreeAllowances.Result.Map.Count.ShouldBe(1); - userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); - userBFreeAllowances.Result.Map.Count.ShouldBe(1); - userBFreeAllowances.Result.Map.Keys.First().ShouldBe("USDT"); - userBFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); - userAFreeAllowances.Result.Map.Add("USDT", userBFreeAllowances.Result.Map.Values.First()); - userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); - } - } - - [Fact] - public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test() - { - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAndIssueAsync(); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = 1_00000000 - } - } - }, - RefreshSeconds = 600, - Threshold = 1_00000000 - }, - new ConfigMethodFeeFreeAllowance - { - Symbol = "USDT", - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = 1_00000000 - } - } - }, - RefreshSeconds = 300, - Threshold = 1_000000 - } - } - }); - - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Value.Count.ShouldBe(2); - config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().Threshold.ShouldBe(1_00000000); - config.Value.First().RefreshSeconds.ShouldBe(600); - config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - - config.Value.Last().Symbol.ShouldBe("USDT"); - config.Value.Last().Threshold.ShouldBe(1_000000); - config.Value.Last().RefreshSeconds.ShouldBe(300); - config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); - userAFreeAllowances.Result.Map.Count.ShouldBe(1); - userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); - userBFreeAllowances.Result.Map.Count.ShouldBe(1); - userBFreeAllowances.Result.Map.Keys.First().ShouldBe("USDT"); - userBFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); - userAFreeAllowances.Result.Map.Add("USDT", userBFreeAllowances.Result.Map.Values.First()); - userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); - } - - [Fact] - public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_Modify_Test() - { - await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); - await CreateTokenAsync(DefaultSender, "ABC"); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = "USDT", - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = 2_00000000 - }, - new MethodFeeFreeAllowance - { - Symbol = "ABC", - Amount = 2_00000000 - } - } - }, - RefreshSeconds = 1200, - Threshold = 2_000000 - } - } - }); - - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Value.Count.ShouldBe(2); - config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().Threshold.ShouldBe(1_00000000); - config.Value.First().RefreshSeconds.ShouldBe(600); - config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - - config.Value.Last().Symbol.ShouldBe("USDT"); - config.Value.Last().Threshold.ShouldBe(2_000000); - config.Value.Last().RefreshSeconds.ShouldBe(1200); - config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(2_00000000); - config.Value.Last().FreeAllowances.Map.Keys.Last().ShouldBe("ABC"); - config.Value.Last().FreeAllowances.Map.Values.Last().Symbol.ShouldBe("ABC"); - config.Value.Last().FreeAllowances.Map.Values.Last().Amount.ShouldBe(2_00000000); - - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); - userAFreeAllowances.Result.Map.Count.ShouldBe(1); - userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); - userBFreeAllowances.Result.Map.Count.ShouldBe(0); - var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); - userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); - } - - [Fact] - public async Task ConfigMethodFeeFreeAllowances_InvalidInput_Test() - { - var message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance() - } - }); - message.ShouldContain("Invalid input symbol"); - - message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = "TEST" - } - } - }); - message.ShouldContain("Symbol TEST not exist"); - - message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol - } - } - }); - message.ShouldContain("Invalid input allowances"); - - message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = 1_00000000 - } - } - }, - Threshold = -1 - } - } - }); - message.ShouldContain("Invalid input threshold"); - - message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = 1_00000000 - } - } - }, - Threshold = 1_00000000, - RefreshSeconds = -1 - } - } - }); - message.ShouldContain("Invalid input refresh seconds"); - } - - [Fact] - public async Task RemoveMethodFeeFreeAllowancesConfig_Unauthorized_Test() - { - var result = - await TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig.SendWithExceptionAsync( - new RemoveMethodFeeFreeAllowancesConfigInput()); - result.TransactionResult.Error.ShouldContain("Unauthorized behavior."); - } - - [Fact] - public async Task RemoveMethodFeeFreeAllowancesConfig_Test() - { - await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); - await IssueTokenToUserAsync("USDT", 1_000000, UserAAddress); - - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); - userAFreeAllowances.Result.Map.Count.ShouldBe(2); - var config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Result.Value.Count.ShouldBe(2); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput - { - Symbols = { "USDT" } - }); - config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Result.Value.Count.ShouldBe(1); - config.Result.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); - userAFreeAllowances.Result.Map.Count.ShouldBe(1); - userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); - - // symbol not exist - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput - { - Symbols = { "USDT" } - }); - config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Result.Value.Count.ShouldBe(1); - config.Result.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); - userAFreeAllowances.Result.Map.Count.ShouldBe(1); - userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); - - // Duplicate symbols - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput - { - Symbols = { "ELF", "ELF" } - }); - config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Result.Value.Count.ShouldBe(0); - userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); - userAFreeAllowances.Result.Map.Count.ShouldBe(0); - } - - [Fact] - public async Task RemoveMethodFeeFreeAllowancesConfig_MultipleTokens_AtOnce_Test() - { - await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); - await IssueTokenToUserAsync("USDT", 1_000000, UserAAddress); - - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); - userAFreeAllowances.Result.Map.Count.ShouldBe(2); - var config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); - config.Result.Value.Count.ShouldBe(2); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput - { - Symbols = { "ELF", "USDT" } - }); - userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); - userAFreeAllowances.Result.Map.Count.ShouldBe(0); - } - - [Fact] - public async Task RemoveMethodFeeFreeAllowancesConfig_InvalidInput_Test() - { - var message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput - { - Symbols = { "USDT" } - }); - message.ShouldContain("Method fee free allowances config not set"); - - await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); - message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput()); - message.ShouldContain("Invalid input"); - } - - [Theory] - [InlineData(1000, 0, 1000, 0, 100, 0, 0, 0, 800, 0, 1000, 200)] - [InlineData(1000, 0, 100, 0, 100, 0, 0, 0, 0, 0, 900, 200)] - [InlineData(1000, 1000, 500, 10, 100, 500, 20, 100, 300, 500, 1000, 200)] - [InlineData(1000, 1000, 150, 10, 100, 150, 20, 100, 0, 100, 1000, 200)] - public async Task ChargeTransactionFee_Test(long initialELFBalance, long initialUSDTBalance, - long freeAmountELF, long refreshSecondsELF, long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, - long thresholdUSDT, long newFreeAmountELF, long newFreeAmountUSDT, long afterBalance, long basicFee) - { - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, "USDT"); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); - await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = freeAmountELF - } - } - }, - RefreshSeconds = refreshSecondsELF, - Threshold = thresholdELF - }, - new ConfigMethodFeeFreeAllowance - { - Symbol = "USDT", - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = freeAmountUSDT - } - } - }, - RefreshSeconds = refreshSecondsUSDT, - Threshold = thresholdUSDT - } - } - }); - - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = NativeTokenSymbol, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress - }; - - var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(true); - - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountELF); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); - - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterBalance); - } - - [Theory] - [InlineData(1000, 1000, 1000, 1000, 1000, 10, 100, 1000, 20, 100, 700, 500, 1000, 1000, 1000, 1000, 300, 500)] - [InlineData(1000, 1000, 1000, 1000, 100, 10, 100, 1000, 20, 100, 0, 500, 800, 1000, 1000, 1000, 300, 500)] - [InlineData(1000, 1000, 1000, 1000, 500, 10, 10000, 500, 20, 1000, 0, 300, 800, 1000, 1000, 1000, 200, 200)] - [InlineData(1000, 1000, 1000, 1000, 1000, 10, 1000, 1000, 20, 1000, 0, 0, 0, 0, 1000, 1000, 10000, 5000)] - public async Task ChargeTransactionFee_MultipleTokens_Test(long initialELFBalance, long initialUSDTBalance, - long initialTokenABalance, long initialTokenBBalance, long freeAmountELF, long refreshSecondsELF, - long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFreeAmountELF, - long newFreeAmountUSDT, long afterTokenABalance, long afterTokenBBalance, long afterELFBalance, - long afterUSDTBalance, long sizeFee, long basicFee) - { - const string TokenForELF = "TOKENA"; - const string TokenForUSDT = "TOKENB"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, "USDT"); - - await CreateTokenAsync(DefaultSender, TokenForELF); - await CreateTokenAsync(DefaultSender, TokenForUSDT); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); - await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); - await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); - await IssueTokenToDefaultSenderAsync(TokenForUSDT, initialTokenBBalance); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = TokenForELF, - Amount = freeAmountELF - } - } - }, - RefreshSeconds = refreshSecondsELF, - Threshold = thresholdELF - }, - new ConfigMethodFeeFreeAllowance - { - Symbol = "USDT", - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = TokenForUSDT, - Amount = freeAmountUSDT - } - } - }, - RefreshSeconds = refreshSecondsUSDT, - Threshold = thresholdUSDT - } - } - }); - - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = TokenForUSDT, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = TokenForELF, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - if (initialELFBalance >= thresholdELF) - { - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); - } - - if (initialUSDTBalance >= thresholdUSDT) - { - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); - } - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - - var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(initialTokenABalance + freeAmountELF >= sizeFee); - - - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - if (initialELFBalance >= thresholdELF) - { - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountELF); - } - - if (initialUSDTBalance >= thresholdUSDT) - { - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); - } - - await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); - await CheckDefaultSenderTokenAsync(TokenForUSDT, afterTokenBBalance); - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); - await CheckDefaultSenderTokenAsync("USDT", afterUSDTBalance); - } - - [Theory] - [InlineData(1000, 600, 200, 200)] - public async Task ChargeTransactionFee_NoFreeAllowance_Test(long initialBalance, long afterBalance, long sizeFee, - long basicFee) - { - await SetPrimaryTokenSymbolAsync(); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = NativeTokenSymbol, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - - var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(true); - - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterBalance); - } - - [Theory] - [InlineData(1000, 1000, 1000, 2000, 2000, 0, 1000, 1000, 500, 1000, 1000, 1000, 1500)] - public async Task ChargeTransactionFee_SingleThreshold_Test(long initialBalance, long initialTokenABalance, - long initialTokenBBalance, long freeAmountTokenA, long freeAmountTokenB, long refreshSeconds, - long threshold, long newFreeAmountTokenA, long newFreeAmountTokenB, long afterTokenABalance, - long afterTokenBBalance, long sizeFee, long basicFee) - { - const string TokenA = "TOKENA"; - const string TokenB = "TOKENB"; - - await SetPrimaryTokenSymbolAsync(); - - await CreateTokenAsync(DefaultSender, TokenA); - await CreateTokenAsync(DefaultSender, TokenB); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToDefaultSenderAsync(TokenA, initialTokenABalance); - await IssueTokenToDefaultSenderAsync(TokenB, initialTokenBBalance); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = TokenA, - Amount = freeAmountTokenA - }, - new MethodFeeFreeAllowance - { - Symbol = TokenB, - Amount = freeAmountTokenB - } - } - }, - RefreshSeconds = refreshSeconds, - Threshold = threshold - } - } - }); - - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = TokenB, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = TokenA, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenA); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenA); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountTokenA); - - freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(TokenB); - freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(TokenB); - freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(freeAmountTokenB); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - - var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(true); - - - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenA); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenA); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountTokenA); - - freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(TokenB); - freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(TokenB); - freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(newFreeAmountTokenB); - - await CheckDefaultSenderTokenAsync(TokenA, afterTokenABalance); - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterTokenBBalance); - } - - [Theory] - [InlineData(1000, 1000, 1000, 1000, 1000, 10, 100, 1000, 20, 100, 0, 1000, 0, 1000, 3000, 5000)] - public async Task ChargeTransactionFee_NotEnough_Test(long initialELFBalance, long initialUSDTBalance, - long initialTokenABalance, long initialTokenBBalance, long freeAmountELF, long refreshSecondsELF, - long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFreeAmountELF, - long newFreeAmountUSDT, long afterTokenABalance, long afterTokenBBalance, long sizeFee, long basicFee) - { - const string TokenForELF = "TOKENA"; - const string TokenForUSDT = "TOKENB"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, "USDT"); - - await CreateTokenAsync(DefaultSender, TokenForELF); - await CreateTokenAsync(DefaultSender, TokenForUSDT); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); - await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); - await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); - await IssueTokenToDefaultSenderAsync(TokenForUSDT, initialTokenBBalance); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = TokenForELF, - Amount = freeAmountELF - } - } - }, - RefreshSeconds = refreshSecondsELF, - Threshold = thresholdELF - }, - new ConfigMethodFeeFreeAllowance - { - Symbol = "USDT", - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = TokenForUSDT, - Amount = freeAmountUSDT - } - } - }, - RefreshSeconds = refreshSecondsUSDT, - Threshold = thresholdUSDT - } - } - }); - - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = TokenForELF, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = TokenForELF, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - - var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(false); - - - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); - - await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); - await CheckDefaultSenderTokenAsync(TokenForUSDT, afterTokenBBalance); - } - - [Theory] - [InlineData(10000, 500, 50, 10000, 300, 100, 100, 100, 2000, 10000, 7800, 10000)] - public async Task ChargeTransactionFee_ClearFreeAllowance_Test(long initialBalance, long freeAmount, - long refreshSeconds, long threshold, long firstFreeAmount, long secondFreeAmount, long sizeFee, long basicFee, - long transferAmount, long firstBalance, long secondBalance, long thirdBalance) - { - await SetPrimaryTokenSymbolAsync(); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - Amount = freeAmount - } - } - }, - RefreshSeconds = refreshSeconds, - Threshold = threshold - } - } - }); - - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = NativeTokenSymbol, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmount); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - - var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(true); - - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(firstFreeAmount); - - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, firstBalance); - - await TokenContractStub.Transfer.SendAsync(new TransferInput - { - Amount = transferAmount, - Symbol = NativeTokenSymbol, - To = UserCAddress, - Memo = "test" - }); - - chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(true); - - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, secondBalance); - - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.ShouldBeEmpty(); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, transferAmount + sizeFee + basicFee); - - chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(true); - - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, thirdBalance); - - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(secondFreeAmount); - } - - [Fact] - public async Task ChargeTransactionFee_RefreshTime_Test() - { - const string TokenForELF = "TOKENA"; - const string TokenForUSDT = "TOKENB"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, "USDT"); - - await CreateTokenAsync(DefaultSender, TokenForELF); - await CreateTokenAsync(DefaultSender, TokenForUSDT); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 10000); - await IssueTokenToDefaultSenderAsync("USDT", 10000); - await IssueTokenToDefaultSenderAsync(TokenForELF, 10000); - await IssueTokenToDefaultSenderAsync(TokenForUSDT, 10000); - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - { - Value = - { - new ConfigMethodFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = TokenForELF, - Amount = 1000 - } - } - }, - RefreshSeconds = 2, - Threshold = 100 - }, - new ConfigMethodFeeFreeAllowance - { - Symbol = "USDT", - MethodFeeFreeAllowances = new MethodFeeFreeAllowances - { - Value = - { - new MethodFeeFreeAllowance - { - Symbol = TokenForUSDT, - Amount = 1000 - } - } - }, - RefreshSeconds = 1, - Threshold = 100 - } - } - }); - - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = TokenForUSDT, - BasicFee = 500 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = TokenForELF, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(1000); - - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(1000); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = 1000 - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - - var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(true); - - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); - - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(500); - - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); - await CheckDefaultSenderTokenAsync("USDT", 10000); - await CheckDefaultSenderTokenAsync(TokenForELF, 10000); - await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); - - chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(true); - - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); - - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(0); - - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); - await CheckDefaultSenderTokenAsync("USDT", 10000); - await CheckDefaultSenderTokenAsync(TokenForELF, 9000); - await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); - - _blockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddSeconds(1)); - - chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(true); - - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); - - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(500); - - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); - await CheckDefaultSenderTokenAsync("USDT", 10000); - await CheckDefaultSenderTokenAsync(TokenForELF, 8000); - await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); - } - - private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) - { - var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultSender, - Symbol = symbol - }); - - balance.Balance.ShouldBe(amount); - } - - private async Task CreateTokenAndIssueAsync() - { - await CreateTokenAsync(DefaultSender, "USDT"); - await IssueTokenToUserAsync(NativeTokenSymbol, 1_00000000, UserAAddress); - await IssueTokenToUserAsync("USDT", 1_000000, UserBAddress); - await IssueTokenToUserAsync(NativeTokenSymbol, 1_00000000, UserCAddress); - await IssueTokenToUserAsync("USDT", 1_000000, UserCAddress); - } - [Theory] [InlineData(1000, 1000, 1000, 1000, 1000, 1000, 1000, 50, 50, 100, 100, 50, 50, 10, 10, 80, 80, 50, 30, 920)] public async Task ChargeTransactionFee_DelegateNew_First( @@ -2509,39 +1077,46 @@ public async Task ChargeTransactionFee_DelegateNew_First( } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput { - FreeAllowances = new MethodFeeFreeAllowances + Value = { - Value = + new ConfigMethodFeeFreeAllowance { - new MethodFeeFreeAllowance - { - Symbol = basicFeeSymbol, - Amount = baseFeeFreeAmount - }, - new MethodFeeFreeAllowance + Symbol = NativeTokenSymbol, + RefreshSeconds = 100, + Threshold = threshold, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances { - Symbol = sizeFeeSymbol, - Amount = sizeFeeFreeAmount + Value = + { + new MethodFeeFreeAllowance + { + Symbol = basicFeeSymbol, + Amount = baseFeeFreeAmount + }, + new MethodFeeFreeAllowance + { + Symbol = sizeFeeSymbol, + Amount = sizeFeeFreeAmount + } + } } } - }, - RefreshSeconds = 100, - Threshold = threshold + } }); { - var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(userAddress); + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(userAddress); if (threshold <= initialBalance) { - freeAllowances.Value.First().Symbol.ShouldBe(basicFeeSymbol); - freeAllowances.Value.First().Amount.ShouldBe(baseFeeFreeAmount); - freeAllowances.Value.Last().Symbol.ShouldBe(sizeFeeSymbol); - freeAllowances.Value.Last().Amount.ShouldBe(sizeFeeFreeAmount); + freeAllowances.Map.First().Value.Map.Values.First().Symbol.ShouldBe(basicFeeSymbol); + freeAllowances.Map.First().Value.Map.Values.First().Amount.ShouldBe(baseFeeFreeAmount); + freeAllowances.Map.First().Value.Map.Values.Last().Symbol.ShouldBe(sizeFeeSymbol); + freeAllowances.Map.First().Value.Map.Values.Last().Amount.ShouldBe(sizeFeeFreeAmount); } else { - freeAllowances.Value.ShouldBeEmpty(); + freeAllowances.Map.ShouldBeEmpty(); } } @@ -2659,7 +1234,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call } [Theory] - [InlineData( 10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] + [InlineData(10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] public async Task ChargeTransactionFee_DelegationNew_Second_Success( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, @@ -2789,7 +1364,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && + chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) { chargeFeeRetDefault.Output.Success.ShouldBe(true); @@ -2808,7 +1384,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call Owner = delegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(20); - + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, @@ -2849,8 +1425,9 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call delegation2.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); } } + [Theory] - [InlineData( 10, 20, 70, 1000, 1000, 1000, 10, 10, 20, 20, 70, 70, 80, 80, 70, 1000)] + [InlineData(10, 20, 70, 1000, 1000, 1000, 10, 10, 20, 20, 70, 70, 80, 80, 70, 1000)] public async Task ChargeTransactionFee_DelegationNew_Second_Failed( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, @@ -2980,7 +1557,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && + chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) { chargeFeeRetDefault.Output.Success.ShouldBe(false); chargeFeeRetDefault.Output.ChargingInformation.ShouldBe("Transaction fee not enough."); @@ -3000,7 +1578,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call Owner = delegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(20); - + //no change var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { @@ -3023,8 +1601,9 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call chargeFeeRetDefault.Output.Success.ShouldBe(false); } } + [Theory] - [InlineData( 10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] + [InlineData(10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, @@ -3145,7 +1724,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && + chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) { chargeFeeRetDefault.Output.Success.ShouldBe(true); @@ -3164,7 +1744,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call Owner = delegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(20); - + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, @@ -3203,9 +1783,9 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call delegation2.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); } } - + [Theory] - [InlineData( 10, 20, 100, 10, 10, 20, 20, 100, 100, 80, 80, 20)] + [InlineData(10, 20, 100, 10, 10, 20, 20, 100, 100, 80, 80, 20)] public async Task ChargeTransactionFee_DelegationNew_UnlimitedDelegate_Success( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, @@ -3318,7 +1898,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) + if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && + chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) { chargeFeeRetDefault.Output.Success.ShouldBe(true); @@ -3337,7 +1918,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call Owner = delegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(20); - + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Symbol = basicFeeSymbol, @@ -3358,7 +1939,7 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call delegation.Delegations[NativeTokenSymbol].ShouldBe(5); } } - + private async Task GetTokenSupplyAmount(string tokenSymbol) { var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs new file mode 100644 index 0000000000..5aa84de8f1 --- /dev/null +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -0,0 +1,1444 @@ +using System.Linq; +using System.Threading.Tasks; +using AElf.Contracts.MultiToken; +using AElf.CSharp.Core.Extension; +using AElf.Standards.ACS1; +using Google.Protobuf.WellKnownTypes; +using Shouldly; +using Xunit; + +namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; + +public partial class ExecutePluginTransactionDirectlyTest +{ + [Fact] + public async Task ConfigMethodFeeFreeAllowances_Test() + { + await SetPrimaryTokenSymbolAsync(); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 0 + } + } + }, + RefreshSeconds = 600, + Threshold = 0 + } + } + }); + + { + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(1); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(0); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(0); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); + } + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 2_00000000); + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + RefreshSeconds = 600, + Threshold = 1_00000000 + } + } + }); + + { + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(1); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(1_00000000); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + } + } + + [Fact] + public async Task ConfigMethodFeeFreeAllowances_Unauthorized_Test() + { + var result = + await TokenContractImplStub.ConfigMethodFeeFreeAllowances.SendWithExceptionAsync( + new ConfigMethodFeeFreeAllowancesInput()); + result.TransactionResult.Error.ShouldContain("Unauthorized behavior."); + } + + [Fact] + public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_OneByOne_Test() + { + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAndIssueAsync(); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + RefreshSeconds = 600, + Threshold = 1_00000000 + } + } + }); + + { + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(1); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(1_00000000); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + userBFreeAllowances.Result.Map.Count.ShouldBe(0); + var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); + } + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + RefreshSeconds = 300, + Threshold = 1_000000 + } + } + }); + + { + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(2); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(1_00000000); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + config.Value.Last().Symbol.ShouldBe("USDT"); + config.Value.Last().Threshold.ShouldBe(1_000000); + config.Value.Last().RefreshSeconds.ShouldBe(300); + config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(1); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + userBFreeAllowances.Result.Map.Count.ShouldBe(1); + userBFreeAllowances.Result.Map.Keys.First().ShouldBe("USDT"); + userBFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + userAFreeAllowances.Result.Map.Add("USDT", userBFreeAllowances.Result.Map.Values.First()); + userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); + } + } + + [Fact] + public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test() + { + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAndIssueAsync(); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + RefreshSeconds = 600, + Threshold = 1_00000000 + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + RefreshSeconds = 300, + Threshold = 1_000000 + } + } + }); + + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(2); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(1_00000000); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + config.Value.Last().Symbol.ShouldBe("USDT"); + config.Value.Last().Threshold.ShouldBe(1_000000); + config.Value.Last().RefreshSeconds.ShouldBe(300); + config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(1); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + userBFreeAllowances.Result.Map.Count.ShouldBe(1); + userBFreeAllowances.Result.Map.Keys.First().ShouldBe("USDT"); + userBFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + userAFreeAllowances.Result.Map.Add("USDT", userBFreeAllowances.Result.Map.Values.First()); + userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); + } + + [Fact] + public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_Modify_Test() + { + await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + await CreateTokenAsync(DefaultSender, "ABC"); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 2_00000000 + }, + new MethodFeeFreeAllowance + { + Symbol = "ABC", + Amount = 2_00000000 + } + } + }, + RefreshSeconds = 1200, + Threshold = 2_000000 + } + } + }); + + var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Value.Count.ShouldBe(2); + config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().Threshold.ShouldBe(1_00000000); + config.Value.First().RefreshSeconds.ShouldBe(600); + config.Value.First().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); + + config.Value.Last().Symbol.ShouldBe("USDT"); + config.Value.Last().Threshold.ShouldBe(2_000000); + config.Value.Last().RefreshSeconds.ShouldBe(1200); + config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(2_00000000); + config.Value.Last().FreeAllowances.Map.Keys.Last().ShouldBe("ABC"); + config.Value.Last().FreeAllowances.Map.Values.Last().Symbol.ShouldBe("ABC"); + config.Value.Last().FreeAllowances.Map.Values.Last().Amount.ShouldBe(2_00000000); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(1); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); + var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + userBFreeAllowances.Result.Map.Count.ShouldBe(0); + var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); + } + + [Fact] + public async Task ConfigMethodFeeFreeAllowances_InvalidInput_Test() + { + var message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance() + } + }); + message.ShouldContain("Invalid input symbol"); + + message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = "TEST" + } + } + }); + message.ShouldContain("Symbol TEST not exist"); + + message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol + } + } + }); + message.ShouldContain("Invalid input allowances"); + + message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + Threshold = -1 + } + } + }); + message.ShouldContain("Invalid input threshold"); + + message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 1_00000000 + } + } + }, + Threshold = 1_00000000, + RefreshSeconds = -1 + } + } + }); + message.ShouldContain("Invalid input refresh seconds"); + } + + [Fact] + public async Task RemoveMethodFeeFreeAllowancesConfig_Unauthorized_Test() + { + var result = + await TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig.SendWithExceptionAsync( + new RemoveMethodFeeFreeAllowancesConfigInput()); + result.TransactionResult.Error.ShouldContain("Unauthorized behavior."); + } + + [Fact] + public async Task RemoveMethodFeeFreeAllowancesConfig_Test() + { + await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + await IssueTokenToUserAsync("USDT", 1_000000, UserAAddress); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(2); + var config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Result.Value.Count.ShouldBe(2); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput + { + Symbols = { "USDT" } + }); + config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Result.Value.Count.ShouldBe(1); + config.Result.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(1); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + + // symbol not exist + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput + { + Symbols = { "USDT" } + }); + config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Result.Value.Count.ShouldBe(1); + config.Result.Value.First().Symbol.ShouldBe(NativeTokenSymbol); + userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(1); + userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); + + // Duplicate symbols + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput + { + Symbols = { "ELF", "ELF" } + }); + config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Result.Value.Count.ShouldBe(0); + userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(0); + } + + [Fact] + public async Task RemoveMethodFeeFreeAllowancesConfig_MultipleTokens_AtOnce_Test() + { + await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + await IssueTokenToUserAsync("USDT", 1_000000, UserAAddress); + + var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(2); + var config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config.Result.Value.Count.ShouldBe(2); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput + { + Symbols = { "ELF", "USDT" } + }); + userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances.Result.Map.Count.ShouldBe(0); + } + + [Fact] + public async Task RemoveMethodFeeFreeAllowancesConfig_InvalidInput_Test() + { + var message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput + { + Symbols = { "USDT" } + }); + message.ShouldContain("Method fee free allowances config not set"); + + await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), + new RemoveMethodFeeFreeAllowancesConfigInput()); + message.ShouldContain("Invalid input"); + } + + [Theory] + [InlineData(1000, 0, 1000, 0, 100, 0, 0, 0, 800, 0, 1000, 200)] + [InlineData(1000, 0, 100, 0, 100, 0, 0, 0, 0, 0, 900, 200)] + [InlineData(1000, 1000, 500, 10, 100, 500, 20, 100, 300, 500, 1000, 200)] + [InlineData(1000, 1000, 150, 10, 100, 150, 20, 100, 0, 100, 1000, 200)] + public async Task ChargeTransactionFee_Test(long initialELFBalance, long initialUSDTBalance, + long freeAmountELF, long refreshSecondsELF, long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, + long thresholdUSDT, long newFreeAmountELF, long newFreeAmountUSDT, long afterBalance, long basicFee) + { + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, "USDT"); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); + await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = freeAmountELF + } + } + }, + RefreshSeconds = refreshSecondsELF, + Threshold = thresholdELF + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = freeAmountUSDT + } + } + }, + RefreshSeconds = refreshSecondsUSDT, + Threshold = thresholdUSDT + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress + }; + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountELF); + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterBalance); + } + + [Theory] + [InlineData(1000, 1000, 1000, 1000, 1000, 10, 100, 1000, 20, 100, 700, 500, 1000, 1000, 1000, 1000, 300, 500)] + [InlineData(1000, 1000, 1000, 1000, 100, 10, 100, 1000, 20, 100, 0, 500, 800, 1000, 1000, 1000, 300, 500)] + [InlineData(1000, 1000, 1000, 1000, 500, 10, 10000, 500, 20, 1000, 0, 300, 800, 1000, 1000, 1000, 200, 200)] + [InlineData(1000, 1000, 1000, 1000, 1000, 10, 1000, 1000, 20, 1000, 0, 0, 0, 0, 1000, 1000, 10000, 5000)] + public async Task ChargeTransactionFee_MultipleTokens_Test(long initialELFBalance, long initialUSDTBalance, + long initialTokenABalance, long initialTokenBBalance, long freeAmountELF, long refreshSecondsELF, + long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFreeAmountELF, + long newFreeAmountUSDT, long afterTokenABalance, long afterTokenBBalance, long afterELFBalance, + long afterUSDTBalance, long sizeFee, long basicFee) + { + const string TokenForELF = "TOKENA"; + const string TokenForUSDT = "TOKENB"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, "USDT"); + + await CreateTokenAsync(DefaultSender, TokenForELF); + await CreateTokenAsync(DefaultSender, TokenForUSDT); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); + await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); + await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); + await IssueTokenToDefaultSenderAsync(TokenForUSDT, initialTokenBBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForELF, + Amount = freeAmountELF + } + } + }, + RefreshSeconds = refreshSecondsELF, + Threshold = thresholdELF + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForUSDT, + Amount = freeAmountUSDT + } + } + }, + RefreshSeconds = refreshSecondsUSDT, + Threshold = thresholdUSDT + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = TokenForUSDT, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = TokenForELF, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + if (initialELFBalance >= thresholdELF) + { + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); + } + + if (initialUSDTBalance >= thresholdUSDT) + { + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); + } + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(initialTokenABalance + freeAmountELF >= sizeFee); + + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + if (initialELFBalance >= thresholdELF) + { + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountELF); + } + + if (initialUSDTBalance >= thresholdUSDT) + { + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); + } + + await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); + await CheckDefaultSenderTokenAsync(TokenForUSDT, afterTokenBBalance); + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); + await CheckDefaultSenderTokenAsync("USDT", afterUSDTBalance); + } + + [Theory] + [InlineData(1000, 600, 200, 200)] + public async Task ChargeTransactionFee_NoFreeAllowance_Test(long initialBalance, long afterBalance, long sizeFee, + long basicFee) + { + await SetPrimaryTokenSymbolAsync(); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterBalance); + } + + [Theory] + [InlineData(1000, 1000, 1000, 2000, 2000, 0, 1000, 1000, 500, 1000, 1000, 1000, 1500)] + public async Task ChargeTransactionFee_SingleThreshold_Test(long initialBalance, long initialTokenABalance, + long initialTokenBBalance, long freeAmountTokenA, long freeAmountTokenB, long refreshSeconds, + long threshold, long newFreeAmountTokenA, long newFreeAmountTokenB, long afterTokenABalance, + long afterTokenBBalance, long sizeFee, long basicFee) + { + const string TokenA = "TOKENA"; + const string TokenB = "TOKENB"; + + await SetPrimaryTokenSymbolAsync(); + + await CreateTokenAsync(DefaultSender, TokenA); + await CreateTokenAsync(DefaultSender, TokenB); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + await IssueTokenToDefaultSenderAsync(TokenA, initialTokenABalance); + await IssueTokenToDefaultSenderAsync(TokenB, initialTokenBBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenA, + Amount = freeAmountTokenA + }, + new MethodFeeFreeAllowance + { + Symbol = TokenB, + Amount = freeAmountTokenB + } + } + }, + RefreshSeconds = refreshSeconds, + Threshold = threshold + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = TokenB, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = TokenA, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenA); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenA); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountTokenA); + + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(TokenB); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(TokenB); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(freeAmountTokenB); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenA); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenA); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountTokenA); + + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(TokenB); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(TokenB); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(newFreeAmountTokenB); + + await CheckDefaultSenderTokenAsync(TokenA, afterTokenABalance); + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterTokenBBalance); + } + + [Theory] + [InlineData(1000, 1000, 1000, 1000, 1000, 10, 100, 1000, 20, 100, 0, 1000, 0, 1000, 3000, 5000)] + public async Task ChargeTransactionFee_NotEnough_Test(long initialELFBalance, long initialUSDTBalance, + long initialTokenABalance, long initialTokenBBalance, long freeAmountELF, long refreshSecondsELF, + long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFreeAmountELF, + long newFreeAmountUSDT, long afterTokenABalance, long afterTokenBBalance, long sizeFee, long basicFee) + { + const string TokenForELF = "TOKENA"; + const string TokenForUSDT = "TOKENB"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, "USDT"); + + await CreateTokenAsync(DefaultSender, TokenForELF); + await CreateTokenAsync(DefaultSender, TokenForUSDT); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); + await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); + await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); + await IssueTokenToDefaultSenderAsync(TokenForUSDT, initialTokenBBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForELF, + Amount = freeAmountELF + } + } + }, + RefreshSeconds = refreshSecondsELF, + Threshold = thresholdELF + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForUSDT, + Amount = freeAmountUSDT + } + } + }, + RefreshSeconds = refreshSecondsUSDT, + Threshold = thresholdUSDT + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = TokenForELF, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = TokenForELF, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(false); + + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); + + await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); + await CheckDefaultSenderTokenAsync(TokenForUSDT, afterTokenBBalance); + } + + [Theory] + [InlineData(10000, 500, 50, 10000, 300, 100, 100, 100, 2000, 10000, 7800, 10000)] + public async Task ChargeTransactionFee_ClearFreeAllowance_Test(long initialBalance, long freeAmount, + long refreshSeconds, long threshold, long firstFreeAmount, long secondFreeAmount, long sizeFee, long basicFee, + long transferAmount, long firstBalance, long secondBalance, long thirdBalance) + { + await SetPrimaryTokenSymbolAsync(); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = freeAmount + } + } + }, + RefreshSeconds = refreshSeconds, + Threshold = threshold + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmount); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(firstFreeAmount); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, firstBalance); + + await TokenContractStub.Transfer.SendAsync(new TransferInput + { + Amount = transferAmount, + Symbol = NativeTokenSymbol, + To = UserCAddress, + Memo = "test" + }); + + chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, secondBalance); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.ShouldBeEmpty(); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, transferAmount + sizeFee + basicFee); + + chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, thirdBalance); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(secondFreeAmount); + } + + [Fact] + public async Task ChargeTransactionFee_RefreshTime_Test() + { + const string TokenForELF = "TOKENA"; + const string TokenForUSDT = "TOKENB"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, "USDT"); + + await CreateTokenAsync(DefaultSender, TokenForELF); + await CreateTokenAsync(DefaultSender, TokenForUSDT); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 10000); + await IssueTokenToDefaultSenderAsync("USDT", 10000); + await IssueTokenToDefaultSenderAsync(TokenForELF, 10000); + await IssueTokenToDefaultSenderAsync(TokenForUSDT, 10000); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForELF, + Amount = 1000 + } + } + }, + RefreshSeconds = 2, + Threshold = 100 + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForUSDT, + Amount = 1000 + } + } + }, + RefreshSeconds = 1, + Threshold = 100 + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = TokenForUSDT, + BasicFee = 500 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = TokenForELF, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(1000); + + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(1000); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = 1000 + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); + + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(500); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); + await CheckDefaultSenderTokenAsync("USDT", 10000); + await CheckDefaultSenderTokenAsync(TokenForELF, 10000); + await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); + + chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); + + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(0); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); + await CheckDefaultSenderTokenAsync("USDT", 10000); + await CheckDefaultSenderTokenAsync(TokenForELF, 9000); + await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); + + _blockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddSeconds(1)); + + chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); + + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(500); + + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); + await CheckDefaultSenderTokenAsync("USDT", 10000); + await CheckDefaultSenderTokenAsync(TokenForELF, 8000); + await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); + } + + private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DefaultSender, + Symbol = symbol + }); + + balance.Balance.ShouldBe(amount); + } + + private async Task CreateTokenAndIssueAsync() + { + await CreateTokenAsync(DefaultSender, "USDT"); + await IssueTokenToUserAsync(NativeTokenSymbol, 1_00000000, UserAAddress); + await IssueTokenToUserAsync("USDT", 1_000000, UserBAddress); + await IssueTokenToUserAsync(NativeTokenSymbol, 1_00000000, UserCAddress); + await IssueTokenToUserAsync("USDT", 1_000000, UserCAddress); + } +} \ No newline at end of file From 5ba2ac51864a14c9d50033efb7a09618e03d492c Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 8 Jun 2023 15:40:41 +0800 Subject: [PATCH 025/139] fix: ut --- ...inTransactionDirectlyTest_FreeAllowance.cs | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index 5aa84de8f1..9a29fdb74e 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -1422,6 +1422,114 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); } + // [Theory] + // [InlineData(1000, 1000, 1000, 0, 10, 800, 1000, 1000, 100, 100)] + // public async Task ChargeTransactionFee_FreeAllowanceFirst_Test(long initialBalance, long initialTokenABalance, + // long freeAmount, long refreshSeconds, long threshold, long newFreeAmount, long afterTokenABalance, + // long afterELFBalance, long sizeFee, long basicFee) + // { + // const string TokenForELF = "TOKENA"; + // + // await SetPrimaryTokenSymbolAsync(); + // + // await CreateTokenAsync(DefaultSender, TokenForELF); + // + // await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + // await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); + // + // await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + // nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + // { + // Value = + // { + // new ConfigMethodFeeFreeAllowance + // { + // Symbol = NativeTokenSymbol, + // MethodFeeFreeAllowances = new MethodFeeFreeAllowances + // { + // Value = + // { + // new MethodFeeFreeAllowance + // { + // Symbol = TokenForELF, + // Amount = freeAmount + // } + // } + // }, + // RefreshSeconds = refreshSeconds, + // Threshold = threshold + // } + // } + // }); + // + // var methodFee = new MethodFees + // { + // MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + // Fees = + // { + // new MethodFee + // { + // Symbol = NativeTokenSymbol, + // BasicFee = basicFee + // }, + // new MethodFee + // { + // Symbol = TokenForELF, + // BasicFee = basicFee + // } + // } + // }; + // await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + // nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + // + // var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + // { + // SymbolsToPayTxSizeFee = + // { + // new SymbolToPayTxSizeFee + // { + // TokenSymbol = NativeTokenSymbol, + // AddedTokenWeight = 1, + // BaseTokenWeight = 1 + // }, + // new SymbolToPayTxSizeFee + // { + // TokenSymbol = TokenForELF, + // AddedTokenWeight = 1, + // BaseTokenWeight = 1 + // } + // } + // }; + // await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + // nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + // + // var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + // freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + // freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + // freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + // freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmount); + // + // var chargeTransactionFeesInput = new ChargeTransactionFeesInput + // { + // MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + // ContractAddress = TokenContractAddress, + // TransactionSizeFee = sizeFee, + // }; + // chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + // + // var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + // chargeFeeRet.Output.Success.ShouldBe(true); + // + // freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + // freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + // freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + // freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + // freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmount); + // + // await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); + // await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); + // } + private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) { var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput From 4154ca609b06563f46d3c9ef869f90a940e0ec1a Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 8 Jun 2023 18:56:42 +0800 Subject: [PATCH 026/139] feat: adjust ChargeBaseFee and ChargeSizeFee logic --- .../TokenContract_Fees.cs | 85 ++++--- ...inTransactionDirectlyTest_FreeAllowance.cs | 214 +++++++++--------- 2 files changed, 161 insertions(+), 138 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 9f31d3d429..a03a7ac554 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using AElf.CSharp.Core; @@ -96,7 +95,8 @@ private ChargeTransactionFeesOutput TryToChargeTransactionFee(ChargeTransactionF if (!chargingResult) { var transactionFeeDelegatees = State.TransactionFeeDelegateesMap[fromAddress] ?? - State.TransactionFeeDelegateInfoMap[fromAddress][input.ContractAddress][input.MethodName]; + State.TransactionFeeDelegateInfoMap[fromAddress][input.ContractAddress][ + input.MethodName]; if (transactionFeeDelegatees != null) { var delegateeAddress = transactionFeeDelegatees.Delegatees; @@ -166,8 +166,9 @@ private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address // Try to charge delegatees // Get delegatee list according to the delegator var delegationInfo = State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees ?? - State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][input.MethodName]?.Delegatees; - + State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][ + input.MethodName]?.Delegatees; + if (delegationInfo == null) { return false; @@ -440,23 +441,35 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List size fee, else, get 1st > 0 - availableSymbol = allSymbolToTxFee.FirstOrDefault(x => - { - var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, - symbolChargedForBaseFee, amountChargedForBaseFee, methodFeeFreeAllowancesMap, - amountChargedForBaseAllowance); - return balance >= txSizeFeeAmount; - }) ?? allSymbolToTxFee.FirstOrDefault(x => + SymbolToPayTxSizeFee availableSymbolWithAnything = null; + SymbolToPayTxSizeFee availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee = null; + + // get 1st Allowance > size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 + foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) { - var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, - symbolChargedForBaseFee, amountChargedForBaseFee, methodFeeFreeAllowancesMap, - amountChargedForBaseAllowance); - return balance > 0; - }); + var allowance = GetAllowanceCalculatedBaseOnPrimaryToken(symbolToPlayTxSizeFee, + methodFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseAllowance); + var balancePlusAllowance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, + symbolToPlayTxSizeFee, symbolChargedForBaseFee, amountChargedForBaseFee, + methodFeeFreeAllowancesMap, amountChargedForBaseAllowance); + + if (allowance >= txSizeFeeAmount) + { + availableSymbol = symbolToPlayTxSizeFee; + break; + } + + if (balancePlusAllowance <= 0) continue; + availableSymbolWithAnything ??= symbolToPlayTxSizeFee; + + if (balancePlusAllowance < txSizeFeeAmount) continue; + availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbolToPlayTxSizeFee; + } + + availableSymbol ??= availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ?? availableSymbolWithAnything; } else { @@ -673,13 +686,13 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM if (delegations != null) { //from address -> delegatee - chargeResult = TryToChargeDelegateBaseFee(symbolToAmountMap, fromAddress, freeAllowances, delegations, - out amount, out symbol, out existingBalance, out existingAllowance); + chargeResult = TryToChargeDelegateBaseFee(symbolToAmountMap, fromAddress, methodFeeFreeAllowancesMap, + delegations, out amount, out symbol, out existingBalance, out existingAllowance); return chargeResult; } - chargeResult = TryToChargeUserBaseFee(symbolToAmountMap, fromAddress, freeAllowances, - out amount, out symbol, out existingBalance, out existingAllowance); + chargeResult = TryToChargeUserBaseFee(symbolToAmountMap, fromAddress, methodFeeFreeAllowancesMap, out amount, + out symbol, out existingBalance, out existingAllowance); //For user, if charge failed and delegation is null, priority charge primary token if (!chargeResult) @@ -689,7 +702,7 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM { symbol = primaryTokenSymbol; existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); } } @@ -697,10 +710,11 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM } private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, Address fromAddress, - MethodFeeFreeAllowances freeAllowances, out long amount, out string symbolOfValidBalance, + MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, out long amount, out string symbolOfValidBalance, out long existingBalance, out long existingAllowance) { symbolOfValidBalance = null; + string symbolOfValidBalanceAndAllowance = null; amount = 0; existingBalance = 0; existingAllowance = 0; @@ -711,21 +725,28 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, // current token symbol amount = value; existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); if (existingBalance.Add(existingAllowance) > 0) { symbolOfValidBalance = symbol; } + if (existingAllowance >= amount) return true; + if (existingBalance.Add(existingAllowance) >= amount) - return true; + { + symbolOfValidBalanceAndAllowance = symbol; + } } - return false; + if (symbolOfValidBalanceAndAllowance == null) return false; + + symbolOfValidBalance = symbolOfValidBalanceAndAllowance; + return true; } private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountMap, Address fromAddress, - MethodFeeFreeAllowances freeAllowances, TransactionFeeDelegations delegations, + MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, TransactionFeeDelegations delegations, out long amount, out string symbolOfValidBalance, out long existingBalance, out long existingAllowance) { symbolOfValidBalance = null; @@ -738,17 +759,19 @@ private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountM // current token symbol amount = value; existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(freeAllowances, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); // is unlimited delegate is true && balance enough // is unlimited delegate is false && delegation enough && balance enough if (existingBalance.Add(existingAllowance) < amount) continue; - if (delegations.IsUnlimitedDelegate || (!delegations.IsUnlimitedDelegate && delegations.Delegations.ContainsKey(symbol) - && delegations.Delegations[symbol] >= amount)) + if (delegations.IsUnlimitedDelegate || (!delegations.IsUnlimitedDelegate && + delegations.Delegations.ContainsKey(symbol) + && delegations.Delegations[symbol] >= amount)) { symbolOfValidBalance = symbol; return true; } } + return false; } diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index 9a29fdb74e..a0b870c224 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -1422,113 +1422,113 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); } - // [Theory] - // [InlineData(1000, 1000, 1000, 0, 10, 800, 1000, 1000, 100, 100)] - // public async Task ChargeTransactionFee_FreeAllowanceFirst_Test(long initialBalance, long initialTokenABalance, - // long freeAmount, long refreshSeconds, long threshold, long newFreeAmount, long afterTokenABalance, - // long afterELFBalance, long sizeFee, long basicFee) - // { - // const string TokenForELF = "TOKENA"; - // - // await SetPrimaryTokenSymbolAsync(); - // - // await CreateTokenAsync(DefaultSender, TokenForELF); - // - // await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - // await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); - // - // await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - // nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput - // { - // Value = - // { - // new ConfigMethodFeeFreeAllowance - // { - // Symbol = NativeTokenSymbol, - // MethodFeeFreeAllowances = new MethodFeeFreeAllowances - // { - // Value = - // { - // new MethodFeeFreeAllowance - // { - // Symbol = TokenForELF, - // Amount = freeAmount - // } - // } - // }, - // RefreshSeconds = refreshSeconds, - // Threshold = threshold - // } - // } - // }); - // - // var methodFee = new MethodFees - // { - // MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - // Fees = - // { - // new MethodFee - // { - // Symbol = NativeTokenSymbol, - // BasicFee = basicFee - // }, - // new MethodFee - // { - // Symbol = TokenForELF, - // BasicFee = basicFee - // } - // } - // }; - // await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - // nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - // - // var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - // { - // SymbolsToPayTxSizeFee = - // { - // new SymbolToPayTxSizeFee - // { - // TokenSymbol = NativeTokenSymbol, - // AddedTokenWeight = 1, - // BaseTokenWeight = 1 - // }, - // new SymbolToPayTxSizeFee - // { - // TokenSymbol = TokenForELF, - // AddedTokenWeight = 1, - // BaseTokenWeight = 1 - // } - // } - // }; - // await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - // nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - // - // var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - // freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - // freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - // freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); - // freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmount); - // - // var chargeTransactionFeesInput = new ChargeTransactionFeesInput - // { - // MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - // ContractAddress = TokenContractAddress, - // TransactionSizeFee = sizeFee, - // }; - // chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - // - // var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - // chargeFeeRet.Output.Success.ShouldBe(true); - // - // freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - // freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - // freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - // freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); - // freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmount); - // - // await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); - // await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); - // } + [Theory] + [InlineData(1000, 1000, 1000, 0, 10, 800, 1000, 1000, 100, 100)] + public async Task ChargeTransactionFee_FreeAllowanceFirst_Test(long initialBalance, long initialTokenABalance, + long freeAmount, long refreshSeconds, long threshold, long newFreeAmount, long afterTokenABalance, + long afterELFBalance, long sizeFee, long basicFee) + { + const string TokenForELF = "TOKENA"; + + await SetPrimaryTokenSymbolAsync(); + + await CreateTokenAsync(DefaultSender, TokenForELF); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); + await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = TokenForELF, + Amount = freeAmount + } + } + }, + RefreshSeconds = refreshSeconds, + Threshold = threshold + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = basicFee + }, + new MethodFee + { + Symbol = TokenForELF, + BasicFee = basicFee + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = TokenForELF, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmount); + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmount); + + await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); + } private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) { From 7fd4493ec55163a2e81e853f675709e05cb34d2e Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Thu, 8 Jun 2023 20:54:48 +0800 Subject: [PATCH 027/139] feat: priority charge new delegation. --- .../TokenContract_Fees.cs | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 9f04ffdd96..7e7b99925c 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -94,8 +94,9 @@ private ChargeTransactionFeesOutput TryToChargeTransactionFee(ChargeTransactionF if (!chargingResult) { - var transactionFeeDelegatees = State.TransactionFeeDelegateesMap[fromAddress] ?? - State.TransactionFeeDelegateInfoMap[fromAddress][input.ContractAddress][input.MethodName]; + var transactionFeeDelegatees = + State.TransactionFeeDelegateInfoMap[fromAddress][input.ContractAddress][input.MethodName] ?? + State.TransactionFeeDelegateesMap[fromAddress]; if (transactionFeeDelegatees != null) { var delegateeAddress = transactionFeeDelegatees.Delegatees; @@ -164,9 +165,10 @@ private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address var chargingResult = false; // Try to charge delegatees // Get delegatee list according to the delegator - var delegationInfo = State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees ?? - State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][input.MethodName]?.Delegatees; - + var delegationInfo = + State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][input.MethodName]?.Delegatees ?? + State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees; + if (delegationInfo == null) { return false; @@ -203,22 +205,24 @@ private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address } private void ModifyDelegation(TransactionFeeBill bill, TransactionFreeFeeAllowanceBill allowanceBill, - Address delegateeAddress,Address contractAddress,string methodName,Address delegatorAddress) + Address delegateeAddress, Address contractAddress, string methodName, Address delegatorAddress) { foreach (var (symbol, amount) in bill.FeesMap) { if (amount <= 0) continue; - var delegateInfo = State.TransactionFeeDelegateesMap[delegatorAddress] ?? - State.TransactionFeeDelegateInfoMap[delegatorAddress][contractAddress][methodName]; + var delegateInfo = + State.TransactionFeeDelegateInfoMap[delegatorAddress][contractAddress][methodName] ?? + State.TransactionFeeDelegateesMap[delegatorAddress]; delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol] = delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol].Sub(amount); } - + foreach (var (symbol, amount) in allowanceBill.FreeFeeAllowancesMap) { if (amount <= 0) continue; - var delegateInfo = State.TransactionFeeDelegateesMap[delegatorAddress] ?? - State.TransactionFeeDelegateInfoMap[delegatorAddress][contractAddress][methodName]; + var delegateInfo = + State.TransactionFeeDelegateInfoMap[delegatorAddress][contractAddress][methodName] ?? + State.TransactionFeeDelegateesMap[delegatorAddress]; delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol] = delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol].Sub(amount); } From f598be509e31339d59b8e6d0e9073129a46d02a2 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 12 Jun 2023 17:30:10 +0800 Subject: [PATCH 028/139] feat: adjust baseFee and sizeFee logic and add ut --- .../TokenContract_Fees.cs | 48 ++- ...inTransactionDirectlyTest_FreeAllowance.cs | 396 +++++++++++++----- .../ExecutionPluginForMethodFeeTest.cs | 6 +- ...utionPluginForUserContractMethodFeeTest.cs | 6 +- 4 files changed, 344 insertions(+), 112 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index a03a7ac554..54fcf3a41c 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -446,6 +446,7 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) @@ -467,9 +468,13 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List symbolToAmountM chargeResult = TryToChargeUserBaseFee(symbolToAmountMap, fromAddress, methodFeeFreeAllowancesMap, out amount, out symbol, out existingBalance, out existingAllowance); + + if (symbol != null) + { + existingBalance = GetBalance(fromAddress, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); + + } //For user, if charge failed and delegation is null, priority charge primary token if (!chargeResult) @@ -714,7 +726,10 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, out long existingBalance, out long existingAllowance) { symbolOfValidBalance = null; - string symbolOfValidBalanceAndAllowance = null; + string symbolWithAnything = null; + string symbolWithBalancePlusAllowanceEnoughToPayTxFee = null; + string symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; + amount = 0; existingBalance = 0; existingAllowance = 0; @@ -726,22 +741,33 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, amount = value; existingBalance = GetBalance(fromAddress, symbol); existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); - if (existingBalance.Add(existingAllowance) > 0) + + if (existingAllowance >= amount) { symbolOfValidBalance = symbol; + return true; } - if (existingAllowance >= amount) return true; + if (existingBalance.Add(existingAllowance) <= 0) continue; + symbolWithAnything ??= symbol; - if (existingBalance.Add(existingAllowance) >= amount) - { - symbolOfValidBalanceAndAllowance = symbol; - } + if (existingBalance.Add(existingAllowance) < amount) continue; + symbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbol; + + if (existingAllowance <= 0) continue; + symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbol; + } + + if (symbolWithBalancePlusAllowanceEnoughToPayTxFee == null) + { + symbolOfValidBalance = symbolWithAnything; + + return false; } - if (symbolOfValidBalanceAndAllowance == null) return false; + symbolOfValidBalance = symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? + symbolWithBalancePlusAllowanceEnoughToPayTxFee; - symbolOfValidBalance = symbolOfValidBalanceAndAllowance; return true; } @@ -1144,7 +1170,7 @@ public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowance foreach (var allowance in allowances.MethodFeeFreeAllowances!.Value!) { - config.FreeAllowances.Map.Add(allowance.Symbol, allowance); + config.FreeAllowances.Map.TryAdd(allowance.Symbol, allowance); } State.MethodFeeFreeAllowancesConfigMap[allowances.Symbol] = config; diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index a0b870c224..2fa7599fd4 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -666,29 +666,31 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } [Theory] + // case 21 [InlineData(1000, 1000, 1000, 1000, 1000, 10, 100, 1000, 20, 100, 700, 500, 1000, 1000, 1000, 1000, 300, 500)] - [InlineData(1000, 1000, 1000, 1000, 100, 10, 100, 1000, 20, 100, 0, 500, 800, 1000, 1000, 1000, 300, 500)] - [InlineData(1000, 1000, 1000, 1000, 500, 10, 10000, 500, 20, 1000, 0, 300, 800, 1000, 1000, 1000, 200, 200)] - [InlineData(1000, 1000, 1000, 1000, 1000, 10, 1000, 1000, 20, 1000, 0, 0, 0, 0, 1000, 1000, 10000, 5000)] + // case 22 + [InlineData(1000, 1000, 1000, 1000, 100, 10, 100, 1000, 20, 100, 0, 500, 100, 1000, 1000, 1000, 1000, 500)] + // case 25 + [InlineData(1000, 100, 1000, 1000, 1000, 10, 10000, 1000, 20, 100, 1000, 500, 0, 1000, 1000, 100, 1000, 500)] public async Task ChargeTransactionFee_MultipleTokens_Test(long initialELFBalance, long initialUSDTBalance, long initialTokenABalance, long initialTokenBBalance, long freeAmountELF, long refreshSecondsELF, long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFreeAmountELF, long newFreeAmountUSDT, long afterTokenABalance, long afterTokenBBalance, long afterELFBalance, long afterUSDTBalance, long sizeFee, long basicFee) { - const string TokenForELF = "TOKENA"; - const string TokenForUSDT = "TOKENB"; + const string Token1 = "TOKENA"; + const string Token2 = "TOKENB"; await SetPrimaryTokenSymbolAsync(); await CreateTokenAsync(DefaultSender, "USDT"); - await CreateTokenAsync(DefaultSender, TokenForELF); - await CreateTokenAsync(DefaultSender, TokenForUSDT); + await CreateTokenAsync(DefaultSender, Token1); + await CreateTokenAsync(DefaultSender, Token2); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); - await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); - await IssueTokenToDefaultSenderAsync(TokenForUSDT, initialTokenBBalance); + await IssueTokenToDefaultSenderAsync(Token1, initialTokenABalance); + await IssueTokenToDefaultSenderAsync(Token2, initialTokenBBalance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput @@ -704,7 +706,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFeeFreeAllowance { - Symbol = TokenForELF, + Symbol = Token1, Amount = freeAmountELF } } @@ -721,7 +723,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFeeFreeAllowance { - Symbol = TokenForUSDT, + Symbol = Token2, Amount = freeAmountUSDT } } @@ -739,7 +741,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFee { - Symbol = TokenForUSDT, + Symbol = Token2, BasicFee = basicFee } } @@ -753,7 +755,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new SymbolToPayTxSizeFee { - TokenSymbol = TokenForELF, + TokenSymbol = Token1, AddedTokenWeight = 1, BaseTokenWeight = 1 }, @@ -772,16 +774,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, if (initialELFBalance >= thresholdELF) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); } if (initialUSDTBalance >= thresholdUSDT) { freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); } @@ -801,21 +803,21 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, if (initialELFBalance >= thresholdELF) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountELF); } if (initialUSDTBalance >= thresholdUSDT) { freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); } - await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); - await CheckDefaultSenderTokenAsync(TokenForUSDT, afterTokenBBalance); + await CheckDefaultSenderTokenAsync(Token1, afterTokenABalance); + await CheckDefaultSenderTokenAsync(Token2, afterTokenBBalance); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); await CheckDefaultSenderTokenAsync("USDT", afterUSDTBalance); } @@ -1003,19 +1005,19 @@ public async Task ChargeTransactionFee_NotEnough_Test(long initialELFBalance, lo long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFreeAmountELF, long newFreeAmountUSDT, long afterTokenABalance, long afterTokenBBalance, long sizeFee, long basicFee) { - const string TokenForELF = "TOKENA"; - const string TokenForUSDT = "TOKENB"; + const string Token1 = "TOKENA"; + const string Token2 = "TOKENB"; await SetPrimaryTokenSymbolAsync(); await CreateTokenAsync(DefaultSender, "USDT"); - await CreateTokenAsync(DefaultSender, TokenForELF); - await CreateTokenAsync(DefaultSender, TokenForUSDT); + await CreateTokenAsync(DefaultSender, Token1); + await CreateTokenAsync(DefaultSender, Token2); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); - await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); - await IssueTokenToDefaultSenderAsync(TokenForUSDT, initialTokenBBalance); + await IssueTokenToDefaultSenderAsync(Token1, initialTokenABalance); + await IssueTokenToDefaultSenderAsync(Token2, initialTokenBBalance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput @@ -1031,7 +1033,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFeeFreeAllowance { - Symbol = TokenForELF, + Symbol = Token1, Amount = freeAmountELF } } @@ -1048,7 +1050,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFeeFreeAllowance { - Symbol = TokenForUSDT, + Symbol = Token2, Amount = freeAmountUSDT } } @@ -1066,7 +1068,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFee { - Symbol = TokenForELF, + Symbol = Token1, BasicFee = basicFee } } @@ -1080,7 +1082,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new SymbolToPayTxSizeFee { - TokenSymbol = TokenForELF, + TokenSymbol = Token1, AddedTokenWeight = 1, BaseTokenWeight = 1 }, @@ -1097,12 +1099,12 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); var chargeTransactionFeesInput = new ChargeTransactionFeesInput @@ -1120,12 +1122,12 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); - await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); - await CheckDefaultSenderTokenAsync(TokenForUSDT, afterTokenBBalance); + await CheckDefaultSenderTokenAsync(Token1, afterTokenABalance); + await CheckDefaultSenderTokenAsync(Token2, afterTokenBBalance); } [Theory] @@ -1251,19 +1253,19 @@ await TokenContractStub.Transfer.SendAsync(new TransferInput [Fact] public async Task ChargeTransactionFee_RefreshTime_Test() { - const string TokenForELF = "TOKENA"; - const string TokenForUSDT = "TOKENB"; + const string Token1 = "TOKENA"; + const string Token2 = "TOKENB"; await SetPrimaryTokenSymbolAsync(); await CreateTokenAsync(DefaultSender, "USDT"); - await CreateTokenAsync(DefaultSender, TokenForELF); - await CreateTokenAsync(DefaultSender, TokenForUSDT); + await CreateTokenAsync(DefaultSender, Token1); + await CreateTokenAsync(DefaultSender, Token2); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 10000); await IssueTokenToDefaultSenderAsync("USDT", 10000); - await IssueTokenToDefaultSenderAsync(TokenForELF, 10000); - await IssueTokenToDefaultSenderAsync(TokenForUSDT, 10000); + await IssueTokenToDefaultSenderAsync(Token1, 10000); + await IssueTokenToDefaultSenderAsync(Token2, 10000); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput @@ -1279,7 +1281,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFeeFreeAllowance { - Symbol = TokenForELF, + Symbol = Token1, Amount = 1000 } } @@ -1296,7 +1298,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFeeFreeAllowance { - Symbol = TokenForUSDT, + Symbol = Token2, Amount = 1000 } } @@ -1314,7 +1316,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFee { - Symbol = TokenForUSDT, + Symbol = Token2, BasicFee = 500 } } @@ -1328,7 +1330,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new SymbolToPayTxSizeFee { - TokenSymbol = TokenForELF, + TokenSymbol = Token1, AddedTokenWeight = 1, BaseTokenWeight = 1 }, @@ -1345,13 +1347,13 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(1000); freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(1000); var chargeTransactionFeesInput = new ChargeTransactionFeesInput @@ -1367,38 +1369,38 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(500); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); await CheckDefaultSenderTokenAsync("USDT", 10000); - await CheckDefaultSenderTokenAsync(TokenForELF, 10000); - await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); + await CheckDefaultSenderTokenAsync(Token1, 10000); + await CheckDefaultSenderTokenAsync(Token2, 10000); chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(0); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); await CheckDefaultSenderTokenAsync("USDT", 10000); - await CheckDefaultSenderTokenAsync(TokenForELF, 9000); - await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); + await CheckDefaultSenderTokenAsync(Token1, 9000); + await CheckDefaultSenderTokenAsync(Token2, 10000); _blockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddSeconds(1)); @@ -1407,19 +1409,19 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); freeAllowances.Map.Keys.Last().ShouldBe("USDT"); - freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(TokenForUSDT); - freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(TokenForUSDT); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(500); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); await CheckDefaultSenderTokenAsync("USDT", 10000); - await CheckDefaultSenderTokenAsync(TokenForELF, 8000); - await CheckDefaultSenderTokenAsync(TokenForUSDT, 10000); + await CheckDefaultSenderTokenAsync(Token1, 8000); + await CheckDefaultSenderTokenAsync(Token2, 10000); } [Theory] @@ -1428,15 +1430,15 @@ public async Task ChargeTransactionFee_FreeAllowanceFirst_Test(long initialBalan long freeAmount, long refreshSeconds, long threshold, long newFreeAmount, long afterTokenABalance, long afterELFBalance, long sizeFee, long basicFee) { - const string TokenForELF = "TOKENA"; - + const string Token1 = "TOKENA"; + await SetPrimaryTokenSymbolAsync(); - - await CreateTokenAsync(DefaultSender, TokenForELF); - + + await CreateTokenAsync(DefaultSender, Token1); + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToDefaultSenderAsync(TokenForELF, initialTokenABalance); - + await IssueTokenToDefaultSenderAsync(Token1, initialTokenABalance); + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput { @@ -1451,7 +1453,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFeeFreeAllowance { - Symbol = TokenForELF, + Symbol = Token1, Amount = freeAmount } } @@ -1461,7 +1463,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }); - + var methodFee = new MethodFees { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), @@ -1474,14 +1476,14 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }, new MethodFee { - Symbol = TokenForELF, + Symbol = Token1, BasicFee = basicFee } } }; await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { SymbolsToPayTxSizeFee = @@ -1494,7 +1496,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }, new SymbolToPayTxSizeFee { - TokenSymbol = TokenForELF, + TokenSymbol = Token1, AddedTokenWeight = 1, BaseTokenWeight = 1 } @@ -1502,13 +1504,13 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }; await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmount); - + var chargeTransactionFeesInput = new ChargeTransactionFeesInput { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), @@ -1516,20 +1518,224 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, TransactionSizeFee = sizeFee, }; chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); - + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenForELF); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenForELF); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmount); - - await CheckDefaultSenderTokenAsync(TokenForELF, afterTokenABalance); + + await CheckDefaultSenderTokenAsync(Token1, afterTokenABalance); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); } + [Theory] + // case 24 + [InlineData(1000, 1000, 1000, 1000, "TOKENA", 1000, "TOKENA", 1000, 600, 10, "TOKENB", 1000, "TOKENB", 1000, 300, 10, 1000, 1000, 1000, 1000, 0, 0, 1000, 1000, 5000, 1, 1, "USDT", 3000, "TOKENB", 3000, false)] + // case 28 + [InlineData(10000, 10000, 1000, 0, "TOKENA", 2000, NativeTokenSymbol, 2000, 600, 10000, "TOKENA", 1000, "USDT", 200, 300, 10000, 2000, 0, 0, 200, 10000, 10000, 1000, 0, 2000, 1, 2, "TOKENA", 1000, "USDT", 200, true)] + // case 29 + [InlineData(10000, 10000, 1000, 0, "TOKENA", 2000, NativeTokenSymbol, 1000, 600, 10000, "TOKENA", 1000, "USDT", 100, 300, 10000, 1000, 1000, 0, 100, 10000, 10000, 1000, 0, 2000, 1, 2, "TOKENA", 1000, "USDT", 200, true)] + // case 30 + [InlineData(10000, 10000, 1000, 0, "TOKENA", 1000, NativeTokenSymbol, 1000, 600, 100, "TOKENA", 1000, "USDT", 100, 300, 100, 500, 0, 0, 100, 9000, 10000, 1000, 0, 2000, 1, 1, "TOKENA", 1500, "USDT", 200, true)] + // case 31 + [InlineData(10000, 10000, 10000, 0, "TOKENA", 1000, NativeTokenSymbol, 1000, 600, 100, "TOKENA", 1000, "ELF", 1000, 300, 100, 0, 0, 0, 0, 9000, 10000, 7000, 0, 3000, 5, 3, NativeTokenSymbol, 3000, "TOKENA", 3000, true)] + // case 32 + [InlineData(10000, 10000, 1000, 0, "TOKENA", 1000, NativeTokenSymbol, 1000, 600, 100, "TOKENA", 1000, "ELF", 1000, 300, 100, 0, 0, 0, 0, 0, 10000, 0, 0, 3000, 5, 3, NativeTokenSymbol, 15000, "USDT", 20000, false)] + // case 33 + [InlineData(5000, 10000, 0, 0, "TOKENA", 1000, "TOKENA", 1000, 600, 100, "TOKENB", 1000, "TOKENB", 1000, 300, 100, 0, 0, 1000, 1000, 0, 8000, 0, 0, 10000, 1, 5, "USDT", 2000, "ELF", 0, false)] + public async Task ChargeTransactionFee_MultipleTxFeeTokens_Test(long initialELFBalance, long initialUSDTBalance, + long initialTokenABalance, long initialTokenBBalance, string firstFreeSymbolELF, long firstFreeAmountELF, + string secondFreeSymbolELF, long secondFreeAmountELF, long refreshSecondsELF, long thresholdELF, + string firstFreeSymbolUSDT, long firstFreeAmountUSDT, string secondFreeSymbolUSDT, long secondFreeAmountUSDT, + long refreshSecondsUSDT, long thresholdUSDT, long newFirstFreeAmountELF, long newSecondFreeAmountELF, + long newFirstFreeAmountUSDT, long newSecondFreeAmountUSDT, long afterELFBalance, long afterUSDTBalance, + long afterTokenABalance, long afterTokenBBalance, long sizeFee, int addedTokenWeight, int baseTokenWeight, + string firstBaseFeeSymbol, long firstBaseFeeAmount, string secondBaseFeeSymbol, long secondBaseFeeAmount, + bool chargeFeeResult) + { + const string Token1 = "TOKENA"; + const string Token2 = "TOKENB"; + + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, "USDT"); + + await CreateTokenAsync(DefaultSender, Token1); + await CreateTokenAsync(DefaultSender, Token2); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); + await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); + await IssueTokenToDefaultSenderAsync(Token1, initialTokenABalance); + await IssueTokenToDefaultSenderAsync(Token2, initialTokenBBalance); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + { + Value = + { + new ConfigMethodFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = firstFreeSymbolELF, + Amount = firstFreeAmountELF + }, + new MethodFeeFreeAllowance + { + Symbol = secondFreeSymbolELF, + Amount = secondFreeAmountELF + } + } + }, + RefreshSeconds = refreshSecondsELF, + Threshold = thresholdELF + }, + new ConfigMethodFeeFreeAllowance + { + Symbol = "USDT", + MethodFeeFreeAllowances = new MethodFeeFreeAllowances + { + Value = + { + new MethodFeeFreeAllowance + { + Symbol = firstFreeSymbolUSDT, + Amount = firstFreeAmountUSDT + }, + new MethodFeeFreeAllowance + { + Symbol = secondFreeSymbolUSDT, + Amount = secondFreeAmountUSDT + } + } + }, + RefreshSeconds = refreshSecondsUSDT, + Threshold = thresholdUSDT + } + } + }); + + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = firstBaseFeeSymbol, + BasicFee = firstBaseFeeAmount + } + } + }; + + if (secondBaseFeeAmount > 0) + { + methodFee.Fees.Add(new MethodFee + { + Symbol = secondBaseFeeSymbol, + BasicFee = secondBaseFeeAmount + }); + } + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = Token1, + AddedTokenWeight = addedTokenWeight, + BaseTokenWeight = baseTokenWeight + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + if (initialELFBalance >= thresholdELF) + { + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(firstFreeSymbolELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(firstFreeSymbolELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(firstFreeAmountELF); + + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(secondFreeSymbolELF); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(secondFreeSymbolELF); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(secondFreeAmountELF); + } + + if (initialUSDTBalance >= thresholdUSDT) + { + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(firstFreeSymbolUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(firstFreeSymbolUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(firstFreeAmountUSDT); + + freeAllowances.Map.Values.Last().Map.Keys.Last().ShouldBe(secondFreeSymbolUSDT); + freeAllowances.Map.Values.Last().Map.Values.Last().Symbol.ShouldBe(secondFreeSymbolUSDT); + freeAllowances.Map.Values.Last().Map.Values.Last().Amount.ShouldBe(secondFreeAmountUSDT); + } + + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = sizeFee, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(chargeFeeResult); + + freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + if (afterELFBalance >= thresholdELF) + { + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(firstFreeSymbolELF); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(firstFreeSymbolELF); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFirstFreeAmountELF); + + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(secondFreeSymbolELF); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(secondFreeSymbolELF); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(newSecondFreeAmountELF); + } + + if (afterUSDTBalance >= thresholdUSDT) + { + freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(firstFreeSymbolUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(firstFreeSymbolUSDT); + freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFirstFreeAmountUSDT); + + freeAllowances.Map.Values.Last().Map.Keys.Last().ShouldBe(secondFreeSymbolUSDT); + freeAllowances.Map.Values.Last().Map.Values.Last().Symbol.ShouldBe(secondFreeSymbolUSDT); + freeAllowances.Map.Values.Last().Map.Values.Last().Amount.ShouldBe(newSecondFreeAmountUSDT); + } + + await CheckDefaultSenderTokenAsync(Token1, afterTokenABalance); + await CheckDefaultSenderTokenAsync(Token2, afterTokenBBalance); + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); + await CheckDefaultSenderTokenAsync("USDT", afterUSDTBalance); + } + private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) { var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs index 006c7697dd..6940935f4d 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs @@ -335,11 +335,11 @@ await tokenContractStub.Transfer.SendAsync(new TransferInput } [Theory] - [InlineData(100000000, 0, 3, 10, 1, 2, "ELF", 20260010, true)] + [InlineData(100000000, 0, 3, 10, 1, 2, "ELF", 20260002, true)] [InlineData(9, 0, 1, 10, 1, 2, "ELF", 9, false)] - [InlineData(100000000, 2, 2, 0, 1, 2, "TSA", 1, true)] + [InlineData(100000000, 2, 2, 0, 1, 2, "TSA", 2, true)] [InlineData(100000000, 2, 2, 0, 13, 2, "TSB", 2, true)] - [InlineData(100000000, 2, 2, 0, 20, 20, "TSB", 2, false)] + [InlineData(100000000, 2, 2, 0, 20, 20, "TSA", 2, false)] [InlineData(1, 0, 1, 0, 1, 2, "TSB", 1, false)] [InlineData(10, 0, 0, 0, 1, 2, "ELF", 10, false)] // Charge 10 ELFs tx size fee. public async Task ChargeFee_Set_Method_Fees_Tests(long balance1, long balance2, long balance3, long fee1, long fee2, diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs index f10baf828c..2a12cde602 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs @@ -151,11 +151,11 @@ public async Task GetPreTransactions_None_PreTransaction_Test() } [Theory] - [InlineData(100000000, 0, 3, 10, 1, 2, "ELF", 20135010, true)] + [InlineData(100000000, 0, 3, 10, 1, 2, "ELF", 20135002, true)] [InlineData(9, 0, 1, 10, 1, 2, "ELF", 9, false)] - [InlineData(100000000, 2, 2, 0, 1, 2, "TSA", 1, true)] + [InlineData(100000000, 2, 2, 0, 1, 2, "TSA", 2, true)] [InlineData(100000000, 2, 2, 0, 13, 2, "TSB", 2, true)] - [InlineData(100000000, 2, 2, 0, 20, 20, "TSB", 2, false)] + [InlineData(100000000, 2, 2, 0, 20, 20, "TSA", 2, false)] [InlineData(1, 0, 1, 0, 1, 2, "TSB", 1, false)] [InlineData(10, 0, 0, 0, 1, 2, "ELF", 10, false)] // Charge 10 ELFs tx size fee. public async Task ChargeFee_SetConfiguration_Tests(long balance1, long balance2, long balance3, long fee1, From f5af56ebb64e6805a99e2305765a98f1d630b4f0 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 12 Jun 2023 19:03:39 +0800 Subject: [PATCH 029/139] fix: ut --- ...inTransactionDirectlyTest_FreeAllowance.cs | 223 ++++++++---------- .../ExecutionPluginForMethodFeeTestBase.cs | 3 + 2 files changed, 106 insertions(+), 120 deletions(-) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index 2fa7599fd4..14ad8b124a 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -170,7 +170,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new ConfigMethodFeeFreeAllowance { - Symbol = "USDT", + Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = @@ -198,7 +198,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - config.Value.Last().Symbol.ShouldBe("USDT"); + config.Value.Last().Symbol.ShouldBe(USDT); config.Value.Last().Threshold.ShouldBe(1_000000); config.Value.Last().RefreshSeconds.ShouldBe(300); config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -213,12 +213,12 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); userBFreeAllowances.Result.Map.Count.ShouldBe(1); - userBFreeAllowances.Result.Map.Keys.First().ShouldBe("USDT"); + userBFreeAllowances.Result.Map.Keys.First().ShouldBe(USDT); userBFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); - userAFreeAllowances.Result.Map.Add("USDT", userBFreeAllowances.Result.Map.Values.First()); + userAFreeAllowances.Result.Map.Add(USDT, userBFreeAllowances.Result.Map.Values.First()); userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); } } @@ -253,7 +253,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }, new ConfigMethodFeeFreeAllowance { - Symbol = "USDT", + Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = @@ -280,7 +280,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - config.Value.Last().Symbol.ShouldBe("USDT"); + config.Value.Last().Symbol.ShouldBe(USDT); config.Value.Last().Threshold.ShouldBe(1_000000); config.Value.Last().RefreshSeconds.ShouldBe(300); config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -295,12 +295,12 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); userBFreeAllowances.Result.Map.Count.ShouldBe(1); - userBFreeAllowances.Result.Map.Keys.First().ShouldBe("USDT"); + userBFreeAllowances.Result.Map.Keys.First().ShouldBe(USDT); userBFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); - userAFreeAllowances.Result.Map.Add("USDT", userBFreeAllowances.Result.Map.Values.First()); + userAFreeAllowances.Result.Map.Add(USDT, userBFreeAllowances.Result.Map.Values.First()); userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); } @@ -317,7 +317,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new ConfigMethodFeeFreeAllowance { - Symbol = "USDT", + Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = @@ -349,7 +349,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - config.Value.Last().Symbol.ShouldBe("USDT"); + config.Value.Last().Symbol.ShouldBe(USDT); config.Value.Last().Threshold.ShouldBe(2_000000); config.Value.Last().RefreshSeconds.ShouldBe(1200); config.Value.Last().FreeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -475,7 +475,7 @@ await TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig.SendWithExceptio public async Task RemoveMethodFeeFreeAllowancesConfig_Test() { await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); - await IssueTokenToUserAsync("USDT", 1_000000, UserAAddress); + await IssueTokenToUserAsync(USDT, 1_000000, UserAAddress); var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(2); @@ -486,7 +486,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), new RemoveMethodFeeFreeAllowancesConfigInput { - Symbols = { "USDT" } + Symbols = { USDT } }); config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Result.Value.Count.ShouldBe(1); @@ -500,7 +500,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), new RemoveMethodFeeFreeAllowancesConfigInput { - Symbols = { "USDT" } + Symbols = { USDT } }); config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Result.Value.Count.ShouldBe(1); @@ -526,7 +526,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, public async Task RemoveMethodFeeFreeAllowancesConfig_MultipleTokens_AtOnce_Test() { await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); - await IssueTokenToUserAsync("USDT", 1_000000, UserAAddress); + await IssueTokenToUserAsync(USDT, 1_000000, UserAAddress); var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(2); @@ -537,7 +537,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), new RemoveMethodFeeFreeAllowancesConfigInput { - Symbols = { "ELF", "USDT" } + Symbols = { "ELF", USDT } }); userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(0); @@ -550,7 +550,7 @@ public async Task RemoveMethodFeeFreeAllowancesConfig_InvalidInput_Test() nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), new RemoveMethodFeeFreeAllowancesConfigInput { - Symbols = { "USDT" } + Symbols = { USDT } }); message.ShouldContain("Method fee free allowances config not set"); @@ -571,10 +571,10 @@ public async Task ChargeTransactionFee_Test(long initialELFBalance, long initial long thresholdUSDT, long newFreeAmountELF, long newFreeAmountUSDT, long afterBalance, long basicFee) { await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, "USDT"); + await CreateTokenAsync(DefaultSender, USDT); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); - await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); + await IssueTokenToDefaultSenderAsync(USDT, initialUSDTBalance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput @@ -600,7 +600,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }, new ConfigMethodFeeFreeAllowance { - Symbol = "USDT", + Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = @@ -638,7 +638,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); @@ -657,7 +657,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountELF); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); @@ -673,24 +673,21 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, // case 25 [InlineData(1000, 100, 1000, 1000, 1000, 10, 10000, 1000, 20, 100, 1000, 500, 0, 1000, 1000, 100, 1000, 500)] public async Task ChargeTransactionFee_MultipleTokens_Test(long initialELFBalance, long initialUSDTBalance, - long initialTokenABalance, long initialTokenBBalance, long freeAmountELF, long refreshSecondsELF, + long initialToken1Balance, long initialToken2Balance, long freeAmountELF, long refreshSecondsELF, long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFreeAmountELF, - long newFreeAmountUSDT, long afterTokenABalance, long afterTokenBBalance, long afterELFBalance, + long newFreeAmountUSDT, long afterToken1Balance, long afterToken2Balance, long afterELFBalance, long afterUSDTBalance, long sizeFee, long basicFee) { - const string Token1 = "TOKENA"; - const string Token2 = "TOKENB"; - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, "USDT"); + await CreateTokenAsync(DefaultSender, USDT); await CreateTokenAsync(DefaultSender, Token1); await CreateTokenAsync(DefaultSender, Token2); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); - await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); - await IssueTokenToDefaultSenderAsync(Token1, initialTokenABalance); - await IssueTokenToDefaultSenderAsync(Token2, initialTokenBBalance); + await IssueTokenToDefaultSenderAsync(USDT, initialUSDTBalance); + await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); + await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput @@ -716,7 +713,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }, new ConfigMethodFeeFreeAllowance { - Symbol = "USDT", + Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = @@ -781,7 +778,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, if (initialUSDTBalance >= thresholdUSDT) { - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); @@ -796,7 +793,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRet.Output.Success.ShouldBe(initialTokenABalance + freeAmountELF >= sizeFee); + chargeFeeRet.Output.Success.ShouldBe(initialToken1Balance + freeAmountELF >= sizeFee); freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); @@ -810,16 +807,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, if (initialUSDTBalance >= thresholdUSDT) { - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); } - await CheckDefaultSenderTokenAsync(Token1, afterTokenABalance); - await CheckDefaultSenderTokenAsync(Token2, afterTokenBBalance); + await CheckDefaultSenderTokenAsync(Token1, afterToken1Balance); + await CheckDefaultSenderTokenAsync(Token2, afterToken2Balance); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); - await CheckDefaultSenderTokenAsync("USDT", afterUSDTBalance); + await CheckDefaultSenderTokenAsync(USDT, afterUSDTBalance); } [Theory] @@ -877,22 +874,19 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, [Theory] [InlineData(1000, 1000, 1000, 2000, 2000, 0, 1000, 1000, 500, 1000, 1000, 1000, 1500)] - public async Task ChargeTransactionFee_SingleThreshold_Test(long initialBalance, long initialTokenABalance, - long initialTokenBBalance, long freeAmountTokenA, long freeAmountTokenB, long refreshSeconds, - long threshold, long newFreeAmountTokenA, long newFreeAmountTokenB, long afterTokenABalance, - long afterTokenBBalance, long sizeFee, long basicFee) + public async Task ChargeTransactionFee_SingleThreshold_Test(long initialBalance, long initialToken1Balance, + long initialToken2Balance, long freeAmountTokenA, long freeAmountTokenB, long refreshSeconds, + long threshold, long newFreeAmountTokenA, long newFreeAmountTokenB, long afterToken1Balance, + long afterToken2Balance, long sizeFee, long basicFee) { - const string TokenA = "TOKENA"; - const string TokenB = "TOKENB"; - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, TokenA); - await CreateTokenAsync(DefaultSender, TokenB); + await CreateTokenAsync(DefaultSender, Token1); + await CreateTokenAsync(DefaultSender, Token2); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToDefaultSenderAsync(TokenA, initialTokenABalance); - await IssueTokenToDefaultSenderAsync(TokenB, initialTokenBBalance); + await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); + await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput @@ -908,12 +902,12 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFeeFreeAllowance { - Symbol = TokenA, + Symbol = Token1, Amount = freeAmountTokenA }, new MethodFeeFreeAllowance { - Symbol = TokenB, + Symbol = Token2, Amount = freeAmountTokenB } } @@ -931,7 +925,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new MethodFee { - Symbol = TokenB, + Symbol = Token2, BasicFee = basicFee } } @@ -945,7 +939,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new SymbolToPayTxSizeFee { - TokenSymbol = TokenA, + TokenSymbol = Token1, AddedTokenWeight = 1, BaseTokenWeight = 1 }, @@ -963,12 +957,12 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenA); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenA); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountTokenA); - freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(TokenB); - freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(TokenB); + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(Token2); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(freeAmountTokenB); var chargeTransactionFeesInput = new ChargeTransactionFeesInput @@ -986,38 +980,35 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); - freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(TokenA); - freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(TokenA); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmountTokenA); - freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(TokenB); - freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(TokenB); + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(Token2); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(newFreeAmountTokenB); - await CheckDefaultSenderTokenAsync(TokenA, afterTokenABalance); - await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterTokenBBalance); + await CheckDefaultSenderTokenAsync(Token1, afterToken1Balance); + await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterToken2Balance); } [Theory] [InlineData(1000, 1000, 1000, 1000, 1000, 10, 100, 1000, 20, 100, 0, 1000, 0, 1000, 3000, 5000)] public async Task ChargeTransactionFee_NotEnough_Test(long initialELFBalance, long initialUSDTBalance, - long initialTokenABalance, long initialTokenBBalance, long freeAmountELF, long refreshSecondsELF, + long initialToken1Balance, long initialToken2Balance, long freeAmountELF, long refreshSecondsELF, long thresholdELF, long freeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFreeAmountELF, - long newFreeAmountUSDT, long afterTokenABalance, long afterTokenBBalance, long sizeFee, long basicFee) + long newFreeAmountUSDT, long afterToken1Balance, long afterToken2Balance, long sizeFee, long basicFee) { - const string Token1 = "TOKENA"; - const string Token2 = "TOKENB"; - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, "USDT"); + await CreateTokenAsync(DefaultSender, USDT); await CreateTokenAsync(DefaultSender, Token1); await CreateTokenAsync(DefaultSender, Token2); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); - await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); - await IssueTokenToDefaultSenderAsync(Token1, initialTokenABalance); - await IssueTokenToDefaultSenderAsync(Token2, initialTokenBBalance); + await IssueTokenToDefaultSenderAsync(USDT, initialUSDTBalance); + await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); + await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput @@ -1043,7 +1034,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }, new ConfigMethodFeeFreeAllowance { - Symbol = "USDT", + Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = @@ -1102,7 +1093,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(freeAmountELF); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(freeAmountUSDT); @@ -1121,13 +1112,13 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFreeAmountUSDT); - await CheckDefaultSenderTokenAsync(Token1, afterTokenABalance); - await CheckDefaultSenderTokenAsync(Token2, afterTokenBBalance); + await CheckDefaultSenderTokenAsync(Token1, afterToken1Balance); + await CheckDefaultSenderTokenAsync(Token2, afterToken2Balance); } [Theory] @@ -1253,17 +1244,14 @@ await TokenContractStub.Transfer.SendAsync(new TransferInput [Fact] public async Task ChargeTransactionFee_RefreshTime_Test() { - const string Token1 = "TOKENA"; - const string Token2 = "TOKENB"; - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, "USDT"); + await CreateTokenAsync(DefaultSender, USDT); await CreateTokenAsync(DefaultSender, Token1); await CreateTokenAsync(DefaultSender, Token2); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 10000); - await IssueTokenToDefaultSenderAsync("USDT", 10000); + await IssueTokenToDefaultSenderAsync(USDT, 10000); await IssueTokenToDefaultSenderAsync(Token1, 10000); await IssueTokenToDefaultSenderAsync(Token2, 10000); @@ -1291,7 +1279,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }, new ConfigMethodFeeFreeAllowance { - Symbol = "USDT", + Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = @@ -1351,7 +1339,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(1000); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(1000); @@ -1373,13 +1361,13 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(500); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); - await CheckDefaultSenderTokenAsync("USDT", 10000); + await CheckDefaultSenderTokenAsync(USDT, 10000); await CheckDefaultSenderTokenAsync(Token1, 10000); await CheckDefaultSenderTokenAsync(Token2, 10000); @@ -1392,13 +1380,13 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(0); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); - await CheckDefaultSenderTokenAsync("USDT", 10000); + await CheckDefaultSenderTokenAsync(USDT, 10000); await CheckDefaultSenderTokenAsync(Token1, 9000); await CheckDefaultSenderTokenAsync(Token2, 10000); @@ -1413,31 +1401,29 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(Token2); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(500); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, 10000); - await CheckDefaultSenderTokenAsync("USDT", 10000); + await CheckDefaultSenderTokenAsync(USDT, 10000); await CheckDefaultSenderTokenAsync(Token1, 8000); await CheckDefaultSenderTokenAsync(Token2, 10000); } [Theory] [InlineData(1000, 1000, 1000, 0, 10, 800, 1000, 1000, 100, 100)] - public async Task ChargeTransactionFee_FreeAllowanceFirst_Test(long initialBalance, long initialTokenABalance, - long freeAmount, long refreshSeconds, long threshold, long newFreeAmount, long afterTokenABalance, + public async Task ChargeTransactionFee_FreeAllowanceFirst_Test(long initialBalance, long initialToken1Balance, + long freeAmount, long refreshSeconds, long threshold, long newFreeAmount, long afterToken1Balance, long afterELFBalance, long sizeFee, long basicFee) { - const string Token1 = "TOKENA"; - await SetPrimaryTokenSymbolAsync(); await CreateTokenAsync(DefaultSender, Token1); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToDefaultSenderAsync(Token1, initialTokenABalance); + await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput @@ -1528,48 +1514,45 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(newFreeAmount); - await CheckDefaultSenderTokenAsync(Token1, afterTokenABalance); + await CheckDefaultSenderTokenAsync(Token1, afterToken1Balance); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); } [Theory] // case 24 - [InlineData(1000, 1000, 1000, 1000, "TOKENA", 1000, "TOKENA", 1000, 600, 10, "TOKENB", 1000, "TOKENB", 1000, 300, 10, 1000, 1000, 1000, 1000, 0, 0, 1000, 1000, 5000, 1, 1, "USDT", 3000, "TOKENB", 3000, false)] + [InlineData(1000, 1000, 1000, 1000, Token1, 1000, Token1, 1000, 600, 10, Token2, 1000, Token2, 1000, 300, 10, 1000, 1000, 1000, 1000, 0, 0, 1000, 1000, 5000, 1, 1, USDT, 3000, Token2, 3000, false)] // case 28 - [InlineData(10000, 10000, 1000, 0, "TOKENA", 2000, NativeTokenSymbol, 2000, 600, 10000, "TOKENA", 1000, "USDT", 200, 300, 10000, 2000, 0, 0, 200, 10000, 10000, 1000, 0, 2000, 1, 2, "TOKENA", 1000, "USDT", 200, true)] + [InlineData(10000, 10000, 1000, 0, Token1, 2000, NativeTokenSymbol, 2000, 600, 10000, Token1, 1000, USDT, 200, 300, 10000, 2000, 0, 0, 200, 10000, 10000, 1000, 0, 2000, 1, 2, Token1, 1000, USDT, 200, true)] // case 29 - [InlineData(10000, 10000, 1000, 0, "TOKENA", 2000, NativeTokenSymbol, 1000, 600, 10000, "TOKENA", 1000, "USDT", 100, 300, 10000, 1000, 1000, 0, 100, 10000, 10000, 1000, 0, 2000, 1, 2, "TOKENA", 1000, "USDT", 200, true)] + [InlineData(10000, 10000, 1000, 0, Token1, 2000, NativeTokenSymbol, 1000, 600, 10000, Token1, 1000, USDT, 100, 300, 10000, 1000, 1000, 0, 100, 10000, 10000, 1000, 0, 2000, 1, 2, Token1, 1000, USDT, 200, true)] // case 30 - [InlineData(10000, 10000, 1000, 0, "TOKENA", 1000, NativeTokenSymbol, 1000, 600, 100, "TOKENA", 1000, "USDT", 100, 300, 100, 500, 0, 0, 100, 9000, 10000, 1000, 0, 2000, 1, 1, "TOKENA", 1500, "USDT", 200, true)] + [InlineData(10000, 10000, 1000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, USDT, 100, 300, 100, 500, 0, 0, 100, 9000, 10000, 1000, 0, 2000, 1, 1, Token1, 1500, USDT, 200, true)] // case 31 - [InlineData(10000, 10000, 10000, 0, "TOKENA", 1000, NativeTokenSymbol, 1000, 600, 100, "TOKENA", 1000, "ELF", 1000, 300, 100, 0, 0, 0, 0, 9000, 10000, 7000, 0, 3000, 5, 3, NativeTokenSymbol, 3000, "TOKENA", 3000, true)] + [InlineData(10000, 10000, 10000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, "ELF", 1000, 300, 100, 0, 0, 0, 0, 9000, 10000, 7000, 0, 3000, 5, 3, NativeTokenSymbol, 3000, Token1, 3000, true)] // case 32 - [InlineData(10000, 10000, 1000, 0, "TOKENA", 1000, NativeTokenSymbol, 1000, 600, 100, "TOKENA", 1000, "ELF", 1000, 300, 100, 0, 0, 0, 0, 0, 10000, 0, 0, 3000, 5, 3, NativeTokenSymbol, 15000, "USDT", 20000, false)] + [InlineData(10000, 10000, 1000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, "ELF", 1000, 300, 100, 0, 0, 0, 0, 0, 10000, 0, 0, 3000, 5, 3, NativeTokenSymbol, 15000, USDT, 20000, false)] // case 33 - [InlineData(5000, 10000, 0, 0, "TOKENA", 1000, "TOKENA", 1000, 600, 100, "TOKENB", 1000, "TOKENB", 1000, 300, 100, 0, 0, 1000, 1000, 0, 8000, 0, 0, 10000, 1, 5, "USDT", 2000, "ELF", 0, false)] + [InlineData(5000, 10000, 0, 0, Token1, 1000, Token1, 1000, 600, 100, Token2, 1000, Token2, 1000, 300, 100, 0, 0, 1000, 1000, 0, 8000, 0, 0, 10000, 1, 5, USDT, 2000, "ELF", 0, false)] public async Task ChargeTransactionFee_MultipleTxFeeTokens_Test(long initialELFBalance, long initialUSDTBalance, - long initialTokenABalance, long initialTokenBBalance, string firstFreeSymbolELF, long firstFreeAmountELF, + long initialToken1Balance, long initialToken2Balance, string firstFreeSymbolELF, long firstFreeAmountELF, string secondFreeSymbolELF, long secondFreeAmountELF, long refreshSecondsELF, long thresholdELF, string firstFreeSymbolUSDT, long firstFreeAmountUSDT, string secondFreeSymbolUSDT, long secondFreeAmountUSDT, long refreshSecondsUSDT, long thresholdUSDT, long newFirstFreeAmountELF, long newSecondFreeAmountELF, long newFirstFreeAmountUSDT, long newSecondFreeAmountUSDT, long afterELFBalance, long afterUSDTBalance, - long afterTokenABalance, long afterTokenBBalance, long sizeFee, int addedTokenWeight, int baseTokenWeight, + long afterToken1Balance, long afterToken2Balance, long sizeFee, int addedTokenWeight, int baseTokenWeight, string firstBaseFeeSymbol, long firstBaseFeeAmount, string secondBaseFeeSymbol, long secondBaseFeeAmount, bool chargeFeeResult) { - const string Token1 = "TOKENA"; - const string Token2 = "TOKENB"; - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, "USDT"); + await CreateTokenAsync(DefaultSender, USDT); await CreateTokenAsync(DefaultSender, Token1); await CreateTokenAsync(DefaultSender, Token2); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); - await IssueTokenToDefaultSenderAsync("USDT", initialUSDTBalance); - await IssueTokenToDefaultSenderAsync(Token1, initialTokenABalance); - await IssueTokenToDefaultSenderAsync(Token2, initialTokenBBalance); + await IssueTokenToDefaultSenderAsync(USDT, initialUSDTBalance); + await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); + await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput @@ -1600,7 +1583,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }, new ConfigMethodFeeFreeAllowance { - Symbol = "USDT", + Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances { Value = @@ -1684,7 +1667,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, if (initialUSDTBalance >= thresholdUSDT) { - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(firstFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(firstFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(firstFreeAmountUSDT); @@ -1720,7 +1703,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, if (afterUSDTBalance >= thresholdUSDT) { - freeAllowances.Map.Keys.Last().ShouldBe("USDT"); + freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(firstFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(firstFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFirstFreeAmountUSDT); @@ -1730,10 +1713,10 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.Last().Map.Values.Last().Amount.ShouldBe(newSecondFreeAmountUSDT); } - await CheckDefaultSenderTokenAsync(Token1, afterTokenABalance); - await CheckDefaultSenderTokenAsync(Token2, afterTokenBBalance); + await CheckDefaultSenderTokenAsync(Token1, afterToken1Balance); + await CheckDefaultSenderTokenAsync(Token2, afterToken2Balance); await CheckDefaultSenderTokenAsync(NativeTokenSymbol, afterELFBalance); - await CheckDefaultSenderTokenAsync("USDT", afterUSDTBalance); + await CheckDefaultSenderTokenAsync(USDT, afterUSDTBalance); } private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) @@ -1749,10 +1732,10 @@ private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) private async Task CreateTokenAndIssueAsync() { - await CreateTokenAsync(DefaultSender, "USDT"); + await CreateTokenAsync(DefaultSender, USDT); await IssueTokenToUserAsync(NativeTokenSymbol, 1_00000000, UserAAddress); - await IssueTokenToUserAsync("USDT", 1_000000, UserBAddress); + await IssueTokenToUserAsync(USDT, 1_000000, UserBAddress); await IssueTokenToUserAsync(NativeTokenSymbol, 1_00000000, UserCAddress); - await IssueTokenToUserAsync("USDT", 1_000000, UserCAddress); + await IssueTokenToUserAsync(USDT, 1_000000, UserCAddress); } } \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index 29a88fb142..2e30818c8d 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -286,6 +286,9 @@ public class ExecutePluginTransactionDirectlyForMethodFeeTestBase : ContractTest ExecutionPluginTransactionDirectlyForMethodFeeTestModule> { protected const string NativeTokenSymbol = "ELF"; + protected const string USDT = "USDT"; + protected const string Token1 = "TOKENA"; + protected const string Token2 = "TOKENB"; protected readonly IBlockTimeProvider _blockTimeProvider; From d04c285a34d55cbeab3d29a8de21425fde641206 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Mon, 12 Jun 2023 21:20:11 +0800 Subject: [PATCH 030/139] feat: adjust ChargeBaseFee and ChargeSizeFee logic with delegatee. --- .../TokenContract_Fees.cs | 98 ++++++++++--------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 54fcf3a41c..b4e2e0fa5e 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -442,53 +442,49 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 - foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) + SymbolToPayTxSizeFee availableSymbolWithAnything = null; + SymbolToPayTxSizeFee availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee = null; + SymbolToPayTxSizeFee availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; + + // get 1st Allowance > size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 + foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) + { + var allowance = GetAllowanceCalculatedBaseOnPrimaryToken(symbolToPlayTxSizeFee, + methodFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseAllowance); + var balancePlusAllowance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, + symbolToPlayTxSizeFee, symbolChargedForBaseFee, amountChargedForBaseFee, + methodFeeFreeAllowancesMap, amountChargedForBaseAllowance); + if (delegations != null) { - var allowance = GetAllowanceCalculatedBaseOnPrimaryToken(symbolToPlayTxSizeFee, - methodFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseAllowance); - var balancePlusAllowance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, - symbolToPlayTxSizeFee, symbolChargedForBaseFee, amountChargedForBaseFee, - methodFeeFreeAllowancesMap, amountChargedForBaseAllowance); - - if (allowance >= txSizeFeeAmount) + var delegationEnough = IsDelegationEnoughBaseOnPrimaryToken(symbolToPlayTxSizeFee, + symbolChargedForBaseFee, amountChargedForBaseFee.Add(amountChargedForBaseAllowance), txSizeFeeAmount, delegations); + if (!delegationEnough) { - availableSymbol = symbolToPlayTxSizeFee; break; } + } - if (balancePlusAllowance <= 0) continue; - availableSymbolWithAnything ??= symbolToPlayTxSizeFee; - - if (balancePlusAllowance < txSizeFeeAmount) continue; - availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbolToPlayTxSizeFee; - - if (allowance <= 0) continue; - availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbolToPlayTxSizeFee; + if (allowance >= txSizeFeeAmount) + { + availableSymbol = symbolToPlayTxSizeFee; + break; } - availableSymbol ??= availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? - availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ?? availableSymbolWithAnything; - } - else - { - availableSymbol = allSymbolToTxFee.FirstOrDefault(x => + if (delegations == null && balancePlusAllowance > 0) { - var delegationEnough = IsDelegationEnoughBaseOnPrimaryToken(x, symbolChargedForBaseFee, - amountChargedForBaseFee.Add(amountChargedForBaseAllowance), txSizeFeeAmount, delegations); - var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, - symbolChargedForBaseFee, amountChargedForBaseFee, methodFeeFreeAllowancesMap, - amountChargedForBaseAllowance); - return delegationEnough && balance >= txSizeFeeAmount; - }); + availableSymbolWithAnything ??= symbolToPlayTxSizeFee; + } + + if (balancePlusAllowance < txSizeFeeAmount) continue; + availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbolToPlayTxSizeFee; + + if (allowance <= 0) continue; + availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbolToPlayTxSizeFee; } + availableSymbol ??= availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? + availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ?? availableSymbolWithAnything; + return availableSymbol; } @@ -779,6 +775,8 @@ private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountM amount = 0; existingBalance = 0; existingAllowance = 0; + string symbolWithBalancePlusAllowanceEnoughToPayTxFee = null; + string symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; //Find the token that satisfies the delegate limit and satisfies the balance of the fee foreach (var (symbol, value) in symbolToAmountMap) { @@ -786,19 +784,29 @@ private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountM amount = value; existingBalance = GetBalance(fromAddress, symbol); existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); - // is unlimited delegate is true && balance enough - // is unlimited delegate is false && delegation enough && balance enough - if (existingBalance.Add(existingAllowance) < amount) continue; + // is unlimited delegate is true || is unlimited delegate is false and delegation is enough if (delegations.IsUnlimitedDelegate || (!delegations.IsUnlimitedDelegate && - delegations.Delegations.ContainsKey(symbol) - && delegations.Delegations[symbol] >= amount)) + delegations.Delegations.ContainsKey(symbol) && delegations.Delegations[symbol] >= amount)) { - symbolOfValidBalance = symbol; - return true; + //If allowance is enough,return true + if (existingAllowance >= amount) + { + symbolOfValidBalance = symbol; + return true; + } + //Find symbol which balance+allowance >= amount + if (existingBalance.Add(existingAllowance) < amount) continue; + symbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbol; + //If balance+allowance is enough,priority find the symbol which allowance > 0 + if (existingAllowance <= 0) continue; + symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbol; } } - return false; + symbolOfValidBalance = symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? + symbolWithBalancePlusAllowanceEnoughToPayTxFee; + + return symbolOfValidBalance != null; } public override Empty ClaimTransactionFees(TotalTransactionFeesMap input) From 70be00c4ad4334cd076157f1fed60bae3e71aa87 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 12 Jun 2023 21:58:50 +0800 Subject: [PATCH 031/139] fix: change method to transaction --- .../TokenContractState_ChargeFee.cs | 12 +- .../TokenContract_ACS2_StatePathsProvider.cs | 16 +- .../TokenContract_Fees.cs | 234 ++++++++-------- .../TokenContract_Helper.cs | 24 +- protobuf/token_contract_impl.proto | 32 +-- .../BVT/TokenFeeTest.cs | 8 +- .../ExecutePluginTransactionDirectlyTest.cs | 32 +-- ...inTransactionDirectlyTest_FreeAllowance.cs | 250 +++++++++--------- 8 files changed, 300 insertions(+), 308 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs index 5776abb8a1..0411e2ccec 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs @@ -42,20 +42,20 @@ public partial class TokenContractState /// /// Symbol List /// - public SingletonState MethodFeeFreeAllowancesSymbolList { get; set; } + public SingletonState TransactionFeeFreeAllowancesSymbolList { get; set; } /// - /// Symbol -> FreeAllowanceConfig + /// Symbol -> TransactionFeeFreeAllowanceConfig /// - public MappedState MethodFeeFreeAllowancesConfigMap { get; set; } + public MappedState TransactionFeeFreeAllowancesConfigMap { get; set; } /// - /// Address -> Symbol -> MethodFeeFreeAllowanceMap + /// Address -> Symbol -> TransactionFeeFreeAllowanceMap /// - public MappedState MethodFeeFreeAllowances { get; set; } + public MappedState TransactionFeeFreeAllowances { get; set; } /// /// Address -> Symbol -> LastRefreshTime /// - public MappedState MethodFeeFreeAllowancesLastRefreshTimes { get; set; } + public MappedState TransactionFeeFreeAllowancesLastRefreshTimes { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index 5d2a01a48a..bd194a5ddf 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -22,14 +22,14 @@ public override ResourceInfo GetResourceInfo(Transaction txn) { GetPath(nameof(TokenContractState.Balances), txn.From.ToString(), args.Symbol), GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowances), txn.From.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesLastRefreshTimes), txn.From.ToString(), args.Symbol) + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowances), txn.From.ToString(), args.Symbol), + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesLastRefreshTimes), txn.From.ToString(), args.Symbol) }, ReadPaths = { GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesSymbolList)) + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesSymbolList)) } }; AddPathForTransactionFee(resourceInfo, txn.From.ToString()); @@ -49,14 +49,14 @@ public override ResourceInfo GetResourceInfo(Transaction txn) GetPath(nameof(TokenContractState.Balances), args.From.ToString(), args.Symbol), GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol), GetPath(nameof(TokenContractState.LockWhiteLists), args.Symbol, txn.From.ToString()), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowances), txn.From.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesLastRefreshTimes), txn.From.ToString(), args.Symbol) + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowances), txn.From.ToString(), args.Symbol), + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesLastRefreshTimes), txn.From.ToString(), args.Symbol) }, ReadPaths = { GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)), - GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesSymbolList)) + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesSymbolList)) } }; AddPathForTransactionFee(resourceInfo, txn.From.ToString()); @@ -108,8 +108,8 @@ private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from, strin if (delegations == null) return; var add = Address.FromBase58(delegations).ToString(); AddPathForTransactionFee(resourceInfo, add); - resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.MethodFeeFreeAllowances), add, symbol)); - resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.MethodFeeFreeAllowancesLastRefreshTimes), add, symbol)); + resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowances), add, symbol)); + resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesLastRefreshTimes), add, symbol)); } } } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index b4e2e0fa5e..f54cbffcef 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -228,8 +228,8 @@ private void ModifyDelegation(TransactionFeeBill bill, TransactionFreeFeeAllowan private void ModifyBalance(Address fromAddress, TransactionFeeBill bill, TransactionFreeFeeAllowanceBill allowanceBill) { - SetOrRefreshMethodFeeFreeAllowances(fromAddress); - var freeAllowancesMap = CalculateMethodFeeFreeAllowances(fromAddress); + SetOrRefreshTransactionFeeFreeAllowances(fromAddress); + var freeAllowancesMap = CalculateTransactionFeeFreeAllowances(fromAddress); // Update balances and allowances foreach (var (symbol, amount) in bill.FeesMap) @@ -262,8 +262,8 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre { var successToChargeBaseFee = true; - SetOrRefreshMethodFeeFreeAllowances(fromAddress); - var freeAllowancesMap = CalculateMethodFeeFreeAllowances(fromAddress); + SetOrRefreshTransactionFeeFreeAllowances(fromAddress); + var freeAllowancesMap = CalculateTransactionFeeFreeAllowances(fromAddress); if (fee.Count != 0) { @@ -289,22 +289,22 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre return successToChargeBaseFee && successToChargeSizeFee; } - private void SetOrRefreshMethodFeeFreeAllowances(Address address) + private void SetOrRefreshTransactionFeeFreeAllowances(Address address) { - var config = State.MethodFeeFreeAllowancesSymbolList.Value; + var config = State.TransactionFeeFreeAllowancesSymbolList.Value; if (config == null) return; foreach (var symbol in config.Symbols) { - if (State.Balances[address][symbol] < State.MethodFeeFreeAllowancesConfigMap[symbol].Threshold) continue; - var lastRefreshTime = State.MethodFeeFreeAllowancesLastRefreshTimes[address][symbol]; + if (State.Balances[address][symbol] < State.TransactionFeeFreeAllowancesConfigMap[symbol].Threshold) continue; + var lastRefreshTime = State.TransactionFeeFreeAllowancesLastRefreshTimes[address][symbol]; - if (lastRefreshTime != null && State.MethodFeeFreeAllowancesConfigMap[symbol].RefreshSeconds > + if (lastRefreshTime != null && State.TransactionFeeFreeAllowancesConfigMap[symbol].RefreshSeconds > (Context.CurrentBlockTime - lastRefreshTime).Seconds) continue; - State.MethodFeeFreeAllowancesLastRefreshTimes[address][symbol] = Context.CurrentBlockTime; - State.MethodFeeFreeAllowances[address][symbol] = - State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone(); + State.TransactionFeeFreeAllowancesLastRefreshTimes[address][symbol] = Context.CurrentBlockTime; + State.TransactionFeeFreeAllowances[address][symbol] = + State.TransactionFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone(); } } @@ -323,12 +323,12 @@ private Dictionary GetUserContractFeeDictionary(UserContractMethod } private bool ChargeBaseFee(Dictionary methodFeeMap, Address fromAddress, ref TransactionFeeBill bill, - MethodFeeFreeAllowancesMap freeAllowancesMap, ref TransactionFreeFeeAllowanceBill allowanceBill, + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { // Fail to charge if (!ChargeFirstSufficientToken(methodFeeMap, fromAddress, out var symbolToChargeBaseFee, - out var amountToChargeBaseFee, out var existingBalance, out var existingAllowance, freeAllowancesMap, + out var amountToChargeBaseFee, out var existingBalance, out var existingAllowance, transactionFeeFreeAllowancesMap, delegations)) { Context.LogDebug(() => "Failed to charge first sufficient token."); @@ -358,14 +358,14 @@ private bool ChargeBaseFee(Dictionary methodFeeMap, Address fromAd } private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress, ref TransactionFeeBill bill, - MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, ref TransactionFreeFeeAllowanceBill allowanceBill, + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { //If delegation != null,from address->delegateeAddress // Size Fee is charged in primary token, elf. var symbolToPayTxFee = State.ChainPrimaryTokenSymbol.Value; //Get primary token balance - GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, methodFeeFreeAllowancesMap, allowanceBill, + GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, transactionFeeFreeAllowancesMap, allowanceBill, out var symbolChargedForBaseFee, out var amountChargedForBaseFee, out var amountChargedForBaseAllowance, out var availableBalance, out var availableAllowance); var txSizeFeeAmount = input.TransactionSizeFee; @@ -375,7 +375,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress { var allSymbolToTxFee = input.SymbolsToPayTxSizeFee.ToList(); var availableSymbol = GetAvailableSymbolToPayTxFee(allSymbolToTxFee, fromAddress, txSizeFeeAmount, - methodFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseFee, + transactionFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseFee, amountChargedForBaseAllowance, delegations); if (availableSymbol != null && availableSymbol.TokenSymbol != symbolToPayTxFee) @@ -383,7 +383,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress symbolToPayTxFee = availableSymbol.TokenSymbol; txSizeFeeAmount = txSizeFeeAmount.Mul(availableSymbol.AddedTokenWeight) .Div(availableSymbol.BaseTokenWeight); - GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, methodFeeFreeAllowancesMap, allowanceBill, + GetAvailableBalance(symbolToPayTxFee, fromAddress, bill, transactionFeeFreeAllowancesMap, allowanceBill, out symbolChargedForBaseFee, out amountChargedForBaseFee, out amountChargedForBaseAllowance, out availableBalance, out availableAllowance); } @@ -412,7 +412,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress } private void GetAvailableBalance(string symbolToPayTxFee, Address fromAddress, TransactionFeeBill bill, - MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, TransactionFreeFeeAllowanceBill allowanceBill, + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, TransactionFreeFeeAllowanceBill allowanceBill, out string symbolChargedForBaseFee, out long amountChargedForBaseFee, out long amountChargedForBaseAllowance, out long availableBalance, out long availableAllowance) { @@ -432,58 +432,62 @@ private void GetAvailableBalance(string symbolToPayTxFee, Address fromAddress, T ? GetBalance(fromAddress, symbolToPayTxFee).Sub(amountChargedForBaseFee) : GetBalance(fromAddress, symbolToPayTxFee); availableAllowance = symbolChargedForBaseFee == symbolToPayTxFee - ? GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) - : GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbolToPayTxFee); + ? GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) + : GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbolToPayTxFee); } private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List allSymbolToTxFee, - Address fromAddress, long txSizeFeeAmount, MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, + Address fromAddress, long txSizeFeeAmount, TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, string symbolChargedForBaseFee, long amountChargedForBaseFee, long amountChargedForBaseAllowance, TransactionFeeDelegations delegations = null) { SymbolToPayTxSizeFee availableSymbol = null; - SymbolToPayTxSizeFee availableSymbolWithAnything = null; - SymbolToPayTxSizeFee availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee = null; - SymbolToPayTxSizeFee availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; - - // get 1st Allowance > size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 - foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) - { - var allowance = GetAllowanceCalculatedBaseOnPrimaryToken(symbolToPlayTxSizeFee, - methodFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseAllowance); - var balancePlusAllowance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, - symbolToPlayTxSizeFee, symbolChargedForBaseFee, amountChargedForBaseFee, - methodFeeFreeAllowancesMap, amountChargedForBaseAllowance); - if (delegations != null) + if (delegations == null) + { + SymbolToPayTxSizeFee availableSymbolWithAnything = null; + SymbolToPayTxSizeFee availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee = null; + SymbolToPayTxSizeFee availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; + + // get 1st Allowance > size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 + foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) { - var delegationEnough = IsDelegationEnoughBaseOnPrimaryToken(symbolToPlayTxSizeFee, - symbolChargedForBaseFee, amountChargedForBaseFee.Add(amountChargedForBaseAllowance), txSizeFeeAmount, delegations); - if (!delegationEnough) + var allowance = GetAllowanceCalculatedBaseOnPrimaryToken(symbolToPlayTxSizeFee, + transactionFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseAllowance); + var balancePlusAllowance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, + symbolToPlayTxSizeFee, symbolChargedForBaseFee, amountChargedForBaseFee, + transactionFeeFreeAllowancesMap, amountChargedForBaseAllowance); + + if (allowance >= txSizeFeeAmount) { + availableSymbol = symbolToPlayTxSizeFee; break; } - } - - if (allowance >= txSizeFeeAmount) - { - availableSymbol = symbolToPlayTxSizeFee; - break; - } - if (delegations == null && balancePlusAllowance > 0) - { + if (balancePlusAllowance <= 0) continue; availableSymbolWithAnything ??= symbolToPlayTxSizeFee; - } - if (balancePlusAllowance < txSizeFeeAmount) continue; - availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbolToPlayTxSizeFee; + if (balancePlusAllowance < txSizeFeeAmount) continue; + availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbolToPlayTxSizeFee; - if (allowance <= 0) continue; - availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbolToPlayTxSizeFee; - } + if (allowance <= 0) continue; + availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbolToPlayTxSizeFee; + } - availableSymbol ??= availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? - availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ?? availableSymbolWithAnything; + availableSymbol ??= availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? + availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ?? availableSymbolWithAnything; + } + else + { + availableSymbol = allSymbolToTxFee.FirstOrDefault(x => + { + var delegationEnough = IsDelegationEnoughBaseOnPrimaryToken(x, symbolChargedForBaseFee, + amountChargedForBaseFee.Add(amountChargedForBaseAllowance), txSizeFeeAmount, delegations); + var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, + symbolChargedForBaseFee, amountChargedForBaseFee, transactionFeeFreeAllowancesMap, + amountChargedForBaseAllowance); + return delegationEnough && balance >= txSizeFeeAmount; + }); + } return availableSymbol; } @@ -671,12 +675,12 @@ public override Empty SetSymbolsToPayTxSizeFee(SymbolListToPayTxSizeFee input) /// /// /// - /// + /// /// /// private bool ChargeFirstSufficientToken(Dictionary symbolToAmountMap, Address fromAddress, out string symbol, out long amount, out long existingBalance, out long existingAllowance, - MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, TransactionFeeDelegations delegations = null) + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, TransactionFeeDelegations delegations = null) { symbol = null; amount = 0L; @@ -687,18 +691,18 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM if (delegations != null) { //from address -> delegatee - chargeResult = TryToChargeDelegateBaseFee(symbolToAmountMap, fromAddress, methodFeeFreeAllowancesMap, + chargeResult = TryToChargeDelegateBaseFee(symbolToAmountMap, fromAddress, transactionFeeFreeAllowancesMap, delegations, out amount, out symbol, out existingBalance, out existingAllowance); return chargeResult; } - chargeResult = TryToChargeUserBaseFee(symbolToAmountMap, fromAddress, methodFeeFreeAllowancesMap, out amount, + chargeResult = TryToChargeUserBaseFee(symbolToAmountMap, fromAddress, transactionFeeFreeAllowancesMap, out amount, out symbol, out existingBalance, out existingAllowance); if (symbol != null) { existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); } @@ -710,7 +714,7 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM { symbol = primaryTokenSymbol; existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); } } @@ -718,7 +722,7 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM } private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, Address fromAddress, - MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, out long amount, out string symbolOfValidBalance, + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, out long amount, out string symbolOfValidBalance, out long existingBalance, out long existingAllowance) { symbolOfValidBalance = null; @@ -736,7 +740,7 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, // current token symbol amount = value; existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); + existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); if (existingAllowance >= amount) { @@ -768,45 +772,33 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, } private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountMap, Address fromAddress, - MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, TransactionFeeDelegations delegations, + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, TransactionFeeDelegations delegations, out long amount, out string symbolOfValidBalance, out long existingBalance, out long existingAllowance) { symbolOfValidBalance = null; amount = 0; existingBalance = 0; existingAllowance = 0; - string symbolWithBalancePlusAllowanceEnoughToPayTxFee = null; - string symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; //Find the token that satisfies the delegate limit and satisfies the balance of the fee foreach (var (symbol, value) in symbolToAmountMap) { // current token symbol amount = value; existingBalance = GetBalance(fromAddress, symbol); - existingAllowance = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); - // is unlimited delegate is true || is unlimited delegate is false and delegation is enough + existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); + // is unlimited delegate is true && balance enough + // is unlimited delegate is false && delegation enough && balance enough + if (existingBalance.Add(existingAllowance) < amount) continue; if (delegations.IsUnlimitedDelegate || (!delegations.IsUnlimitedDelegate && - delegations.Delegations.ContainsKey(symbol) && delegations.Delegations[symbol] >= amount)) + delegations.Delegations.ContainsKey(symbol) + && delegations.Delegations[symbol] >= amount)) { - //If allowance is enough,return true - if (existingAllowance >= amount) - { - symbolOfValidBalance = symbol; - return true; - } - //Find symbol which balance+allowance >= amount - if (existingBalance.Add(existingAllowance) < amount) continue; - symbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbol; - //If balance+allowance is enough,priority find the symbol which allowance > 0 - if (existingAllowance <= 0) continue; - symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbol; + symbolOfValidBalance = symbol; + return true; } } - symbolOfValidBalance = symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? - symbolWithBalancePlusAllowanceEnoughToPayTxFee; - - return symbolOfValidBalance != null; + return false; } public override Empty ClaimTransactionFees(TotalTransactionFeesMap input) @@ -1149,12 +1141,12 @@ public override Address GetFeeReceiver(Empty input) return State.FeeReceiver.Value; } - public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowancesInput input) + public override Empty ConfigTransactionFeeFreeAllowances(ConfigTransactionFeeFreeAllowancesInput input) { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); Assert(input.Value != null && input.Value.Count > 0, "Invalid input"); - State.MethodFeeFreeAllowancesSymbolList.Value ??= new MethodFeeFreeAllowancesSymbolList + State.TransactionFeeFreeAllowancesSymbolList.Value ??= new TransactionFeeFreeAllowancesSymbolList { Symbols = { new RepeatedField() } }; @@ -1168,12 +1160,12 @@ public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowance Assert(allowances.Threshold >= 0, "Invalid input threshold"); Assert(allowances.RefreshSeconds >= 0, "Invalid input refresh seconds"); - var config = new FreeAllowanceConfig + var config = new TransactionFeeFreeAllowanceConfig { Symbol = allowances.Symbol, Threshold = allowances.Threshold, RefreshSeconds = allowances.RefreshSeconds, - FreeAllowances = new MethodFeeFreeAllowanceMap() + FreeAllowances = new TransactionFeeFreeAllowanceMap() }; foreach (var allowance in allowances.MethodFeeFreeAllowances!.Value!) @@ -1181,11 +1173,11 @@ public override Empty ConfigMethodFeeFreeAllowances(ConfigMethodFeeFreeAllowance config.FreeAllowances.Map.TryAdd(allowance.Symbol, allowance); } - State.MethodFeeFreeAllowancesConfigMap[allowances.Symbol] = config; + State.TransactionFeeFreeAllowancesConfigMap[allowances.Symbol] = config; - if (!State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Contains(allowances.Symbol)) + if (!State.TransactionFeeFreeAllowancesSymbolList.Value.Symbols.Contains(allowances.Symbol)) { - State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Add(allowances.Symbol); + State.TransactionFeeFreeAllowancesSymbolList.Value.Symbols.Add(allowances.Symbol); } } @@ -1198,89 +1190,89 @@ private void ValidateToken(string symbol) Assert(State.TokenInfos[symbol] != null, $"Symbol {symbol} not exist"); } - public override Empty RemoveMethodFeeFreeAllowancesConfig(RemoveMethodFeeFreeAllowancesConfigInput input) + public override Empty RemoveTransactionFeeFreeAllowancesConfig(RemoveTransactionFeeFreeAllowancesConfigInput input) { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); Assert(input.Symbols != null && input.Symbols.Count > 0, "Invalid input"); - Assert(State.MethodFeeFreeAllowancesSymbolList.Value != null, "Method fee free allowances config not set"); + Assert(State.TransactionFeeFreeAllowancesSymbolList.Value != null, "Method fee free allowances config not set"); var symbols = input.Symbols!.Distinct(); foreach (var symbol in symbols) { - if (State.MethodFeeFreeAllowancesSymbolList.Value!.Symbols.Contains(symbol)) + if (State.TransactionFeeFreeAllowancesSymbolList.Value!.Symbols.Contains(symbol)) { - State.MethodFeeFreeAllowancesSymbolList.Value.Symbols.Remove(symbol); + State.TransactionFeeFreeAllowancesSymbolList.Value.Symbols.Remove(symbol); } } return new Empty(); } - public override GetMethodFeeFreeAllowancesConfigOutput GetMethodFeeFreeAllowancesConfig(Empty input) + public override GetTransactionFeeFreeAllowancesConfigOutput GetTransactionFeeFreeAllowancesConfig(Empty input) { - var symbols = State.MethodFeeFreeAllowancesSymbolList.Value.Symbols; - var output = new GetMethodFeeFreeAllowancesConfigOutput(); + var symbols = State.TransactionFeeFreeAllowancesSymbolList.Value.Symbols; + var output = new GetTransactionFeeFreeAllowancesConfigOutput(); foreach (var symbol in symbols) { - output.Value.Add(State.MethodFeeFreeAllowancesConfigMap[symbol]); + output.Value.Add(State.TransactionFeeFreeAllowancesConfigMap[symbol]); } return output; } - public override MethodFeeFreeAllowancesMap GetMethodFeeFreeAllowances(Address input) + public override TransactionFeeFreeAllowancesMap GetTransactionFeeFreeAllowances(Address input) { - return CalculateMethodFeeFreeAllowances(input); + return CalculateTransactionFeeFreeAllowances(input); } - private MethodFeeFreeAllowancesMap CalculateMethodFeeFreeAllowances(Address input) + private TransactionFeeFreeAllowancesMap CalculateTransactionFeeFreeAllowances(Address input) { - var freeAllowanceMap = State.MethodFeeFreeAllowances[input]; + var freeAllowanceMap = State.TransactionFeeFreeAllowances[input]; - var freeAllowancesConfig = State.MethodFeeFreeAllowancesSymbolList.Value; + var freeAllowancesConfig = State.TransactionFeeFreeAllowancesSymbolList.Value; if (freeAllowancesConfig == null) { - return new MethodFeeFreeAllowancesMap(); + return new TransactionFeeFreeAllowancesMap(); } - var methodFeeFreeAllowancesMap = new MethodFeeFreeAllowancesMap(); + var transactionFeeFreeAllowancesMap = new TransactionFeeFreeAllowancesMap(); foreach (var symbol in freeAllowancesConfig.Symbols) { var balance = State.Balances[input][symbol]; - if (balance < State.MethodFeeFreeAllowancesConfigMap[symbol].Threshold) continue; + if (balance < State.TransactionFeeFreeAllowancesConfigMap[symbol].Threshold) continue; - var lastRefreshTime = State.MethodFeeFreeAllowancesLastRefreshTimes[input][symbol]; + var lastRefreshTime = State.TransactionFeeFreeAllowancesLastRefreshTimes[input][symbol]; var freeAllowances = freeAllowanceMap[symbol]; if (freeAllowances == null) { - if (balance >= State.MethodFeeFreeAllowancesConfigMap[symbol].Threshold) + if (balance >= State.TransactionFeeFreeAllowancesConfigMap[symbol].Threshold) { - methodFeeFreeAllowancesMap.Map.Add(symbol, - State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone()); + transactionFeeFreeAllowancesMap.Map.Add(symbol, + State.TransactionFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone()); continue; } } if (lastRefreshTime == null) { - methodFeeFreeAllowancesMap.Map.Add(symbol, freeAllowances); + transactionFeeFreeAllowancesMap.Map.Add(symbol, freeAllowances); } else { - methodFeeFreeAllowancesMap.Map[symbol] = + transactionFeeFreeAllowancesMap.Map[symbol] = (Context.CurrentBlockTime - lastRefreshTime).Seconds > - State.MethodFeeFreeAllowancesConfigMap[symbol].RefreshSeconds - ? State.MethodFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone() + State.TransactionFeeFreeAllowancesConfigMap[symbol].RefreshSeconds + ? State.TransactionFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone() : freeAllowances; } } - return methodFeeFreeAllowancesMap; + return transactionFeeFreeAllowancesMap; } private long GetBalanceCalculatedBaseOnPrimaryToken(Address fromAddress, SymbolToPayTxSizeFee tokenInfo, @@ -1296,18 +1288,18 @@ private long GetBalanceCalculatedBaseOnPrimaryToken(Address fromAddress, SymbolT private long GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(Address fromAddress, SymbolToPayTxSizeFee tokenInfo, string baseSymbol, - long cost, MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, long allowanceCost) + long cost, TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, long allowanceCost) { return GetBalanceCalculatedBaseOnPrimaryToken(fromAddress, tokenInfo, baseSymbol, cost).Add( - GetAllowanceCalculatedBaseOnPrimaryToken(tokenInfo, methodFeeFreeAllowancesMap, baseSymbol, allowanceCost)); + GetAllowanceCalculatedBaseOnPrimaryToken(tokenInfo, transactionFeeFreeAllowancesMap, baseSymbol, allowanceCost)); } private long GetAllowanceCalculatedBaseOnPrimaryToken(SymbolToPayTxSizeFee tokenInfo, - MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, string baseSymbol, + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, string baseSymbol, long allowanceCost) { var availableAllowance = - GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, + GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, tokenInfo.TokenSymbol); //GetBalance(Context.Sender, tokenInfo.TokenSymbol); if (tokenInfo.TokenSymbol == baseSymbol) availableAllowance = availableAllowance.Sub(allowanceCost); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index b59a1767d2..22d50a496c 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -84,40 +84,40 @@ private void ModifyBalance(Address address, string symbol, long addAmount) } private void ModifyFreeFeeAllowanceAmount(Address fromAddress, - MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, string symbol, + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, string symbol, long addAmount) { - var freeAllowanceAmount = GetFreeFeeAllowanceAmount(methodFeeFreeAllowancesMap, symbol); + var freeAllowanceAmount = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); if (addAmount < 0 && freeAllowanceAmount < -addAmount) { Assert(false, $"Insufficient amount of {symbol} for free fee allowance. Need amount: {-addAmount}; Current amount: {freeAllowanceAmount}"); } - var symbolList = GetSymbolListSortedByExpirationTime(methodFeeFreeAllowancesMap, fromAddress); + var symbolList = GetSymbolListSortedByExpirationTime(transactionFeeFreeAllowancesMap, fromAddress); foreach (var s in symbolList) { if (addAmount >= 0) break; - if (!methodFeeFreeAllowancesMap.Map[s].Map.ContainsKey(symbol)) continue; + if (!transactionFeeFreeAllowancesMap.Map[s].Map.ContainsKey(symbol)) continue; - var currentAllowance = methodFeeFreeAllowancesMap.Map[s].Map[symbol].Amount; + var currentAllowance = transactionFeeFreeAllowancesMap.Map[s].Map[symbol].Amount; if (currentAllowance == 0) continue; addAmount += currentAllowance; - methodFeeFreeAllowancesMap.Map[s].Map[symbol].Amount = addAmount >= 0 ? addAmount : 0; + transactionFeeFreeAllowancesMap.Map[s].Map[symbol].Amount = addAmount >= 0 ? addAmount : 0; } } - private List GetSymbolListSortedByExpirationTime(MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, + private List GetSymbolListSortedByExpirationTime(TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, Address fromAddress) { - return methodFeeFreeAllowancesMap.Map.Keys.OrderBy(t => - State.MethodFeeFreeAllowancesConfigMap[t].RefreshSeconds - (Context.CurrentBlockTime - - State.MethodFeeFreeAllowancesLastRefreshTimes[ + return transactionFeeFreeAllowancesMap.Map.Keys.OrderBy(t => + State.TransactionFeeFreeAllowancesConfigMap[t].RefreshSeconds - (Context.CurrentBlockTime - + State.TransactionFeeFreeAllowancesLastRefreshTimes[ fromAddress][t]).Seconds).ToList(); } @@ -132,10 +132,10 @@ private long GetBalance(Address address, string symbol) // return freeAllowances?.Value.FirstOrDefault(a => a.Symbol == symbol); // } - private long GetFreeFeeAllowanceAmount(MethodFeeFreeAllowancesMap methodFeeFreeAllowancesMap, string symbol) + private long GetFreeFeeAllowanceAmount(TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, string symbol) { var allowance = 0L; - var map = methodFeeFreeAllowancesMap?.Map; + var map = transactionFeeFreeAllowancesMap?.Map; if (map == null) return allowance; diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index 5f1a67124c..a8aa1a9a06 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -77,10 +77,10 @@ service TokenContractImpl { rpc ChangeDeveloperController (AuthorityInfo) returns (google.protobuf.Empty) { } - rpc ConfigMethodFeeFreeAllowances (ConfigMethodFeeFreeAllowancesInput) returns (google.protobuf.Empty) { + rpc ConfigTransactionFeeFreeAllowances (ConfigTransactionFeeFreeAllowancesInput) returns (google.protobuf.Empty) { } - rpc RemoveMethodFeeFreeAllowancesConfig (RemoveMethodFeeFreeAllowancesConfigInput) returns (google.protobuf.Empty) { + rpc RemoveTransactionFeeFreeAllowancesConfig (RemoveTransactionFeeFreeAllowancesConfigInput) returns (google.protobuf.Empty) { } // Delegatee sets the delegation and related information of the delegator based on a transaction. @@ -148,10 +148,10 @@ service TokenContractImpl { } // Query - rpc GetMethodFeeFreeAllowances (aelf.Address) returns (MethodFeeFreeAllowancesMap) { + rpc GetTransactionFeeFreeAllowances (aelf.Address) returns (TransactionFeeFreeAllowancesMap) { option (aelf.is_view) = true; } - rpc GetMethodFeeFreeAllowancesConfig (google.protobuf.Empty) returns (GetMethodFeeFreeAllowancesConfigOutput) { + rpc GetTransactionFeeFreeAllowancesConfig (google.protobuf.Empty) returns (GetTransactionFeeFreeAllowancesConfigOutput) { option (aelf.is_view) = true; } @@ -295,42 +295,42 @@ message MethodFeeFreeAllowance { int64 amount = 2; } -message MethodFeeFreeAllowancesSymbolList { +message TransactionFeeFreeAllowancesSymbolList { repeated string symbols = 1; } -message ConfigMethodFeeFreeAllowancesInput { - repeated ConfigMethodFeeFreeAllowance value = 1; +message ConfigTransactionFeeFreeAllowancesInput { + repeated ConfigTransactionFeeFreeAllowance value = 1; } -message ConfigMethodFeeFreeAllowance { +message ConfigTransactionFeeFreeAllowance { string symbol = 1; MethodFeeFreeAllowances method_fee_free_allowances = 2; int64 refresh_seconds = 3; int64 threshold = 4; } -message RemoveMethodFeeFreeAllowancesConfigInput { +message RemoveTransactionFeeFreeAllowancesConfigInput { repeated string symbols = 1; } -message GetMethodFeeFreeAllowancesConfigOutput { - repeated FreeAllowanceConfig value = 1; +message GetTransactionFeeFreeAllowancesConfigOutput { + repeated TransactionFeeFreeAllowanceConfig value = 1; } -message FreeAllowanceConfig { +message TransactionFeeFreeAllowanceConfig { string symbol = 1; - MethodFeeFreeAllowanceMap free_allowances = 2; + TransactionFeeFreeAllowanceMap free_allowances = 2; int64 refresh_seconds = 3; int64 threshold = 4; } -message MethodFeeFreeAllowanceMap { +message TransactionFeeFreeAllowanceMap { map map = 1; } -message MethodFeeFreeAllowancesMap { - map map = 1; +message TransactionFeeFreeAllowancesMap { + map map = 1; } message SetTransactionFeeDelegateInfosInput{ // the delegator address diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs index c169957480..6785360c48 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs @@ -166,11 +166,11 @@ public async Task InitializeAuthorizedController_Test() } [Fact(DisplayName = "[MultiToken] illegal controller try to set free allowances")] - public async Task ConfigMethodFeeFreeAllowances_Without_Authorization_Test() + public async Task ConfigTransactionFeeFreeAllowances_Without_Authorization_Test() { - var configMethodFeeFreeAllowancesRet = - await TokenContractStub.ConfigMethodFeeFreeAllowances.SendWithExceptionAsync(new ConfigMethodFeeFreeAllowancesInput()); - configMethodFeeFreeAllowancesRet.TransactionResult.Error.ShouldContain("Unauthorized behavior."); + var configTransactionFeeFreeAllowancesRet = + await TokenContractStub.ConfigTransactionFeeFreeAllowances.SendWithExceptionAsync(new ConfigTransactionFeeFreeAllowancesInput()); + configTransactionFeeFreeAllowancesRet.TransactionResult.Error.ShouldContain("Unauthorized behavior."); } [Fact] diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 5db2237857..2646206854 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -300,11 +300,11 @@ public async Task FreeAllowancesTest(long threshold, long initialBalance, long f await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -340,7 +340,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); { - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); if (threshold <= initialBalance) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -384,7 +384,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, chargeFeeRet.Output.Success.ShouldBe(true); { - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); if (threshold <= initialBalance) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -428,11 +428,11 @@ public async Task FreeAllowances_MultToken_Test( } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { MethodFeeFreeAllowances = new MethodFeeFreeAllowances { @@ -495,7 +495,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); { - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); if (threshold <= initialBalance) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -524,7 +524,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, chargeFeeRet.Output.Success.ShouldBe(true); { - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); if (threshold <= initialBalance) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -614,11 +614,11 @@ public async Task ChargeTransactionFee_Delegate( } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { MethodFeeFreeAllowances = new MethodFeeFreeAllowances { @@ -643,7 +643,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } }); { - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(userAddress); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(userAddress); if (threshold <= initialBalance) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -822,11 +822,11 @@ await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransacti } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { MethodFeeFreeAllowances = new MethodFeeFreeAllowances { @@ -1159,11 +1159,11 @@ public async Task ChargeTransactionFee_DelegateNew_First( } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, RefreshSeconds = 100, @@ -1188,7 +1188,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } }); { - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(userAddress); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(userAddress); if (threshold <= initialBalance) { freeAllowances.Map.First().Value.Map.Values.First().Symbol.ShouldBe(basicFeeSymbol); diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index 14ad8b124a..a212bf6b8c 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -12,16 +12,16 @@ namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; public partial class ExecutePluginTransactionDirectlyTest { [Fact] - public async Task ConfigMethodFeeFreeAllowances_Test() + public async Task ConfigTransactionFeeFreeAllowances_Test() { await SetPrimaryTokenSymbolAsync(); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -42,7 +42,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }); { - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + var config = await TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Value.Count.ShouldBe(1); config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().Threshold.ShouldBe(0); @@ -51,7 +51,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(0); - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); @@ -60,11 +60,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 2_00000000); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -85,7 +85,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }); { - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + var config = await TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Value.Count.ShouldBe(1); config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().Threshold.ShouldBe(1_00000000); @@ -94,7 +94,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); @@ -103,26 +103,26 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } [Fact] - public async Task ConfigMethodFeeFreeAllowances_Unauthorized_Test() + public async Task ConfigTransactionFeeFreeAllowances_Unauthorized_Test() { var result = - await TokenContractImplStub.ConfigMethodFeeFreeAllowances.SendWithExceptionAsync( - new ConfigMethodFeeFreeAllowancesInput()); + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendWithExceptionAsync( + new ConfigTransactionFeeFreeAllowancesInput()); result.TransactionResult.Error.ShouldContain("Unauthorized behavior."); } [Fact] - public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_OneByOne_Test() + public async Task ConfigTransactionFeeFreeAllowances_MultipleTokens_OneByOne_Test() { await SetPrimaryTokenSymbolAsync(); await CreateTokenAndIssueAsync(); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -143,7 +143,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }); { - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + var config = await TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Value.Count.ShouldBe(1); config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().Threshold.ShouldBe(1_00000000); @@ -152,23 +152,23 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, config.Value.First().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + var userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + var userBFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserBAddress); userBFreeAllowances.Result.Map.Count.ShouldBe(0); - var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + var userCFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserCAddress); userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -189,7 +189,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }); { - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + var config = await TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Value.Count.ShouldBe(2); config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().Threshold.ShouldBe(1_00000000); @@ -205,36 +205,36 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + var userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(1); userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + var userBFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserBAddress); userBFreeAllowances.Result.Map.Count.ShouldBe(1); userBFreeAllowances.Result.Map.Keys.First().ShouldBe(USDT); userBFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + var userCFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserCAddress); userAFreeAllowances.Result.Map.Add(USDT, userBFreeAllowances.Result.Map.Values.First()); userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); } } [Fact] - public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test() + public async Task ConfigTransactionFeeFreeAllowances_MultipleTokens_AtOnce_Test() { await SetPrimaryTokenSymbolAsync(); await CreateTokenAndIssueAsync(); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -251,7 +251,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, RefreshSeconds = 600, Threshold = 1_00000000 }, - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -271,7 +271,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } }); - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + var config = await TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Value.Count.ShouldBe(2); config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().Threshold.ShouldBe(1_00000000); @@ -287,35 +287,35 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, config.Value.Last().FreeAllowances.Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.Last().FreeAllowances.Map.Values.First().Amount.ShouldBe(1_00000000); - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + var userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(1); userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + var userBFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserBAddress); userBFreeAllowances.Result.Map.Count.ShouldBe(1); userBFreeAllowances.Result.Map.Keys.First().ShouldBe(USDT); userBFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); userBFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + var userCFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserCAddress); userAFreeAllowances.Result.Map.Add(USDT, userBFreeAllowances.Result.Map.Values.First()); userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); } [Fact] - public async Task ConfigMethodFeeFreeAllowances_MultipleTokens_Modify_Test() + public async Task ConfigTransactionFeeFreeAllowances_MultipleTokens_Modify_Test() { - await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + await ConfigTransactionFeeFreeAllowances_MultipleTokens_AtOnce_Test(); await CreateTokenAsync(DefaultSender, "ABC"); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -340,7 +340,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } }); - var config = await TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + var config = await TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Value.Count.ShouldBe(2); config.Value.First().Symbol.ShouldBe(NativeTokenSymbol); config.Value.First().Threshold.ShouldBe(1_00000000); @@ -359,37 +359,37 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, config.Value.Last().FreeAllowances.Map.Values.Last().Symbol.ShouldBe("ABC"); config.Value.Last().FreeAllowances.Map.Values.Last().Amount.ShouldBe(2_00000000); - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + var userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(1); userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); userAFreeAllowances.Result.Map.Values.First().Map.Values.First().Amount.ShouldBe(1_00000000); - var userBFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserBAddress); + var userBFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserBAddress); userBFreeAllowances.Result.Map.Count.ShouldBe(0); - var userCFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserCAddress); + var userCFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserCAddress); userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); } [Fact] - public async Task ConfigMethodFeeFreeAllowances_InvalidInput_Test() + public async Task ConfigTransactionFeeFreeAllowances_InvalidInput_Test() { var message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance() + new ConfigTransactionFeeFreeAllowance() } }); message.ShouldContain("Invalid input symbol"); message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = "TEST" } @@ -398,11 +398,11 @@ public async Task ConfigMethodFeeFreeAllowances_InvalidInput_Test() message.ShouldContain("Symbol TEST not exist"); message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol } @@ -411,11 +411,11 @@ public async Task ConfigMethodFeeFreeAllowances_InvalidInput_Test() message.ShouldContain("Invalid input allowances"); message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -436,11 +436,11 @@ public async Task ConfigMethodFeeFreeAllowances_InvalidInput_Test() message.ShouldContain("Invalid input threshold"); message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -463,101 +463,101 @@ public async Task ConfigMethodFeeFreeAllowances_InvalidInput_Test() } [Fact] - public async Task RemoveMethodFeeFreeAllowancesConfig_Unauthorized_Test() + public async Task RemoveTransactionFeeFreeAllowancesConfig_Unauthorized_Test() { var result = - await TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig.SendWithExceptionAsync( - new RemoveMethodFeeFreeAllowancesConfigInput()); + await TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig.SendWithExceptionAsync( + new RemoveTransactionFeeFreeAllowancesConfigInput()); result.TransactionResult.Error.ShouldContain("Unauthorized behavior."); } [Fact] - public async Task RemoveMethodFeeFreeAllowancesConfig_Test() + public async Task RemoveTransactionFeeFreeAllowancesConfig_Test() { - await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + await ConfigTransactionFeeFreeAllowances_MultipleTokens_AtOnce_Test(); await IssueTokenToUserAsync(USDT, 1_000000, UserAAddress); - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + var userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(2); - var config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + var config = TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Result.Value.Count.ShouldBe(2); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput + nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + new RemoveTransactionFeeFreeAllowancesConfigInput { Symbols = { USDT } }); - config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config = TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Result.Value.Count.ShouldBe(1); config.Result.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(1); userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); // symbol not exist await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput + nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + new RemoveTransactionFeeFreeAllowancesConfigInput { Symbols = { USDT } }); - config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config = TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Result.Value.Count.ShouldBe(1); config.Result.Value.First().Symbol.ShouldBe(NativeTokenSymbol); - userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(1); userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); // Duplicate symbols await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput + nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + new RemoveTransactionFeeFreeAllowancesConfigInput { Symbols = { "ELF", "ELF" } }); - config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + config = TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Result.Value.Count.ShouldBe(0); - userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(0); } [Fact] - public async Task RemoveMethodFeeFreeAllowancesConfig_MultipleTokens_AtOnce_Test() + public async Task RemoveTransactionFeeFreeAllowancesConfig_MultipleTokens_AtOnce_Test() { - await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + await ConfigTransactionFeeFreeAllowances_MultipleTokens_AtOnce_Test(); await IssueTokenToUserAsync(USDT, 1_000000, UserAAddress); - var userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + var userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(2); - var config = TokenContractImplStub.GetMethodFeeFreeAllowancesConfig.CallAsync(new Empty()); + var config = TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Result.Value.Count.ShouldBe(2); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput + nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + new RemoveTransactionFeeFreeAllowancesConfigInput { Symbols = { "ELF", USDT } }); - userAFreeAllowances = TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(UserAAddress); + userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(0); } [Fact] - public async Task RemoveMethodFeeFreeAllowancesConfig_InvalidInput_Test() + public async Task RemoveTransactionFeeFreeAllowancesConfig_InvalidInput_Test() { var message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput + nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + new RemoveTransactionFeeFreeAllowancesConfigInput { Symbols = { USDT } }); message.ShouldContain("Method fee free allowances config not set"); - await ConfigMethodFeeFreeAllowances_MultipleTokens_AtOnce_Test(); + await ConfigTransactionFeeFreeAllowances_MultipleTokens_AtOnce_Test(); message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveMethodFeeFreeAllowancesConfig), - new RemoveMethodFeeFreeAllowancesConfigInput()); + nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + new RemoveTransactionFeeFreeAllowancesConfigInput()); message.ShouldContain("Invalid input"); } @@ -577,11 +577,11 @@ public async Task ChargeTransactionFee_Test(long initialELFBalance, long initial await IssueTokenToDefaultSenderAsync(USDT, initialUSDTBalance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -598,7 +598,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, RefreshSeconds = refreshSecondsELF, Threshold = thresholdELF }, - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -633,7 +633,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); @@ -652,7 +652,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); @@ -690,11 +690,11 @@ public async Task ChargeTransactionFee_MultipleTokens_Test(long initialELFBalanc await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -711,7 +711,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, RefreshSeconds = refreshSecondsELF, Threshold = thresholdELF }, - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -767,7 +767,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); if (initialELFBalance >= thresholdELF) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -796,7 +796,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, chargeFeeRet.Output.Success.ShouldBe(initialToken1Balance + freeAmountELF >= sizeFee); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); if (initialELFBalance >= thresholdELF) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -889,11 +889,11 @@ public async Task ChargeTransactionFee_SingleThreshold_Test(long initialBalance, await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -954,7 +954,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); @@ -977,7 +977,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, chargeFeeRet.Output.Success.ShouldBe(true); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); @@ -1011,11 +1011,11 @@ public async Task ChargeTransactionFee_NotEnough_Test(long initialELFBalance, lo await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -1032,7 +1032,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, RefreshSeconds = refreshSecondsELF, Threshold = thresholdELF }, - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -1088,7 +1088,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); @@ -1110,7 +1110,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, chargeFeeRet.Output.Success.ShouldBe(false); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.Last().ShouldBe(USDT); freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(Token2); @@ -1132,11 +1132,11 @@ public async Task ChargeTransactionFee_ClearFreeAllowance_Test(long initialBalan await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -1186,7 +1186,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); @@ -1203,7 +1203,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); @@ -1224,7 +1224,7 @@ await TokenContractStub.Transfer.SendAsync(new TransferInput await CheckDefaultSenderTokenAsync(NativeTokenSymbol, secondBalance); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.ShouldBeEmpty(); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, transferAmount + sizeFee + basicFee); @@ -1234,7 +1234,7 @@ await TokenContractStub.Transfer.SendAsync(new TransferInput await CheckDefaultSenderTokenAsync(NativeTokenSymbol, thirdBalance); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); @@ -1256,11 +1256,11 @@ public async Task ChargeTransactionFee_RefreshTime_Test() await IssueTokenToDefaultSenderAsync(Token2, 10000); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -1277,7 +1277,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, RefreshSeconds = 2, Threshold = 100 }, - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -1333,7 +1333,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); @@ -1355,7 +1355,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); @@ -1374,7 +1374,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); @@ -1395,7 +1395,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); @@ -1426,11 +1426,11 @@ public async Task ChargeTransactionFee_FreeAllowanceFirst_Test(long initialBalan await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -1491,7 +1491,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); @@ -1508,7 +1508,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(Token1); @@ -1555,11 +1555,11 @@ public async Task ChargeTransactionFee_MultipleTxFeeTokens_Test(long initialELFB await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigMethodFeeFreeAllowances), new ConfigMethodFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { Value = { - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -1581,7 +1581,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, RefreshSeconds = refreshSecondsELF, Threshold = thresholdELF }, - new ConfigMethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { Symbol = USDT, MethodFeeFreeAllowances = new MethodFeeFreeAllowances @@ -1652,7 +1652,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - var freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); if (initialELFBalance >= thresholdELF) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -1688,7 +1688,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(chargeFeeResult); - freeAllowances = await TokenContractImplStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); if (afterELFBalance >= thresholdELF) { freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); From 601c5555c738e25ee3635baf4c0eb208c66023e6 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Tue, 13 Jun 2023 10:24:19 +0800 Subject: [PATCH 032/139] feat: adjust delegate charge transaction fee logic. --- .../TokenContract_Fees.cs | 64 ++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index f54cbffcef..85e0d34636 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -442,11 +442,9 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) @@ -456,6 +454,12 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List= txSizeFeeAmount) { @@ -463,8 +467,10 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List 0) + { + availableSymbolWithAnything ??= symbolToPlayTxSizeFee; + } if (balancePlusAllowance < txSizeFeeAmount) continue; availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbolToPlayTxSizeFee; @@ -475,21 +481,8 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List - { - var delegationEnough = IsDelegationEnoughBaseOnPrimaryToken(x, symbolChargedForBaseFee, - amountChargedForBaseFee.Add(amountChargedForBaseAllowance), txSizeFeeAmount, delegations); - var balance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, x, - symbolChargedForBaseFee, amountChargedForBaseFee, transactionFeeFreeAllowancesMap, - amountChargedForBaseAllowance); - return delegationEnough && balance >= txSizeFeeAmount; - }); - } - return availableSymbol; + return availableSymbol; } private void GenerateBill(long txSizeFeeAmount, string symbolToPayTxFee, string symbolChargedForBaseFee, @@ -779,6 +772,8 @@ private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountM amount = 0; existingBalance = 0; existingAllowance = 0; + string symbolWithBalancePlusAllowanceEnoughToPayTxFee = null; + string symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; //Find the token that satisfies the delegate limit and satisfies the balance of the fee foreach (var (symbol, value) in symbolToAmountMap) { @@ -786,19 +781,30 @@ private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountM amount = value; existingBalance = GetBalance(fromAddress, symbol); existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); - // is unlimited delegate is true && balance enough - // is unlimited delegate is false && delegation enough && balance enough - if (existingBalance.Add(existingAllowance) < amount) continue; + // is unlimited delegate is true || is unlimited delegate is false and delegation is enough if (delegations.IsUnlimitedDelegate || (!delegations.IsUnlimitedDelegate && - delegations.Delegations.ContainsKey(symbol) - && delegations.Delegations[symbol] >= amount)) + delegations.Delegations.ContainsKey(symbol) && delegations.Delegations[symbol] >= amount)) { - symbolOfValidBalance = symbol; - return true; + //If allowance is enough,return true + if (existingAllowance >= amount) + { + symbolOfValidBalance = symbol; + return true; + } + + //Find symbol which balance+allowance >= amount + if (existingBalance.Add(existingAllowance) < amount) continue; + symbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbol; + //If balance+allowance is enough,priority find the symbol which allowance > 0 + if (existingAllowance <= 0) continue; + symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbol; } } - return false; + symbolOfValidBalance = symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? + symbolWithBalancePlusAllowanceEnoughToPayTxFee; + + return symbolOfValidBalance != null; } public override Empty ClaimTransactionFees(TotalTransactionFeesMap input) From d0859e85fcb4f3e484d49decf2032076d223c7d9 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Tue, 13 Jun 2023 11:53:22 +0800 Subject: [PATCH 033/139] feat: format code and merge secondary-delegate --- .../TokenContract_Fees.cs | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index e06c2cf70f..6aada0e858 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -448,43 +448,44 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 - foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) + // get 1st Allowance > size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 + foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) + { + var allowance = GetAllowanceCalculatedBaseOnPrimaryToken(symbolToPlayTxSizeFee, + transactionFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseAllowance); + var balancePlusAllowance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, + symbolToPlayTxSizeFee, symbolChargedForBaseFee, amountChargedForBaseFee, + transactionFeeFreeAllowancesMap, amountChargedForBaseAllowance); + if (delegations != null) { - var allowance = GetAllowanceCalculatedBaseOnPrimaryToken(symbolToPlayTxSizeFee, - transactionFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseAllowance); - var balancePlusAllowance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, - symbolToPlayTxSizeFee, symbolChargedForBaseFee, amountChargedForBaseFee, - transactionFeeFreeAllowancesMap, amountChargedForBaseAllowance); - if (delegations != null) - { - var delegationEnough = IsDelegationEnoughBaseOnPrimaryToken(symbolToPlayTxSizeFee, - symbolChargedForBaseFee, amountChargedForBaseFee.Add(amountChargedForBaseAllowance), txSizeFeeAmount, delegations); - if (!delegationEnough) break; - } + var delegationEnough = IsDelegationEnoughBaseOnPrimaryToken(symbolToPlayTxSizeFee, + symbolChargedForBaseFee, amountChargedForBaseFee.Add(amountChargedForBaseAllowance), + txSizeFeeAmount, delegations); + if (!delegationEnough) break; + } - if (allowance >= txSizeFeeAmount) - { - availableSymbol = symbolToPlayTxSizeFee; - break; - } + if (allowance >= txSizeFeeAmount) + { + availableSymbol = symbolToPlayTxSizeFee; + break; + } - if (delegations == null && balancePlusAllowance > 0) - { - availableSymbolWithAnything ??= symbolToPlayTxSizeFee; - } + if (delegations == null && balancePlusAllowance > 0) + { + availableSymbolWithAnything ??= symbolToPlayTxSizeFee; + } - if (balancePlusAllowance < txSizeFeeAmount) continue; - availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbolToPlayTxSizeFee; + if (balancePlusAllowance < txSizeFeeAmount) continue; + availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbolToPlayTxSizeFee; - if (allowance <= 0) continue; - availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbolToPlayTxSizeFee; - } + if (allowance <= 0) continue; + availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbolToPlayTxSizeFee; + } - availableSymbol ??= availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? - availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ?? availableSymbolWithAnything; + availableSymbol ??= availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? + availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee ?? availableSymbolWithAnything; - return availableSymbol; + return availableSymbol; } private void GenerateBill(long txSizeFeeAmount, string symbolToPayTxFee, string symbolChargedForBaseFee, @@ -698,7 +699,6 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM { existingBalance = GetBalance(fromAddress, symbol); existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); - } //For user, if charge failed and delegation is null, priority charge primary token @@ -1299,7 +1299,8 @@ private long GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(Address fromAdd long cost, TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, long allowanceCost) { return GetBalanceCalculatedBaseOnPrimaryToken(fromAddress, tokenInfo, baseSymbol, cost).Add( - GetAllowanceCalculatedBaseOnPrimaryToken(tokenInfo, transactionFeeFreeAllowancesMap, baseSymbol, allowanceCost)); + GetAllowanceCalculatedBaseOnPrimaryToken(tokenInfo, transactionFeeFreeAllowancesMap, baseSymbol, + allowanceCost)); } private long GetAllowanceCalculatedBaseOnPrimaryToken(SymbolToPayTxSizeFee tokenInfo, From b736c4b59853a5c582897f1e9a71cdc7f21ee7eb Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 13 Jun 2023 17:19:29 +0800 Subject: [PATCH 034/139] feat: adjust code structure --- .../ElectionContractState.cs | 4 ++ .../ElectionContract_Elector.cs | 69 ++++++++++++------- .../AElf.Contracts.Election/ViewMethods.cs | 24 ++++--- protobuf/election_contract.proto | 2 + .../BVT/ElectionViewTests.cs | 7 +- 5 files changed, 69 insertions(+), 37 deletions(-) diff --git a/contract/AElf.Contracts.Election/ElectionContractState.cs b/contract/AElf.Contracts.Election/ElectionContractState.cs index 90920ac79d..fa6ebc6089 100644 --- a/contract/AElf.Contracts.Election/ElectionContractState.cs +++ b/contract/AElf.Contracts.Election/ElectionContractState.cs @@ -15,7 +15,11 @@ public partial class ElectionContractState : ContractState public SingletonState FlexibleHash { get; set; } public SingletonState WelcomeHash { get; set; } + // Pubkey -> ElectorVote public MappedState ElectorVotes { get; set; } + + // Address -> ElectorVote + public MappedState ElectorVotesByAddress { get; set; } public MappedState CandidateVotes { get; set; } diff --git a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs index a021802fb6..233cacaa80 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs @@ -129,7 +129,7 @@ private void ExtendVoterWelfareProfits(Hash voteId) { var treasury = State.ProfitContract.GetScheme.Call(State.TreasuryHash.Value); var electionVotingRecord = GetElectionVotingRecordByVoteId(voteId); - + // Extend endPeriod from now no, so the lockTime will *NOT* be changed. var lockTime = State.LockTimeMap[voteId]; var lockPeriod = lockTime.Div(State.TimeEachTerm.Value); @@ -182,7 +182,7 @@ private ProfitDetail GetProfitDetailByElectionVotingRecord(ElectionVotingRecord { profitDetail = profitDetails.Details.LastOrDefault(d => d.Shares == electionVotingRecord.Weight); } - + return profitDetail; } @@ -499,14 +499,14 @@ private void TryToBecomeAValidationDataCenter(VoteMinerInput input, long candida /// private void UpdateElectorInformation(byte[] recoveredPublicKey, long amount, Hash voteId) { - var voterPublicKey = recoveredPublicKey.ToHex(); - var voterPublicKeyByteString = ByteString.CopyFrom(recoveredPublicKey); - var voterVotes = State.ElectorVotes[voterPublicKey]; + var voterVotes = GetElectorVote(recoveredPublicKey); + if (voterVotes == null) { voterVotes = new ElectorVote { - Pubkey = voterPublicKeyByteString, + Address = Context.Sender, + Pubkey = recoveredPublicKey != null ? ByteString.CopyFrom(recoveredPublicKey) : null, ActiveVotingRecordIds = { voteId }, ActiveVotedVotesAmount = amount, AllVotedVotesAmount = amount @@ -517,9 +517,31 @@ private void UpdateElectorInformation(byte[] recoveredPublicKey, long amount, Ha voterVotes.ActiveVotingRecordIds.Add(voteId); voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Add(amount); voterVotes.AllVotedVotesAmount = voterVotes.AllVotedVotesAmount.Add(amount); + voterVotes.Address ??= Context.Sender; } - State.ElectorVotes[voterPublicKey] = voterVotes; + State.ElectorVotesByAddress[Context.Sender.ToBase58()] = voterVotes; + } + + private ElectorVote GetElectorVote(byte[] recoveredPublicKey) + { + var voteVotes = State.ElectorVotesByAddress[Context.Sender.ToBase58()]; + if (voteVotes != null) return voteVotes; + + if (recoveredPublicKey != null) + { + var publicKey = recoveredPublicKey.ToHex(); + + voteVotes = State.ElectorVotes[publicKey]?.Clone(); + + if (voteVotes != null) + { + State.ElectorVotes.Remove(publicKey); + return voteVotes; + } + } + + return null; } /// @@ -619,25 +641,26 @@ public override Empty Withdraw(Hash input) var claimedLockDays = State.LockTimeMap[input]; Assert(actualLockedTime >= claimedLockDays, $"Still need {claimedLockDays.Sub(actualLockedTime).Div(86400)} days to unlock your token."); + + var voterPublicKey = Context.RecoverPublicKey(); - // Update Elector's Votes information. - var voterPublicKey = Context.RecoverPublicKey().ToHex(); - var voterVotes = State.ElectorVotes[voterPublicKey]; - if (voterVotes == null) throw new AssertionException($"Voter {voterPublicKey} never votes before."); + var voterVotes = GetElectorVote(voterPublicKey); - voterVotes.ActiveVotingRecordIds.Remove(input); + Assert(voterVotes != null, $"Voter {Context.Sender.ToBase58()} never votes before"); + + voterVotes!.ActiveVotingRecordIds.Remove(input); voterVotes.WithdrawnVotingRecordIds.Add(input); voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Sub(votingRecord.Amount); - State.ElectorVotes[voterPublicKey] = voterVotes; + voterVotes.Address ??= Context.Sender; + State.ElectorVotesByAddress[Context.Sender.ToBase58()] = voterVotes; // Update Candidate's Votes information. var newestPubkey = GetNewestPubkey(votingRecord.Option); var candidateVotes = State.CandidateVotes[newestPubkey]; - if (candidateVotes == null) - throw new AssertionException( - $"Newest pubkey {newestPubkey} is invalid. Old pubkey is {votingRecord.Option}"); + + Assert(candidateVotes != null, $"Newest pubkey {newestPubkey} is invalid. Old pubkey is {votingRecord.Option}"); - candidateVotes.ObtainedActiveVotingRecordIds.Remove(input); + candidateVotes!.ObtainedActiveVotingRecordIds.Remove(input); candidateVotes.ObtainedWithdrawnVotingRecordIds.Add(input); candidateVotes.ObtainedActiveVotedVotesAmount = candidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount); @@ -744,12 +767,12 @@ private void NotifyProfitReplaceCandidateInDataCenter(string oldCandidateInDataC #region subsidy helper - private Hash GenerateSubsidyId(string pubkey,Address beneficiaryAddress) + private Hash GenerateSubsidyId(string pubkey, Address beneficiaryAddress) { return HashHelper.ConcatAndCompute(HashHelper.ComputeFrom(pubkey), HashHelper.ComputeFrom(beneficiaryAddress), HashHelper.ComputeFrom(Context.Self)); } - + private Address GetProfitsReceiverOrDefault(string pubkey) { if (State.TreasuryContract.Value == null) @@ -765,7 +788,7 @@ private Address GetProfitsReceiverOrDefault(string pubkey) private void AddBeneficiary(string candidatePubkey, Address profitsReceiver = null) { var beneficiaryAddress = GetBeneficiaryAddress(candidatePubkey, profitsReceiver); - var subsidyId = GenerateSubsidyId(candidatePubkey,beneficiaryAddress); + var subsidyId = GenerateSubsidyId(candidatePubkey, beneficiaryAddress); State.ProfitContract.AddBeneficiary.Send(new AddBeneficiaryInput { SchemeId = State.SubsidyHash.Value, @@ -778,10 +801,10 @@ private void AddBeneficiary(string candidatePubkey, Address profitsReceiver = nu }); } - private void RemoveBeneficiary(string candidatePubkey,Address profitsReceiver = null) + private void RemoveBeneficiary(string candidatePubkey, Address profitsReceiver = null) { var beneficiaryAddress = GetBeneficiaryAddress(candidatePubkey, profitsReceiver); - var previousSubsidyId = GenerateSubsidyId(candidatePubkey,beneficiaryAddress); + var previousSubsidyId = GenerateSubsidyId(candidatePubkey, beneficiaryAddress); State.ProfitContract.RemoveBeneficiary.Send(new RemoveBeneficiaryInput { SchemeId = State.SubsidyHash.Value, @@ -798,6 +821,6 @@ private Address GetBeneficiaryAddress(string candidatePubkey, Address profitsRec : Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(candidatePubkey)); return beneficiaryAddress; } - + #endregion } \ No newline at end of file diff --git a/contract/AElf.Contracts.Election/ViewMethods.cs b/contract/AElf.Contracts.Election/ViewMethods.cs index e3f318e211..85315fbbd7 100644 --- a/contract/AElf.Contracts.Election/ViewMethods.cs +++ b/contract/AElf.Contracts.Election/ViewMethods.cs @@ -161,20 +161,26 @@ private TermSnapshot GetPreviousTermSnapshotWithNewestPubkey() public override ElectorVote GetElectorVote(StringValue input) { - return State.ElectorVotes[input.Value] ?? new ElectorVote + Assert(input.Value != null && input.Value.Length > 1, "Invalid input."); + + var voterVotes = AddressHelper.VerifyFormattedAddress(input.Value) ? State.ElectorVotesByAddress[input.Value] : State.ElectorVotes[input.Value]; + + if (voterVotes == null) { - Pubkey = ByteStringHelper.FromHexString(input.Value) - }; + voterVotes = State.ElectorVotesByAddress[ + Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Value)).ToBase58()]; + } + + return voterVotes ?? new ElectorVote(); } public override ElectorVote GetElectorVoteWithRecords(StringValue input) { - var votes = State.ElectorVotes[input.Value]; - if (votes == null) - return new ElectorVote - { - Pubkey = ByteStringHelper.FromHexString(input.Value) - }; + var votes = GetElectorVote(input); + + if (votes.Address == null && votes.Pubkey == null) + return votes; + var votedRecords = State.VoteContract.GetVotingRecords.Call(new GetVotingRecordsInput { Ids = { votes.ActiveVotingRecordIds } diff --git a/protobuf/election_contract.proto b/protobuf/election_contract.proto index 099a56590f..9720786297 100644 --- a/protobuf/election_contract.proto +++ b/protobuf/election_contract.proto @@ -341,6 +341,8 @@ message ElectorVote { repeated ElectionVotingRecord withdrawn_votes_records = 6; // Public key for voter. bytes pubkey = 7; + // Address for voter + aelf.Address address = 8; } message CandidateVote { diff --git a/test/AElf.Contracts.Election.Tests/BVT/ElectionViewTests.cs b/test/AElf.Contracts.Election.Tests/BVT/ElectionViewTests.cs index 61d8128ced..a8d4093af4 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/ElectionViewTests.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/ElectionViewTests.cs @@ -47,10 +47,7 @@ public async Task GetElectorVoteWithRecords_NotExist_Test() { Value = ValidationDataCenterKeyPairs.Last().PublicKey.ToHex() }); - voteRecords.ShouldBe(new ElectorVote - { - Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs.Last().PublicKey) - }); + voteRecords.ShouldBe(new ElectorVote()); } [Fact] @@ -305,7 +302,7 @@ public async Task Election_GetElectorVote_Test() { Value = key }); - ret.ShouldBe(new ElectorVote { Pubkey = ByteStringHelper.FromHexString(key) }); + ret.ShouldBe(new ElectorVote()); } [Fact] From 6809337aaacccfde389d786c1f6090b5a9de5c0c Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 13 Jun 2023 17:32:38 +0800 Subject: [PATCH 035/139] feat: add TransactionFeeFreeAllowances and TransactionFeeFreeAllowance --- .../TokenContract_Fees.cs | 4 +- protobuf/token_contract_impl.proto | 13 ++- .../ExecutePluginTransactionDirectlyTest.cs | 28 +++--- ...inTransactionDirectlyTest_FreeAllowance.cs | 96 +++++++++---------- 4 files changed, 75 insertions(+), 66 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 6aada0e858..89eaff04a5 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -1163,7 +1163,7 @@ public override Empty ConfigTransactionFeeFreeAllowances(ConfigTransactionFeeFre { ValidateToken(allowances.Symbol); Assert( - allowances.MethodFeeFreeAllowances?.Value != null && allowances.MethodFeeFreeAllowances.Value.Count > 0, + allowances.TransactionFeeFreeAllowances?.Value != null && allowances.TransactionFeeFreeAllowances.Value.Count > 0, "Invalid input allowances"); Assert(allowances.Threshold >= 0, "Invalid input threshold"); Assert(allowances.RefreshSeconds >= 0, "Invalid input refresh seconds"); @@ -1176,7 +1176,7 @@ public override Empty ConfigTransactionFeeFreeAllowances(ConfigTransactionFeeFre FreeAllowances = new TransactionFeeFreeAllowanceMap() }; - foreach (var allowance in allowances.MethodFeeFreeAllowances!.Value!) + foreach (var allowance in allowances.TransactionFeeFreeAllowances!.Value!) { config.FreeAllowances.Map.TryAdd(allowance.Symbol, allowance); } diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index a8aa1a9a06..d2880fc51f 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -295,6 +295,15 @@ message MethodFeeFreeAllowance { int64 amount = 2; } +message TransactionFeeFreeAllowances{ + repeated TransactionFeeFreeAllowance value = 1; +} + +message TransactionFeeFreeAllowance { + string symbol = 1; + int64 amount = 2; +} + message TransactionFeeFreeAllowancesSymbolList { repeated string symbols = 1; } @@ -305,7 +314,7 @@ message ConfigTransactionFeeFreeAllowancesInput { message ConfigTransactionFeeFreeAllowance { string symbol = 1; - MethodFeeFreeAllowances method_fee_free_allowances = 2; + TransactionFeeFreeAllowances transaction_fee_free_allowances = 2; int64 refresh_seconds = 3; int64 threshold = 4; } @@ -326,7 +335,7 @@ message TransactionFeeFreeAllowanceConfig { } message TransactionFeeFreeAllowanceMap { - map map = 1; + map map = 1; } message TransactionFeeFreeAllowancesMap { diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 2646206854..5df347a0be 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -307,11 +307,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = freeAmount @@ -434,16 +434,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new ConfigTransactionFeeFreeAllowance { - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = basicFeeSymbol, Amount = baseFeeFreeAmount }, - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = sizeFeeSymbol, Amount = sizeFeeFreeAmount @@ -620,16 +620,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new ConfigTransactionFeeFreeAllowance { - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = basicFeeSymbol, Amount = baseFeeFreeAmount }, - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = sizeFeeSymbol, Amount = sizeFeeFreeAmount @@ -828,16 +828,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, { new ConfigTransactionFeeFreeAllowance { - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = basicFeeSymbol, Amount = baseFeeFreeAmount }, - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = sizeFeeSymbol, Amount = sizeFeeFreeAmount @@ -1168,16 +1168,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, Symbol = NativeTokenSymbol, RefreshSeconds = 100, Threshold = threshold, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = basicFeeSymbol, Amount = baseFeeFreeAmount }, - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = sizeFeeSymbol, Amount = sizeFeeFreeAmount diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index a212bf6b8c..4794b14c42 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -24,11 +24,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = 0 @@ -67,11 +67,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = 1_00000000 @@ -125,11 +125,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = 1_00000000 @@ -171,11 +171,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = USDT, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = 1_00000000 @@ -237,11 +237,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = 1_00000000 @@ -254,11 +254,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = USDT, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = 1_00000000 @@ -318,16 +318,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = USDT, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = 2_00000000 }, - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = "ABC", Amount = 2_00000000 @@ -418,11 +418,11 @@ public async Task ConfigTransactionFeeFreeAllowances_InvalidInput_Test() new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = 1_00000000 @@ -443,11 +443,11 @@ public async Task ConfigTransactionFeeFreeAllowances_InvalidInput_Test() new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = 1_00000000 @@ -584,11 +584,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = freeAmountELF @@ -601,11 +601,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = USDT, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = freeAmountUSDT @@ -697,11 +697,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = Token1, Amount = freeAmountELF @@ -714,11 +714,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = USDT, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = Token2, Amount = freeAmountUSDT @@ -896,16 +896,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = Token1, Amount = freeAmountTokenA }, - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = Token2, Amount = freeAmountTokenB @@ -1018,11 +1018,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = Token1, Amount = freeAmountELF @@ -1035,11 +1035,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = USDT, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = Token2, Amount = freeAmountUSDT @@ -1139,11 +1139,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, Amount = freeAmount @@ -1263,11 +1263,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = Token1, Amount = 1000 @@ -1280,11 +1280,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = USDT, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = Token2, Amount = 1000 @@ -1433,11 +1433,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = Token1, Amount = freeAmount @@ -1562,16 +1562,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = NativeTokenSymbol, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = firstFreeSymbolELF, Amount = firstFreeAmountELF }, - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = secondFreeSymbolELF, Amount = secondFreeAmountELF @@ -1584,16 +1584,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, new ConfigTransactionFeeFreeAllowance { Symbol = USDT, - MethodFeeFreeAllowances = new MethodFeeFreeAllowances + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { Value = { - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = firstFreeSymbolUSDT, Amount = firstFreeAmountUSDT }, - new MethodFeeFreeAllowance + new TransactionFeeFreeAllowance { Symbol = secondFreeSymbolUSDT, Amount = secondFreeAmountUSDT From afac3d6f8be77d1f7631f679a5c964c76a895662 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Tue, 13 Jun 2023 20:04:26 +0800 Subject: [PATCH 036/139] feat: add vrf random hash --- .../AEDPoSContract.cs | 3 +- ...tract_ACS4_ConsensusInformationProvider.cs | 41 +++++++++++-- .../AEDPoSContract_NextTerm.cs | 2 +- ...PoSContract_ProcessConsensusInformation.cs | 55 +++++++++++++---- ...und_ExtractInformationToUpdateConsensus.cs | 6 +- protobuf/aedpos_contract.proto | 60 ++++++++++++++++++- .../BlockMiningService.cs | 8 +-- .../AElf.Kernel.Consensus.AEDPoS.csproj | 6 +- .../Application/AEDPoSInformationProvider.cs | 11 +++- .../AEDPoSTriggerInformationProvider.cs | 19 ++++-- .../Application/IAEDPoSInformationProvider.cs | 4 +- .../Application/IRandomHashProvider.cs | 32 ++++++++++ .../Application/ConsensusService.cs | 2 +- .../ITriggerInformationProvider.cs | 2 +- .../ISmartContractBridgeContext.cs | 2 + .../HostSmartContractBridgeContext.cs | 6 ++ .../CSharpSmartContractContext.cs | 5 ++ .../BVT/ACS4ImplTest.cs | 22 +++---- .../BVT/MinersCountTest.cs | 10 ++-- .../BVT/MiningProcessTest.cs | 8 +-- .../BVT/ViewTests.cs | 3 +- .../Types/Round_Generation.cs | 8 ++- .../ContractsPreparation.cs | 2 +- .../Types/MinerList.cs | 38 +++++++++++- .../Types/Round_Generation.cs | 8 ++- .../Types/Round_Generation.cs | 8 ++- .../AEDPoSTestAElfModule.cs | 11 ++++ .../AEDPoSTriggerInformationProviderTests.cs | 5 +- .../ConsensusTestAElfModule.cs | 2 +- 29 files changed, 319 insertions(+), 70 deletions(-) create mode 100644 src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs index 9517ca71b1..3e3499e4d6 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs @@ -80,6 +80,7 @@ public override Empty FirstRound(Round input) State.CurrentTermNumber.Value = 1; State.CurrentRoundNumber.Value = 1; State.FirstRoundNumberOfEachTerm[1] = 1; + State.RandomHashes[Context.CurrentHeight] = Context.PreviousBlockHash; State.MiningInterval.Value = input.GetMiningInterval(); SetMinerList(input.GetMinerList(), 1); @@ -158,7 +159,7 @@ public override Empty RecordCandidateReplacement(RecordCandidateReplacementInput #region NextRound - public override Empty NextRound(Round input) + public override Empty NextRound(NextRoundInput input) { SupplyCurrentRoundInformation(); ProcessConsensusInformation(input); diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs index 4bbf853a65..a7b768bef2 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs @@ -1,5 +1,6 @@ using System.Linq; using AElf.Standards.ACS4; +using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -66,9 +67,10 @@ public override TransactionList GenerateConsensusTransactions(BytesValue input) "Data to request consensus information should contain pubkey."); var pubkey = triggerInformation.Pubkey; + var randomHash = triggerInformation.RandomHash; var consensusInformation = new AElfConsensusHeaderInformation(); consensusInformation.MergeFrom(GetConsensusBlockExtraData(input, true).Value); - var transactionList = GenerateTransactionListByExtraData(consensusInformation, pubkey); + var transactionList = GenerateTransactionListByExtraData(consensusInformation, pubkey, randomHash); return transactionList; } @@ -126,7 +128,7 @@ public override ValidationResult ValidateConsensusAfterExecution(BytesValue inpu } private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderInformation consensusInformation, - ByteString pubkey) + ByteString pubkey, Hash randomHash) { var round = consensusInformation.Round; var behaviour = consensusInformation.Behaviour; @@ -140,7 +142,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn Transactions = { GenerateTransaction(nameof(UpdateValue), - round.ExtractInformationToUpdateConsensus(pubkey.ToHex())) + round.ExtractInformationToUpdateConsensus(pubkey.ToHex(),randomHash)) } }; case AElfConsensusBehaviour.TinyBlock: @@ -154,7 +156,8 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn { ActualMiningTime = minerInRound.ActualMiningTimes.Last(), ProducedBlocks = minerInRound.ProducedBlocks, - RoundId = round.RoundIdForValidation + RoundId = round.RoundIdForValidation, + RandomHash = randomHash }) } }; @@ -163,7 +166,20 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn { Transactions = { - GenerateTransaction(nameof(NextRound), round) + GenerateTransaction(nameof(NextRound), new NextRoundInput + { + RoundNumber = round.RoundNumber, + RealTimeMinersInformation = { round.RealTimeMinersInformation }, + ExtraBlockProducerOfPreviousRound = round.ExtraBlockProducerOfPreviousRound, + BlockchainAge = round.BlockchainAge, + TermNumber = round.TermNumber, + ConfirmedIrreversibleBlockHeight = round.ConfirmedIrreversibleBlockHeight, + ConfirmedIrreversibleBlockRoundNumber = round.ConfirmedIrreversibleBlockRoundNumber, + IsMinerListJustChanged = round.IsMinerListJustChanged, + RoundIdForValidation = round.RoundIdForValidation, + MainChainMinersRoundNumber = round.MainChainMinersRoundNumber, + RandomHash = randomHash + }) } }; case AElfConsensusBehaviour.NextTerm: @@ -171,7 +187,20 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn { Transactions = { - GenerateTransaction(nameof(NextTerm), round) + GenerateTransaction(nameof(NextTerm), new NextTermInput + { + RoundNumber = round.RoundNumber, + RealTimeMinersInformation = { round.RealTimeMinersInformation }, + ExtraBlockProducerOfPreviousRound = round.ExtraBlockProducerOfPreviousRound, + BlockchainAge = round.BlockchainAge, + TermNumber = round.TermNumber, + ConfirmedIrreversibleBlockHeight = round.ConfirmedIrreversibleBlockHeight, + ConfirmedIrreversibleBlockRoundNumber = round.ConfirmedIrreversibleBlockRoundNumber, + IsMinerListJustChanged = round.IsMinerListJustChanged, + RoundIdForValidation = round.RoundIdForValidation, + MainChainMinersRoundNumber = round.MainChainMinersRoundNumber, + RandomHash = randomHash + }) } }; default: diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_NextTerm.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_NextTerm.cs index fbe886f8a4..d6569b7cdd 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_NextTerm.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_NextTerm.cs @@ -10,7 +10,7 @@ namespace AElf.Contracts.Consensus.AEDPoS; // ReSharper disable once InconsistentNaming public partial class AEDPoSContract { - public override Empty NextTerm(Round input) + public override Empty NextTerm(NextTermInput input) { SupplyCurrentRoundInformation(); ProcessConsensusInformation(input); diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs index 4e37a46580..53e804add6 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs @@ -28,19 +28,25 @@ private void ProcessConsensusInformation(dynamic input, [CallerMemberName] strin State.RoundBeforeLatestExecution.Value = GetCurrentRoundInformation(new Empty()); + var randomHash = Hash.Empty; + // The only difference. switch (input) { - case Round round when callerMethodName == nameof(NextRound): - ProcessNextRound(round); + case NextRoundInput nextRoundInput: + randomHash = nextRoundInput.RandomHash; + ProcessNextRound(nextRoundInput); break; - case Round round when callerMethodName == nameof(NextTerm): - ProcessNextTerm(round); + case NextTermInput nextTermInput: + randomHash = nextTermInput.RandomHash; + ProcessNextTerm(nextTermInput); break; case UpdateValueInput updateValueInput: + randomHash = updateValueInput.RandomHash; ProcessUpdateValue(updateValueInput); break; case TinyBlockInput tinyBlockInput: + randomHash = tinyBlockInput.RandomHash; ProcessTinyBlock(tinyBlockInput); break; } @@ -65,12 +71,9 @@ private void ProcessConsensusInformation(dynamic input, [CallerMemberName] strin Context.LogDebug(() => $"Current round information:\n{currentRound.ToString(_processingBlockMinerPubkey)}"); - var latestSignature = GetLatestSignature(currentRound); - var previousRandomHash = State.RandomHashes[Context.CurrentHeight.Sub(1)]; - var randomHash = previousRandomHash == null - ? latestSignature - : HashHelper.XorAndCompute(previousRandomHash, latestSignature); - + var previousRandomHash = State.RandomHashes[Context.CurrentHeight.Sub(1)] ?? Hash.Empty; + Assert(Context.ECVRFVerify(Context.RecoverPublicKey(), previousRandomHash.ToHex(), randomHash.ToHex()), + "Invalid random hash."); State.RandomHashes[Context.CurrentHeight] = randomHash; Context.LogDebug(() => $"New random hash generated: {randomHash} - height {Context.CurrentHeight}"); @@ -100,8 +103,22 @@ private Hash GetLatestSignature(Round currentRound) return latestSignature; } - private void ProcessNextRound(Round nextRound) + private void ProcessNextRound(NextRoundInput input) { + var nextRound = new Round + { + RoundNumber = input.RoundNumber, + RealTimeMinersInformation = { input.RealTimeMinersInformation }, + ExtraBlockProducerOfPreviousRound = input.ExtraBlockProducerOfPreviousRound, + BlockchainAge = input.BlockchainAge, + TermNumber = input.TermNumber, + ConfirmedIrreversibleBlockHeight = input.ConfirmedIrreversibleBlockHeight, + ConfirmedIrreversibleBlockRoundNumber = input.ConfirmedIrreversibleBlockRoundNumber, + IsMinerListJustChanged = input.IsMinerListJustChanged, + RoundIdForValidation = input.RoundIdForValidation, + MainChainMinersRoundNumber = input.MainChainMinersRoundNumber + }; + RecordMinedMinerListOfCurrentRound(); TryToGetCurrentRoundInformation(out var currentRound); @@ -149,8 +166,22 @@ private void ProcessNextRound(Round nextRound) Assert(TryToUpdateRoundNumber(nextRound.RoundNumber), "Failed to update round number."); } - private void ProcessNextTerm(Round nextRound) + private void ProcessNextTerm(NextTermInput input) { + var nextRound = new Round + { + RoundNumber = input.RoundNumber, + RealTimeMinersInformation = { input.RealTimeMinersInformation }, + ExtraBlockProducerOfPreviousRound = input.ExtraBlockProducerOfPreviousRound, + BlockchainAge = input.BlockchainAge, + TermNumber = input.TermNumber, + ConfirmedIrreversibleBlockHeight = input.ConfirmedIrreversibleBlockHeight, + ConfirmedIrreversibleBlockRoundNumber = input.ConfirmedIrreversibleBlockRoundNumber, + IsMinerListJustChanged = input.IsMinerListJustChanged, + RoundIdForValidation = input.RoundIdForValidation, + MainChainMinersRoundNumber = input.MainChainMinersRoundNumber + }; + RecordMinedMinerListOfCurrentRound(); // Count missed time slot of current round. diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs index 786eef5ca0..592343668a 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs @@ -10,8 +10,9 @@ public partial class Round /// will record this purpose to their FinalOrderOfNextRound field. /// /// + /// /// - public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) + public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey, Hash randomHash) { if (!RealTimeMinersInformation.ContainsKey(pubkey)) return null; @@ -43,7 +44,8 @@ public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) EncryptedPieces = { minerInRound.EncryptedPieces }, DecryptedPieces = { decryptedPreviousInValues }, MinersPreviousInValues = { minersPreviousInValues }, - ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight + ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight, + RandomHash = randomHash }; } } \ No newline at end of file diff --git a/protobuf/aedpos_contract.proto b/protobuf/aedpos_contract.proto index 73742d45fe..b09cabf7ef 100644 --- a/protobuf/aedpos_contract.proto +++ b/protobuf/aedpos_contract.proto @@ -31,11 +31,11 @@ service AEDPoSContract { } // Update consensus information, create a new round. - rpc NextRound (Round) returns (google.protobuf.Empty) { + rpc NextRound (NextRoundInput) returns (google.protobuf.Empty) { } // Update consensus information, create a new term. - rpc NextTerm (Round) returns (google.protobuf.Empty) { + rpc NextTerm (NextTermInput) returns (google.protobuf.Empty) { } // Update consensus tiny block information. @@ -216,6 +216,8 @@ message UpdateValueInput { map miners_previous_in_values = 11; // The irreversible block height that miner recorded. int64 implied_irreversible_block_height = 12; + // The random hash of AEDPoS. + aelf.Hash random_hash = 13; } message MinerList { @@ -339,6 +341,8 @@ message AElfConsensusTriggerInformation { map decrypted_pieces = 6; // The revealed InValues. map revealed_in_values = 7; + // The random hash of AEDPoS. + aelf.Hash random_hash = 8; } message TermInfo { @@ -360,6 +364,8 @@ message TinyBlockInput { google.protobuf.Timestamp actual_mining_time = 2; // Count of blocks currently produced int64 produced_blocks = 3; + // The random hash of AEDPoS. + aelf.Hash random_hash = 4; } message VoteMinersCountInput { @@ -446,4 +452,54 @@ message MinerReplaced { message RecordCandidateReplacementInput { string old_pubkey = 1; string new_pubkey = 2; +} + +message NextRoundInput { + // The round number. + int64 round_number = 1; + // Current miner information, miner public key -> miner information. + map real_time_miners_information = 2; + // The round number on the main chain + int64 main_chain_miners_round_number = 3; + // The time from chain start to current round (seconds). + int64 blockchain_age = 4; + // The miner public key that produced the extra block in the previous round. + string extra_block_producer_of_previous_round = 5; + // The current term number. + int64 term_number = 6; + // The height of the confirmed irreversible block. + int64 confirmed_irreversible_block_height = 7; + // The round number of the confirmed irreversible block. + int64 confirmed_irreversible_block_round_number = 8; + // Is miner list different from the the miner list in the previous round. + bool is_miner_list_just_changed = 9; + // The round id, calculated by summing block producers’ expecting time (second). + int64 round_id_for_validation = 10; + // The random hash of AEDPoS. + aelf.Hash random_hash = 11; +} + +message NextTermInput { + // The round number. + int64 round_number = 1; + // Current miner information, miner public key -> miner information. + map real_time_miners_information = 2; + // The round number on the main chain + int64 main_chain_miners_round_number = 3; + // The time from chain start to current round (seconds). + int64 blockchain_age = 4; + // The miner public key that produced the extra block in the previous round. + string extra_block_producer_of_previous_round = 5; + // The current term number. + int64 term_number = 6; + // The height of the confirmed irreversible block. + int64 confirmed_irreversible_block_height = 7; + // The round number of the confirmed irreversible block. + int64 confirmed_irreversible_block_round_number = 8; + // Is miner list different from the the miner list in the previous round. + bool is_miner_list_just_changed = 9; + // The round id, calculated by summing block producers’ expecting time (second). + int64 round_id_for_validation = 10; + // The random hash of AEDPoS. + aelf.Hash random_hash = 11; } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs index 87cc138f45..251590b8b0 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs @@ -294,16 +294,16 @@ await contractStub.UpdateValue.SendWithExceptionAsync( break; case nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.NextRound): if (withException) - await contractStub.NextRound.SendWithExceptionAsync(Round.Parser.ParseFrom(transaction.Params)); + await contractStub.NextRound.SendWithExceptionAsync(NextRoundInput.Parser.ParseFrom(transaction.Params)); else - await contractStub.NextRound.SendAsync(Round.Parser.ParseFrom(transaction.Params)); + await contractStub.NextRound.SendAsync(NextRoundInput.Parser.ParseFrom(transaction.Params)); break; case nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.NextTerm): if (withException) - await contractStub.NextTerm.SendWithExceptionAsync(Round.Parser.ParseFrom(transaction.Params)); + await contractStub.NextTerm.SendWithExceptionAsync(NextTermInput.Parser.ParseFrom(transaction.Params)); else - await contractStub.NextTerm.SendAsync(Round.Parser.ParseFrom(transaction.Params)); + await contractStub.NextTerm.SendAsync(NextTermInput.Parser.ParseFrom(transaction.Params)); break; } diff --git a/src/AElf.Kernel.Consensus.AEDPoS/AElf.Kernel.Consensus.AEDPoS.csproj b/src/AElf.Kernel.Consensus.AEDPoS/AElf.Kernel.Consensus.AEDPoS.csproj index beb55cf877..fc3fc47069 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/AElf.Kernel.Consensus.AEDPoS.csproj +++ b/src/AElf.Kernel.Consensus.AEDPoS/AElf.Kernel.Consensus.AEDPoS.csproj @@ -1,5 +1,5 @@ - + net6.0 @@ -15,7 +15,7 @@ - + @@ -31,7 +31,7 @@ - + diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs index a893dd3eb5..e1d82c2795 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs @@ -4,6 +4,7 @@ using AElf.Contracts.Consensus.AEDPoS; using AElf.Kernel.Consensus.Application; using AElf.Kernel.SmartContract.Application; +using AElf.Types; using Google.Protobuf.WellKnownTypes; namespace AElf.Kernel.Consensus.AEDPoS.Application; @@ -22,7 +23,7 @@ public AEDPoSInformationProvider( _consensusReaderContextService = consensusReaderContextService; } - public async Task> GetCurrentMinerList(ChainContext chainContext) + public async Task> GetCurrentMinerListAsync(ChainContext chainContext) { var contractReaderContext = await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); @@ -31,4 +32,12 @@ await _contractReaderFactory .Create(contractReaderContext).GetCurrentMinerList.CallAsync(new Empty()); return minersWithRoundNumber.Pubkeys.Select(k => k.ToHex()); } + + public async Task GetRandomHashAsync(IChainContext chainContext, long blockHeight) + { + var contractReaderContext = + await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); + return await _contractReaderFactory + .Create(contractReaderContext).GetRandomHash.CallAsync(new Int64Value { Value = blockHeight }); + } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs index 255d1549f0..564aa694cd 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs @@ -1,6 +1,8 @@ +using System.Threading.Tasks; using AElf.Contracts.Consensus.AEDPoS; using AElf.Kernel.Account.Application; using AElf.Kernel.Consensus.Application; +using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; @@ -14,13 +16,15 @@ internal class AEDPoSTriggerInformationProvider : ITriggerInformationProvider private readonly IAccountService _accountService; private readonly IInValueCache _inValueCache; private readonly ISecretSharingService _secretSharingService; + private readonly IRandomHashProvider _randomHashProvider; public AEDPoSTriggerInformationProvider(IAccountService accountService, - ISecretSharingService secretSharingService, IInValueCache inValueCache) + ISecretSharingService secretSharingService, IInValueCache inValueCache, IRandomHashProvider randomHashProvider) { _accountService = accountService; _secretSharingService = secretSharingService; _inValueCache = inValueCache; + _randomHashProvider = randomHashProvider; Logger = NullLogger.Instance; } @@ -70,13 +74,16 @@ public BytesValue GetTriggerInformationForBlockHeaderExtraData(BytesValue consen }.ToBytesValue(); } - public BytesValue GetTriggerInformationForConsensusTransactions(BytesValue consensusCommandBytes) + public BytesValue GetTriggerInformationForConsensusTransactions(IChainContext chainContext, BytesValue consensusCommandBytes) { + var randomHash = AsyncHelper.RunSync(async ()=> await _randomHashProvider.GenerateRandomHashAsync(chainContext)); + if (consensusCommandBytes == null) return new AElfConsensusTriggerInformation { Pubkey = Pubkey, - Behaviour = AElfConsensusBehaviour.UpdateValue + Behaviour = AElfConsensusBehaviour.UpdateValue, + RandomHash = randomHash }.ToBytesValue(); var command = consensusCommandBytes.ToConsensusCommand(); @@ -90,7 +97,8 @@ public BytesValue GetTriggerInformationForConsensusTransactions(BytesValue conse Pubkey = Pubkey, InValue = inValue, PreviousInValue = _inValueCache.GetInValue(hint.PreviousRoundId), - Behaviour = hint.Behaviour + Behaviour = hint.Behaviour, + RandomHash = randomHash }; var secretPieces = _secretSharingService.GetEncryptedPieces(hint.RoundId); @@ -111,7 +119,8 @@ public BytesValue GetTriggerInformationForConsensusTransactions(BytesValue conse return new AElfConsensusTriggerInformation { Pubkey = Pubkey, - Behaviour = hint.Behaviour + Behaviour = hint.Behaviour, + RandomHash = randomHash }.ToBytesValue(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs index 0eb4d0f7cc..21d817cbfb 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs @@ -1,10 +1,12 @@ using System.Collections.Generic; using System.Threading.Tasks; +using AElf.Types; namespace AElf.Kernel.Consensus.AEDPoS.Application; // ReSharper disable once InconsistentNaming public interface IAEDPoSInformationProvider { - Task> GetCurrentMinerList(ChainContext chainContext); + Task> GetCurrentMinerListAsync(ChainContext chainContext); + Task GetRandomHashAsync(IChainContext chainContext, long blockHeight); } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs new file mode 100644 index 0000000000..832e3ce68c --- /dev/null +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using AElf.Kernel.Account.Application; +using AElf.Types; + +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +public interface IRandomHashProvider +{ + Task GenerateRandomHashAsync(IChainContext chainContext); +} + +public class RandomHashProvider : IRandomHashProvider +{ + private readonly IAEDPoSInformationProvider _aedPoSInformationProvider; + private readonly IAccountService _accountService; + + public RandomHashProvider(IAEDPoSInformationProvider aedPoSInformationProvider, IAccountService accountService) + { + _aedPoSInformationProvider = aedPoSInformationProvider; + _accountService = accountService; + } + + public async Task GenerateRandomHashAsync(IChainContext chainContext) + { + var previousRandomHash = + await _aedPoSInformationProvider.GetRandomHashAsync(chainContext, chainContext.BlockHeight); + // TODO: Use real random hash. + var randomHash = Hash.Empty; + + return randomHash; + } +} diff --git a/src/AElf.Kernel.Consensus.Core/Application/ConsensusService.cs b/src/AElf.Kernel.Consensus.Core/Application/ConsensusService.cs index 680a36dfb5..50a75d9f90 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/ConsensusService.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/ConsensusService.cs @@ -215,7 +215,7 @@ public async Task> GenerateConsensusTransactionsAsync(ChainCon .Create(contractReaderContext) .GenerateConsensusTransactions .CallAsync(_triggerInformationProvider.GetTriggerInformationForConsensusTransactions( - _consensusCommand.ToBytesValue()))) + chainContext, _consensusCommand.ToBytesValue()))) .Transactions .ToList(); diff --git a/src/AElf.Kernel.Consensus.Core/Application/ITriggerInformationProvider.cs b/src/AElf.Kernel.Consensus.Core/Application/ITriggerInformationProvider.cs index 26567a68b5..7ba7d31e5c 100644 --- a/src/AElf.Kernel.Consensus.Core/Application/ITriggerInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.Core/Application/ITriggerInformationProvider.cs @@ -7,5 +7,5 @@ public interface ITriggerInformationProvider { BytesValue GetTriggerInformationForConsensusCommand(BytesValue consensusCommandBytes); BytesValue GetTriggerInformationForBlockHeaderExtraData(BytesValue consensusCommandBytes); - BytesValue GetTriggerInformationForConsensusTransactions(BytesValue consensusCommandBytes); + BytesValue GetTriggerInformationForConsensusTransactions(IChainContext chainContext, BytesValue consensusCommandBytes); } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs index a7f5fbcf99..1ab72838fb 100644 --- a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs @@ -88,6 +88,8 @@ Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualA long ConvertHashToInt64(Hash hash, long start = 0, long end = long.MaxValue); object ValidateStateSize(object obj); + + bool ECVRFVerify(byte[] pubKey, string pi, string alpha); } [Serializable] diff --git a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs index 144f1aa0a5..22cf833ea7 100644 --- a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs @@ -349,4 +349,10 @@ public byte[] RecoverPublicKey(byte[] signature, byte[] hash) var cabBeRecovered = CryptoHelper.RecoverPublicKey(signature, hash, out var publicKey); return !cabBeRecovered ? null : publicKey; } + + public bool ECVRFVerify(byte[] pubKey, string pi, string alpha) + { + // TODO: implement + return true; + } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs index 2f56f80931..6a8edada5f 100644 --- a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs +++ b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs @@ -372,4 +372,9 @@ public Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash v return SmartContractBridgeContextImplementation.ConvertVirtualAddressToContractAddressWithContractHashName( virtualAddress); } + + public bool ECVRFVerify(byte[] pubKey, string pi, string alpha) + { + return SmartContractBridgeContextImplementation.ECVRFVerify(pubKey, pi, alpha); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs index f567de3d69..1b41018c34 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Threading.Tasks; using AElf.CSharp.Core; +using AElf.Kernel; using AElf.Standards.ACS4; using AElf.TestBase; using AElf.Types; @@ -74,7 +75,7 @@ private async Task AEDPoSContract_GenerateConsensusTransactions }); var triggerForCommand = - TriggerInformationProvider.GetTriggerInformationForConsensusTransactions( + TriggerInformationProvider.GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); @@ -175,7 +176,7 @@ private async Task AEDPoSContract_GenerateConsensusTransactions }); var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); + .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); @@ -275,7 +276,7 @@ private async Task }); var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); + .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); @@ -298,7 +299,7 @@ public async Task AEDPoSContract_FirstRound_Terminate_Test() .Div(1000) }); - var nextRound = new Round(); + var nextRound = new NextRoundInput(); nextRound.MergeFrom(transaction.Params); await AEDPoSContractStub.NextRound.SendAsync(nextRound); @@ -323,10 +324,11 @@ public async Task AEDPoSContract_ConsensusTransactionValidation_Test() validateBeforeResult.Success.ShouldBeTrue(); var roundInfo = await AEDPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); - roundInfo.RoundNumber++; - roundInfo.IsMinerListJustChanged = false; - roundInfo.TermNumber++; - var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(roundInfo); + var nextRoundInput = NextRoundInput.Parser.ParseFrom(roundInfo.ToByteArray()); + nextRoundInput.RoundNumber++; + nextRoundInput.IsMinerListJustChanged = false; + nextRoundInput.TermNumber++; + var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var validateAfterResult = @@ -402,7 +404,7 @@ public async Task AEDPoSContract_GenerateConsensusTransaction_TinyBlock_Test() }); var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); + .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); @@ -433,7 +435,7 @@ public async Task AEDPoSContract_GenerateConsensusTransaction_NextTerm_Test() }); var triggerForCommand = TriggerInformationProvider - .GetTriggerInformationForConsensusTransactions(consensusCommand.ToBytesValue()); + .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs index bbc2310b9f..3b8ea9368c 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs @@ -80,7 +80,8 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); - await AEDPoSContractStub.NextRound.SendAsync(nextTermInformation.Round); + var nextRoundInput = NextRoundInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); + await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); changeTermTime = BlockchainStartTimestamp.ToDateTime().AddMinutes(termIntervalMin).AddSeconds(10); BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); @@ -91,7 +92,8 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); - var transactionResult = await AEDPoSContractStub.NextTerm.SendAsync(nextTermInformation.Round); + var nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); + var transactionResult = await AEDPoSContractStub.NextTerm.SendAsync(nextTermInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var newMinerStub = GetAEDPoSContractStub(ValidationDataCenterKeyPairs[0]); @@ -117,8 +119,8 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() Pubkey = ByteStringHelper.FromHexString(currentRound.RealTimeMinersInformation.ElementAt(0).Value .Pubkey) }.ToBytesValue())).ToConsensusHeaderInformation(); - - await newMinerStub.NextTerm.SendAsync(nextRoundInformation.Round); + nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); + await newMinerStub.NextTerm.SendAsync(nextTermInput); termCount++; } } diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs index cb9dfcf1ff..ec0bbefe0f 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs @@ -73,8 +73,8 @@ await voter.Vote.SendAsync(new VoteMinerInput Behaviour = AElfConsensusBehaviour.NextTerm, Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); - - await AEDPoSContractStub.NextTerm.SendAsync(nextTermInformation.Round); + var nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); + await AEDPoSContractStub.NextTerm.SendAsync(nextTermInput); // First candidate cheat others with in value. var oneCandidate = GetAEDPoSContractStub(ValidationDataCenterKeyPairs[0]); @@ -100,8 +100,8 @@ await voter.Vote.SendAsync(new VoteMinerInput Behaviour = AElfConsensusBehaviour.NextRound, Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation().Round; - - await oneCandidate.NextRound.SendAsync(thirdRound); + var nextRoundInput = NextRoundInput.Parser.ParseFrom(thirdRound.ToByteArray()); + await oneCandidate.NextRound.SendAsync(nextRoundInput); var cheatInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( new AElfConsensusTriggerInformation diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs index b75b324ccf..8f3ac03be7 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs @@ -27,7 +27,8 @@ public async Task Query_RoundInformation_Test() Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); - var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextTermInformation.Round); + var nextRoundInput = NextRoundInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); + var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); roundNumber = await AEDPoSContractStub.GetCurrentRoundNumber.CallAsync(new Empty()); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs index 34830558d0..60a91cab03 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using AElf.CSharp.Core; +using AElf.Types; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.Consensus.AEDPoS; @@ -8,9 +9,9 @@ namespace AElf.Contracts.Consensus.AEDPoS; internal partial class Round { public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, - out Round nextRound) + out NextRoundInput nextRound) { - nextRound = new Round(); + nextRound = new NextRoundInput(); var minersMinedCurrentRound = GetMinedMiners(); var minersNotMinedCurrentRound = GetNotMinedMiners(); @@ -66,6 +67,9 @@ public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timest else expectedExtraBlockProducer.IsExtraBlockProducer = true; + // TODO: Set random hash. + nextRound.RandomHash = Hash.Empty; + return true; } diff --git a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs index 04437a46a8..890947e9f4 100644 --- a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs +++ b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs @@ -500,7 +500,7 @@ protected async Task InitializeAElfConsensus() new MinerList { Pubkeys = { InitialCoreDataCenterKeyPairs.Select(p => ByteString.CopyFrom(p.PublicKey)) } - }.GenerateFirstRoundOfNewTerm(EconomicContractsTestConstants.MiningInterval, StartTimestamp)); + }.GenerateFirstRound(EconomicContractsTestConstants.MiningInterval, StartTimestamp)); CheckResult(result.TransactionResult); } } diff --git a/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs b/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs index ed9c3082b5..d66277fbdb 100644 --- a/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs +++ b/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs @@ -8,7 +8,7 @@ namespace AElf.Contracts.Consensus.AEDPoS; internal partial class MinerList { - public Round GenerateFirstRoundOfNewTerm(int miningInterval, + public Round GenerateFirstRound(int miningInterval, Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { var sortedMiners = @@ -41,4 +41,40 @@ orderby obj.Value descending return round; } + + public NextTermInput GenerateFirstRoundOfNewTerm(int miningInterval, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + { + var sortedMiners = + (from obj in Pubkeys + .ToDictionary(miner => miner.ToHex(), miner => miner[0]) + orderby obj.Value descending + select obj.Key).ToList(); + + var input = new NextTermInput(); + + for (var i = 0; i < sortedMiners.Count; i++) + { + var minerInRound = new MinerInRound(); + + // The first miner will be the extra block producer of first round of each term. + if (i == 0) minerInRound.IsExtraBlockProducer = true; + + minerInRound.Pubkey = sortedMiners[i]; + minerInRound.Order = i + 1; + minerInRound.ExpectedMiningTime = currentBlockTime.AddMilliseconds(i * miningInterval + miningInterval); + // Should be careful during validation. + minerInRound.PreviousInValue = Hash.Empty; + + input.RealTimeMinersInformation.Add(sortedMiners[i], minerInRound); + } + + input.RoundNumber = currentRoundNumber + 1; + input.TermNumber = currentTermNumber + 1; + input.IsMinerListJustChanged = true; + // TODO: Set random hash. + input.RandomHash = Hash.Empty; + + return input; + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs b/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs index 567ca6cf6a..bd7ae4d32e 100644 --- a/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs +++ b/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using AElf.CSharp.Core; +using AElf.Types; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.Consensus.AEDPoS; @@ -8,9 +9,9 @@ namespace AElf.Contracts.Consensus.AEDPoS; internal partial class Round { public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, - out Round nextRound) + out NextRoundInput nextRound) { - nextRound = new Round(); + nextRound = new NextRoundInput(); var minersMinedCurrentRound = GetMinedMiners(); var minersNotMinedCurrentRound = GetNotMinedMiners(); @@ -63,6 +64,9 @@ public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timest else expectedExtraBlockProducer.IsExtraBlockProducer = true; + // TODO: Set random hash. + nextRound.RandomHash = Hash.Empty; + return true; } diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs index 34830558d0..60a91cab03 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using AElf.CSharp.Core; +using AElf.Types; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.Consensus.AEDPoS; @@ -8,9 +9,9 @@ namespace AElf.Contracts.Consensus.AEDPoS; internal partial class Round { public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, - out Round nextRound) + out NextRoundInput nextRound) { - nextRound = new Round(); + nextRound = new NextRoundInput(); var minersMinedCurrentRound = GetMinedMiners(); var minersNotMinedCurrentRound = GetNotMinedMiners(); @@ -66,6 +67,9 @@ public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timest else expectedExtraBlockProducer.IsExtraBlockProducer = true; + // TODO: Set random hash. + nextRound.RandomHash = Hash.Empty; + return true; } diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestAElfModule.cs b/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestAElfModule.cs index 685b78a9ab..fd63a97d83 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestAElfModule.cs +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/AEDPoSTestAElfModule.cs @@ -170,6 +170,17 @@ public override void ConfigureServices(ServiceConfigurationContext context) } }.ToByteArray()) })); + + mockService.Setup(m => + m.ExecuteAsync(It.IsAny(), + It.Is(tx => + tx.MethodName == "GetRandomHash"), + It.IsAny())) + .Returns(Task.FromResult(new TransactionTrace + { + ExecutionStatus = ExecutionStatus.Executed, + ReturnValue = Hash.Empty.ToByteString() + })); return mockService.Object; }); diff --git a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSTriggerInformationProviderTests.cs b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSTriggerInformationProviderTests.cs index e17515599c..4e4172f345 100644 --- a/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSTriggerInformationProviderTests.cs +++ b/test/AElf.Kernel.Consensus.AEDPoS.Tests/Application/AEDPoSTriggerInformationProviderTests.cs @@ -4,6 +4,7 @@ using AElf.Kernel.Consensus.AEDPoS.Application; using AElf.Kernel.Consensus.Application; using AElf.Standards.ACS4; +using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; @@ -43,7 +44,7 @@ public Task GetTriggerInformationForBlockHeaderExtraData_ConsensusCommand_Test() [Fact] public async Task GetCurrentMinerList_Test() { - var result = await _aedpoSInformationProvider.GetCurrentMinerList(new ChainContext()); + var result = await _aedpoSInformationProvider.GetCurrentMinerListAsync(new ChainContext()); result.Count().ShouldBe(3); } @@ -60,7 +61,7 @@ public void GetTriggerInformationForBlockHeaderExtraData_CommandIsNull_Test() public void GetTriggerInformationForConsensusTransactions_CommandIsNull_Test() { var result = - _triggerInformationProvider.GetTriggerInformationForConsensusTransactions(null); + _triggerInformationProvider.GetTriggerInformationForConsensusTransactions(new ChainContext(), null); var triggerInformation = AElfConsensusTriggerInformation.Parser.ParseFrom(result.Value); triggerInformation.Behaviour.ShouldBe(AElfConsensusBehaviour.UpdateValue); } diff --git a/test/AElf.Kernel.Consensus.Tests/ConsensusTestAElfModule.cs b/test/AElf.Kernel.Consensus.Tests/ConsensusTestAElfModule.cs index b31b834a82..8f05ef3b78 100644 --- a/test/AElf.Kernel.Consensus.Tests/ConsensusTestAElfModule.cs +++ b/test/AElf.Kernel.Consensus.Tests/ConsensusTestAElfModule.cs @@ -38,7 +38,7 @@ public override void ConfigureServices(ServiceConfigurationContext context) .Returns(new BytesValue()); mockService.Setup(m => m.GetTriggerInformationForBlockHeaderExtraData(It.IsAny())) .Returns(new BytesValue()); - mockService.Setup(m => m.GetTriggerInformationForConsensusTransactions(It.IsAny())) + mockService.Setup(m => m.GetTriggerInformationForConsensusTransactions(It.IsAny(), It.IsAny())) .Returns(new BytesValue()); return mockService.Object; From ac98def00468d153b8bd117e3f0b83cc82b33ae6 Mon Sep 17 00:00:00 2001 From: gldeng Date: Tue, 13 Jun 2023 21:40:55 +0800 Subject: [PATCH 037/139] Implement Prove method --- src/AElf.Cryptography/ECVRF/IVrf.cs | 15 + src/AElf.Cryptography/ECVRF/Vrf.cs | 292 ++++++++++++++++++ .../AElf.Cryptography.Tests.csproj | 20 +- .../AElf.Cryptography.Tests/ECVRF/VRFTests.cs | 87 ++++++ 4 files changed, 406 insertions(+), 8 deletions(-) create mode 100644 src/AElf.Cryptography/ECVRF/IVrf.cs create mode 100644 src/AElf.Cryptography/ECVRF/Vrf.cs create mode 100644 test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs diff --git a/src/AElf.Cryptography/ECVRF/IVrf.cs b/src/AElf.Cryptography/ECVRF/IVrf.cs new file mode 100644 index 0000000000..d5989147a8 --- /dev/null +++ b/src/AElf.Cryptography/ECVRF/IVrf.cs @@ -0,0 +1,15 @@ +using AElf.Cryptography.ECDSA; + +namespace AElf.Cryptography.ECVRF; + +public struct Proof +{ + public byte[] Beta { get; set; } + public byte[] Pi { get; set; } +} + +public interface IVrf +{ + Proof Prove(ECKeyPair keyPair, byte[] alpha); + byte[] Verify(byte[] publicKey, Proof proof); +} \ No newline at end of file diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs new file mode 100644 index 0000000000..e916503579 --- /dev/null +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -0,0 +1,292 @@ +using System; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using AElf.Cryptography.ECDSA; +using Org.BouncyCastle.Math; +using Secp256k1Net; +using ECParameters = AElf.Cryptography.ECDSA.ECParameters; + +namespace AElf.Cryptography.ECVRF; + +public class InvalidSerializedPublicKeyException : Exception +{ +} + +public class FailedToHashToCurveException : Exception +{ +} + +public struct Point +{ + public byte[] Inner { get; private set; } + + public static Point FromInner(byte[] inner) + { + return new Point() { Inner = inner }; + } + + public static Point FromSerialized(Secp256k1 secp256k1, byte[] pkSerialized) + { + if (pkSerialized.Length != Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH && + pkSerialized.Length != Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH) + { + throw new InvalidSerializedPublicKeyException(); + } + + if (pkSerialized.Length == Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH) + { + if (pkSerialized[0] != 0x02 && pkSerialized[0] != 0x03) + { + throw new InvalidSerializedPublicKeyException(); + } + } + + if (pkSerialized.Length == Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH) + { + if (pkSerialized[0] != 0x04) + { + throw new InvalidSerializedPublicKeyException(); + } + } + + var inner = new byte[Secp256k1.PUBKEY_LENGTH]; + var successful = secp256k1.PublicKeyParse(inner, pkSerialized); + if (!successful) + { + throw new InvalidSerializedPublicKeyException(); + } + + return new Point() { Inner = inner }; + } + + public byte[] Serialize(Secp256k1 secp256k1, bool compressed = true) + { + if (compressed) + { + var output = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH]; + secp256k1.PublicKeySerialize(output, Inner, Flags.SECP256K1_EC_COMPRESSED); + return output; + } + else + { + var output = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH]; + secp256k1.PublicKeySerialize(output, Inner, Flags.SECP256K1_EC_UNCOMPRESSED); + return output; + } + } +} + +public struct VrfConfig +{ + public byte SuiteString { get; private set; } + + public VrfConfig(byte suiteString) + { + SuiteString = suiteString; + } +} + +public class Vrf : IVrf +{ + private const int QBitsLength = 256; + private const int N = 16; + private VrfConfig _config; + + public Vrf(VrfConfig config) + { + _config = config; + } + + public Proof Prove(ECKeyPair keyPair, byte[] alpha) + { + using var secp256k1 = new Secp256k1(); + var point = Point.FromSerialized(secp256k1, keyPair.PublicKey); + var hashPoint = HashToCurveTryAndIncrement(point, alpha); + var gamma = new byte[Secp256k1.PUBKEY_LENGTH]; + Buffer.BlockCopy(hashPoint.Inner, 0, gamma, 0, gamma.Length); + secp256k1.PublicKeyMultiply(gamma, keyPair.PrivateKey); + var nonce = Rfc6979Nonce(secp256k1, keyPair, hashPoint); + var kB = new byte[Secp256k1.PUBKEY_LENGTH]; + secp256k1.PublicKeyCreate(kB, nonce); + var kH = new byte[Secp256k1.PUBKEY_LENGTH]; + Buffer.BlockCopy(hashPoint.Inner, 0, kH, 0, kH.Length); + secp256k1.PublicKeyMultiply(kH, nonce); + var c = HashPoints(secp256k1, hashPoint, Point.FromInner(gamma), Point.FromInner(kB), Point.FromInner(kH)); + var cX = c.Multiply(new BigInteger(1, keyPair.PrivateKey)); + var s = cX.Add(new BigInteger(1, nonce)).Mod(ECParameters.DomainParams.N); + var pi = EncodeProof(Point.FromInner(gamma), c, s); + var beta = GammaToHash(secp256k1, Point.FromInner(gamma)); + return new Proof + { + Pi = pi, Beta = beta + }; + } + + public byte[] Verify(byte[] publicKey, Proof proof) + { + throw new System.NotImplementedException(); + } + + public Point HashToCurveTryAndIncrement(Point point, byte[] alpha) + { + using var secp256k1 = new Secp256k1(); + + // Step 1: ctr = 0 + var ctr = 0; + + // Step 2: PK_string = point_to_string(Y) + var pkString = point.Serialize(secp256k1, true); + + // Steps 3 ~ 6 + byte oneString = 0x01; + for (; ctr < 256; ctr++) + { + using var hasher = SHA256.Create(); + using var stream = new MemoryStream(); + stream.WriteByte(_config.SuiteString); + stream.WriteByte(oneString); + stream.Write(pkString); + stream.Write(alpha); + stream.WriteByte((byte)ctr); + stream.Seek(0, SeekOrigin.Begin); + var hash = hasher.ComputeHash(stream); + var pkSerialized = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH]; + pkSerialized[0] = 0x02; + Buffer.BlockCopy(hash, 0, pkSerialized, 1, hash.Length); + try + { + var outputPoint = Point.FromSerialized(secp256k1, pkSerialized); + return outputPoint; + } + catch (InvalidSerializedPublicKeyException ex) + { + } + } + + throw new FailedToHashToCurveException(); + } + + public BigInteger HashPoints(Secp256k1 secp256k1, params Point[] points) + { + using var hasher = SHA256.Create(); + using var stream = new MemoryStream(); + stream.WriteByte(_config.SuiteString); + stream.WriteByte(0x02); + foreach (var point in points) + { + var pkBytes = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH]; + secp256k1.PublicKeySerialize(pkBytes, point.Inner, Flags.SECP256K1_EC_COMPRESSED); + stream.Write(pkBytes); + } + + stream.Seek(0, SeekOrigin.Begin); + var hash = hasher.ComputeHash(stream); + var hashTruncated = hash.Take(N).ToArray(); + return new BigInteger(1, hashTruncated); + } + + // + // public BigInteger Bits2Int(byte[] inputBytes, int qlen) + // { + // var output = new BigInteger(inputBytes); + // if (inputBytes.Length * 8 > qlen) + // { + // return output.ShiftRight(inputBytes.Length * 8 - qlen); + // } + // + // return output; + // } + public byte[] EncodeProof(Point gamma, BigInteger c, BigInteger s) + { + using var secp256k1 = new Secp256k1(); + var gammaBytes = gamma.Serialize(secp256k1, true); + var cBytes = Int2Bytes(c, N); + var sBytes = Int2Bytes(s, (QBitsLength + 7) / 8); + var output = new byte[gammaBytes.Length + cBytes.Length + sBytes.Length]; + Buffer.BlockCopy(gammaBytes, 0, output, 0, gammaBytes.Length); + Buffer.BlockCopy(cBytes, 0, output, gammaBytes.Length, cBytes.Length); + Buffer.BlockCopy(sBytes, 0, output, gammaBytes.Length + cBytes.Length, sBytes.Length); + return output; + } + + private static byte[] AddLeadingZeros(byte[] data, int requiredLength) + { + var zeroBytesLength = requiredLength - data.Length; + if (zeroBytesLength <= 0) return data; + var output = new byte[requiredLength]; + Buffer.BlockCopy(data, 0, output, zeroBytesLength, data.Length); + for (int i = zeroBytesLength - 1; i >= 0; i--) + { + output[i] = 0x0; + } + + return output; + } + + public byte[] GammaToHash(Secp256k1 secp256k1, Point gamma) + { + var gammaBytes = gamma.Serialize(secp256k1, true); + using var hasher = SHA256.Create(); + using var stream = new MemoryStream(); + stream.WriteByte(_config.SuiteString); + stream.WriteByte(0x03); + stream.Write(gammaBytes); + stream.Seek(0, SeekOrigin.Begin); + return hasher.ComputeHash(stream); + } + + public byte[] Rfc6979Nonce(Secp256k1 secp256k1, ECKeyPair keyPair, Point hashPoint) + { + using var hasher = SHA256.Create(); + var roLen = (QBitsLength + 7) / 8; + var hBytes = hashPoint.Serialize(secp256k1, true); + + var hash = hasher.ComputeHash(hBytes); + var bh = Bits2Bytes(hash, ECParameters.DomainParams.N, roLen); + + var nonce = new byte[Secp256k1.NONCE_LENGTH]; + secp256k1.Rfc6979Nonce(nonce, bh, keyPair.PrivateKey, null, null, 0); + return nonce; + } + + public byte[] Int2Bytes(BigInteger v, int rolen) + { + var result = v.ToByteArray(); + if ( result.Length < rolen) + { + return AddLeadingZeros(result, rolen); + } + + if (result.Length > rolen) + { + var skipLength = result.Length - rolen; + return result.Skip(skipLength).ToArray(); + } + + return result; + } + + public BigInteger Bits2Int(byte[]inputBytes, int qlen) + { + var output = new BigInteger(1, inputBytes); + if (inputBytes.Length * 8 > qlen) + { + return output.ShiftRight(inputBytes.Length * 8 - qlen); + } + + return output; + } + + public byte[] Bits2Bytes(byte[]input, BigInteger q, int rolen) + { + var z1 = Bits2Int(input, q.BitLength); + var z2 = z1.Subtract(q); + if (z2.SignValue == -1) + { + return Int2Bytes(z1, rolen); + } + + return Int2Bytes(z2, rolen); + } +} \ No newline at end of file diff --git a/test/AElf.Cryptography.Tests/AElf.Cryptography.Tests.csproj b/test/AElf.Cryptography.Tests/AElf.Cryptography.Tests.csproj index b42e0e1bd3..7ef8543522 100644 --- a/test/AElf.Cryptography.Tests/AElf.Cryptography.Tests.csproj +++ b/test/AElf.Cryptography.Tests/AElf.Cryptography.Tests.csproj @@ -9,18 +9,22 @@ runtime; build; native; contentfiles; analyzers - + + - all - runtime; build; native; contentfiles; analyzers - + all + runtime; build; native; contentfiles; analyzers + - all - runtime; build; native; contentfiles; analyzers - + all + runtime; build; native; contentfiles; analyzers + + + + - + \ No newline at end of file diff --git a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs new file mode 100644 index 0000000000..5b66790cfc --- /dev/null +++ b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using AElf.Cryptography.ECVRF; +using Secp256k1Net; +using Xunit; + +namespace AElf.Cryptography.Tests.ECVRF; + +public class VRFTests +{ + public class TestVector + { + [JsonPropertyName("sk")] + public string Sk { get; set; } + + [JsonPropertyName("pk")] + public string Pk { get; set; } + + [JsonPropertyName("alpha")] + public string Alpha { get; set; } + + [JsonPropertyName("beta")] + public string Beta { get; set; } + + [JsonPropertyName("pi")] + public string Pi { get; set; } + } + + [Fact] + public void HashToCurveTryAndIncrement_Test() + { + var pkSerialized = Convert.FromHexString("0360fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb6"); + var alpha = Encoding.ASCII.GetBytes("sample"); + var expectedHashPoint = Convert.FromHexString("027AD7D4C3A454D9ECC905F1E5436A328F2A106A2606EC4B44111CF9DC72A5B9FF"); + + using var secp256k1 = new Secp256k1(); + var cfg = new VrfConfig( 0xfe); + var vrf = new Vrf(cfg); + var output = vrf.HashToCurveTryAndIncrement(Point.FromSerialized(secp256k1, pkSerialized), alpha); + var outputSerialized = output.Serialize(secp256k1, true); + Assert.Equal(outputSerialized, expectedHashPoint); + } + + [Fact] + public void Prove_Test() + { + var path = Path.Combine( Directory.GetCurrentDirectory(), "secp256_k1_sha256_tai.json"); + var text = File.ReadAllText(path); + var vectors = JsonSerializer.Deserialize>(text); + using var secp256k1 = new Secp256k1(); + foreach (var vector in vectors) + { + var sk = AddLeadingZeros(Convert.FromHexString(vector.Sk)); + var kp = CryptoHelper.FromPrivateKey(sk); + var alpha = Convert.FromHexString(vector.Alpha); + var expectedPi = Convert.FromHexString(vector.Pi); + var expectedBeta = Convert.FromHexString(vector.Beta); + var cfg = new VrfConfig( 0xfe); + var vrf = new Vrf(cfg); + var proof = vrf.Prove(kp, alpha); + Assert.Equal(expectedPi, proof.Pi); + Assert.Equal(expectedBeta, proof.Beta); + } + } + + private byte[] AddLeadingZeros(byte[] sk) + { + if (sk.Length < 32) + { + var output = new byte[32]; + var zeroBytesLength = 32 - sk.Length; + for (int i = zeroBytesLength - 1; i >= 0; i--) + { + output[i] = 0; + } + Buffer.BlockCopy(sk, 0, output, zeroBytesLength, sk.Length); + return output; + } + + return sk; + + } +} \ No newline at end of file From 4abcab8f4a8b739f6771170609913e46ce746535 Mon Sep 17 00:00:00 2001 From: gldeng Date: Tue, 13 Jun 2023 21:44:28 +0800 Subject: [PATCH 038/139] Check in json file --- .../secp256_k1_sha256_tai.json | 324 ++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 test/AElf.Cryptography.Tests/secp256_k1_sha256_tai.json diff --git a/test/AElf.Cryptography.Tests/secp256_k1_sha256_tai.json b/test/AElf.Cryptography.Tests/secp256_k1_sha256_tai.json new file mode 100644 index 0000000000..40900f6b17 --- /dev/null +++ b/test/AElf.Cryptography.Tests/secp256_k1_sha256_tai.json @@ -0,0 +1,324 @@ +[ + { + "beta": "612065e309e937ef46c2ef04d5886b9c6efd2991ac484ec64a9b014366fc5d81", + "alpha": "73616d706c65", + "pi": "031f4dbca087a1972d04a07a779b7df1caa99e0f5db2aa21f3aecc4f9e10e85d08748c9fbe6b95d17359707bfb8e8ab0c93ba0c515333adcb8b64f372c535e115ccf66ebf5abe6fadb01b5efb37c0a0ec9", + "sk": "c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721", + "pk": "032c8c31fc9f990c6b55e3865a184a4ce50e09481f2eaeb3e60ec1cea13a6ae645" + }, + { + "beta": "00acd42d48046e13552f54919286c2085aec6fb874854d036f66ad572c99e7ab", + "alpha": "73616d706c65", + "pi": "029a2df6ca1d5f734945fb6847669f839eb9ecf127fa8314e5a6a5c4695c3f4d159009b3741cdec6b0d7c70e3aae6b82aeb1aad555499bd6ce10b35fa230079e6fa752e8d4755ffd285aef5133dad7a64b", + "sk": "01", + "pk": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + }, + { + "beta": "c355718640883112731fce0b5dd97c34492d226280654dcf0ada1d6b32e3384b", + "alpha": "73616d706c65", + "pi": "0205c5a6ed80f7ffbf9f47583e873717e86c8405349266745a0504ea7ca68876ce6afe0e3cccfc7bba83a6d16771d80e26a46ad25be631869d6f60a34c12a19b868815182657288f57afb91166ceed3cc5", + "sk": "02", + "pk": "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + }, + { + "beta": "09a93f6e8a6037db146d862eec33f56c8053bb4fda309f8ecbcbe04592aabd37", + "alpha": "73616d706c65", + "pi": "02a14b92076becc501b9ac761c18cacd792e0b30ad2b6907e1273dbe3762a9d29cf97fe3a904d2123ef98030a929ea91b40f1d5f78d9eb09c85ee2caa962b17de41abd4cf6be036e90c9826ae4e6e3673a", + "sk": "03", + "pk": "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9" + }, + { + "beta": "5a0bce08f650d5ef80b0254ee814360e1f2c944a6c2b15e3171374f362cd92b4", + "alpha": "73616d706c65", + "pi": "03a3ca50b6f1873b8ca55348d0c62b0a2fd774aa9b96d1061c0917d6f9da5fe560dcddbda349d2db15751c965baf88ddb67075b5a441400c5ef85d9dffd6a16833993af6f05901c2421210d72d114c4ba0", + "sk": "04", + "pk": "02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13" + }, + { + "beta": "e06dc093da223b40225633628c94a0bf909a3bb19a2f838932b4627f740354a1", + "alpha": "73616d706c65", + "pi": "030b4806f7f7398ba03951990740243d3f84a0815d85e2be439ee42bd8f249bd44e56800354296f9c05d30e06966009baf98c963028070217f28c0a298f9ecd56726bbc7c4faf1c62691972bfbc9fbd684", + "sk": "05", + "pk": "022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4" + }, + { + "beta": "811a4fe231758d65b9b20d436a19256765776c812966032b16ce2b21e5c69be7", + "alpha": "73616d706c65", + "pi": "02f0fdc752a0c63cae4d33f65af4167a7a8b04711d840230df0d211ee3d6e2a2ad66625f4d9db7798ab664bb2da77736db6c9b7828cd8310a2e5f677224e1676afbb731cf92018a49c0452d1080aac5f3a", + "sk": "06", + "pk": "03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556" + }, + { + "beta": "0b772c54b2125194bd26b7e3ce2c4606043f65d99d3c65aef6e3b61dffd20aae", + "alpha": "73616d706c65", + "pi": "036e041791df3880003115548bf1c491700133a23fb6c1edbef6a23f7dd67c05d5e227f496df589bdd68ffc28fb00246681abb9399a4207fbf42c2a64fa47615b4a64dc25cf0f6bc368353bfb25f63c95b", + "sk": "07", + "pk": "025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc" + }, + { + "beta": "8f7729e4288e7630b358a6cef560479f0e441926ae0fa6a3a96f17b63b3d1fb8", + "alpha": "73616d706c65", + "pi": "02b5a04c6340c0d09b26da8f75c7713ed871e9f673bb87c00ee0e76e8045faad9ece28cfdbc41eab04205963c3252b7229d94793491e4a7f48e09c2d85b3ee2a1131a27b670b07c016dc00e4d8f3daa242", + "sk": "08", + "pk": "022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01" + }, + { + "beta": "ce465b7e061bae415e10d8aafd32d92e2f499d959632fe5983cb0b2d4ee7b3b5", + "alpha": "73616d706c65", + "pi": "02cf1639991c8eb219993f1b9921a413e2ebc72d7b533ab952c92188b9b4ee2bd8cd5417a75c80d3022a3719297b2699b958d27e5e9fe03c8fc96766234fa497bee8287a76f6db22ff482cec9505e51a5f", + "sk": "09", + "pk": "03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe" + }, + { + "beta": "941b5f76d95772045e824e30d85106a4a3b5920b901e178d3f62ec8e473ccf69", + "alpha": "73616d706c65", + "pi": "034e371e26303b9deb6f650f8faee60a2673b2bfef5b5a9af066aca5e7c12695becd27149218141ceb7f7e58da293679388c3b7b5109ec360a1f50decb1fa89c11b19476f5b2786ecba75f3642d942ba31", + "sk": "0a", + "pk": "03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7" + }, + { + "beta": "79403a19944c3516d102cfa42cd5dd3f16c5c9bd457bf0659e2305374af3dccd", + "alpha": "73616d706c65", + "pi": "0384e3011d9e8235de77c211c0e57b0ed4bbffbe4b1d1a946278d13943be6c4280206842bfc58d564262a3214cfab3098d2887923eb659ff543aaa9c48d821acf1198bde5d824d27e9a9a6c2f84c6bdfdb", + "sk": "0b", + "pk": "03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb" + }, + { + "beta": "746ca26b7c90df37d309ecce42757e6bf9423ad31211a02e8d9d86aea72f2f3a", + "alpha": "73616d706c65", + "pi": "03ad49eb72e2c7789d851c7bf2a3137cee17ab304ae7acb7b22739c5aae48eb339199381d85ae4654b2f5488499b4d3a13d6055ca740de70bb6d9b2c0cb962d873e13cd1d1d1c0c4eef9f9809f88e36fc0", + "sk": "0c", + "pk": "03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a" + }, + { + "beta": "51096a3de69492e852477271a77a5b95de5a0cc2fc43128177b9a85e3184318d", + "alpha": "73616d706c65", + "pi": "038be9f8885740d6a336f0ec8249ec010f99fb4f0e42f09804c6f98f0be907327419f8249ebc3fb6fb372402893c55422987d9d36f6dfbdc7cfa88fb75dca13b095f412a1d82b358b1d17406991af576e4", + "sk": "0d", + "pk": "03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" + }, + { + "beta": "b3a048bc1682c3d5ba4d79a951b38f6d9729a328afb38fdd22c5f17247eeb642", + "alpha": "73616d706c65", + "pi": "0354a5641699f62565bec88e75ed465c052f655048a2de85ae39f32e968a80faeb6e21ac4919dc0710e1f1a76184988926a2b354c52cf1ca8529157aa5574c385b86def3a76a7cb9e0d0a11227bc651dac", + "sk": "0e", + "pk": "03499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4" + }, + { + "beta": "eb5c23bc8773fa4c83ef3bf88bf63aceffe6b042e220d8826db222dc55f915fe", + "alpha": "73616d706c65", + "pi": "0398f53f2ed4d687e6a65eaf7ce4d63e99e2db78a12302c782ffe6012737eb2d10257f7a86288479153dafa74c14092fd5acc60c953f225840ee6c92ec67106a979ead5f8c12142373b119190a012ac780", + "sk": "0f", + "pk": "02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e" + }, + { + "beta": "e96f1bab42d66b32d2fb8ea1e4655808881cd9f208279a0757ef990575e7adc0", + "alpha": "73616d706c65", + "pi": "024ca2c0b270a6c632cade38ff097d66de362c54064e847fd96bd4067b71028db4ead3e112b4cc78b826165d6fde084924f58ae74f69c4542d68cdd5a33e03d5bd2e7fc5f5fda4c9e3d157fbb213fddd3d", + "sk": "10", + "pk": "03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a" + }, + { + "beta": "dbfeac68bfc25d1fd3f9d0bfe093edfef9e90c1b4d2940ac961c1d08ba66deb4", + "alpha": "73616d706c65", + "pi": "028594a13f389fbb3618bb5db54059ea673f087d7193ed8513d1abc7f3a5228d0e99a976d08666bdb46b287ec41945de29cce12c2dac0ba226ef3ef383a0fba8e138b415816c5243af66ef5a51244d9616", + "sk": "11", + "pk": "03defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34" + }, + { + "beta": "87a0ff6de5a282746082ed187abc29f534c1ee4f641e604c7d241fea5155b2a2", + "alpha": "73616d706c65", + "pi": "03e9593d98552a6e3c3f45a8a566b4d2de9bd5ff1837b4ca91655dc6e91d59fb5b335fd59c15668b371093ee81df275c876761ebcbd60fa8127c7e601f99ce340a3ae8c00864c0e38ebe749e566c151240", + "sk": "12", + "pk": "025601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc" + }, + { + "beta": "32306c22ad369a6e0fd638f503c0dbf674cd9d66b5da0a8c83c1d78157814f90", + "alpha": "73616d706c65", + "pi": "02833a4a802ec7f90b91dc59cfc8138669d2e6ec3f933c4fc7e44389a5e02c6032816f05729899c003ae77025e22c703809f8ee1b35d04d250800c7e90533dc4f29b3667065fc2cae0cc3cd356962ac62a", + "sk": "13", + "pk": "022b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c" + }, + { + "beta": "4e853d2b79f1d2dd8e23be493efa8c685afc30198070aa5acbc53fddcace9aa9", + "alpha": "73616d706c65", + "pi": "022d2bb6961468e5a3aadae02157e584a4d45f58121185cafa11b93fae6eb4a4604d03e431646fb1ee06c04e562cbd0e7d8c4fc01bc8dc0ca0f7f5d4e138be2963f6ab25843a12dd6c5e34cfda1ecabf04", + "sk": "14", + "pk": "024ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97" + }, + { + "beta": "642a4819a8e8e5739cc0f4bd5221d641774f2d33b75007c4de61f4f2089df92c", + "alpha": "73616d706c65", + "pi": "02570056bade9dc5204721d0ecd39906a72468d027dfa1a896b8f6a88d50fc5526f7afb112bb95a2e13f326cbf1c8de77b7596195575b4dd712edbfd96acafdcbc0fa1dfae4041bb64d8e25b276426ea5a", + "sk": "018ebbb95eed0e13", + "pk": "02a90cc3d3f3e146daadfc74ca1372207cb4b725ae708cef713a98edd73d99ef29" + }, + { + "beta": "b042e27b4d0e1f1a1c8ec7d4c2c0b2ae988d4cbc526d1ffb11b0087bea97a630", + "alpha": "73616d706c65", + "pi": "02b87402d5f26e06c14a3136a6c868316d2a2d413d5ef2ef91cae3625d57e87ea326b2bb5f67e4fe3f5c65df958d1ecd7a9bebea344b1facd08fbc7512701bcababbc39c410d9d1c0980e688feada47468", + "sk": "159d893d4cdd747246cdca43590e13", + "pk": "03e5a2636bcfd412ebf36ec45b19bfb68a1bc5f8632e678132b885f7df99c5e9b3" + }, + { + "beta": "3a36fc2ff539e516897c53d61951209dcac171500ed79692434a28e0cb9c3272", + "alpha": "73616d706c65", + "pi": "02e111fc96dd022c02f45df180c3707d5a48a5eb669aad2f7b45345b5f95a38f68b82b8cfa5dee906023fe4c2a15723636e29c8fc8d65ade1620b0d6453331f0237f632e89f0352fd25662d5630b3a6034", + "sk": "3fffffffffffffffffffffffffffffffaeabb739abd2280eeff497a3340d9050", + "pk": "03a6b594b38fb3e77c6edf78161fade2041f4e09fd8497db776e546c41567feb3c" + }, + { + "beta": "c6e3b662984301fc84c5eb2f5c0f435aee2975a731e6707bb9e50113e4bc2809", + "alpha": "73616d706c65", + "pi": "023a435fc5fab74b0b33eeb7c62447efc323e6e33a19657e7a0a473451b885fe841f28b91f43834ab659f26ea94d9dbca325192c45589afc1415e508b72247c64e385d3f9aa13c2e571d252335b8f63a3e", + "sk": "7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", + "pk": "0300000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63" + }, + { + "beta": "a25353782f363555d90c822a347151272d364103aa49513105bcc247287ff6a9", + "alpha": "73616d706c65", + "pi": "02f769ca0cb1a96046265c19d5ef44deade0eb42a6aab094c7fde5bcdae09455db2ba3ffa7e72d01ead1fedc0162507c5d8ccbde61e09cd533b807404b75a4acb8573881f86abbf41bc0877acb3362604f", + "sk": "bfffffffffffffffffffffffffffffff0c0325ad0376782ccfddc6e99c28b0f0", + "pk": "02e24ce4beee294aa6350faa67512b99d388693ae4e7f53d19882a6ea169fc1ce1" + }, + { + "beta": "9731f862d34587fb91521d785a30ff57188c57efd4b55239199ae4ed31bcebf8", + "alpha": "73616d706c65", + "pi": "02d196a5eb787d5d8a33247607d78d5a48164ac4d899dba33cb3a5f68032124ba1b2221b96ae997d450ddd8e5863a0cc7cf1b3f50431aa6031b6807396edfab5d1f5812c7e8d40f157028afb7aa51a41d5", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036412d", + "pk": "034ce119c96e2fa357200b559b2f7dd5a5f02d5290aff74b03f3e471b273211c97" + }, + { + "beta": "54c8f3e98a8a8e5b77d327cdb7a71e5959996b5619972a8b472d7a3799a79387", + "alpha": "73616d706c65", + "pi": "0391aeaecb887e9d6f0c0f64d20f28acbe687bffabaaea0ff5237f236693eb5b56c88099425415cd9d242c70249f7abb8958a327ad341b4fca735f8ba61b57c9735252b72afab7e0cb6e49c9436366e800", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036412e", + "pk": "032b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c" + }, + { + "beta": "f9fba571cb27776c07d2bc42d670952e1965357942eca3edb5f80e28bc9aaed0", + "alpha": "73616d706c65", + "pi": "03b9ffede3d97b9753f8f31cd5d56442c525a5bccc2de1fc547886ee08bca9b4f3c1d44da0826ddfd763801c42875d41deeae99422c0e9e6a97e07e2689f58289bffe499069785dcffa4ff93a5b1e15856", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036412f", + "pk": "035601570cb47f238d2b0286db4a990fa0f3ba28d1a319f5e7cf55c2a2444da7cc" + }, + { + "beta": "c66931ad96cb4e1a44202fcd7882089b1cf77b07c426d292e0e15deca5c1b027", + "alpha": "73616d706c65", + "pi": "03ca01e6d80f99bd12c5c00142a9eb0c0e029f999a1e945a70110c944d5d5981c9814fb051e88c36f0c14d9acdfc3040b37fcc77fa1bfc23466730a108849e0a08f5e9c79331b04803e568ea4b553ce3f1", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364130", + "pk": "02defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34" + }, + { + "beta": "4b00d6d00864c7972105755b538d5f62a3585b6e8e7061fd107317fa1004efc0", + "alpha": "73616d706c65", + "pi": "03df963611501cf382e2730131618377ab38486f483db1eab7feb6ade0e1b0141bd3d291b7e45a1b94cabbafa5fca3fb7ba36b158bbcdb2292383689a6231e201a3f78f9f40757e99f80e8032adbc8d4ce", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364131", + "pk": "02e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a" + }, + { + "beta": "e1e9b8491278b6faf79d433cee7d9b01256f18b3d63601f6231332ce3751411c", + "alpha": "73616d706c65", + "pi": "03ee58341c2222f7671318eff4bf2bd5588221d37d133a8aafcff5162d56af906581ce8cc5d45d546b8cf2c6d22026b934688e9a68555d4386d75f9b9e554b58b886ad91285872a2a6f137576b6bf9513f", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364132", + "pk": "03d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e" + }, + { + "beta": "72c8e10530d3f0c6e452f8f20d911908eb01887c62bbae0b1eb35cb1f36b7985", + "alpha": "73616d706c65", + "pi": "03ae19c4bac9d64009b7dabf9095c3ee3c848249269d41d5ee492683cef4a0b8464fa567b84a2bfe1c7359696522d01e083defdf2c4fe5aaad7bf67c93aab74d23069d05419c59c5cd5daed14e63bdc26f", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364133", + "pk": "02499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4" + }, + { + "beta": "11fee8e23d484d9aa8ed151f8452be11e70cfad8a44f707c00b04a11270c3d7a", + "alpha": "73616d706c65", + "pi": "0261cb37ca1f9c0ee11e41aadf4637fdddccb3f70f8ff1903727fbc2bd220720e737048df6aa7ddec95dc6a5f93f6808b5bbf2983c1733ce7b686dddc457001dbbae277d251d61f69e1af22d69b60c975e", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364134", + "pk": "02f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8" + }, + { + "beta": "dfa3543db662a08aac90bfd7dd9b39b77dacf16dda462fe5eaa26b0f595fc0f5", + "alpha": "73616d706c65", + "pi": "0376661cbff92aae582298a7348f4d8f7834e2d8f6707c9706f52e65aacf968d80b24c972d16acca689cf66a1d100c26d2b141b1c8b9835e6710db5126284b9540f43cf31394f9b3e0a87449df7ef6aee6", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364135", + "pk": "02d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a" + }, + { + "beta": "caae0b8dd19e20fd52f43b2fd416228b46ad625aa68ef6424ff388fb4727e0dc", + "alpha": "73616d706c65", + "pi": "0204fa576f63771c34e6cdb98f59997584528d109c7592ab867374d9b91051a4d1e875685ea35673d901ff06f18d7e89bc098be8762abf7688dba945d09d9b71348624b40c4b903de2bd3cc44abb2fafc7", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364136", + "pk": "02774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb" + }, + { + "beta": "97e0785b78305d909af2a255e1b26d4faf5879d4e7640bceac71e56b3851bec0", + "alpha": "73616d706c65", + "pi": "024d4ff3ad7689b905b5c4be9de0bd8d7960e30f145903fe715af943852229f269122fadc5f835ee029d306ad7d90f5c6011ad67d24a327cccf3f39018e34df7a1544d6748755fa07ce2013729816e2330", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364137", + "pk": "02a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7" + }, + { + "beta": "e0a3519f3dd1597039b5617d5b09c8ed5c723d1589010c1d6284dd8fb9d5ea7b", + "alpha": "73616d706c65", + "pi": "022eb72eccc7228307eaf7946a28feac02de8223534800cc71d7d1195fb0a7c88630d9be168212ecee12897644c456c22eaa9be58c9c8bb92a86a73e787f44f55a57203ddd9d80bf4e1ad4ac21c03a5f2c", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364138", + "pk": "02acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe" + }, + { + "beta": "ba9235a6d8c3a2efa2b6cc2d8f23d3b9169ae0a0363db2192465aefbff07ed09", + "alpha": "73616d706c65", + "pi": "038fbe2d674ae973b17ee720413e94ee0387d1f794766ec9649d97ccbf6afaa22ce90783ffc7eb0c082db401cb81203ced6223bf24f66cd2c19351f4e18c9fd7a2884d82870ea357bd5bbb4ce9e1e4e840", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364139", + "pk": "032f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01" + }, + { + "beta": "9c9dc6b4b61b59950c15c35fb665cc94879b0297fac4edf2803de529b00f8c0c", + "alpha": "73616d706c65", + "pi": "0235731391a2ed6ff06cdb279b71ae0151d4f43041cfa8c27d958ab95d08b1bcae807694c56c2ec4ebc855253e3a66e798ea6701ae6861a2ad67a8c2a3ce14c3e8af2f3936fabd5a13dde062afd040e50a", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413a", + "pk": "035cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc" + }, + { + "beta": "110f1fa93881cf624c22b72f1b79e6138a052a462ff10d7aa56f501835a8f6b8", + "alpha": "73616d706c65", + "pi": "03913bdfa315ab0963b03c34ebe265751e8b5904837bbda75629423b485924fee45b397e9d697239fdcfd435f1b21082d94f1917c792300c4ada68c0ac4e9da7cf2db99c5cbf2775ac4161ea2ed3c589a6", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413b", + "pk": "02fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556" + }, + { + "beta": "a43ebaef2262310b95e140287c861c53edefc13c37696c3f89234d1a45eccf17", + "alpha": "73616d706c65", + "pi": "024dbc319514312b5544e6b587a978dfccbdc862d7fc33c5dda706efb569613df99fa8b04b237169cb92397564f92bd1e45e041817e7a3368fa1f47fcca1e9bd01a6915e645b2d411815b2b95c9efef590", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413c", + "pk": "032f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4" + }, + { + "beta": "c8952a9439d26d3e761399de1fd734a2338c15893ece5a3efc72e25c9f007da8", + "alpha": "73616d706c65", + "pi": "03e30118c907034baf1456063bf7b423972e13e1743bf8dbb2e00fd8ba4a8c367a299bc3859123464d87fd4a508e5a1321f6bde3f00104b2c8af1769781dfb02e749946f4e17f6e429be0f4e4e3085e320", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413d", + "pk": "03e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13" + }, + { + "beta": "25daded1cb7561c8e0013315a6f6d9dd1611d95c92caf5f920bc437ae0180a55", + "alpha": "73616d706c65", + "pi": "02ed1bb54a9092c8fd50ae8cea3322e127600a0e32840d9bc4664cfab08b1c6ba3a36ad7913367088f6e6cdbc91a061cfbd0fab0093344414aa16e43dcc5394c7a06cb46afb049eeffc2e99d16992bc228", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "pk": "03f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9" + }, + { + "beta": "3bcee6576d82d011563480c8fcc5751ba6aea58313dbba4cb278d2f74eaee3ea", + "alpha": "73616d706c65", + "pi": "03359425334b14173856433b4e695f1d19c7c0cb4eb9b5c72b0b00afe170ce7fd738334a976a8be4582b05a480cdecf8a4f4dd9d0694ae1dcb384429a1c99082bdb2845e2c3010054071489f41fc4b65a5", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f", + "pk": "03c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5" + }, + { + "beta": "8efc7ce3fa0ee91c2e7d45ead94883776e37bdb3af67f386e7ec500e76e066dd", + "alpha": "73616d706c65", + "pi": "03cc27d840191d06dfca94d9346cc5b85830dcf9c9e7e4a41cc857d841bd48186c6c5d463591b9632297b3aab781d23263fd9cfc41fbb6affa02840bb903f51b494dc492087ba6fe04acf7c5b54ec0de24", + "sk": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "pk": "0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" + } +] \ No newline at end of file From cbc6e6224e462729f580a7af5b6a2b0439a63c94 Mon Sep 17 00:00:00 2001 From: gldeng Date: Tue, 13 Jun 2023 21:45:54 +0800 Subject: [PATCH 039/139] Clean up --- src/AElf.Cryptography/ECVRF/Vrf.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index e916503579..d2940984dd 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -186,17 +186,6 @@ public BigInteger HashPoints(Secp256k1 secp256k1, params Point[] points) return new BigInteger(1, hashTruncated); } - // - // public BigInteger Bits2Int(byte[] inputBytes, int qlen) - // { - // var output = new BigInteger(inputBytes); - // if (inputBytes.Length * 8 > qlen) - // { - // return output.ShiftRight(inputBytes.Length * 8 - qlen); - // } - // - // return output; - // } public byte[] EncodeProof(Point gamma, BigInteger c, BigInteger s) { using var secp256k1 = new Secp256k1(); From 7e9a77c7110ecb82a7ef4eaaeb1cdb299a91815d Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Wed, 14 Jun 2023 11:27:26 +0800 Subject: [PATCH 040/139] feat: add delegatee charge fee unit test. --- ...inTransactionDirectlyTest_FreeAllowance.cs | 321 ++++++++++++++++++ 1 file changed, 321 insertions(+) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index 4794b14c42..042e03b9d9 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -1,8 +1,10 @@ +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using AElf.Contracts.MultiToken; using AElf.CSharp.Core.Extension; using AElf.Standards.ACS1; +using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; @@ -1719,6 +1721,314 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await CheckDefaultSenderTokenAsync(USDT, afterUSDTBalance); } + [Theory] + [InlineData(100, 100, 100)] + public async Task ChargeTransactionFee_DelegateMultipleFeeTokens_PriorityAllowance_Success_Test(long initialELFBalance, long initialUSDTBalance, + long initialToken1Balance) + { + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, USDT); + await CreateTokenAsync(DefaultSender, Token1); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 5); + await IssueTokenToDefaultSenderAsync(USDT, 5); + await IssueTokenToDefaultSenderAsync(Token1,5); + await IssueTokenToUserAsync(NativeTokenSymbol, initialELFBalance, DelegateeAddress); + await IssueTokenToUserAsync(USDT, initialUSDTBalance, DelegateeAddress); + await IssueTokenToUserAsync(Token1, initialToken1Balance, DelegateeAddress); + + await SetDelegateeAsync(); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + { + Value = + { + new ConfigTransactionFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances + { + Value = + { + new TransactionFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + Amount = 5 + }, + new TransactionFeeFreeAllowance + { + Symbol = USDT, + Amount = 30 + }, + new TransactionFeeFreeAllowance + { + Symbol = Token1, + Amount = 10 + } + } + }, + RefreshSeconds = 600, + Threshold = 100 + } + } + }); + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = 6 + }, + new MethodFee + { + Symbol = Token1, + BasicFee = 7 + } + } + }; + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = USDT, + AddedTokenWeight = 3, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DelegateeAddress); + if (initialELFBalance >= 100) + { + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(5); + + freeAllowances.Map.Values.First().Map.Keys.ElementAt(1).ShouldBe(USDT); + freeAllowances.Map.Values.First().Map.Values.ElementAt(1).Symbol.ShouldBe(USDT); + freeAllowances.Map.Values.First().Map.Values.ElementAt(1).Amount.ShouldBe(30); + + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(10); + } + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = 7, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DelegateeAddress); + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DelegateeAddress, + Symbol = NativeTokenSymbol + }); + if (balance.Balance >= 100) + { + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(5); + + freeAllowances.Map.Values.First().Map.Keys.ElementAt(1).ShouldBe(USDT); + freeAllowances.Map.Values.First().Map.Values.ElementAt(1).Symbol.ShouldBe(USDT); + freeAllowances.Map.Values.First().Map.Values.ElementAt(1).Amount.ShouldBe(9); + + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(3); + } + + await CheckUserTokenAsync(DelegateeAddress,Token1, 100); + await CheckUserTokenAsync(DelegateeAddress,NativeTokenSymbol, 100); + await CheckUserTokenAsync(DelegateeAddress,USDT, 100); + } + + [Fact] + public async Task ChargeTransactionFee_DelegateMultipleFeeTokens_PriorityAllowanceGreaterThan0_Success_Test() + { + await SetPrimaryTokenSymbolAsync(); + await CreateTokenAsync(DefaultSender, USDT); + await CreateTokenAsync(DefaultSender, Token1); + + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 5); + await IssueTokenToDefaultSenderAsync(USDT, 5); + await IssueTokenToDefaultSenderAsync(Token1,5); + await IssueTokenToUserAsync(NativeTokenSymbol, 100, DelegateeAddress); + await IssueTokenToUserAsync(USDT, 100, DelegateeAddress); + await IssueTokenToUserAsync(Token1, 100, DelegateeAddress); + + await SetDelegateeAsync(); + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + { + Value = + { + new ConfigTransactionFeeFreeAllowance + { + Symbol = NativeTokenSymbol, + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances + { + Value = + { + new TransactionFeeFreeAllowance + { + Symbol = USDT, + Amount = 10 + }, + new TransactionFeeFreeAllowance + { + Symbol = Token1, + Amount = 10 + } + } + }, + RefreshSeconds = 600, + Threshold = 100 + } + } + }); + var methodFee = new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = + { + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = 10 + }, + new MethodFee + { + Symbol = Token1, + BasicFee = 30 + } + } + }; + + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + var sizeFeeSymbolList = new SymbolListToPayTxSizeFee + { + SymbolsToPayTxSizeFee = + { + new SymbolToPayTxSizeFee + { + TokenSymbol = NativeTokenSymbol, + AddedTokenWeight = 1, + BaseTokenWeight = 1 + }, + new SymbolToPayTxSizeFee + { + TokenSymbol = USDT, + AddedTokenWeight = 3, + BaseTokenWeight = 1 + } + } + }; + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + var initialELFBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DelegateeAddress, + Symbol = NativeTokenSymbol + })).Balance; + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DelegateeAddress); + if (initialELFBalance >= 100) + { + freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); + + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(USDT); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(USDT); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(10); + + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(10); + } + var chargeTransactionFeesInput = new ChargeTransactionFeesInput + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + TransactionSizeFee = 7, + }; + chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); + + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); + chargeFeeRet.Output.Success.ShouldBe(true); + + freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DelegateeAddress); + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = DelegateeAddress, + Symbol = NativeTokenSymbol + }); + if (balance.Balance >= 100) + { + freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(USDT); + freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(USDT); + freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); + + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(Token1); + freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(0); + } + + await CheckUserTokenAsync(DelegateeAddress,Token1, 80); + await CheckUserTokenAsync(DelegateeAddress,NativeTokenSymbol, 100); + await CheckUserTokenAsync(DelegateeAddress,USDT, 89); + } + + private async Task SetDelegateeAsync() + { + var delegations = new Dictionary + { + [NativeTokenSymbol] = 100, + [USDT] = 100, + [Token1] = 100 + }; + var delegateInfo1 = new DelegateInfo + { + Delegations = { delegations }, + IsUnlimitedDelegate = false, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + ContractAddress = TokenContractAddress, + }; + await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( + new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = DefaultSender, + DelegateInfoList = { delegateInfo1 } + }); + } + private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) { var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput @@ -1729,6 +2039,17 @@ private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) balance.Balance.ShouldBe(amount); } + + private async Task CheckUserTokenAsync(Address user,string symbol, long amount) + { + var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = user, + Symbol = symbol + }); + + balance.Balance.ShouldBe(amount); + } private async Task CreateTokenAndIssueAsync() { From d49a8431a75b7fe886f2aef4580745eab5eb55be Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 14 Jun 2023 11:47:14 +0800 Subject: [PATCH 041/139] fix: ut --- .../ExecutePluginTransactionDirectlyTest_FreeAllowance.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index 042e03b9d9..33ae44c475 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -1276,7 +1276,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }, - RefreshSeconds = 2, + RefreshSeconds = 20, Threshold = 100 }, new ConfigTransactionFeeFreeAllowance @@ -1293,7 +1293,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }, - RefreshSeconds = 1, + RefreshSeconds = 10, Threshold = 100 } } @@ -1392,7 +1392,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await CheckDefaultSenderTokenAsync(Token1, 9000); await CheckDefaultSenderTokenAsync(Token2, 10000); - _blockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddSeconds(1)); + _blockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddSeconds(10)); chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); From fe3b0ea877ded79f9a265a6bb13c717c42eed2e4 Mon Sep 17 00:00:00 2001 From: gldeng Date: Wed, 14 Jun 2023 15:20:24 +0800 Subject: [PATCH 042/139] Implement Verify method --- src/AElf.Cryptography/ECVRF/IVrf.cs | 10 +- src/AElf.Cryptography/ECVRF/Vrf.cs | 135 ++++++++++++++++-- .../AElf.Cryptography.Tests/ECVRF/VRFTests.cs | 20 +++ 3 files changed, 156 insertions(+), 9 deletions(-) diff --git a/src/AElf.Cryptography/ECVRF/IVrf.cs b/src/AElf.Cryptography/ECVRF/IVrf.cs index d5989147a8..b494d617eb 100644 --- a/src/AElf.Cryptography/ECVRF/IVrf.cs +++ b/src/AElf.Cryptography/ECVRF/IVrf.cs @@ -1,4 +1,5 @@ using AElf.Cryptography.ECDSA; +using Org.BouncyCastle.Math; namespace AElf.Cryptography.ECVRF; @@ -8,8 +9,15 @@ public struct Proof public byte[] Pi { get; set; } } +public struct ProofInput +{ + public Point Gamma { get; set; } + public BigInteger C { get; set; } + public BigInteger S { get; set; } +} + public interface IVrf { Proof Prove(ECKeyPair keyPair, byte[] alpha); - byte[] Verify(byte[] publicKey, Proof proof); + byte[] Verify(byte[] publicKey, byte[] alpha, byte[] pi); } \ No newline at end of file diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index d2940984dd..f1292a9b25 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -17,10 +17,39 @@ public class FailedToHashToCurveException : Exception { } +public class InvalidProofLengthException : Exception +{ +} + +public class InvalidScalarException : Exception +{ +} + +public class FailedToMultiplyScalarException : Exception +{ +} + +public class FailedToNegatePublicKeyException : Exception +{ +} + +public class FailedToCombinePublicKeysException : Exception +{ +} + +public class InvalidProofException : Exception +{ +} public struct Point { + private BigInteger P = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16); public byte[] Inner { get; private set; } + private Point(byte[] inner) + { + Inner = inner; + } + public static Point FromInner(byte[] inner) { return new Point() { Inner = inner }; @@ -89,8 +118,10 @@ public VrfConfig(byte suiteString) public class Vrf : IVrf { + private const int BitSize = 256; private const int QBitsLength = 256; private const int N = 16; + private VrfConfig _config; public Vrf(VrfConfig config) @@ -123,9 +154,76 @@ public Proof Prove(ECKeyPair keyPair, byte[] alpha) }; } - public byte[] Verify(byte[] publicKey, Proof proof) + public byte[] Verify(byte[] publicKey, byte[] alpha, byte[] pi) { - throw new System.NotImplementedException(); + using var secp256k1 = new Secp256k1(); + var proofInput = DecodeProof(secp256k1, pi); + + var pkPoint = Point.FromSerialized(secp256k1, publicKey); + var hashPoint = HashToCurveTryAndIncrement(pkPoint, alpha); + var sBytes = AddLeadingZeros(proofInput.S.ToByteArray(), Secp256k1.PRIVKEY_LENGTH) + .TakeLast(Secp256k1.PRIVKEY_LENGTH).ToArray(); + + var sB = new byte[Secp256k1.PUBKEY_LENGTH]; + if (!secp256k1.PublicKeyCreate(sB, sBytes)) + { + throw new InvalidScalarException(); + } + + var cYNeg = new byte[Secp256k1.PUBKEY_LENGTH]; + Buffer.BlockCopy(pkPoint.Inner, 0, cYNeg, 0, cYNeg.Length); + + if (!secp256k1.PublicKeyMultiply(cYNeg, AddLeadingZeros(proofInput.C.ToByteArray(), Secp256k1.PRIVKEY_LENGTH))) + { + throw new FailedToMultiplyScalarException(); + } + + if (!secp256k1.PublicKeyNegate(cYNeg)) + { + throw new FailedToNegatePublicKeyException(); + } + + var u = new byte[Secp256k1.PUBKEY_LENGTH]; + + if (!secp256k1.PublicKeysCombine(u, sB, cYNeg)) + { + throw new FailedToCombinePublicKeysException(); + } + + var sH = new byte[Secp256k1.PUBKEY_LENGTH]; + Buffer.BlockCopy(hashPoint.Inner, 0, sH, 0, sH.Length); + + if (!secp256k1.PublicKeyMultiply(sH, sBytes)) + { + throw new FailedToMultiplyScalarException(); + } + + var cGammaNeg = new byte[Secp256k1.PUBKEY_LENGTH]; + Buffer.BlockCopy(proofInput.Gamma.Inner, 0, cGammaNeg, 0, cGammaNeg.Length); + if (!secp256k1.PublicKeyMultiply(cGammaNeg, AddLeadingZeros(proofInput.C.ToByteArray(), Secp256k1.PRIVKEY_LENGTH))) + { + throw new FailedToMultiplyScalarException(); + } + + if (!secp256k1.PublicKeyNegate(cGammaNeg)) + { + throw new FailedToNegatePublicKeyException(); + } + + var v = new byte[Secp256k1.PUBKEY_LENGTH]; + + if (!secp256k1.PublicKeysCombine(v, sH, cGammaNeg)) + { + throw new FailedToCombinePublicKeysException(); + } + + var derivedC = HashPoints(secp256k1, hashPoint, proofInput.Gamma, Point.FromInner(u), Point.FromInner(v)); + if (!derivedC.Equals(proofInput.C)) + { + throw new InvalidProofException(); + } + + return GammaToHash(secp256k1, proofInput.Gamma); } public Point HashToCurveTryAndIncrement(Point point, byte[] alpha) @@ -199,6 +297,27 @@ public byte[] EncodeProof(Point gamma, BigInteger c, BigInteger s) return output; } + public ProofInput DecodeProof(Secp256k1 secp256k1, byte[] pi) + { + const int ptLength = (BitSize + 7) / 8 + 1; + const int cLength = N; + const int sLength = (QBitsLength + 7) / 8; + if (pi.Length != ptLength + cLength + sLength) + { + throw new InvalidProofLengthException(); + } + + var gammaPoint = Point.FromSerialized(secp256k1, pi.Take(ptLength).ToArray()); + var c = new BigInteger(1, pi.Skip(ptLength).Take(cLength).ToArray()); + var s = new BigInteger(1, pi.TakeLast(sLength).ToArray()); + return new ProofInput() + { + Gamma = gammaPoint, + C = c, + S = s + }; + } + private static byte[] AddLeadingZeros(byte[] data, int requiredLength) { var zeroBytesLength = requiredLength - data.Length; @@ -233,7 +352,7 @@ public byte[] Rfc6979Nonce(Secp256k1 secp256k1, ECKeyPair keyPair, Point hashPoi var hash = hasher.ComputeHash(hBytes); var bh = Bits2Bytes(hash, ECParameters.DomainParams.N, roLen); - + var nonce = new byte[Secp256k1.NONCE_LENGTH]; secp256k1.Rfc6979Nonce(nonce, bh, keyPair.PrivateKey, null, null, 0); return nonce; @@ -242,7 +361,7 @@ public byte[] Rfc6979Nonce(Secp256k1 secp256k1, ECKeyPair keyPair, Point hashPoi public byte[] Int2Bytes(BigInteger v, int rolen) { var result = v.ToByteArray(); - if ( result.Length < rolen) + if (result.Length < rolen) { return AddLeadingZeros(result, rolen); } @@ -255,19 +374,19 @@ public byte[] Int2Bytes(BigInteger v, int rolen) return result; } - - public BigInteger Bits2Int(byte[]inputBytes, int qlen) + + public BigInteger Bits2Int(byte[] inputBytes, int qlen) { var output = new BigInteger(1, inputBytes); if (inputBytes.Length * 8 > qlen) { return output.ShiftRight(inputBytes.Length * 8 - qlen); } - + return output; } - public byte[] Bits2Bytes(byte[]input, BigInteger q, int rolen) + public byte[] Bits2Bytes(byte[] input, BigInteger q, int rolen) { var z1 = Bits2Int(input, q.BitLength); var z2 = z1.Subtract(q); diff --git a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs index 5b66790cfc..419480859e 100644 --- a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs +++ b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs @@ -67,6 +67,26 @@ public void Prove_Test() } } + [Fact] + public void Verify_Test() + { + var path = Path.Combine( Directory.GetCurrentDirectory(), "secp256_k1_sha256_tai.json"); + var text = File.ReadAllText(path); + var vectors = JsonSerializer.Deserialize>(text); + using var secp256k1 = new Secp256k1(); + foreach (var vector in vectors) + { + var pk =Convert.FromHexString(vector.Pk); + var alpha = Convert.FromHexString(vector.Alpha); + var pi = Convert.FromHexString(vector.Pi); + var expectedBeta = Convert.FromHexString(vector.Beta); + var cfg = new VrfConfig( 0xfe); + var vrf = new Vrf(cfg); + var beta = vrf.Verify(pk, alpha, pi); + Assert.Equal(expectedBeta, beta); + } + } + private byte[] AddLeadingZeros(byte[] sk) { if (sk.Length < 32) From 65a7e90155f4e7dc32fcde34f1e96ca8b70bc731 Mon Sep 17 00:00:00 2001 From: gldeng Date: Wed, 14 Jun 2023 15:26:14 +0800 Subject: [PATCH 043/139] Add negative test cases --- test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs index 419480859e..9670a23f74 100644 --- a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs +++ b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs @@ -87,6 +87,23 @@ public void Verify_Test() } } + [Fact] + public void Verify_BadMessageFailsVerification_Test() + { + var path = Path.Combine( Directory.GetCurrentDirectory(), "secp256_k1_sha256_tai.json"); + var text = File.ReadAllText(path); + var vectors = JsonSerializer.Deserialize>(text); + using var secp256k1 = new Secp256k1(); + foreach (var vector in vectors) + { + var pk =Convert.FromHexString(vector.Pk); + var alpha = Encoding.ASCII.GetBytes("this is a wrong message"); + var pi = Convert.FromHexString(vector.Pi); + var cfg = new VrfConfig( 0xfe); + var vrf = new Vrf(cfg); + Assert.Throws(() => vrf.Verify(pk, alpha, pi)); + } + } private byte[] AddLeadingZeros(byte[] sk) { if (sk.Length < 32) From 162bc52498266c9684064155e76c47e29151a6b5 Mon Sep 17 00:00:00 2001 From: gldeng Date: Wed, 14 Jun 2023 15:32:53 +0800 Subject: [PATCH 044/139] Extract helpers --- src/AElf.Cryptography/ECVRF/Helpers.cs | 69 +++++++++++++++++++++++ src/AElf.Cryptography/ECVRF/Vrf.cs | 77 +++++--------------------- 2 files changed, 82 insertions(+), 64 deletions(-) create mode 100644 src/AElf.Cryptography/ECVRF/Helpers.cs diff --git a/src/AElf.Cryptography/ECVRF/Helpers.cs b/src/AElf.Cryptography/ECVRF/Helpers.cs new file mode 100644 index 0000000000..1f115786c6 --- /dev/null +++ b/src/AElf.Cryptography/ECVRF/Helpers.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using AElf.Cryptography.ECDSA; +using Org.BouncyCastle.Math; +using Secp256k1Net; +using ECParameters = System.Security.Cryptography.ECParameters; + +namespace AElf.Cryptography.ECVRF; + +public static class Helpers +{ + + public static byte[] AddLeadingZeros(byte[] data, int requiredLength) + { + var zeroBytesLength = requiredLength - data.Length; + if (zeroBytesLength <= 0) return data; + var output = new byte[requiredLength]; + Buffer.BlockCopy(data, 0, output, zeroBytesLength, data.Length); + for (int i = zeroBytesLength - 1; i >= 0; i--) + { + output[i] = 0x0; + } + + return output; + } + + + public static byte[] Int2Bytes(BigInteger v, int rolen) + { + var result = v.ToByteArray(); + if (result.Length < rolen) + { + return AddLeadingZeros(result, rolen); + } + + if (result.Length > rolen) + { + var skipLength = result.Length - rolen; + return result.Skip(skipLength).ToArray(); + } + + return result; + } + + public static BigInteger Bits2Int(byte[] inputBytes, int qlen) + { + var output = new BigInteger(1, inputBytes); + if (inputBytes.Length * 8 > qlen) + { + return output.ShiftRight(inputBytes.Length * 8 - qlen); + } + + return output; + } + + public static byte[] Bits2Bytes(byte[] input, BigInteger q, int rolen) + { + var z1 = Bits2Int(input, q.BitLength); + var z2 = z1.Subtract(q); + if (z2.SignValue == -1) + { + return Int2Bytes(z1, rolen); + } + + return Int2Bytes(z2, rolen); + } +} \ No newline at end of file diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index f1292a9b25..95c6447bf9 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -40,6 +40,7 @@ public class FailedToCombinePublicKeysException : Exception public class InvalidProofException : Exception { } + public struct Point { private BigInteger P = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16); @@ -161,7 +162,7 @@ public byte[] Verify(byte[] publicKey, byte[] alpha, byte[] pi) var pkPoint = Point.FromSerialized(secp256k1, publicKey); var hashPoint = HashToCurveTryAndIncrement(pkPoint, alpha); - var sBytes = AddLeadingZeros(proofInput.S.ToByteArray(), Secp256k1.PRIVKEY_LENGTH) + var sBytes = Helpers.AddLeadingZeros(proofInput.S.ToByteArray(), Secp256k1.PRIVKEY_LENGTH) .TakeLast(Secp256k1.PRIVKEY_LENGTH).ToArray(); var sB = new byte[Secp256k1.PUBKEY_LENGTH]; @@ -173,7 +174,8 @@ public byte[] Verify(byte[] publicKey, byte[] alpha, byte[] pi) var cYNeg = new byte[Secp256k1.PUBKEY_LENGTH]; Buffer.BlockCopy(pkPoint.Inner, 0, cYNeg, 0, cYNeg.Length); - if (!secp256k1.PublicKeyMultiply(cYNeg, AddLeadingZeros(proofInput.C.ToByteArray(), Secp256k1.PRIVKEY_LENGTH))) + if (!secp256k1.PublicKeyMultiply(cYNeg, + Helpers.AddLeadingZeros(proofInput.C.ToByteArray(), Secp256k1.PRIVKEY_LENGTH))) { throw new FailedToMultiplyScalarException(); } @@ -192,15 +194,16 @@ public byte[] Verify(byte[] publicKey, byte[] alpha, byte[] pi) var sH = new byte[Secp256k1.PUBKEY_LENGTH]; Buffer.BlockCopy(hashPoint.Inner, 0, sH, 0, sH.Length); - + if (!secp256k1.PublicKeyMultiply(sH, sBytes)) { throw new FailedToMultiplyScalarException(); } - + var cGammaNeg = new byte[Secp256k1.PUBKEY_LENGTH]; Buffer.BlockCopy(proofInput.Gamma.Inner, 0, cGammaNeg, 0, cGammaNeg.Length); - if (!secp256k1.PublicKeyMultiply(cGammaNeg, AddLeadingZeros(proofInput.C.ToByteArray(), Secp256k1.PRIVKEY_LENGTH))) + if (!secp256k1.PublicKeyMultiply(cGammaNeg, + Helpers.AddLeadingZeros(proofInput.C.ToByteArray(), Secp256k1.PRIVKEY_LENGTH))) { throw new FailedToMultiplyScalarException(); } @@ -211,7 +214,7 @@ public byte[] Verify(byte[] publicKey, byte[] alpha, byte[] pi) } var v = new byte[Secp256k1.PUBKEY_LENGTH]; - + if (!secp256k1.PublicKeysCombine(v, sH, cGammaNeg)) { throw new FailedToCombinePublicKeysException(); @@ -288,8 +291,8 @@ public byte[] EncodeProof(Point gamma, BigInteger c, BigInteger s) { using var secp256k1 = new Secp256k1(); var gammaBytes = gamma.Serialize(secp256k1, true); - var cBytes = Int2Bytes(c, N); - var sBytes = Int2Bytes(s, (QBitsLength + 7) / 8); + var cBytes = Helpers.Int2Bytes(c, N); + var sBytes = Helpers.Int2Bytes(s, (QBitsLength + 7) / 8); var output = new byte[gammaBytes.Length + cBytes.Length + sBytes.Length]; Buffer.BlockCopy(gammaBytes, 0, output, 0, gammaBytes.Length); Buffer.BlockCopy(cBytes, 0, output, gammaBytes.Length, cBytes.Length); @@ -318,20 +321,6 @@ public ProofInput DecodeProof(Secp256k1 secp256k1, byte[] pi) }; } - private static byte[] AddLeadingZeros(byte[] data, int requiredLength) - { - var zeroBytesLength = requiredLength - data.Length; - if (zeroBytesLength <= 0) return data; - var output = new byte[requiredLength]; - Buffer.BlockCopy(data, 0, output, zeroBytesLength, data.Length); - for (int i = zeroBytesLength - 1; i >= 0; i--) - { - output[i] = 0x0; - } - - return output; - } - public byte[] GammaToHash(Secp256k1 secp256k1, Point gamma) { var gammaBytes = gamma.Serialize(secp256k1, true); @@ -344,57 +333,17 @@ public byte[] GammaToHash(Secp256k1 secp256k1, Point gamma) return hasher.ComputeHash(stream); } - public byte[] Rfc6979Nonce(Secp256k1 secp256k1, ECKeyPair keyPair, Point hashPoint) + public static byte[] Rfc6979Nonce(Secp256k1 secp256k1, ECKeyPair keyPair, Point hashPoint) { using var hasher = SHA256.Create(); var roLen = (QBitsLength + 7) / 8; var hBytes = hashPoint.Serialize(secp256k1, true); var hash = hasher.ComputeHash(hBytes); - var bh = Bits2Bytes(hash, ECParameters.DomainParams.N, roLen); + var bh = Helpers.Bits2Bytes(hash, ECParameters.DomainParams.N, roLen); var nonce = new byte[Secp256k1.NONCE_LENGTH]; secp256k1.Rfc6979Nonce(nonce, bh, keyPair.PrivateKey, null, null, 0); return nonce; } - - public byte[] Int2Bytes(BigInteger v, int rolen) - { - var result = v.ToByteArray(); - if (result.Length < rolen) - { - return AddLeadingZeros(result, rolen); - } - - if (result.Length > rolen) - { - var skipLength = result.Length - rolen; - return result.Skip(skipLength).ToArray(); - } - - return result; - } - - public BigInteger Bits2Int(byte[] inputBytes, int qlen) - { - var output = new BigInteger(1, inputBytes); - if (inputBytes.Length * 8 > qlen) - { - return output.ShiftRight(inputBytes.Length * 8 - qlen); - } - - return output; - } - - public byte[] Bits2Bytes(byte[] input, BigInteger q, int rolen) - { - var z1 = Bits2Int(input, q.BitLength); - var z2 = z1.Subtract(q); - if (z2.SignValue == -1) - { - return Int2Bytes(z1, rolen); - } - - return Int2Bytes(z2, rolen); - } } \ No newline at end of file From d8a285512137daf6d05ab8b931fe63458ee868f5 Mon Sep 17 00:00:00 2001 From: gldeng Date: Wed, 14 Jun 2023 15:38:11 +0800 Subject: [PATCH 045/139] Reorg code --- src/AElf.Cryptography/ECVRF/Exceptions.cs | 35 +++++++ src/AElf.Cryptography/ECVRF/Helpers.cs | 6 -- src/AElf.Cryptography/ECVRF/IVrf.cs | 10 ++ src/AElf.Cryptography/ECVRF/Point.cs | 70 +++++++++++++ src/AElf.Cryptography/ECVRF/Vrf.cs | 118 +--------------------- 5 files changed, 120 insertions(+), 119 deletions(-) create mode 100644 src/AElf.Cryptography/ECVRF/Exceptions.cs create mode 100644 src/AElf.Cryptography/ECVRF/Point.cs diff --git a/src/AElf.Cryptography/ECVRF/Exceptions.cs b/src/AElf.Cryptography/ECVRF/Exceptions.cs new file mode 100644 index 0000000000..39ac629cad --- /dev/null +++ b/src/AElf.Cryptography/ECVRF/Exceptions.cs @@ -0,0 +1,35 @@ +using System; + +namespace AElf.Cryptography.ECVRF; + +public class InvalidSerializedPublicKeyException : Exception +{ +} + +public class FailedToHashToCurveException : Exception +{ +} + +public class InvalidProofLengthException : Exception +{ +} + +public class InvalidScalarException : Exception +{ +} + +public class FailedToMultiplyScalarException : Exception +{ +} + +public class FailedToNegatePublicKeyException : Exception +{ +} + +public class FailedToCombinePublicKeysException : Exception +{ +} + +public class InvalidProofException : Exception +{ +} \ No newline at end of file diff --git a/src/AElf.Cryptography/ECVRF/Helpers.cs b/src/AElf.Cryptography/ECVRF/Helpers.cs index 1f115786c6..bfdac47711 100644 --- a/src/AElf.Cryptography/ECVRF/Helpers.cs +++ b/src/AElf.Cryptography/ECVRF/Helpers.cs @@ -1,17 +1,11 @@ using System; -using System.IO; using System.Linq; -using System.Security.Cryptography; -using AElf.Cryptography.ECDSA; using Org.BouncyCastle.Math; -using Secp256k1Net; -using ECParameters = System.Security.Cryptography.ECParameters; namespace AElf.Cryptography.ECVRF; public static class Helpers { - public static byte[] AddLeadingZeros(byte[] data, int requiredLength) { var zeroBytesLength = requiredLength - data.Length; diff --git a/src/AElf.Cryptography/ECVRF/IVrf.cs b/src/AElf.Cryptography/ECVRF/IVrf.cs index b494d617eb..5fb8ac9344 100644 --- a/src/AElf.Cryptography/ECVRF/IVrf.cs +++ b/src/AElf.Cryptography/ECVRF/IVrf.cs @@ -16,6 +16,16 @@ public struct ProofInput public BigInteger S { get; set; } } +public struct VrfConfig +{ + public byte SuiteString { get; private set; } + + public VrfConfig(byte suiteString) + { + SuiteString = suiteString; + } +} + public interface IVrf { Proof Prove(ECKeyPair keyPair, byte[] alpha); diff --git a/src/AElf.Cryptography/ECVRF/Point.cs b/src/AElf.Cryptography/ECVRF/Point.cs new file mode 100644 index 0000000000..5c414ff6e4 --- /dev/null +++ b/src/AElf.Cryptography/ECVRF/Point.cs @@ -0,0 +1,70 @@ +using Org.BouncyCastle.Math; +using Secp256k1Net; + +namespace AElf.Cryptography.ECVRF; + +public struct Point +{ + private BigInteger P = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16); + public byte[] Inner { get; private set; } + + private Point(byte[] inner) + { + Inner = inner; + } + + public static Point FromInner(byte[] inner) + { + return new Point() { Inner = inner }; + } + + public static Point FromSerialized(Secp256k1 secp256k1, byte[] pkSerialized) + { + if (pkSerialized.Length != Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH && + pkSerialized.Length != Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH) + { + throw new InvalidSerializedPublicKeyException(); + } + + if (pkSerialized.Length == Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH) + { + if (pkSerialized[0] != 0x02 && pkSerialized[0] != 0x03) + { + throw new InvalidSerializedPublicKeyException(); + } + } + + if (pkSerialized.Length == Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH) + { + if (pkSerialized[0] != 0x04) + { + throw new InvalidSerializedPublicKeyException(); + } + } + + var inner = new byte[Secp256k1.PUBKEY_LENGTH]; + var successful = secp256k1.PublicKeyParse(inner, pkSerialized); + if (!successful) + { + throw new InvalidSerializedPublicKeyException(); + } + + return new Point() { Inner = inner }; + } + + public byte[] Serialize(Secp256k1 secp256k1, bool compressed = true) + { + if (compressed) + { + var output = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH]; + secp256k1.PublicKeySerialize(output, Inner, Flags.SECP256K1_EC_COMPRESSED); + return output; + } + else + { + var output = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH]; + secp256k1.PublicKeySerialize(output, Inner, Flags.SECP256K1_EC_UNCOMPRESSED); + return output; + } + } +} \ No newline at end of file diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index 95c6447bf9..a1b367ea83 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -9,114 +9,6 @@ namespace AElf.Cryptography.ECVRF; -public class InvalidSerializedPublicKeyException : Exception -{ -} - -public class FailedToHashToCurveException : Exception -{ -} - -public class InvalidProofLengthException : Exception -{ -} - -public class InvalidScalarException : Exception -{ -} - -public class FailedToMultiplyScalarException : Exception -{ -} - -public class FailedToNegatePublicKeyException : Exception -{ -} - -public class FailedToCombinePublicKeysException : Exception -{ -} - -public class InvalidProofException : Exception -{ -} - -public struct Point -{ - private BigInteger P = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16); - public byte[] Inner { get; private set; } - - private Point(byte[] inner) - { - Inner = inner; - } - - public static Point FromInner(byte[] inner) - { - return new Point() { Inner = inner }; - } - - public static Point FromSerialized(Secp256k1 secp256k1, byte[] pkSerialized) - { - if (pkSerialized.Length != Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH && - pkSerialized.Length != Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH) - { - throw new InvalidSerializedPublicKeyException(); - } - - if (pkSerialized.Length == Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH) - { - if (pkSerialized[0] != 0x02 && pkSerialized[0] != 0x03) - { - throw new InvalidSerializedPublicKeyException(); - } - } - - if (pkSerialized.Length == Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH) - { - if (pkSerialized[0] != 0x04) - { - throw new InvalidSerializedPublicKeyException(); - } - } - - var inner = new byte[Secp256k1.PUBKEY_LENGTH]; - var successful = secp256k1.PublicKeyParse(inner, pkSerialized); - if (!successful) - { - throw new InvalidSerializedPublicKeyException(); - } - - return new Point() { Inner = inner }; - } - - public byte[] Serialize(Secp256k1 secp256k1, bool compressed = true) - { - if (compressed) - { - var output = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH]; - secp256k1.PublicKeySerialize(output, Inner, Flags.SECP256K1_EC_COMPRESSED); - return output; - } - else - { - var output = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH]; - secp256k1.PublicKeySerialize(output, Inner, Flags.SECP256K1_EC_UNCOMPRESSED); - return output; - } - } -} - -public struct VrfConfig -{ - public byte SuiteString { get; private set; } - - public VrfConfig(byte suiteString) - { - SuiteString = suiteString; - } -} - public class Vrf : IVrf { private const int BitSize = 256; @@ -268,7 +160,7 @@ public Point HashToCurveTryAndIncrement(Point point, byte[] alpha) throw new FailedToHashToCurveException(); } - public BigInteger HashPoints(Secp256k1 secp256k1, params Point[] points) + private BigInteger HashPoints(Secp256k1 secp256k1, params Point[] points) { using var hasher = SHA256.Create(); using var stream = new MemoryStream(); @@ -287,7 +179,7 @@ public BigInteger HashPoints(Secp256k1 secp256k1, params Point[] points) return new BigInteger(1, hashTruncated); } - public byte[] EncodeProof(Point gamma, BigInteger c, BigInteger s) + private byte[] EncodeProof(Point gamma, BigInteger c, BigInteger s) { using var secp256k1 = new Secp256k1(); var gammaBytes = gamma.Serialize(secp256k1, true); @@ -300,7 +192,7 @@ public byte[] EncodeProof(Point gamma, BigInteger c, BigInteger s) return output; } - public ProofInput DecodeProof(Secp256k1 secp256k1, byte[] pi) + private ProofInput DecodeProof(Secp256k1 secp256k1, byte[] pi) { const int ptLength = (BitSize + 7) / 8 + 1; const int cLength = N; @@ -321,7 +213,7 @@ public ProofInput DecodeProof(Secp256k1 secp256k1, byte[] pi) }; } - public byte[] GammaToHash(Secp256k1 secp256k1, Point gamma) + private byte[] GammaToHash(Secp256k1 secp256k1, Point gamma) { var gammaBytes = gamma.Serialize(secp256k1, true); using var hasher = SHA256.Create(); @@ -333,7 +225,7 @@ public byte[] GammaToHash(Secp256k1 secp256k1, Point gamma) return hasher.ComputeHash(stream); } - public static byte[] Rfc6979Nonce(Secp256k1 secp256k1, ECKeyPair keyPair, Point hashPoint) + private static byte[] Rfc6979Nonce(Secp256k1 secp256k1, ECKeyPair keyPair, Point hashPoint) { using var hasher = SHA256.Create(); var roLen = (QBitsLength + 7) / 8; From 4ca835c1c0d8967ca74a02be5292d4bcfd1a1cdb Mon Sep 17 00:00:00 2001 From: gldeng Date: Wed, 14 Jun 2023 16:32:39 +0800 Subject: [PATCH 046/139] Make use of ECParameters --- src/AElf.Cryptography/ECVRF/IVrf.cs | 6 +++++- src/AElf.Cryptography/ECVRF/Vrf.cs | 19 +++++++++---------- .../AElf.Cryptography.Tests/ECVRF/VRFTests.cs | 10 ++++++---- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/AElf.Cryptography/ECVRF/IVrf.cs b/src/AElf.Cryptography/ECVRF/IVrf.cs index 5fb8ac9344..2ce5199e34 100644 --- a/src/AElf.Cryptography/ECVRF/IVrf.cs +++ b/src/AElf.Cryptography/ECVRF/IVrf.cs @@ -1,4 +1,5 @@ using AElf.Cryptography.ECDSA; +using Org.BouncyCastle.Asn1.X9; using Org.BouncyCastle.Math; namespace AElf.Cryptography.ECVRF; @@ -20,9 +21,12 @@ public struct VrfConfig { public byte SuiteString { get; private set; } - public VrfConfig(byte suiteString) + public X9ECParameters EcParameters { get; private set; } + + public VrfConfig(byte suiteString, X9ECParameters ecParameters) { SuiteString = suiteString; + EcParameters = ecParameters; } } diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index a1b367ea83..10726f45ee 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -5,15 +5,14 @@ using AElf.Cryptography.ECDSA; using Org.BouncyCastle.Math; using Secp256k1Net; -using ECParameters = AElf.Cryptography.ECDSA.ECParameters; namespace AElf.Cryptography.ECVRF; public class Vrf : IVrf { - private const int BitSize = 256; - private const int QBitsLength = 256; - private const int N = 16; + private int BitSize => _config.EcParameters.Curve.FieldSize; + private int QBitsLength => _config.EcParameters.N.BitLength; + private int N => ((BitSize + 1) / 2 + 7) / 8; private VrfConfig _config; @@ -38,7 +37,7 @@ public Proof Prove(ECKeyPair keyPair, byte[] alpha) secp256k1.PublicKeyMultiply(kH, nonce); var c = HashPoints(secp256k1, hashPoint, Point.FromInner(gamma), Point.FromInner(kB), Point.FromInner(kH)); var cX = c.Multiply(new BigInteger(1, keyPair.PrivateKey)); - var s = cX.Add(new BigInteger(1, nonce)).Mod(ECParameters.DomainParams.N); + var s = cX.Add(new BigInteger(1, nonce)).Mod(_config.EcParameters.N); var pi = EncodeProof(Point.FromInner(gamma), c, s); var beta = GammaToHash(secp256k1, Point.FromInner(gamma)); return new Proof @@ -194,9 +193,9 @@ private byte[] EncodeProof(Point gamma, BigInteger c, BigInteger s) private ProofInput DecodeProof(Secp256k1 secp256k1, byte[] pi) { - const int ptLength = (BitSize + 7) / 8 + 1; - const int cLength = N; - const int sLength = (QBitsLength + 7) / 8; + var ptLength = (BitSize + 7) / 8 + 1; + var cLength = N; + var sLength = (QBitsLength + 7) / 8; if (pi.Length != ptLength + cLength + sLength) { throw new InvalidProofLengthException(); @@ -225,14 +224,14 @@ private byte[] GammaToHash(Secp256k1 secp256k1, Point gamma) return hasher.ComputeHash(stream); } - private static byte[] Rfc6979Nonce(Secp256k1 secp256k1, ECKeyPair keyPair, Point hashPoint) + private byte[] Rfc6979Nonce(Secp256k1 secp256k1, ECKeyPair keyPair, Point hashPoint) { using var hasher = SHA256.Create(); var roLen = (QBitsLength + 7) / 8; var hBytes = hashPoint.Serialize(secp256k1, true); var hash = hasher.ComputeHash(hBytes); - var bh = Helpers.Bits2Bytes(hash, ECParameters.DomainParams.N, roLen); + var bh = Helpers.Bits2Bytes(hash, _config.EcParameters.N, roLen); var nonce = new byte[Secp256k1.NONCE_LENGTH]; secp256k1.Rfc6979Nonce(nonce, bh, keyPair.PrivateKey, null, null, 0); diff --git a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs index 9670a23f74..1c871389d0 100644 --- a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs +++ b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs @@ -4,6 +4,7 @@ using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using AElf.Cryptography.ECDSA; using AElf.Cryptography.ECVRF; using Secp256k1Net; using Xunit; @@ -38,7 +39,7 @@ public void HashToCurveTryAndIncrement_Test() var expectedHashPoint = Convert.FromHexString("027AD7D4C3A454D9ECC905F1E5436A328F2A106A2606EC4B44111CF9DC72A5B9FF"); using var secp256k1 = new Secp256k1(); - var cfg = new VrfConfig( 0xfe); + var cfg = new VrfConfig( 0xfe, ECParameters.Curve); var vrf = new Vrf(cfg); var output = vrf.HashToCurveTryAndIncrement(Point.FromSerialized(secp256k1, pkSerialized), alpha); var outputSerialized = output.Serialize(secp256k1, true); @@ -59,7 +60,7 @@ public void Prove_Test() var alpha = Convert.FromHexString(vector.Alpha); var expectedPi = Convert.FromHexString(vector.Pi); var expectedBeta = Convert.FromHexString(vector.Beta); - var cfg = new VrfConfig( 0xfe); + var cfg = new VrfConfig( 0xfe, ECParameters.Curve); var vrf = new Vrf(cfg); var proof = vrf.Prove(kp, alpha); Assert.Equal(expectedPi, proof.Pi); @@ -70,6 +71,7 @@ public void Prove_Test() [Fact] public void Verify_Test() { + var c = ECParameters.Curve; var path = Path.Combine( Directory.GetCurrentDirectory(), "secp256_k1_sha256_tai.json"); var text = File.ReadAllText(path); var vectors = JsonSerializer.Deserialize>(text); @@ -80,7 +82,7 @@ public void Verify_Test() var alpha = Convert.FromHexString(vector.Alpha); var pi = Convert.FromHexString(vector.Pi); var expectedBeta = Convert.FromHexString(vector.Beta); - var cfg = new VrfConfig( 0xfe); + var cfg = new VrfConfig( 0xfe, ECParameters.Curve); var vrf = new Vrf(cfg); var beta = vrf.Verify(pk, alpha, pi); Assert.Equal(expectedBeta, beta); @@ -99,7 +101,7 @@ public void Verify_BadMessageFailsVerification_Test() var pk =Convert.FromHexString(vector.Pk); var alpha = Encoding.ASCII.GetBytes("this is a wrong message"); var pi = Convert.FromHexString(vector.Pi); - var cfg = new VrfConfig( 0xfe); + var cfg = new VrfConfig( 0xfe, ECParameters.Curve); var vrf = new Vrf(cfg); Assert.Throws(() => vrf.Verify(pk, alpha, pi)); } From 941b1e6b179dc1168eefc74d4755bf2674c21019 Mon Sep 17 00:00:00 2001 From: gldeng Date: Wed, 14 Jun 2023 16:33:23 +0800 Subject: [PATCH 047/139] Make field readonly --- src/AElf.Cryptography/ECVRF/Vrf.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index 10726f45ee..692bc5d712 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -14,7 +14,7 @@ public class Vrf : IVrf private int QBitsLength => _config.EcParameters.N.BitLength; private int N => ((BitSize + 1) / 2 + 7) / 8; - private VrfConfig _config; + private readonly VrfConfig _config; public Vrf(VrfConfig config) { From 6d2f235b8e38095f4621d9c5ce98fb401d1540a0 Mon Sep 17 00:00:00 2001 From: gldeng Date: Wed, 14 Jun 2023 18:53:05 +0800 Subject: [PATCH 048/139] Refactor to make VRF generic --- src/AElf.Cryptography/Core/Exceptions.cs | 28 ++++ .../{ECVRF => Core}/Helpers.cs | 2 +- src/AElf.Cryptography/Core/IECCurve.cs | 15 ++ src/AElf.Cryptography/Core/IECPoint.cs | 6 + src/AElf.Cryptography/Core/IECScalar.cs | 6 + src/AElf.Cryptography/Core/Secp256k1Curve.cs | 121 ++++++++++++++ src/AElf.Cryptography/Core/Secp256k1Point.cs | 27 ++++ src/AElf.Cryptography/Core/Secp256k1Scalar.cs | 28 ++++ .../Core/Sha256HasherFactory.cs | 12 ++ src/AElf.Cryptography/ECVRF/Exceptions.cs | 20 --- src/AElf.Cryptography/ECVRF/IVrf.cs | 9 +- src/AElf.Cryptography/ECVRF/Point.cs | 70 -------- src/AElf.Cryptography/ECVRF/Vrf.cs | 153 +++++++----------- .../AElf.Cryptography.Tests/ECVRF/VRFTests.cs | 19 +-- 14 files changed, 316 insertions(+), 200 deletions(-) create mode 100644 src/AElf.Cryptography/Core/Exceptions.cs rename src/AElf.Cryptography/{ECVRF => Core}/Helpers.cs (97%) create mode 100644 src/AElf.Cryptography/Core/IECCurve.cs create mode 100644 src/AElf.Cryptography/Core/IECPoint.cs create mode 100644 src/AElf.Cryptography/Core/IECScalar.cs create mode 100644 src/AElf.Cryptography/Core/Secp256k1Curve.cs create mode 100644 src/AElf.Cryptography/Core/Secp256k1Point.cs create mode 100644 src/AElf.Cryptography/Core/Secp256k1Scalar.cs create mode 100644 src/AElf.Cryptography/Core/Sha256HasherFactory.cs delete mode 100644 src/AElf.Cryptography/ECVRF/Point.cs diff --git a/src/AElf.Cryptography/Core/Exceptions.cs b/src/AElf.Cryptography/Core/Exceptions.cs new file mode 100644 index 0000000000..99bf00dd80 --- /dev/null +++ b/src/AElf.Cryptography/Core/Exceptions.cs @@ -0,0 +1,28 @@ +using System; + +namespace AElf.Cryptography.Core; + +public class InvalidSerializedPublicKeyException : Exception +{ +} +public class FailedToSerializePointException : Exception +{ +} +public class FailedToCreatePointFromScalarException : Exception +{ +} +public class FailedToNegatePublicKeyException : Exception +{ +} + +public class FailedToCombinePublicKeysException : Exception +{ +} + +public class FailedToMultiplyScalarException : Exception +{ +} + +public class FailedToGetNonceException : Exception +{ +} \ No newline at end of file diff --git a/src/AElf.Cryptography/ECVRF/Helpers.cs b/src/AElf.Cryptography/Core/Helpers.cs similarity index 97% rename from src/AElf.Cryptography/ECVRF/Helpers.cs rename to src/AElf.Cryptography/Core/Helpers.cs index bfdac47711..0faa2f68c7 100644 --- a/src/AElf.Cryptography/ECVRF/Helpers.cs +++ b/src/AElf.Cryptography/Core/Helpers.cs @@ -2,7 +2,7 @@ using System.Linq; using Org.BouncyCastle.Math; -namespace AElf.Cryptography.ECVRF; +namespace AElf.Cryptography.Core; public static class Helpers { diff --git a/src/AElf.Cryptography/Core/IECCurve.cs b/src/AElf.Cryptography/Core/IECCurve.cs new file mode 100644 index 0000000000..5fef5efed6 --- /dev/null +++ b/src/AElf.Cryptography/Core/IECCurve.cs @@ -0,0 +1,15 @@ +using System; + +namespace AElf.Cryptography.Core; + +public interface IECCurve : IDisposable +{ + IECPoint MultiplyScalar(IECPoint point, IECScalar scalar); + IECPoint GetPoint(IECScalar scalar); + byte[] SerializePoint(IECPoint point, bool compressed); + IECPoint Add(IECPoint point1, IECPoint point2); + IECPoint Sub(IECPoint point1, IECPoint point2); + IECPoint DeserializePoint(byte[] input); + IECScalar DeserializeScalar(byte[] input); + byte[] GetNonce(IECScalar privateKey, byte[] hash); +} \ No newline at end of file diff --git a/src/AElf.Cryptography/Core/IECPoint.cs b/src/AElf.Cryptography/Core/IECPoint.cs new file mode 100644 index 0000000000..5fc6b82132 --- /dev/null +++ b/src/AElf.Cryptography/Core/IECPoint.cs @@ -0,0 +1,6 @@ +namespace AElf.Cryptography.Core; + +public interface IECPoint +{ + byte[] Representation { get; } +} \ No newline at end of file diff --git a/src/AElf.Cryptography/Core/IECScalar.cs b/src/AElf.Cryptography/Core/IECScalar.cs new file mode 100644 index 0000000000..071d09f11a --- /dev/null +++ b/src/AElf.Cryptography/Core/IECScalar.cs @@ -0,0 +1,6 @@ +namespace AElf.Cryptography.Core; + +public interface IECScalar +{ + byte[] Representation { get; } +} \ No newline at end of file diff --git a/src/AElf.Cryptography/Core/Secp256k1Curve.cs b/src/AElf.Cryptography/Core/Secp256k1Curve.cs new file mode 100644 index 0000000000..6f59c49e5e --- /dev/null +++ b/src/AElf.Cryptography/Core/Secp256k1Curve.cs @@ -0,0 +1,121 @@ +using System; +using System.Linq; +using Secp256k1Net; + +namespace AElf.Cryptography.Core; + +public sealed class Secp256k1Curve : IECCurve +{ + private Secp256k1 _inner; + + public Secp256k1Curve() + { + _inner = new Secp256k1(); + } + + public IECPoint MultiplyScalar(IECPoint point, IECScalar scalar) + { + var output = point.Representation; + if (!_inner.PublicKeyMultiply(output, scalar.Representation)) + { + throw new FailedToMultiplyScalarException(); + } + + return Secp256k1Point.FromNative(output); + } + + public IECPoint GetPoint(IECScalar scalar) + { + var pkBytes = new byte[Secp256k1.PUBKEY_LENGTH]; + if (!_inner.PublicKeyCreate(pkBytes, scalar.Representation)) + { + throw new FailedToCreatePointFromScalarException(); + } + + return Secp256k1Point.FromNative(pkBytes); + } + + public byte[] SerializePoint(IECPoint point, bool compressed) + { + var repr = point.Representation; + if (compressed) + { + var serialized = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH]; + if (!_inner.PublicKeySerialize(serialized, repr, Flags.SECP256K1_EC_COMPRESSED)) + { + throw new FailedToSerializePointException(); + } + + return serialized; + } + else + { + var serialized = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH]; + if (!_inner.PublicKeySerialize(serialized, repr, Flags.SECP256K1_EC_UNCOMPRESSED)) + { + throw new FailedToSerializePointException(); + } + + return serialized; + } + } + + + public IECPoint Add(IECPoint point1, IECPoint point2) + { + var output = new byte[Secp256k1.PUBKEY_LENGTH]; + + if (!_inner.PublicKeysCombine(output, point1.Representation, point2.Representation)) + { + throw new FailedToCombinePublicKeysException(); + } + + return Secp256k1Point.FromNative(output); + } + + public IECPoint Sub(IECPoint point1, IECPoint point2) + { + var point2Neg = point2.Representation; + + if (!_inner.PublicKeyNegate(point2Neg)) + { + throw new FailedToNegatePublicKeyException(); + } + + return Add(point1, Secp256k1Point.FromNative(point2Neg)); + } + + public IECPoint DeserializePoint(byte[] input) + { + var pkBytes = new byte[Secp256k1.PUBKEY_LENGTH]; + if (!_inner.PublicKeyParse(pkBytes, input)) + { + throw new InvalidSerializedPublicKeyException(); + } + + return Secp256k1Point.FromNative(pkBytes); + } + + public IECScalar DeserializeScalar(byte[] input) + { + var normalized = Helpers.AddLeadingZeros(input, Secp256k1.PRIVKEY_LENGTH) + .TakeLast(Secp256k1.PRIVKEY_LENGTH).ToArray(); + return Secp256k1Scalar.FromNative(normalized); + } + + public byte[] GetNonce(IECScalar privateKey, byte[] hash) + { + var nonce = new byte[Secp256k1.NONCE_LENGTH]; + if (!_inner.Rfc6979Nonce(nonce, hash, privateKey.Representation, null, null, 0)) + { + throw new FailedToGetNonceException(); + } + + return nonce; + } + + public void Dispose() + { + _inner.Dispose(); + } +} \ No newline at end of file diff --git a/src/AElf.Cryptography/Core/Secp256k1Point.cs b/src/AElf.Cryptography/Core/Secp256k1Point.cs new file mode 100644 index 0000000000..e972727fd8 --- /dev/null +++ b/src/AElf.Cryptography/Core/Secp256k1Point.cs @@ -0,0 +1,27 @@ +using System; + +namespace AElf.Cryptography.Core; + +public class Secp256k1Point : IECPoint +{ + private readonly byte[] _nativeRep; + + private Secp256k1Point(byte[] nativeRep) + { + _nativeRep = nativeRep; + } + + public static Secp256k1Point FromNative(byte[]nativeRep) + { + return new Secp256k1Point(nativeRep); + } + public byte[] Representation + { + get + { + var output = new byte[_nativeRep.Length]; + Buffer.BlockCopy(_nativeRep, 0, output, 0, _nativeRep.Length); + return output; + } + } +} \ No newline at end of file diff --git a/src/AElf.Cryptography/Core/Secp256k1Scalar.cs b/src/AElf.Cryptography/Core/Secp256k1Scalar.cs new file mode 100644 index 0000000000..7851503439 --- /dev/null +++ b/src/AElf.Cryptography/Core/Secp256k1Scalar.cs @@ -0,0 +1,28 @@ +using System; + +namespace AElf.Cryptography.Core; + +public class Secp256k1Scalar:IECScalar +{ + private readonly byte[] _nativeRep; + + private Secp256k1Scalar(byte[] nativeRep) + { + _nativeRep = nativeRep; + } + + public static Secp256k1Scalar FromNative(byte[]nativeRep) + { + return new Secp256k1Scalar(nativeRep); + } + public byte[] Representation + { + get + { + var output = new byte[_nativeRep.Length]; + Buffer.BlockCopy(_nativeRep, 0, output, 0, _nativeRep.Length); + return output; + } + } + +} \ No newline at end of file diff --git a/src/AElf.Cryptography/Core/Sha256HasherFactory.cs b/src/AElf.Cryptography/Core/Sha256HasherFactory.cs new file mode 100644 index 0000000000..48638040a6 --- /dev/null +++ b/src/AElf.Cryptography/Core/Sha256HasherFactory.cs @@ -0,0 +1,12 @@ +using System.Security.Cryptography; +using AElf.Cryptography.ECVRF; + +namespace AElf.Cryptography.Core; + +public class Sha256HasherFactory:IHasherFactory +{ + public HashAlgorithm Create() + { + return SHA256.Create(); + } +} \ No newline at end of file diff --git a/src/AElf.Cryptography/ECVRF/Exceptions.cs b/src/AElf.Cryptography/ECVRF/Exceptions.cs index 39ac629cad..471f15a394 100644 --- a/src/AElf.Cryptography/ECVRF/Exceptions.cs +++ b/src/AElf.Cryptography/ECVRF/Exceptions.cs @@ -2,10 +2,6 @@ namespace AElf.Cryptography.ECVRF; -public class InvalidSerializedPublicKeyException : Exception -{ -} - public class FailedToHashToCurveException : Exception { } @@ -14,22 +10,6 @@ public class InvalidProofLengthException : Exception { } -public class InvalidScalarException : Exception -{ -} - -public class FailedToMultiplyScalarException : Exception -{ -} - -public class FailedToNegatePublicKeyException : Exception -{ -} - -public class FailedToCombinePublicKeysException : Exception -{ -} - public class InvalidProofException : Exception { } \ No newline at end of file diff --git a/src/AElf.Cryptography/ECVRF/IVrf.cs b/src/AElf.Cryptography/ECVRF/IVrf.cs index 2ce5199e34..a0af437fa8 100644 --- a/src/AElf.Cryptography/ECVRF/IVrf.cs +++ b/src/AElf.Cryptography/ECVRF/IVrf.cs @@ -1,3 +1,5 @@ +using System.Security.Cryptography; +using AElf.Cryptography.Core; using AElf.Cryptography.ECDSA; using Org.BouncyCastle.Asn1.X9; using Org.BouncyCastle.Math; @@ -12,7 +14,7 @@ public struct Proof public struct ProofInput { - public Point Gamma { get; set; } + public IECPoint Gamma { get; set; } public BigInteger C { get; set; } public BigInteger S { get; set; } } @@ -30,6 +32,11 @@ public VrfConfig(byte suiteString, X9ECParameters ecParameters) } } +public interface IHasherFactory +{ + HashAlgorithm Create(); +} + public interface IVrf { Proof Prove(ECKeyPair keyPair, byte[] alpha); diff --git a/src/AElf.Cryptography/ECVRF/Point.cs b/src/AElf.Cryptography/ECVRF/Point.cs deleted file mode 100644 index 5c414ff6e4..0000000000 --- a/src/AElf.Cryptography/ECVRF/Point.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Org.BouncyCastle.Math; -using Secp256k1Net; - -namespace AElf.Cryptography.ECVRF; - -public struct Point -{ - private BigInteger P = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16); - public byte[] Inner { get; private set; } - - private Point(byte[] inner) - { - Inner = inner; - } - - public static Point FromInner(byte[] inner) - { - return new Point() { Inner = inner }; - } - - public static Point FromSerialized(Secp256k1 secp256k1, byte[] pkSerialized) - { - if (pkSerialized.Length != Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH && - pkSerialized.Length != Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH) - { - throw new InvalidSerializedPublicKeyException(); - } - - if (pkSerialized.Length == Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH) - { - if (pkSerialized[0] != 0x02 && pkSerialized[0] != 0x03) - { - throw new InvalidSerializedPublicKeyException(); - } - } - - if (pkSerialized.Length == Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH) - { - if (pkSerialized[0] != 0x04) - { - throw new InvalidSerializedPublicKeyException(); - } - } - - var inner = new byte[Secp256k1.PUBKEY_LENGTH]; - var successful = secp256k1.PublicKeyParse(inner, pkSerialized); - if (!successful) - { - throw new InvalidSerializedPublicKeyException(); - } - - return new Point() { Inner = inner }; - } - - public byte[] Serialize(Secp256k1 secp256k1, bool compressed = true) - { - if (compressed) - { - var output = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH]; - secp256k1.PublicKeySerialize(output, Inner, Flags.SECP256K1_EC_COMPRESSED); - return output; - } - else - { - var output = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH]; - secp256k1.PublicKeySerialize(output, Inner, Flags.SECP256K1_EC_UNCOMPRESSED); - return output; - } - } -} \ No newline at end of file diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index 692bc5d712..7ebeaf7df1 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -2,44 +2,44 @@ using System.IO; using System.Linq; using System.Security.Cryptography; +using AElf.Cryptography.Core; using AElf.Cryptography.ECDSA; using Org.BouncyCastle.Math; using Secp256k1Net; namespace AElf.Cryptography.ECVRF; -public class Vrf : IVrf +public class Vrf : IVrf where TCurve : IECCurve, new() + where THasherFactory : IHasherFactory, new() { private int BitSize => _config.EcParameters.Curve.FieldSize; private int QBitsLength => _config.EcParameters.N.BitLength; private int N => ((BitSize + 1) / 2 + 7) / 8; private readonly VrfConfig _config; + private readonly IHasherFactory _hasherFactory; public Vrf(VrfConfig config) { _config = config; + _hasherFactory = new THasherFactory(); } public Proof Prove(ECKeyPair keyPair, byte[] alpha) { - using var secp256k1 = new Secp256k1(); - var point = Point.FromSerialized(secp256k1, keyPair.PublicKey); + using var curve = new TCurve(); + var point = curve.DeserializePoint(keyPair.PublicKey); var hashPoint = HashToCurveTryAndIncrement(point, alpha); - var gamma = new byte[Secp256k1.PUBKEY_LENGTH]; - Buffer.BlockCopy(hashPoint.Inner, 0, gamma, 0, gamma.Length); - secp256k1.PublicKeyMultiply(gamma, keyPair.PrivateKey); - var nonce = Rfc6979Nonce(secp256k1, keyPair, hashPoint); - var kB = new byte[Secp256k1.PUBKEY_LENGTH]; - secp256k1.PublicKeyCreate(kB, nonce); - var kH = new byte[Secp256k1.PUBKEY_LENGTH]; - Buffer.BlockCopy(hashPoint.Inner, 0, kH, 0, kH.Length); - secp256k1.PublicKeyMultiply(kH, nonce); - var c = HashPoints(secp256k1, hashPoint, Point.FromInner(gamma), Point.FromInner(kB), Point.FromInner(kH)); + var gamma = curve.MultiplyScalar(hashPoint, curve.DeserializeScalar(keyPair.PrivateKey)); + + var nonce = Rfc6979Nonce(keyPair, hashPoint); + var kB = curve.GetPoint(nonce); + var kH = curve.MultiplyScalar(hashPoint, nonce); + var c = HashPoints(hashPoint, gamma, kB, kH); var cX = c.Multiply(new BigInteger(1, keyPair.PrivateKey)); - var s = cX.Add(new BigInteger(1, nonce)).Mod(_config.EcParameters.N); - var pi = EncodeProof(Point.FromInner(gamma), c, s); - var beta = GammaToHash(secp256k1, Point.FromInner(gamma)); + var s = cX.Add(new BigInteger(1, nonce.Representation)).Mod(_config.EcParameters.N); + var pi = EncodeProof(gamma, c, s); + var beta = GammaToHash(gamma); return new Proof { Pi = pi, Beta = beta @@ -48,93 +48,46 @@ public Proof Prove(ECKeyPair keyPair, byte[] alpha) public byte[] Verify(byte[] publicKey, byte[] alpha, byte[] pi) { - using var secp256k1 = new Secp256k1(); - var proofInput = DecodeProof(secp256k1, pi); + using var curve = new TCurve(); + var proofInput = DecodeProof(pi); - var pkPoint = Point.FromSerialized(secp256k1, publicKey); + var pkPoint = curve.DeserializePoint(publicKey); var hashPoint = HashToCurveTryAndIncrement(pkPoint, alpha); - var sBytes = Helpers.AddLeadingZeros(proofInput.S.ToByteArray(), Secp256k1.PRIVKEY_LENGTH) - .TakeLast(Secp256k1.PRIVKEY_LENGTH).ToArray(); - - var sB = new byte[Secp256k1.PUBKEY_LENGTH]; - if (!secp256k1.PublicKeyCreate(sB, sBytes)) - { - throw new InvalidScalarException(); - } + var s = curve.DeserializeScalar(proofInput.S.ToByteArray()); + var c = curve.DeserializeScalar(proofInput.C.ToByteArray()); - var cYNeg = new byte[Secp256k1.PUBKEY_LENGTH]; - Buffer.BlockCopy(pkPoint.Inner, 0, cYNeg, 0, cYNeg.Length); + var sB = curve.GetPoint(s); + var cY = curve.MultiplyScalar(pkPoint, c); + var u = curve.Sub(sB, cY); - if (!secp256k1.PublicKeyMultiply(cYNeg, - Helpers.AddLeadingZeros(proofInput.C.ToByteArray(), Secp256k1.PRIVKEY_LENGTH))) - { - throw new FailedToMultiplyScalarException(); - } + var sH = curve.MultiplyScalar(hashPoint, s); + var cGamma = curve.MultiplyScalar(proofInput.Gamma, c); + var v = curve.Sub(sH, cGamma); - if (!secp256k1.PublicKeyNegate(cYNeg)) - { - throw new FailedToNegatePublicKeyException(); - } - - var u = new byte[Secp256k1.PUBKEY_LENGTH]; - - if (!secp256k1.PublicKeysCombine(u, sB, cYNeg)) - { - throw new FailedToCombinePublicKeysException(); - } - - var sH = new byte[Secp256k1.PUBKEY_LENGTH]; - Buffer.BlockCopy(hashPoint.Inner, 0, sH, 0, sH.Length); - - if (!secp256k1.PublicKeyMultiply(sH, sBytes)) - { - throw new FailedToMultiplyScalarException(); - } - - var cGammaNeg = new byte[Secp256k1.PUBKEY_LENGTH]; - Buffer.BlockCopy(proofInput.Gamma.Inner, 0, cGammaNeg, 0, cGammaNeg.Length); - if (!secp256k1.PublicKeyMultiply(cGammaNeg, - Helpers.AddLeadingZeros(proofInput.C.ToByteArray(), Secp256k1.PRIVKEY_LENGTH))) - { - throw new FailedToMultiplyScalarException(); - } - - if (!secp256k1.PublicKeyNegate(cGammaNeg)) - { - throw new FailedToNegatePublicKeyException(); - } - - var v = new byte[Secp256k1.PUBKEY_LENGTH]; - - if (!secp256k1.PublicKeysCombine(v, sH, cGammaNeg)) - { - throw new FailedToCombinePublicKeysException(); - } - - var derivedC = HashPoints(secp256k1, hashPoint, proofInput.Gamma, Point.FromInner(u), Point.FromInner(v)); + var derivedC = HashPoints(hashPoint, proofInput.Gamma, u, v); if (!derivedC.Equals(proofInput.C)) { throw new InvalidProofException(); } - return GammaToHash(secp256k1, proofInput.Gamma); + return GammaToHash(proofInput.Gamma); } - public Point HashToCurveTryAndIncrement(Point point, byte[] alpha) + public IECPoint HashToCurveTryAndIncrement(IECPoint point, byte[] alpha) { - using var secp256k1 = new Secp256k1(); + using var curve = new TCurve(); // Step 1: ctr = 0 var ctr = 0; // Step 2: PK_string = point_to_string(Y) - var pkString = point.Serialize(secp256k1, true); + var pkString = curve.SerializePoint(point, true); // Steps 3 ~ 6 byte oneString = 0x01; for (; ctr < 256; ctr++) { - using var hasher = SHA256.Create(); + using var hasher = _hasherFactory.Create(); using var stream = new MemoryStream(); stream.WriteByte(_config.SuiteString); stream.WriteByte(oneString); @@ -148,28 +101,28 @@ public Point HashToCurveTryAndIncrement(Point point, byte[] alpha) Buffer.BlockCopy(hash, 0, pkSerialized, 1, hash.Length); try { - var outputPoint = Point.FromSerialized(secp256k1, pkSerialized); + var outputPoint = curve.DeserializePoint(pkSerialized); return outputPoint; } catch (InvalidSerializedPublicKeyException ex) { + // Ignore this exception and try the next ctr } } throw new FailedToHashToCurveException(); } - private BigInteger HashPoints(Secp256k1 secp256k1, params Point[] points) + private BigInteger HashPoints(params IECPoint[] points) { - using var hasher = SHA256.Create(); + using var curve = new TCurve(); + using var hasher = _hasherFactory.Create(); using var stream = new MemoryStream(); stream.WriteByte(_config.SuiteString); stream.WriteByte(0x02); foreach (var point in points) { - var pkBytes = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH]; - secp256k1.PublicKeySerialize(pkBytes, point.Inner, Flags.SECP256K1_EC_COMPRESSED); - stream.Write(pkBytes); + stream.Write(curve.SerializePoint(point, true)); } stream.Seek(0, SeekOrigin.Begin); @@ -178,10 +131,10 @@ private BigInteger HashPoints(Secp256k1 secp256k1, params Point[] points) return new BigInteger(1, hashTruncated); } - private byte[] EncodeProof(Point gamma, BigInteger c, BigInteger s) + private byte[] EncodeProof(IECPoint gamma, BigInteger c, BigInteger s) { - using var secp256k1 = new Secp256k1(); - var gammaBytes = gamma.Serialize(secp256k1, true); + using var curve = new TCurve(); + var gammaBytes = curve.SerializePoint(gamma, true); var cBytes = Helpers.Int2Bytes(c, N); var sBytes = Helpers.Int2Bytes(s, (QBitsLength + 7) / 8); var output = new byte[gammaBytes.Length + cBytes.Length + sBytes.Length]; @@ -191,8 +144,9 @@ private byte[] EncodeProof(Point gamma, BigInteger c, BigInteger s) return output; } - private ProofInput DecodeProof(Secp256k1 secp256k1, byte[] pi) + private ProofInput DecodeProof(byte[] pi) { + using var curve = new TCurve(); var ptLength = (BitSize + 7) / 8 + 1; var cLength = N; var sLength = (QBitsLength + 7) / 8; @@ -201,7 +155,7 @@ private ProofInput DecodeProof(Secp256k1 secp256k1, byte[] pi) throw new InvalidProofLengthException(); } - var gammaPoint = Point.FromSerialized(secp256k1, pi.Take(ptLength).ToArray()); + var gammaPoint = curve.DeserializePoint(pi.Take(ptLength).ToArray()); var c = new BigInteger(1, pi.Skip(ptLength).Take(cLength).ToArray()); var s = new BigInteger(1, pi.TakeLast(sLength).ToArray()); return new ProofInput() @@ -212,9 +166,10 @@ private ProofInput DecodeProof(Secp256k1 secp256k1, byte[] pi) }; } - private byte[] GammaToHash(Secp256k1 secp256k1, Point gamma) + private byte[] GammaToHash(IECPoint gamma) { - var gammaBytes = gamma.Serialize(secp256k1, true); + using var curve = new TCurve(); + var gammaBytes = curve.SerializePoint(gamma, true); using var hasher = SHA256.Create(); using var stream = new MemoryStream(); stream.WriteByte(_config.SuiteString); @@ -224,17 +179,17 @@ private byte[] GammaToHash(Secp256k1 secp256k1, Point gamma) return hasher.ComputeHash(stream); } - private byte[] Rfc6979Nonce(Secp256k1 secp256k1, ECKeyPair keyPair, Point hashPoint) + private IECScalar Rfc6979Nonce(ECKeyPair keyPair, IECPoint hashPoint) { - using var hasher = SHA256.Create(); + using var curve = new TCurve(); + using var hasher = _hasherFactory.Create(); var roLen = (QBitsLength + 7) / 8; - var hBytes = hashPoint.Serialize(secp256k1, true); + var hBytes = curve.SerializePoint(hashPoint, true); var hash = hasher.ComputeHash(hBytes); var bh = Helpers.Bits2Bytes(hash, _config.EcParameters.N, roLen); - var nonce = new byte[Secp256k1.NONCE_LENGTH]; - secp256k1.Rfc6979Nonce(nonce, bh, keyPair.PrivateKey, null, null, 0); - return nonce; + var nonce = curve.GetNonce(curve.DeserializeScalar(keyPair.PrivateKey), bh); + return curve.DeserializeScalar(nonce); } } \ No newline at end of file diff --git a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs index 1c871389d0..7f032483dd 100644 --- a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs +++ b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs @@ -4,6 +4,7 @@ using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using AElf.Cryptography.Core; using AElf.Cryptography.ECDSA; using AElf.Cryptography.ECVRF; using Secp256k1Net; @@ -37,12 +38,12 @@ public void HashToCurveTryAndIncrement_Test() var pkSerialized = Convert.FromHexString("0360fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb6"); var alpha = Encoding.ASCII.GetBytes("sample"); var expectedHashPoint = Convert.FromHexString("027AD7D4C3A454D9ECC905F1E5436A328F2A106A2606EC4B44111CF9DC72A5B9FF"); - - using var secp256k1 = new Secp256k1(); + + using var curve = new Secp256k1Curve(); var cfg = new VrfConfig( 0xfe, ECParameters.Curve); - var vrf = new Vrf(cfg); - var output = vrf.HashToCurveTryAndIncrement(Point.FromSerialized(secp256k1, pkSerialized), alpha); - var outputSerialized = output.Serialize(secp256k1, true); + var vrf = new Vrf(cfg); + var output = vrf.HashToCurveTryAndIncrement(curve.DeserializePoint( pkSerialized), alpha); + var outputSerialized = curve.SerializePoint(output, true); Assert.Equal(outputSerialized, expectedHashPoint); } @@ -61,13 +62,13 @@ public void Prove_Test() var expectedPi = Convert.FromHexString(vector.Pi); var expectedBeta = Convert.FromHexString(vector.Beta); var cfg = new VrfConfig( 0xfe, ECParameters.Curve); - var vrf = new Vrf(cfg); + var vrf = new Vrf(cfg); var proof = vrf.Prove(kp, alpha); Assert.Equal(expectedPi, proof.Pi); Assert.Equal(expectedBeta, proof.Beta); } } - + [Fact] public void Verify_Test() { @@ -83,7 +84,7 @@ public void Verify_Test() var pi = Convert.FromHexString(vector.Pi); var expectedBeta = Convert.FromHexString(vector.Beta); var cfg = new VrfConfig( 0xfe, ECParameters.Curve); - var vrf = new Vrf(cfg); + var vrf = new Vrf(cfg); var beta = vrf.Verify(pk, alpha, pi); Assert.Equal(expectedBeta, beta); } @@ -102,7 +103,7 @@ public void Verify_BadMessageFailsVerification_Test() var alpha = Encoding.ASCII.GetBytes("this is a wrong message"); var pi = Convert.FromHexString(vector.Pi); var cfg = new VrfConfig( 0xfe, ECParameters.Curve); - var vrf = new Vrf(cfg); + var vrf = new Vrf(cfg); Assert.Throws(() => vrf.Verify(pk, alpha, pi)); } } From d6f7aaeea1316f4bee3e399fec01962537c6ec4f Mon Sep 17 00:00:00 2001 From: gldeng Date: Wed, 14 Jun 2023 18:58:05 +0800 Subject: [PATCH 049/139] Cater to curves with cofactor different from 1 --- src/AElf.Cryptography/ECVRF/Vrf.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index 7ebeaf7df1..5329ccb825 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -102,6 +102,12 @@ public IECPoint HashToCurveTryAndIncrement(IECPoint point, byte[] alpha) try { var outputPoint = curve.DeserializePoint(pkSerialized); + if (_config.EcParameters.Curve.Cofactor.CompareTo(BigInteger.One) > 0) + { + return curve.MultiplyScalar(outputPoint, + curve.DeserializeScalar(_config.EcParameters.Curve.Cofactor.ToByteArray())); + } + return outputPoint; } catch (InvalidSerializedPublicKeyException ex) From c61b358f1ad0854eccdfef9c21670b84b50daed5 Mon Sep 17 00:00:00 2001 From: gldeng Date: Wed, 14 Jun 2023 19:09:47 +0800 Subject: [PATCH 050/139] Rename file --- src/AElf.Cryptography/ECVRF/{IVrf.cs => Types.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/AElf.Cryptography/ECVRF/{IVrf.cs => Types.cs} (100%) diff --git a/src/AElf.Cryptography/ECVRF/IVrf.cs b/src/AElf.Cryptography/ECVRF/Types.cs similarity index 100% rename from src/AElf.Cryptography/ECVRF/IVrf.cs rename to src/AElf.Cryptography/ECVRF/Types.cs From 32c8b2c7a4b28436ea09c3b3b0cff563f73959b5 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Wed, 14 Jun 2023 19:13:08 +0800 Subject: [PATCH 051/139] test: fix aedpos tests --- .../BlockMiningService.cs | 4 +++- .../Application/IRandomHashProvider.cs | 3 ++- .../BVT/ACS4ImplTest.cs | 2 ++ .../BVT/MinersCountTest.cs | 8 +++++++- .../BVT/MiningProcessTest.cs | 8 +++++++- .../BVT/ViewTests.cs | 2 ++ .../Types/Round.cs | 4 +++- .../AElf.Contracts.Economic.TestBase.csproj | 14 ++++++------- .../EconomicContractsTestModule.cs | 2 ++ .../MockAEDPoSInformationProvider.cs | 20 +++++++++++++++++++ .../OtherContractsOperation.cs | 4 +++- 11 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 test/AElf.Contracts.Economic.TestBase/MockAEDPoSInformationProvider.cs diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs index 251590b8b0..40d043de6d 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs @@ -388,7 +388,9 @@ private async Task GetConsensusTriggerInfoAsync // It doesn't matter for testing. InValue = HashHelper.ComputeFrom($"InValueOf{pubkey}"), PreviousInValue = HashHelper.ComputeFrom($"InValueOf{pubkey}"), - Pubkey = pubkey.Value + Pubkey = pubkey.Value, + // TODO: Set random hash. + RandomHash = Hash.Empty }; var consensusExtraData = await contractStub.GetConsensusExtraData.CallAsync(new BytesValue diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs index 832e3ce68c..0e18d3c659 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using AElf.Kernel.Account.Application; using AElf.Types; +using Volo.Abp.DependencyInjection; namespace AElf.Kernel.Consensus.AEDPoS.Application; @@ -9,7 +10,7 @@ public interface IRandomHashProvider Task GenerateRandomHashAsync(IChainContext chainContext); } -public class RandomHashProvider : IRandomHashProvider +public class RandomHashProvider : IRandomHashProvider, ITransientDependency { private readonly IAEDPoSInformationProvider _aedPoSInformationProvider; private readonly IAccountService _accountService; diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs index 1b41018c34..044ab7a959 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs @@ -328,6 +328,8 @@ public async Task AEDPoSContract_ConsensusTransactionValidation_Test() nextRoundInput.RoundNumber++; nextRoundInput.IsMinerListJustChanged = false; nextRoundInput.TermNumber++; + // TODO: Set random hash. + nextRoundInput.RandomHash = Hash.Empty; var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs index 3b8ea9368c..728ed8ffa8 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs @@ -81,6 +81,8 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() }.ToBytesValue())).ToConsensusHeaderInformation(); var nextRoundInput = NextRoundInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); + // TODO: Set random hash. + nextRoundInput.RandomHash = Hash.Empty; await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); changeTermTime = BlockchainStartTimestamp.ToDateTime().AddMinutes(termIntervalMin).AddSeconds(10); BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); @@ -93,6 +95,8 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() }.ToBytesValue())).ToConsensusHeaderInformation(); var nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); + // TODO: Set random hash. + nextTermInput.RandomHash = Hash.Empty; var transactionResult = await AEDPoSContractStub.NextTerm.SendAsync(nextTermInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); @@ -119,7 +123,9 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() Pubkey = ByteStringHelper.FromHexString(currentRound.RealTimeMinersInformation.ElementAt(0).Value .Pubkey) }.ToBytesValue())).ToConsensusHeaderInformation(); - nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); + nextTermInput = NextTermInput.Parser.ParseFrom(nextRoundInformation.Round.ToByteArray()); + // TODO: Set random hash. + nextTermInput.RandomHash = Hash.Empty; await newMinerStub.NextTerm.SendAsync(nextTermInput); termCount++; } diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs index ec0bbefe0f..075142361a 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs @@ -74,6 +74,8 @@ await voter.Vote.SendAsync(new VoteMinerInput Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); var nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); + // TODO: Set random hash. + nextTermInput.RandomHash = Hash.Empty; await AEDPoSContractStub.NextTerm.SendAsync(nextTermInput); // First candidate cheat others with in value. @@ -101,6 +103,8 @@ await voter.Vote.SendAsync(new VoteMinerInput Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation().Round; var nextRoundInput = NextRoundInput.Parser.ParseFrom(thirdRound.ToByteArray()); + // TODO: Set random hash. + nextRoundInput.RandomHash = Hash.Empty; await oneCandidate.NextRound.SendAsync(nextRoundInput); var cheatInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( @@ -131,7 +135,9 @@ public async Task Update_TinyBlockInformation_Test() { RoundId = roundInfo.RoundId, ProducedBlocks = 4, - ActualMiningTime = BlockTimeProvider.GetBlockTime() + ActualMiningTime = BlockTimeProvider.GetBlockTime(), + // TODO: Set random hash. + RandomHash = Hash.Empty }; var transactionResult = await AEDPoSContractStub.UpdateTinyBlockInformation.SendAsync(input); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs index 8f3ac03be7..04f4b9abf0 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs @@ -28,6 +28,8 @@ public async Task Query_RoundInformation_Test() }.ToBytesValue())).ToConsensusHeaderInformation(); var nextRoundInput = NextRoundInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); + // TODO: Set random hash. + nextRoundInput.RandomHash = Hash.Empty; var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs index f0e6cee28e..ac1b484fe8 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs @@ -117,7 +117,9 @@ public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) TuneOrderInformation = { tuneOrderInformation }, EncryptedPieces = { minerInRound.EncryptedPieces }, DecryptedPieces = { decryptedPreviousInValues }, - MinersPreviousInValues = { minersPreviousInValues } + MinersPreviousInValues = { minersPreviousInValues }, + // TODO: Set random hash. + RandomHash = Hash.Empty }; } diff --git a/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj b/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj index 95287fb207..d6b4579761 100644 --- a/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj +++ b/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj @@ -13,7 +13,7 @@ runtime; build; native; contentfiles; analyzers - + all @@ -71,9 +71,9 @@ Contract PreserveNewest - - - + + + false Contract @@ -99,8 +99,8 @@ Contract PreserveNewest - - + + @@ -181,6 +181,6 @@ - + diff --git a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs index 158133ef8a..568b55446e 100644 --- a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs +++ b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs @@ -26,6 +26,8 @@ public override void ConfigureServices(ServiceConfigurationContext context) // context.Services.AddSingleton(); context.Services.AddSingleton(); context.Services.AddSingleton(); + context.Services.AddTransient(); + context.Services.AddTransient(); context.Services.RemoveAll(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/MockAEDPoSInformationProvider.cs b/test/AElf.Contracts.Economic.TestBase/MockAEDPoSInformationProvider.cs new file mode 100644 index 0000000000..77a4ad24ca --- /dev/null +++ b/test/AElf.Contracts.Economic.TestBase/MockAEDPoSInformationProvider.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using AElf.Kernel; +using AElf.Kernel.Consensus.AEDPoS.Application; +using AElf.Types; + +namespace AElf.Contracts.Economic.TestBase; + +public class MockAEDPoSInformationProvider : IAEDPoSInformationProvider +{ + public Task> GetCurrentMinerListAsync(ChainContext chainContext) + { + throw new System.NotImplementedException(); + } + + public async Task GetRandomHashAsync(IChainContext chainContext, long blockHeight) + { + return Hash.Empty; + } +} \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs index 76622df755..0b78ec3379 100644 --- a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs +++ b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs @@ -56,7 +56,9 @@ await miner.UpdateValue.SendAsync(new UpdateValueInput RoundId = round.RoundId, ProducedBlocks = minerInRound.ProducedBlocks + 1, ActualMiningTime = minerInRound.ExpectedMiningTime, - SupposedOrderOfNextRound = 1 + SupposedOrderOfNextRound = 1, + // TODO: Set random hash. + RandomHash = Hash.Empty }); } From f90ad9ae09d6d4e6b2aade99839c5e8647d98a70 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 14 Jun 2023 19:55:06 +0800 Subject: [PATCH 052/139] fix: ut --- ...utePluginTransactionDirectlyTest_FreeAllowance.cs | 12 ++++++------ .../ExecutionPluginForMethodFeeTestBase.cs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index 33ae44c475..ce504dd6f5 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -516,7 +516,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), new RemoveTransactionFeeFreeAllowancesConfigInput { - Symbols = { "ELF", "ELF" } + Symbols = { NativeTokenSymbol, NativeTokenSymbol } }); config = TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Result.Value.Count.ShouldBe(0); @@ -539,7 +539,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), new RemoveTransactionFeeFreeAllowancesConfigInput { - Symbols = { "ELF", USDT } + Symbols = { NativeTokenSymbol, USDT } }); userAFreeAllowances = TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(UserAAddress); userAFreeAllowances.Result.Map.Count.ShouldBe(0); @@ -1392,7 +1392,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, await CheckDefaultSenderTokenAsync(Token1, 9000); await CheckDefaultSenderTokenAsync(Token2, 10000); - _blockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddSeconds(10)); + BlockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddSeconds(10)); chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); @@ -1530,11 +1530,11 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, // case 30 [InlineData(10000, 10000, 1000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, USDT, 100, 300, 100, 500, 0, 0, 100, 9000, 10000, 1000, 0, 2000, 1, 1, Token1, 1500, USDT, 200, true)] // case 31 - [InlineData(10000, 10000, 10000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, "ELF", 1000, 300, 100, 0, 0, 0, 0, 9000, 10000, 7000, 0, 3000, 5, 3, NativeTokenSymbol, 3000, Token1, 3000, true)] + [InlineData(10000, 10000, 10000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, NativeTokenSymbol, 1000, 300, 100, 0, 0, 0, 0, 9000, 10000, 7000, 0, 3000, 5, 3, NativeTokenSymbol, 3000, Token1, 3000, true)] // case 32 - [InlineData(10000, 10000, 1000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, "ELF", 1000, 300, 100, 0, 0, 0, 0, 0, 10000, 0, 0, 3000, 5, 3, NativeTokenSymbol, 15000, USDT, 20000, false)] + [InlineData(10000, 10000, 1000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, NativeTokenSymbol, 1000, 300, 100, 0, 0, 0, 0, 0, 10000, 0, 0, 3000, 5, 3, NativeTokenSymbol, 15000, USDT, 20000, false)] // case 33 - [InlineData(5000, 10000, 0, 0, Token1, 1000, Token1, 1000, 600, 100, Token2, 1000, Token2, 1000, 300, 100, 0, 0, 1000, 1000, 0, 8000, 0, 0, 10000, 1, 5, USDT, 2000, "ELF", 0, false)] + [InlineData(5000, 10000, 0, 0, Token1, 1000, Token1, 1000, 600, 100, Token2, 1000, Token2, 1000, 300, 100, 0, 0, 1000, 1000, 0, 8000, 0, 0, 10000, 1, 5, USDT, 2000, NativeTokenSymbol, 0, false)] public async Task ChargeTransactionFee_MultipleTxFeeTokens_Test(long initialELFBalance, long initialUSDTBalance, long initialToken1Balance, long initialToken2Balance, string firstFreeSymbolELF, long firstFreeAmountELF, string secondFreeSymbolELF, long secondFreeAmountELF, long refreshSecondsELF, long thresholdELF, diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index 2e30818c8d..72f7ff3345 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -290,11 +290,11 @@ public class ExecutePluginTransactionDirectlyForMethodFeeTestBase : ContractTest protected const string Token1 = "TOKENA"; protected const string Token2 = "TOKENB"; - protected readonly IBlockTimeProvider _blockTimeProvider; + protected readonly IBlockTimeProvider BlockTimeProvider; protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() { - _blockTimeProvider = GetRequiredService(); + BlockTimeProvider = GetRequiredService(); AsyncHelper.RunSync(InitializeContracts); } From 0da12e7c3031ff5976917145003083c08f103aa6 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Thu, 15 Jun 2023 13:51:59 +0800 Subject: [PATCH 053/139] feat: use package AElf.Secp256k1.Net --- src/AElf.Cryptography/AElf.Cryptography.csproj | 12 ++++++------ test/AElf.Cryptography.Tests/AssemblyInfo.cs | 3 +++ 2 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 test/AElf.Cryptography.Tests/AssemblyInfo.cs diff --git a/src/AElf.Cryptography/AElf.Cryptography.csproj b/src/AElf.Cryptography/AElf.Cryptography.csproj index 0ac287552c..22d264f402 100644 --- a/src/AElf.Cryptography/AElf.Cryptography.csproj +++ b/src/AElf.Cryptography/AElf.Cryptography.csproj @@ -1,5 +1,5 @@ - + net6.0 AElf.Cryptography @@ -7,12 +7,12 @@ Cryptographic primitives used in AElf. - - - - + + + + - + diff --git a/test/AElf.Cryptography.Tests/AssemblyInfo.cs b/test/AElf.Cryptography.Tests/AssemblyInfo.cs new file mode 100644 index 0000000000..41a898e37e --- /dev/null +++ b/test/AElf.Cryptography.Tests/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using Xunit; + +[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file From db3f73d9d770200d7a53e364c39d63ed38b85cb8 Mon Sep 17 00:00:00 2001 From: gldeng Date: Thu, 15 Jun 2023 17:38:47 +0800 Subject: [PATCH 054/139] Consider cofactor in GammaToHash --- src/AElf.Cryptography/ECVRF/Vrf.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index 5329ccb825..b1b4cfcc25 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -175,12 +175,20 @@ private ProofInput DecodeProof(byte[] pi) private byte[] GammaToHash(IECPoint gamma) { using var curve = new TCurve(); - var gammaBytes = curve.SerializePoint(gamma, true); + + var gammaCof = gamma; + if (_config.EcParameters.Curve.Cofactor.CompareTo(BigInteger.One) > 0) + { + gammaCof = curve.MultiplyScalar(gamma, + curve.DeserializeScalar(_config.EcParameters.Curve.Cofactor.ToByteArray())); + } + + var gammaCofBytes = curve.SerializePoint(gammaCof, true); using var hasher = SHA256.Create(); using var stream = new MemoryStream(); stream.WriteByte(_config.SuiteString); stream.WriteByte(0x03); - stream.Write(gammaBytes); + stream.Write(gammaCofBytes); stream.Seek(0, SeekOrigin.Begin); return hasher.ComputeHash(stream); } From ddb5bca5e112dd587645e88aa1da12b87acb03c6 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Thu, 15 Jun 2023 17:52:13 +0800 Subject: [PATCH 055/139] feat: use vrf --- ...tract_ACS4_ConsensusInformationProvider.cs | 12 +++---- ...PoSContract_ProcessConsensusInformation.cs | 19 +++++++----- .../AElfConsensusContractState.cs | 2 +- ...und_ExtractInformationToUpdateConsensus.cs | 6 ++-- protobuf/aedpos_contract.proto | 27 ++++++++++------ src/AElf.Cryptography/CryptoHelper.cs | 31 +++++++++++++++++++ .../Account/Application/IAccountService.cs | 8 +++++ .../ISmartContractBridgeContext.cs | 2 +- .../HostSmartContractBridgeContext.cs | 5 ++- .../Account/Application/AccountService.cs | 7 +++++ .../CSharpSmartContractContext.cs | 4 +-- .../CryptoHelperTests.cs | 16 ++++++++++ .../Application/AccountServiceTests.cs | 11 +++++++ .../Application/AccountServiceTests.cs | 11 +++++++ 14 files changed, 127 insertions(+), 34 deletions(-) diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs index a7b768bef2..993bad1881 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs @@ -67,7 +67,7 @@ public override TransactionList GenerateConsensusTransactions(BytesValue input) "Data to request consensus information should contain pubkey."); var pubkey = triggerInformation.Pubkey; - var randomHash = triggerInformation.RandomHash; + var randomHash = triggerInformation.VrfRandomProof; var consensusInformation = new AElfConsensusHeaderInformation(); consensusInformation.MergeFrom(GetConsensusBlockExtraData(input, true).Value); var transactionList = GenerateTransactionListByExtraData(consensusInformation, pubkey, randomHash); @@ -128,7 +128,7 @@ public override ValidationResult ValidateConsensusAfterExecution(BytesValue inpu } private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderInformation consensusInformation, - ByteString pubkey, Hash randomHash) + ByteString pubkey, VrfRandomProof vrfRandomProof) { var round = consensusInformation.Round; var behaviour = consensusInformation.Behaviour; @@ -142,7 +142,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn Transactions = { GenerateTransaction(nameof(UpdateValue), - round.ExtractInformationToUpdateConsensus(pubkey.ToHex(),randomHash)) + round.ExtractInformationToUpdateConsensus(pubkey.ToHex(),vrfRandomProof)) } }; case AElfConsensusBehaviour.TinyBlock: @@ -157,7 +157,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn ActualMiningTime = minerInRound.ActualMiningTimes.Last(), ProducedBlocks = minerInRound.ProducedBlocks, RoundId = round.RoundIdForValidation, - RandomHash = randomHash + VrfRandomProof = vrfRandomProof }) } }; @@ -178,7 +178,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn IsMinerListJustChanged = round.IsMinerListJustChanged, RoundIdForValidation = round.RoundIdForValidation, MainChainMinersRoundNumber = round.MainChainMinersRoundNumber, - RandomHash = randomHash + VrfRandomProof = vrfRandomProof }) } }; @@ -199,7 +199,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn IsMinerListJustChanged = round.IsMinerListJustChanged, RoundIdForValidation = round.RoundIdForValidation, MainChainMinersRoundNumber = round.MainChainMinersRoundNumber, - RandomHash = randomHash + VrfRandomProof = vrfRandomProof }) } }; diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs index 53e804add6..eab386c584 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs @@ -28,25 +28,25 @@ private void ProcessConsensusInformation(dynamic input, [CallerMemberName] strin State.RoundBeforeLatestExecution.Value = GetCurrentRoundInformation(new Empty()); - var randomHash = Hash.Empty; + VrfRandomProof vrfRandomProof = null; // The only difference. switch (input) { case NextRoundInput nextRoundInput: - randomHash = nextRoundInput.RandomHash; + vrfRandomProof = nextRoundInput.VrfRandomProof; ProcessNextRound(nextRoundInput); break; case NextTermInput nextTermInput: - randomHash = nextTermInput.RandomHash; + vrfRandomProof = nextTermInput.VrfRandomProof; ProcessNextTerm(nextTermInput); break; case UpdateValueInput updateValueInput: - randomHash = updateValueInput.RandomHash; + vrfRandomProof = updateValueInput.VrfRandomProof; ProcessUpdateValue(updateValueInput); break; case TinyBlockInput tinyBlockInput: - randomHash = tinyBlockInput.RandomHash; + vrfRandomProof = tinyBlockInput.VrfRandomProof; ProcessTinyBlock(tinyBlockInput); break; } @@ -71,10 +71,13 @@ private void ProcessConsensusInformation(dynamic input, [CallerMemberName] strin Context.LogDebug(() => $"Current round information:\n{currentRound.ToString(_processingBlockMinerPubkey)}"); - var previousRandomHash = State.RandomHashes[Context.CurrentHeight.Sub(1)] ?? Hash.Empty; - Assert(Context.ECVRFVerify(Context.RecoverPublicKey(), previousRandomHash.ToHex(), randomHash.ToHex()), + var previousBeta = State.VrfRandomProofs[Context.CurrentHeight.Sub(1)]?.Beta; + var previousRandomHash = previousBeta == null + ? Hash.Empty.ToByteArray() + : previousBeta.ToByteArray(); + Assert(Context.ECVrfVerify(Context.RecoverPublicKey(), vrfRandomProof.Pi, vrfRandomProof.Beta, ), "Invalid random hash."); - State.RandomHashes[Context.CurrentHeight] = randomHash; + State.VrfRandomProofs[Context.CurrentHeight] = vrfRandomProof; Context.LogDebug(() => $"New random hash generated: {randomHash} - height {Context.CurrentHeight}"); diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs index 75ae35da76..2d304389e6 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs @@ -50,7 +50,7 @@ public partial class AEDPoSContractState : ContractState public SingletonState MethodFeeController { get; set; } public SingletonState MaximumMinersCountController { get; set; } - public MappedState RandomHashes { get; set; } + public MappedState VrfRandomProofs { get; set; } public SingletonState LatestExecutedHeight { get; set; } diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs index 592343668a..acfa7d4580 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs @@ -10,9 +10,9 @@ public partial class Round /// will record this purpose to their FinalOrderOfNextRound field. /// /// - /// + /// /// - public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey, Hash randomHash) + public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey, VrfRandomProof vrfRandomProof) { if (!RealTimeMinersInformation.ContainsKey(pubkey)) return null; @@ -45,7 +45,7 @@ public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey, Hash DecryptedPieces = { decryptedPreviousInValues }, MinersPreviousInValues = { minersPreviousInValues }, ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight, - RandomHash = randomHash + VrfRandomProof = vrfRandomProof }; } } \ No newline at end of file diff --git a/protobuf/aedpos_contract.proto b/protobuf/aedpos_contract.proto index b09cabf7ef..7ba3b677b0 100644 --- a/protobuf/aedpos_contract.proto +++ b/protobuf/aedpos_contract.proto @@ -216,8 +216,8 @@ message UpdateValueInput { map miners_previous_in_values = 11; // The irreversible block height that miner recorded. int64 implied_irreversible_block_height = 12; - // The random hash of AEDPoS. - aelf.Hash random_hash = 13; + // The VRF random proof. + VrfRandomProof vrf_random_proof = 13; } message MinerList { @@ -341,8 +341,8 @@ message AElfConsensusTriggerInformation { map decrypted_pieces = 6; // The revealed InValues. map revealed_in_values = 7; - // The random hash of AEDPoS. - aelf.Hash random_hash = 8; + // The VRF random proof. + VrfRandomProof vrf_random_proof = 8; } message TermInfo { @@ -364,8 +364,8 @@ message TinyBlockInput { google.protobuf.Timestamp actual_mining_time = 2; // Count of blocks currently produced int64 produced_blocks = 3; - // The random hash of AEDPoS. - aelf.Hash random_hash = 4; + // The VRF random proof. + VrfRandomProof vrf_random_proof = 4; } message VoteMinersCountInput { @@ -475,8 +475,8 @@ message NextRoundInput { bool is_miner_list_just_changed = 9; // The round id, calculated by summing block producers’ expecting time (second). int64 round_id_for_validation = 10; - // The random hash of AEDPoS. - aelf.Hash random_hash = 11; + // The VRF random proof. + VrfRandomProof vrf_random_proof = 11; } message NextTermInput { @@ -500,6 +500,13 @@ message NextTermInput { bool is_miner_list_just_changed = 9; // The round id, calculated by summing block producers’ expecting time (second). int64 round_id_for_validation = 10; - // The random hash of AEDPoS. - aelf.Hash random_hash = 11; + // The VRF random proof. + VrfRandomProof vrf_random_proof = 11; +} + +message VrfRandomProof{ + // The VRF proof. + bytes pi = 1; + // The VRF hash output. + bytes beta = 2; } \ No newline at end of file diff --git a/src/AElf.Cryptography/CryptoHelper.cs b/src/AElf.Cryptography/CryptoHelper.cs index 91abb3a64d..d616c012e1 100644 --- a/src/AElf.Cryptography/CryptoHelper.cs +++ b/src/AElf.Cryptography/CryptoHelper.cs @@ -2,10 +2,13 @@ using System.Linq; using System.Security.Cryptography; using System.Threading; +using AElf.Cryptography.Core; using AElf.Cryptography.ECDSA; +using AElf.Cryptography.ECVRF; using AElf.Cryptography.Exceptions; using Secp256k1Net; using Virgil.Crypto; +using ECParameters = AElf.Cryptography.ECDSA.ECParameters; namespace AElf.Cryptography; @@ -16,6 +19,8 @@ public static class CryptoHelper // ReaderWriterLock for thread-safe with Secp256k1 APIs private static readonly ReaderWriterLock Lock = new(); + private static readonly Vrf Vrf = new(new VrfConfig(0xfe, ECParameters.Curve)); + static CryptoHelper() { AppDomain.CurrentDomain.ProcessExit += (sender, arg) => { Secp256K1.Dispose(); }; @@ -160,4 +165,30 @@ public static byte[] Ecdh(byte[] privateKey, byte[] publicKey) Lock.ReleaseWriterLock(); } } + + public static Proof ECVrfProve(ECKeyPair keyPair, byte[] alpha) + { + try + { + Lock.AcquireWriterLock(Timeout.Infinite); + return Vrf.Prove(keyPair, alpha); + } + finally + { + Lock.ReleaseWriterLock(); + } + } + + public static byte[] ECVrfVerify(byte[] publicKey, byte[] alpha, byte[] pi) + { + try + { + Lock.AcquireWriterLock(Timeout.Infinite); + return Vrf.Verify(publicKey, alpha, pi); + } + finally + { + Lock.ReleaseWriterLock(); + } + } } \ No newline at end of file diff --git a/src/AElf.Kernel.Core/Account/Application/IAccountService.cs b/src/AElf.Kernel.Core/Account/Application/IAccountService.cs index fa47a8ecc5..bc06e3ddf4 100644 --- a/src/AElf.Kernel.Core/Account/Application/IAccountService.cs +++ b/src/AElf.Kernel.Core/Account/Application/IAccountService.cs @@ -1,4 +1,6 @@ using AElf.Cryptography; +using AElf.Cryptography.ECDSA; +using AElf.Cryptography.ECVRF; using AElf.Kernel.Account.Infrastructure; namespace AElf.Kernel.Account.Application; @@ -9,6 +11,7 @@ public interface IAccountService Task GetPublicKeyAsync(); Task EncryptMessageAsync(byte[] receiverPublicKey, byte[] plainMessage); Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cipherMessage); + Task ECVrfProveAsync(byte[] message); } public static class AccountServiceExtensions @@ -53,4 +56,9 @@ public Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cipherMes return Task.FromResult(CryptoHelper.DecryptMessage(senderPublicKey, _ecKeyPairProvider.GetKeyPair().PrivateKey, cipherMessage)); } + + public Task ECVrfProveAsync(byte[] message) + { + return Task.FromResult(CryptoHelper.ECVrfProve((ECKeyPair)_ecKeyPairProvider.GetKeyPair(), message)); + } } \ No newline at end of file diff --git a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs index 1ab72838fb..d7c95fd885 100644 --- a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs @@ -89,7 +89,7 @@ Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualA object ValidateStateSize(object obj); - bool ECVRFVerify(byte[] pubKey, string pi, string alpha); + bool ECVrfVerify(byte[] pubKey, byte[] pi, byte[] alpha, byte[] beta); } [Serializable] diff --git a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs index 22cf833ea7..a424a5a0f7 100644 --- a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs @@ -350,9 +350,8 @@ public byte[] RecoverPublicKey(byte[] signature, byte[] hash) return !cabBeRecovered ? null : publicKey; } - public bool ECVRFVerify(byte[] pubKey, string pi, string alpha) + public bool ECVrfVerify(byte[] pubKey, byte[] pi, byte[] alpha, byte[] beta) { - // TODO: implement - return true; + return ByteArrayHelper.BytesEqual(CryptoHelper.ECVrfVerify(pubKey, pi, alpha), beta); } } \ No newline at end of file diff --git a/src/AElf.OS/Account/Application/AccountService.cs b/src/AElf.OS/Account/Application/AccountService.cs index 9e2e2400d4..8967136465 100644 --- a/src/AElf.OS/Account/Application/AccountService.cs +++ b/src/AElf.OS/Account/Application/AccountService.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using AElf.Cryptography; using AElf.Cryptography.ECDSA; +using AElf.Cryptography.ECVRF; using AElf.Kernel.Account.Application; using AElf.OS.Account.Infrastructure; using AElf.Types; @@ -43,6 +44,12 @@ public async Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cip cipherMessage); } + public async Task ECVrfProveAsync(byte[] message) + { + var keyPair = await GetAccountKeyPairAsync(); + return CryptoHelper.ECVrfProve(keyPair, message); + } + public async Task
GetAccountAsync() { var publicKey = (await GetAccountKeyPairAsync()).PublicKey; diff --git a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs index 6a8edada5f..ce9ad92c31 100644 --- a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs +++ b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs @@ -373,8 +373,8 @@ public Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash v virtualAddress); } - public bool ECVRFVerify(byte[] pubKey, string pi, string alpha) + public bool ECVrfVerify(byte[] pubKey, byte[] pi, byte[] alpha, byte[] beta) { - return SmartContractBridgeContextImplementation.ECVRFVerify(pubKey, pi, alpha); + return SmartContractBridgeContextImplementation.ECVrfVerify(pubKey, pi, alpha, beta); } } \ No newline at end of file diff --git a/test/AElf.Cryptography.Tests/CryptoHelperTests.cs b/test/AElf.Cryptography.Tests/CryptoHelperTests.cs index 0a5578c15f..20a7f280c9 100644 --- a/test/AElf.Cryptography.Tests/CryptoHelperTests.cs +++ b/test/AElf.Cryptography.Tests/CryptoHelperTests.cs @@ -1,6 +1,7 @@ using System; using System.Text; using AElf.Cryptography.Exceptions; +using AElf.Types; using Shouldly; using Virgil.Crypto; using Xunit; @@ -132,4 +133,19 @@ public void ExceptionTest() Should.Throw(() => throw new SignatureOperationException(message)); Should.Throw(() => throw new InvalidKeyPairException(message, new Exception())); } + + [Fact] + public void VrfTest() + { + var key = CryptoHelper.GenerateKeyPair(); + var alpha = "5cf8151010716e40e5349ad02821da605df22e9ac95450c7e35f04c720fd4db5"; + var alphaBytes = Hash.LoadFromHex(alpha).ToByteArray(); + var proof = CryptoHelper.ECVrfProve(key, alphaBytes); + var beta = CryptoHelper.ECVrfVerify(key.PublicKey, alphaBytes, proof.Pi); + beta.ToHex().ShouldBe(proof.Beta.ToHex()); + + + var bbb = CryptoHelper.ECVrfProofToHash(proof.Pi); + bbb.ToHex().ShouldBe(proof.Beta.ToHex()); + } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs b/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs index 9d9a44ed36..cc893a3004 100644 --- a/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs @@ -59,4 +59,15 @@ public async Task EncryptAndDecryptMessage_Test() decryptMessage.ShouldBe(plainMessage); } + + [Fact] + public async Task Vrf_Test() + { + var alpha = "5cf8151010716e40e5349ad02821da605df22e9ac95450c7e35f04c720fd4db5"; + var alphaBytes = Hash.LoadFromHex(alpha).ToByteArray(); + var proof = await _accountService.ECVrfProveAsync(alphaBytes); + var pubkey = await _accountService.GetPublicKeyAsync(); + var beta = CryptoHelper.ECVrfVerify(pubkey, alphaBytes, proof.Pi); + beta.ToHex().ShouldBe(proof.Beta.ToHex()); + } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs b/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs index 399bdd6064..984dfbc115 100644 --- a/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs +++ b/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs @@ -99,4 +99,15 @@ public async Task GetAccountAsync_WithOptionEmpty() account = await _accountService.GetAccountAsync(); account.ShouldNotBeNull(); } + + [Fact] + public async Task Vrf_Test() + { + var alpha = "5cf8151010716e40e5349ad02821da605df22e9ac95450c7e35f04c720fd4db5"; + var alphaBytes = Hash.LoadFromHex(alpha).ToByteArray(); + var proof = await _accountService.ECVrfProveAsync(alphaBytes); + var pubkey = await _accountService.GetPublicKeyAsync(); + var beta = CryptoHelper.ECVrfVerify(pubkey, alphaBytes, proof.Pi); + beta.ToHex().ShouldBe(proof.Beta.ToHex()); + } } \ No newline at end of file From 79d4ed67ce63cd7dc2ea0b4fdcf76de378d005d9 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Thu, 15 Jun 2023 17:57:28 +0800 Subject: [PATCH 056/139] feat: vrf prove method returns pi only --- src/AElf.Cryptography/ECVRF/Types.cs | 8 +------- src/AElf.Cryptography/ECVRF/Vrf.cs | 9 ++------- test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs | 6 ++---- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/AElf.Cryptography/ECVRF/Types.cs b/src/AElf.Cryptography/ECVRF/Types.cs index a0af437fa8..d9a9975ae4 100644 --- a/src/AElf.Cryptography/ECVRF/Types.cs +++ b/src/AElf.Cryptography/ECVRF/Types.cs @@ -6,12 +6,6 @@ namespace AElf.Cryptography.ECVRF; -public struct Proof -{ - public byte[] Beta { get; set; } - public byte[] Pi { get; set; } -} - public struct ProofInput { public IECPoint Gamma { get; set; } @@ -39,6 +33,6 @@ public interface IHasherFactory public interface IVrf { - Proof Prove(ECKeyPair keyPair, byte[] alpha); + byte[] Prove(ECKeyPair keyPair, byte[] alpha); byte[] Verify(byte[] publicKey, byte[] alpha, byte[] pi); } \ No newline at end of file diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index 5329ccb825..5d080f568a 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -25,7 +25,7 @@ public Vrf(VrfConfig config) _hasherFactory = new THasherFactory(); } - public Proof Prove(ECKeyPair keyPair, byte[] alpha) + public byte[] Prove(ECKeyPair keyPair, byte[] alpha) { using var curve = new TCurve(); var point = curve.DeserializePoint(keyPair.PublicKey); @@ -38,12 +38,7 @@ public Proof Prove(ECKeyPair keyPair, byte[] alpha) var c = HashPoints(hashPoint, gamma, kB, kH); var cX = c.Multiply(new BigInteger(1, keyPair.PrivateKey)); var s = cX.Add(new BigInteger(1, nonce.Representation)).Mod(_config.EcParameters.N); - var pi = EncodeProof(gamma, c, s); - var beta = GammaToHash(gamma); - return new Proof - { - Pi = pi, Beta = beta - }; + return EncodeProof(gamma, c, s); } public byte[] Verify(byte[] publicKey, byte[] alpha, byte[] pi) diff --git a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs index 7f032483dd..b9ac5f784c 100644 --- a/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs +++ b/test/AElf.Cryptography.Tests/ECVRF/VRFTests.cs @@ -60,12 +60,10 @@ public void Prove_Test() var kp = CryptoHelper.FromPrivateKey(sk); var alpha = Convert.FromHexString(vector.Alpha); var expectedPi = Convert.FromHexString(vector.Pi); - var expectedBeta = Convert.FromHexString(vector.Beta); var cfg = new VrfConfig( 0xfe, ECParameters.Curve); var vrf = new Vrf(cfg); - var proof = vrf.Prove(kp, alpha); - Assert.Equal(expectedPi, proof.Pi); - Assert.Equal(expectedBeta, proof.Beta); + var pi = vrf.Prove(kp, alpha); + Assert.Equal(expectedPi, pi); } } From 1eac10e6b610a7be2dbb89ff8b5266c4ff0b531e Mon Sep 17 00:00:00 2001 From: zhxymh Date: Thu, 15 Jun 2023 20:23:35 +0800 Subject: [PATCH 057/139] feat: use vrf random number --- .../AEDPoSContract.cs | 2 +- ...tract_ACS4_ConsensusInformationProvider.cs | 14 +++++----- ...PoSContract_ProcessConsensusInformation.cs | 24 ++++++++--------- .../AElfConsensusContractState.cs | 2 +- ...und_ExtractInformationToUpdateConsensus.cs | 7 ++--- protobuf/aedpos_contract.proto | 27 +++++++------------ .../BlockMiningService.cs | 2 +- src/AElf.Cryptography/CryptoHelper.cs | 2 +- .../AEDPoSTriggerInformationProvider.cs | 14 +++++----- .../Application/IRandomHashProvider.cs | 15 +++++------ .../Account/Application/IAccountService.cs | 4 +-- .../ISmartContractBridgeContext.cs | 2 +- .../HostSmartContractBridgeContext.cs | 4 +-- .../Account/Application/AccountService.cs | 2 +- .../CSharpSmartContractContext.cs | 4 +-- .../BVT/ACS4ImplTest.cs | 2 +- .../BVT/MinersCountTest.cs | 6 ++--- .../BVT/MiningProcessTest.cs | 6 ++--- .../BVT/ViewTests.cs | 2 +- .../Types/Round.cs | 3 ++- .../Types/Round_Generation.cs | 3 ++- .../EconomicContractsTestModule.cs | 2 +- .../OtherContractsOperation.cs | 3 ++- .../Types/MinerList.cs | 4 +-- .../Types/Round_Generation.cs | 3 ++- .../Types/Round_Generation.cs | 3 ++- .../CryptoHelperTests.cs | 14 +++++----- .../Application/AccountServiceTests.cs | 6 ++--- .../Application/AccountServiceTests.cs | 6 ++--- 29 files changed, 90 insertions(+), 98 deletions(-) diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs index 3e3499e4d6..8249961a4a 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs @@ -117,7 +117,7 @@ public override Empty UpdateTinyBlockInformation(TinyBlockInput input) // Keep this for compatibility. public override Hash GetRandomHash(Int64Value input) { - Assert(input.Value > 1, "Invalid block height."); + Assert(input.Value > 0, "Invalid block height."); Assert(Context.CurrentHeight >= input.Value, "Block height not reached."); return State.RandomHashes[input.Value] ?? Hash.Empty; } diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs index 993bad1881..45fd241277 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs @@ -67,10 +67,10 @@ public override TransactionList GenerateConsensusTransactions(BytesValue input) "Data to request consensus information should contain pubkey."); var pubkey = triggerInformation.Pubkey; - var randomHash = triggerInformation.VrfRandomProof; + var randomNumber = triggerInformation.RandomNumber; var consensusInformation = new AElfConsensusHeaderInformation(); consensusInformation.MergeFrom(GetConsensusBlockExtraData(input, true).Value); - var transactionList = GenerateTransactionListByExtraData(consensusInformation, pubkey, randomHash); + var transactionList = GenerateTransactionListByExtraData(consensusInformation, pubkey, randomNumber); return transactionList; } @@ -128,7 +128,7 @@ public override ValidationResult ValidateConsensusAfterExecution(BytesValue inpu } private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderInformation consensusInformation, - ByteString pubkey, VrfRandomProof vrfRandomProof) + ByteString pubkey, ByteString randomNumber) { var round = consensusInformation.Round; var behaviour = consensusInformation.Behaviour; @@ -142,7 +142,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn Transactions = { GenerateTransaction(nameof(UpdateValue), - round.ExtractInformationToUpdateConsensus(pubkey.ToHex(),vrfRandomProof)) + round.ExtractInformationToUpdateConsensus(pubkey.ToHex(), randomNumber)) } }; case AElfConsensusBehaviour.TinyBlock: @@ -157,7 +157,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn ActualMiningTime = minerInRound.ActualMiningTimes.Last(), ProducedBlocks = minerInRound.ProducedBlocks, RoundId = round.RoundIdForValidation, - VrfRandomProof = vrfRandomProof + RandomNumber = randomNumber }) } }; @@ -178,7 +178,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn IsMinerListJustChanged = round.IsMinerListJustChanged, RoundIdForValidation = round.RoundIdForValidation, MainChainMinersRoundNumber = round.MainChainMinersRoundNumber, - VrfRandomProof = vrfRandomProof + RandomNumber = randomNumber }) } }; @@ -199,7 +199,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn IsMinerListJustChanged = round.IsMinerListJustChanged, RoundIdForValidation = round.RoundIdForValidation, MainChainMinersRoundNumber = round.MainChainMinersRoundNumber, - VrfRandomProof = vrfRandomProof + RandomNumber = randomNumber }) } }; diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs index eab386c584..c4b204c12d 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs @@ -5,6 +5,7 @@ using AElf.Sdk.CSharp; using AElf.Standards.ACS10; using AElf.Types; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.Consensus.AEDPoS; @@ -28,25 +29,25 @@ private void ProcessConsensusInformation(dynamic input, [CallerMemberName] strin State.RoundBeforeLatestExecution.Value = GetCurrentRoundInformation(new Empty()); - VrfRandomProof vrfRandomProof = null; + ByteString randomNumber = null; // The only difference. switch (input) { case NextRoundInput nextRoundInput: - vrfRandomProof = nextRoundInput.VrfRandomProof; + randomNumber = nextRoundInput.RandomNumber; ProcessNextRound(nextRoundInput); break; case NextTermInput nextTermInput: - vrfRandomProof = nextTermInput.VrfRandomProof; + randomNumber = nextTermInput.RandomNumber; ProcessNextTerm(nextTermInput); break; case UpdateValueInput updateValueInput: - vrfRandomProof = updateValueInput.VrfRandomProof; + randomNumber = updateValueInput.RandomNumber; ProcessUpdateValue(updateValueInput); break; case TinyBlockInput tinyBlockInput: - vrfRandomProof = tinyBlockInput.VrfRandomProof; + randomNumber = tinyBlockInput.RandomNumber; ProcessTinyBlock(tinyBlockInput); break; } @@ -71,14 +72,11 @@ private void ProcessConsensusInformation(dynamic input, [CallerMemberName] strin Context.LogDebug(() => $"Current round information:\n{currentRound.ToString(_processingBlockMinerPubkey)}"); - var previousBeta = State.VrfRandomProofs[Context.CurrentHeight.Sub(1)]?.Beta; - var previousRandomHash = previousBeta == null - ? Hash.Empty.ToByteArray() - : previousBeta.ToByteArray(); - Assert(Context.ECVrfVerify(Context.RecoverPublicKey(), vrfRandomProof.Pi, vrfRandomProof.Beta, ), - "Invalid random hash."); - State.VrfRandomProofs[Context.CurrentHeight] = vrfRandomProof; - + var previousRandomHash = State.RandomHashes[Context.CurrentHeight.Sub(1)] ?? Hash.Empty; + var beta = Context.ECVrfVerify(Context.RecoverPublicKey(), previousRandomHash.ToByteArray(), + randomNumber.ToByteArray()); + var randomHash = Hash.LoadFromByteArray(beta); + State.RandomHashes[Context.CurrentHeight] = randomHash; Context.LogDebug(() => $"New random hash generated: {randomHash} - height {Context.CurrentHeight}"); if (!State.IsMainChain.Value && currentRound.RoundNumber > 1) Release(); diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs index 2d304389e6..75ae35da76 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AElfConsensusContractState.cs @@ -50,7 +50,7 @@ public partial class AEDPoSContractState : ContractState public SingletonState MethodFeeController { get; set; } public SingletonState MaximumMinersCountController { get; set; } - public MappedState VrfRandomProofs { get; set; } + public MappedState RandomHashes { get; set; } public SingletonState LatestExecutedHeight { get; set; } diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs index acfa7d4580..b0d93721cb 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/Round_ExtractInformationToUpdateConsensus.cs @@ -1,5 +1,6 @@ using System.Linq; using AElf.Types; +using Google.Protobuf; namespace AElf.Contracts.Consensus.AEDPoS; @@ -10,9 +11,9 @@ public partial class Round /// will record this purpose to their FinalOrderOfNextRound field. /// /// - /// + /// /// - public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey, VrfRandomProof vrfRandomProof) + public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey, ByteString randomNumber) { if (!RealTimeMinersInformation.ContainsKey(pubkey)) return null; @@ -45,7 +46,7 @@ public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey, VrfRa DecryptedPieces = { decryptedPreviousInValues }, MinersPreviousInValues = { minersPreviousInValues }, ImpliedIrreversibleBlockHeight = minerInRound.ImpliedIrreversibleBlockHeight, - VrfRandomProof = vrfRandomProof + RandomNumber = randomNumber }; } } \ No newline at end of file diff --git a/protobuf/aedpos_contract.proto b/protobuf/aedpos_contract.proto index 7ba3b677b0..4f2719a70c 100644 --- a/protobuf/aedpos_contract.proto +++ b/protobuf/aedpos_contract.proto @@ -216,8 +216,8 @@ message UpdateValueInput { map miners_previous_in_values = 11; // The irreversible block height that miner recorded. int64 implied_irreversible_block_height = 12; - // The VRF random proof. - VrfRandomProof vrf_random_proof = 13; + // The random number. + bytes random_number = 13; } message MinerList { @@ -341,8 +341,8 @@ message AElfConsensusTriggerInformation { map decrypted_pieces = 6; // The revealed InValues. map revealed_in_values = 7; - // The VRF random proof. - VrfRandomProof vrf_random_proof = 8; + // The random number. + bytes random_number = 8; } message TermInfo { @@ -364,8 +364,8 @@ message TinyBlockInput { google.protobuf.Timestamp actual_mining_time = 2; // Count of blocks currently produced int64 produced_blocks = 3; - // The VRF random proof. - VrfRandomProof vrf_random_proof = 4; + // The random number. + bytes random_number = 4; } message VoteMinersCountInput { @@ -475,8 +475,8 @@ message NextRoundInput { bool is_miner_list_just_changed = 9; // The round id, calculated by summing block producers’ expecting time (second). int64 round_id_for_validation = 10; - // The VRF random proof. - VrfRandomProof vrf_random_proof = 11; + // The random number. + bytes random_number = 11; } message NextTermInput { @@ -500,13 +500,6 @@ message NextTermInput { bool is_miner_list_just_changed = 9; // The round id, calculated by summing block producers’ expecting time (second). int64 round_id_for_validation = 10; - // The VRF random proof. - VrfRandomProof vrf_random_proof = 11; -} - -message VrfRandomProof{ - // The VRF proof. - bytes pi = 1; - // The VRF hash output. - bytes beta = 2; + // The random number. + bytes random_number = 11; } \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs index 40d043de6d..fbc2ba4d25 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs @@ -390,7 +390,7 @@ private async Task GetConsensusTriggerInfoAsync PreviousInValue = HashHelper.ComputeFrom($"InValueOf{pubkey}"), Pubkey = pubkey.Value, // TODO: Set random hash. - RandomHash = Hash.Empty + RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()) }; var consensusExtraData = await contractStub.GetConsensusExtraData.CallAsync(new BytesValue diff --git a/src/AElf.Cryptography/CryptoHelper.cs b/src/AElf.Cryptography/CryptoHelper.cs index d616c012e1..b274636f31 100644 --- a/src/AElf.Cryptography/CryptoHelper.cs +++ b/src/AElf.Cryptography/CryptoHelper.cs @@ -166,7 +166,7 @@ public static byte[] Ecdh(byte[] privateKey, byte[] publicKey) } } - public static Proof ECVrfProve(ECKeyPair keyPair, byte[] alpha) + public static byte[] ECVrfProve(ECKeyPair keyPair, byte[] alpha) { try { diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs index 564aa694cd..89113766e2 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs @@ -16,15 +16,15 @@ internal class AEDPoSTriggerInformationProvider : ITriggerInformationProvider private readonly IAccountService _accountService; private readonly IInValueCache _inValueCache; private readonly ISecretSharingService _secretSharingService; - private readonly IRandomHashProvider _randomHashProvider; + private readonly IRandomProvider _randomProvider; public AEDPoSTriggerInformationProvider(IAccountService accountService, - ISecretSharingService secretSharingService, IInValueCache inValueCache, IRandomHashProvider randomHashProvider) + ISecretSharingService secretSharingService, IInValueCache inValueCache, IRandomProvider randomProvider) { _accountService = accountService; _secretSharingService = secretSharingService; _inValueCache = inValueCache; - _randomHashProvider = randomHashProvider; + _randomProvider = randomProvider; Logger = NullLogger.Instance; } @@ -76,14 +76,14 @@ public BytesValue GetTriggerInformationForBlockHeaderExtraData(BytesValue consen public BytesValue GetTriggerInformationForConsensusTransactions(IChainContext chainContext, BytesValue consensusCommandBytes) { - var randomHash = AsyncHelper.RunSync(async ()=> await _randomHashProvider.GenerateRandomHashAsync(chainContext)); + var randomProve = AsyncHelper.RunSync(async ()=> await _randomProvider.GenerateRandomProveAsync(chainContext)); if (consensusCommandBytes == null) return new AElfConsensusTriggerInformation { Pubkey = Pubkey, Behaviour = AElfConsensusBehaviour.UpdateValue, - RandomHash = randomHash + RandomNumber = ByteString.CopyFrom(randomProve) }.ToBytesValue(); var command = consensusCommandBytes.ToConsensusCommand(); @@ -98,7 +98,7 @@ public BytesValue GetTriggerInformationForConsensusTransactions(IChainContext ch InValue = inValue, PreviousInValue = _inValueCache.GetInValue(hint.PreviousRoundId), Behaviour = hint.Behaviour, - RandomHash = randomHash + RandomNumber = ByteString.CopyFrom(randomProve) }; var secretPieces = _secretSharingService.GetEncryptedPieces(hint.RoundId); @@ -120,7 +120,7 @@ public BytesValue GetTriggerInformationForConsensusTransactions(IChainContext ch { Pubkey = Pubkey, Behaviour = hint.Behaviour, - RandomHash = randomHash + RandomNumber = ByteString.CopyFrom(randomProve) }.ToBytesValue(); } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs index 0e18d3c659..cc6d15617e 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs @@ -5,29 +5,26 @@ namespace AElf.Kernel.Consensus.AEDPoS.Application; -public interface IRandomHashProvider +public interface IRandomProvider { - Task GenerateRandomHashAsync(IChainContext chainContext); + Task GenerateRandomProveAsync(IChainContext chainContext); } -public class RandomHashProvider : IRandomHashProvider, ITransientDependency +public class RandomProvider : IRandomProvider, ITransientDependency { private readonly IAEDPoSInformationProvider _aedPoSInformationProvider; private readonly IAccountService _accountService; - public RandomHashProvider(IAEDPoSInformationProvider aedPoSInformationProvider, IAccountService accountService) + public RandomProvider(IAEDPoSInformationProvider aedPoSInformationProvider, IAccountService accountService) { _aedPoSInformationProvider = aedPoSInformationProvider; _accountService = accountService; } - public async Task GenerateRandomHashAsync(IChainContext chainContext) + public async Task GenerateRandomProveAsync(IChainContext chainContext) { var previousRandomHash = await _aedPoSInformationProvider.GetRandomHashAsync(chainContext, chainContext.BlockHeight); - // TODO: Use real random hash. - var randomHash = Hash.Empty; - - return randomHash; + return await _accountService.ECVrfProveAsync(previousRandomHash.ToByteArray()); } } diff --git a/src/AElf.Kernel.Core/Account/Application/IAccountService.cs b/src/AElf.Kernel.Core/Account/Application/IAccountService.cs index bc06e3ddf4..523dee30cb 100644 --- a/src/AElf.Kernel.Core/Account/Application/IAccountService.cs +++ b/src/AElf.Kernel.Core/Account/Application/IAccountService.cs @@ -11,7 +11,7 @@ public interface IAccountService Task GetPublicKeyAsync(); Task EncryptMessageAsync(byte[] receiverPublicKey, byte[] plainMessage); Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cipherMessage); - Task ECVrfProveAsync(byte[] message); + Task ECVrfProveAsync(byte[] message); } public static class AccountServiceExtensions @@ -57,7 +57,7 @@ public Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cipherMes _ecKeyPairProvider.GetKeyPair().PrivateKey, cipherMessage)); } - public Task ECVrfProveAsync(byte[] message) + public Task ECVrfProveAsync(byte[] message) { return Task.FromResult(CryptoHelper.ECVrfProve((ECKeyPair)_ecKeyPairProvider.GetKeyPair(), message)); } diff --git a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs index d7c95fd885..1c53303b41 100644 --- a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs @@ -89,7 +89,7 @@ Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualA object ValidateStateSize(object obj); - bool ECVrfVerify(byte[] pubKey, byte[] pi, byte[] alpha, byte[] beta); + byte[] ECVrfVerify(byte[] pubKey, byte[] alpha, byte[] pi); } [Serializable] diff --git a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs index a424a5a0f7..daef5aec24 100644 --- a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs @@ -350,8 +350,8 @@ public byte[] RecoverPublicKey(byte[] signature, byte[] hash) return !cabBeRecovered ? null : publicKey; } - public bool ECVrfVerify(byte[] pubKey, byte[] pi, byte[] alpha, byte[] beta) + public byte[] ECVrfVerify(byte[] pubKey, byte[] alpha, byte[] pi) { - return ByteArrayHelper.BytesEqual(CryptoHelper.ECVrfVerify(pubKey, pi, alpha), beta); + return CryptoHelper.ECVrfVerify(pubKey, alpha, pi); } } \ No newline at end of file diff --git a/src/AElf.OS/Account/Application/AccountService.cs b/src/AElf.OS/Account/Application/AccountService.cs index 8967136465..ec1193c564 100644 --- a/src/AElf.OS/Account/Application/AccountService.cs +++ b/src/AElf.OS/Account/Application/AccountService.cs @@ -44,7 +44,7 @@ public async Task DecryptMessageAsync(byte[] senderPublicKey, byte[] cip cipherMessage); } - public async Task ECVrfProveAsync(byte[] message) + public async Task ECVrfProveAsync(byte[] message) { var keyPair = await GetAccountKeyPairAsync(); return CryptoHelper.ECVrfProve(keyPair, message); diff --git a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs index ce9ad92c31..6b90ae9a63 100644 --- a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs +++ b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs @@ -373,8 +373,8 @@ public Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash v virtualAddress); } - public bool ECVrfVerify(byte[] pubKey, byte[] pi, byte[] alpha, byte[] beta) + public byte[] ECVrfVerify(byte[] pubKey, byte[] alpha, byte[] pi) { - return SmartContractBridgeContextImplementation.ECVrfVerify(pubKey, pi, alpha, beta); + return SmartContractBridgeContextImplementation.ECVrfVerify(pubKey, alpha, pi); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs index 044ab7a959..1d6d7beb69 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs @@ -329,7 +329,7 @@ public async Task AEDPoSContract_ConsensusTransactionValidation_Test() nextRoundInput.IsMinerListJustChanged = false; nextRoundInput.TermNumber++; // TODO: Set random hash. - nextRoundInput.RandomHash = Hash.Empty; + nextRoundInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs index 728ed8ffa8..1d78bf0fd3 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs @@ -82,7 +82,7 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() var nextRoundInput = NextRoundInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); // TODO: Set random hash. - nextRoundInput.RandomHash = Hash.Empty; + nextRoundInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); changeTermTime = BlockchainStartTimestamp.ToDateTime().AddMinutes(termIntervalMin).AddSeconds(10); BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); @@ -96,7 +96,7 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() var nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); // TODO: Set random hash. - nextTermInput.RandomHash = Hash.Empty; + nextTermInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); var transactionResult = await AEDPoSContractStub.NextTerm.SendAsync(nextTermInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); @@ -125,7 +125,7 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() }.ToBytesValue())).ToConsensusHeaderInformation(); nextTermInput = NextTermInput.Parser.ParseFrom(nextRoundInformation.Round.ToByteArray()); // TODO: Set random hash. - nextTermInput.RandomHash = Hash.Empty; + nextTermInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); await newMinerStub.NextTerm.SendAsync(nextTermInput); termCount++; } diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs index 075142361a..98b545ac51 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs @@ -75,7 +75,7 @@ await voter.Vote.SendAsync(new VoteMinerInput }.ToBytesValue())).ToConsensusHeaderInformation(); var nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); // TODO: Set random hash. - nextTermInput.RandomHash = Hash.Empty; + nextTermInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); await AEDPoSContractStub.NextTerm.SendAsync(nextTermInput); // First candidate cheat others with in value. @@ -104,7 +104,7 @@ await voter.Vote.SendAsync(new VoteMinerInput }.ToBytesValue())).ToConsensusHeaderInformation().Round; var nextRoundInput = NextRoundInput.Parser.ParseFrom(thirdRound.ToByteArray()); // TODO: Set random hash. - nextRoundInput.RandomHash = Hash.Empty; + nextRoundInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); await oneCandidate.NextRound.SendAsync(nextRoundInput); var cheatInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( @@ -137,7 +137,7 @@ public async Task Update_TinyBlockInformation_Test() ProducedBlocks = 4, ActualMiningTime = BlockTimeProvider.GetBlockTime(), // TODO: Set random hash. - RandomHash = Hash.Empty + RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()) }; var transactionResult = await AEDPoSContractStub.UpdateTinyBlockInformation.SendAsync(input); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs index 04f4b9abf0..83d405bc97 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs @@ -29,7 +29,7 @@ public async Task Query_RoundInformation_Test() var nextRoundInput = NextRoundInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); // TODO: Set random hash. - nextRoundInput.RandomHash = Hash.Empty; + nextRoundInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs index ac1b484fe8..4fcff801d6 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using AElf.Types; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.Consensus.AEDPoS; @@ -119,7 +120,7 @@ public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) DecryptedPieces = { decryptedPreviousInValues }, MinersPreviousInValues = { minersPreviousInValues }, // TODO: Set random hash. - RandomHash = Hash.Empty + RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()) }; } diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs index 60a91cab03..9a7b3833e4 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs @@ -2,6 +2,7 @@ using System.Linq; using AElf.CSharp.Core; using AElf.Types; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.Consensus.AEDPoS; @@ -68,7 +69,7 @@ public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timest expectedExtraBlockProducer.IsExtraBlockProducer = true; // TODO: Set random hash. - nextRound.RandomHash = Hash.Empty; + nextRound.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); return true; } diff --git a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs index 568b55446e..25bd849b42 100644 --- a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs +++ b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs @@ -26,7 +26,7 @@ public override void ConfigureServices(ServiceConfigurationContext context) // context.Services.AddSingleton(); context.Services.AddSingleton(); context.Services.AddSingleton(); - context.Services.AddTransient(); + context.Services.AddTransient(); context.Services.AddTransient(); context.Services.RemoveAll(); } diff --git a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs index 0b78ec3379..d9618cef7a 100644 --- a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs +++ b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs @@ -3,6 +3,7 @@ using AElf.Contracts.MultiToken; using AElf.Cryptography.ECDSA; using AElf.Types; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; @@ -58,7 +59,7 @@ await miner.UpdateValue.SendAsync(new UpdateValueInput ActualMiningTime = minerInRound.ExpectedMiningTime, SupposedOrderOfNextRound = 1, // TODO: Set random hash. - RandomHash = Hash.Empty + RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()) }); } diff --git a/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs b/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs index d66277fbdb..087d283ce8 100644 --- a/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs +++ b/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs @@ -43,7 +43,7 @@ orderby obj.Value descending } public NextTermInput GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0, byte[] randomNumber= null) { var sortedMiners = (from obj in Pubkeys @@ -73,7 +73,7 @@ orderby obj.Value descending input.TermNumber = currentTermNumber + 1; input.IsMinerListJustChanged = true; // TODO: Set random hash. - input.RandomHash = Hash.Empty; + input.RandomNumber = ByteString.CopyFrom(randomNumber); return input; } diff --git a/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs b/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs index bd7ae4d32e..c57db52769 100644 --- a/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs +++ b/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs @@ -2,6 +2,7 @@ using System.Linq; using AElf.CSharp.Core; using AElf.Types; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.Consensus.AEDPoS; @@ -65,7 +66,7 @@ public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timest expectedExtraBlockProducer.IsExtraBlockProducer = true; // TODO: Set random hash. - nextRound.RandomHash = Hash.Empty; + nextRound.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); return true; } diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs index 60a91cab03..9a7b3833e4 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs @@ -2,6 +2,7 @@ using System.Linq; using AElf.CSharp.Core; using AElf.Types; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.Consensus.AEDPoS; @@ -68,7 +69,7 @@ public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timest expectedExtraBlockProducer.IsExtraBlockProducer = true; // TODO: Set random hash. - nextRound.RandomHash = Hash.Empty; + nextRound.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); return true; } diff --git a/test/AElf.Cryptography.Tests/CryptoHelperTests.cs b/test/AElf.Cryptography.Tests/CryptoHelperTests.cs index 20a7f280c9..7ec4e7c59e 100644 --- a/test/AElf.Cryptography.Tests/CryptoHelperTests.cs +++ b/test/AElf.Cryptography.Tests/CryptoHelperTests.cs @@ -2,6 +2,7 @@ using System.Text; using AElf.Cryptography.Exceptions; using AElf.Types; +using Org.BouncyCastle.Utilities.Encoders; using Shouldly; using Virgil.Crypto; using Xunit; @@ -137,15 +138,12 @@ public void ExceptionTest() [Fact] public void VrfTest() { - var key = CryptoHelper.GenerateKeyPair(); + var key = CryptoHelper.FromPrivateKey( + ByteArrayHelper.HexStringToByteArray("5945c176c4269dc2aa7daf7078bc63b952832e880da66e5f2237cdf79bc59c5f")); var alpha = "5cf8151010716e40e5349ad02821da605df22e9ac95450c7e35f04c720fd4db5"; var alphaBytes = Hash.LoadFromHex(alpha).ToByteArray(); - var proof = CryptoHelper.ECVrfProve(key, alphaBytes); - var beta = CryptoHelper.ECVrfVerify(key.PublicKey, alphaBytes, proof.Pi); - beta.ToHex().ShouldBe(proof.Beta.ToHex()); - - - var bbb = CryptoHelper.ECVrfProofToHash(proof.Pi); - bbb.ToHex().ShouldBe(proof.Beta.ToHex()); + var pi = CryptoHelper.ECVrfProve(key, alphaBytes); + var beta = CryptoHelper.ECVrfVerify(key.PublicKey, alphaBytes, pi); + beta.ToHex().ShouldBe("43765915e86c205f0c28b4d22e157b8474add7faf890a3aa2a88df756651523f"); } } \ No newline at end of file diff --git a/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs b/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs index cc893a3004..74bfda07dd 100644 --- a/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs +++ b/test/AElf.Kernel.Core.Tests/Account/Application/AccountServiceTests.cs @@ -65,9 +65,9 @@ public async Task Vrf_Test() { var alpha = "5cf8151010716e40e5349ad02821da605df22e9ac95450c7e35f04c720fd4db5"; var alphaBytes = Hash.LoadFromHex(alpha).ToByteArray(); - var proof = await _accountService.ECVrfProveAsync(alphaBytes); + var pi = await _accountService.ECVrfProveAsync(alphaBytes); var pubkey = await _accountService.GetPublicKeyAsync(); - var beta = CryptoHelper.ECVrfVerify(pubkey, alphaBytes, proof.Pi); - beta.ToHex().ShouldBe(proof.Beta.ToHex()); + var beta = CryptoHelper.ECVrfVerify(pubkey, alphaBytes, pi); + beta.ShouldNotBeEmpty(); } } \ No newline at end of file diff --git a/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs b/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs index 984dfbc115..d00503a5eb 100644 --- a/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs +++ b/test/AElf.OS.Tests/Account/Application/AccountServiceTests.cs @@ -105,9 +105,9 @@ public async Task Vrf_Test() { var alpha = "5cf8151010716e40e5349ad02821da605df22e9ac95450c7e35f04c720fd4db5"; var alphaBytes = Hash.LoadFromHex(alpha).ToByteArray(); - var proof = await _accountService.ECVrfProveAsync(alphaBytes); + var pi = await _accountService.ECVrfProveAsync(alphaBytes); var pubkey = await _accountService.GetPublicKeyAsync(); - var beta = CryptoHelper.ECVrfVerify(pubkey, alphaBytes, proof.Pi); - beta.ToHex().ShouldBe(proof.Beta.ToHex()); + var beta = CryptoHelper.ECVrfVerify(pubkey, alphaBytes, pi); + beta.ShouldNotBeEmpty(); } } \ No newline at end of file From dbc5656ae4798d702932c3ceef79bd91f02fc71b Mon Sep 17 00:00:00 2001 From: zhxymh Date: Fri, 16 Jun 2023 16:28:10 +0800 Subject: [PATCH 058/139] test: fix random number tests --- ...Elf.ContractTestKit.AEDPoSExtension.csproj | 12 ++++---- .../BlockMiningService.cs | 21 ++++++++++--- .../AEDPoSContractTestBase.cs | 3 +- .../BVT/ACS4ImplTest.cs | 30 +++++++++++++------ .../BVT/MinersCountTest.cs | 22 ++++++++------ .../BVT/MiningProcessTest.cs | 29 ++++++++++-------- .../BVT/ViewTests.cs | 5 ++-- .../Types/Round.cs | 6 ++-- .../Types/Round_Generation.cs | 6 ++-- .../EconomicContractsTestBase.cs | 4 +++ .../OtherContractsOperation.cs | 20 ++++++++++--- .../Types/MinerList.cs | 5 ++-- .../Types/Round_Generation.cs | 6 ++-- .../MultiTokenContractCrossChainTestBase.cs | 23 ++++++++++++-- .../Types/Round_Generation.cs | 6 ++-- 15 files changed, 130 insertions(+), 68 deletions(-) diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/AElf.ContractTestKit.AEDPoSExtension.csproj b/src/AElf.ContractTestKit.AEDPoSExtension/AElf.ContractTestKit.AEDPoSExtension.csproj index 515b666c92..8230cdb5e4 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/AElf.ContractTestKit.AEDPoSExtension.csproj +++ b/src/AElf.ContractTestKit.AEDPoSExtension/AElf.ContractTestKit.AEDPoSExtension.csproj @@ -10,9 +10,9 @@ - - - + + + @@ -49,10 +49,10 @@ - - + + - + \ No newline at end of file diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs index fbc2ba4d25..ebc9f6f87d 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs @@ -7,6 +7,8 @@ using System.Threading.Tasks; using AElf.ContractDeployer; using AElf.Contracts.Consensus.AEDPoS; +using AElf.Cryptography; +using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; @@ -34,6 +36,7 @@ public class BlockMiningService : IBlockMiningService private readonly ISmartContractAddressService _smartContractAddressService; private readonly ITestDataProvider _testDataProvider; private readonly ITransactionResultService _transactionResultService; + private readonly IBlockchainService _blockchainService; private Address _consensusContractAddress; @@ -52,6 +55,7 @@ public BlockMiningService(IServiceProvider serviceProvider) _testDataProvider = serviceProvider.GetRequiredService(); _transactionResultService = serviceProvider.GetRequiredService(); _chainTypeProvider = serviceProvider.GetRequiredService(); + _blockchainService = serviceProvider.GetRequiredService(); } /// @@ -130,7 +134,8 @@ public async Task MineBlockAsync(List transactions = null, bool wit throw new InitializationFailedException("Can't find current round information."); } - var triggerInformation = await GetConsensusTriggerInfoAsync(contractStub, pubkey); + var randomNumber = await GenerateRandomProveAsync(); + var triggerInformation = await GetConsensusTriggerInfoAsync(contractStub, pubkey, ByteString.CopyFrom(randomNumber)); var consensusTransaction = await contractStub.GenerateConsensusTransactions.CallAsync(new BytesValue { Value = triggerInformation.ToByteString() @@ -156,6 +161,15 @@ public async Task MineBlockAsync(List transactions = null, bool wit _isSkipped = false; } + + private async Task GenerateRandomProveAsync() + { + var blockHeight = (await _blockchainService.GetChainAsync()).BestChainHeight; + var previousRandomHash = + await _contractStubs.First().GetRandomHash.CallAsync(new Int64Value + { Value = blockHeight == 0 ? 1 : blockHeight }); + return CryptoHelper.ECVrfProve((ECKeyPair)_testDataProvider.GetKeyPair(), previousRandomHash.ToByteArray()); + } public async Task MineBlockToNextRoundAsync() { @@ -378,7 +392,7 @@ await contractStub.UpdateValue.SendWithExceptionAsync( } private async Task GetConsensusTriggerInfoAsync( - AEDPoSContractImplContainer.AEDPoSContractImplStub contractStub, BytesValue pubkey) + AEDPoSContractImplContainer.AEDPoSContractImplStub contractStub, BytesValue pubkey, ByteString randomNumber) { var command = await contractStub.GetConsensusCommand.CallAsync(pubkey); var hint = AElfConsensusHint.Parser.ParseFrom(command.Hint); @@ -389,8 +403,7 @@ private async Task GetConsensusTriggerInfoAsync InValue = HashHelper.ComputeFrom($"InValueOf{pubkey}"), PreviousInValue = HashHelper.ComputeFrom($"InValueOf{pubkey}"), Pubkey = pubkey.Value, - // TODO: Set random hash. - RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()) + RandomNumber = randomNumber }; var consensusExtraData = await contractStub.GetConsensusExtraData.CallAsync(new BytesValue diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs index 6cc536f844..6d023108d9 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs @@ -153,8 +153,9 @@ protected async Task BootMinerChangeRoundAsync(long nextRoundNumber = 2) .AddMilliseconds( ((long)currentRound.TotalMilliseconds(AEDPoSContractTestConstants.MiningInterval)).Mul( nextRoundNumber.Sub(1))); + var randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); currentRound.GenerateNextRoundInformation(expectedStartTime.ToTimestamp(), BlockchainStartTimestamp, - out var nextRound); + ByteString.CopyFrom(randomNumber), out var nextRound); await AEDPoSContractStub.NextRound.SendAsync(nextRound); } diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs index 1d6d7beb69..48f2f46cbe 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs @@ -77,8 +77,10 @@ private async Task AEDPoSContract_GenerateConsensusTransactions var triggerForCommand = TriggerInformationProvider.GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); + var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(BootMinerKeyPair)); - var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); + var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(trigger.ToBytesValue()); transactionList.Transactions.Count.ShouldBe(1); transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.UpdateValue)); @@ -177,8 +179,10 @@ private async Task AEDPoSContract_GenerateConsensusTransactions var triggerForCommand = TriggerInformationProvider .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); + var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(usingKeyPair)); - var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); + var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(trigger.ToBytesValue()); transactionList.Transactions.Count.ShouldBe(1); transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.UpdateValue)); @@ -253,8 +257,10 @@ public async Task AEDPoSContract_GetInformationToUpdateConsensus_FirstRound_Extr var triggerForCommand = TriggerInformationProvider .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); + var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(usingKeyPair)); - var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggerForCommand); + var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(trigger.ToBytesValue()); var extraData = extraDataBytes.ToConsensusHeaderInformation(); @@ -277,8 +283,10 @@ private async Task var triggerForCommand = TriggerInformationProvider .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); - - var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); + var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(usingKeyPair)); + + var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(trigger.ToBytesValue()); transactionList.Transactions.Count.ShouldBe(1); transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.NextRound)); @@ -328,8 +336,8 @@ public async Task AEDPoSContract_ConsensusTransactionValidation_Test() nextRoundInput.RoundNumber++; nextRoundInput.IsMinerListJustChanged = false; nextRoundInput.TermNumber++; - // TODO: Set random hash. - nextRoundInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); + var randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + nextRoundInput.RandomNumber = ByteString.CopyFrom(randomNumber); var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); @@ -407,9 +415,11 @@ public async Task AEDPoSContract_GenerateConsensusTransaction_TinyBlock_Test() var triggerForCommand = TriggerInformationProvider .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); + var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(usingKeyPair)); var transactionList = - await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); + await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(trigger.ToBytesValue()); transactionList.Transactions.Count.ShouldBe(1); transactionList.Transactions[0].MethodName @@ -438,9 +448,11 @@ public async Task AEDPoSContract_GenerateConsensusTransaction_NextTerm_Test() var triggerForCommand = TriggerInformationProvider .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); + var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(usingKeyPair)); var transactionList = - await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(triggerForCommand); + await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(trigger.ToBytesValue()); transactionList.Transactions.Count.ShouldBe(1); transactionList.Transactions[0].MethodName.ShouldBe(nameof(AEDPoSContractStub.NextTerm)); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs index 1d78bf0fd3..fd5304c99a 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs @@ -52,6 +52,7 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() voteResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } + byte[] randomNumber; foreach (var minerInRound in firstRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order)) { var currentKeyPair = InitialCoreDataCenterKeyPairs.First(p => p.PublicKey.ToHex() == minerInRound.Pubkey); @@ -65,8 +66,11 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() (await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggers[minerInRound.Pubkey] .ToBytesValue())).ToConsensusHeaderInformation(); + randomNumber = await GenerateRandomProveAsync(currentKeyPair); // Update consensus information. - var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey); + var toUpdate = + headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey, + ByteString.CopyFrom(randomNumber)); await tester.UpdateValue.SendAsync(toUpdate); } @@ -81,8 +85,8 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() }.ToBytesValue())).ToConsensusHeaderInformation(); var nextRoundInput = NextRoundInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); - // TODO: Set random hash. - nextRoundInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); + randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + nextRoundInput.RandomNumber = ByteString.CopyFrom(randomNumber); await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); changeTermTime = BlockchainStartTimestamp.ToDateTime().AddMinutes(termIntervalMin).AddSeconds(10); BlockTimeProvider.SetBlockTime(changeTermTime.ToTimestamp()); @@ -95,8 +99,8 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() }.ToBytesValue())).ToConsensusHeaderInformation(); var nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); - // TODO: Set random hash. - nextTermInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); + randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + nextTermInput.RandomNumber = ByteString.CopyFrom(randomNumber); var transactionResult = await AEDPoSContractStub.NextTerm.SendAsync(nextTermInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); @@ -107,8 +111,8 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() { var currentRound = await newMinerStub.GetCurrentRoundInformation.CallAsync(new Empty()); var firstPubKey = currentRound.RealTimeMinersInformation.Keys.First(); - newMinerStub = - GetAEDPoSContractStub(ValidationDataCenterKeyPairs.First(o => o.PublicKey.ToHex() == firstPubKey)); + var keypair = ValidationDataCenterKeyPairs.First(o => o.PublicKey.ToHex() == firstPubKey); + newMinerStub = GetAEDPoSContractStub(keypair); minerCount = currentRound.RealTimeMinersInformation.Count; Assert.Equal(AEDPoSContractTestConstants.SupposedMinersCount.Add(termCount.Mul(2)), minerCount); @@ -124,8 +128,8 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() .Pubkey) }.ToBytesValue())).ToConsensusHeaderInformation(); nextTermInput = NextTermInput.Parser.ParseFrom(nextRoundInformation.Round.ToByteArray()); - // TODO: Set random hash. - nextTermInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); + randomNumber = await GenerateRandomProveAsync(keypair); + nextTermInput.RandomNumber = ByteString.CopyFrom(randomNumber); await newMinerStub.NextTerm.SendAsync(nextTermInput); termCount++; } diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs index 98b545ac51..bebe8cd7c9 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs @@ -44,6 +44,8 @@ await voter.Vote.SendAsync(new VoteMinerInput EndTimestamp = TimestampHelper.GetUtcNow().AddDays(100) }); + var randomHash = Hash.Empty.ToByteArray(); + byte[] randomNumber; foreach (var minerInRound in firstRound.RealTimeMinersInformation.Values.OrderBy(m => m.Order)) { var currentKeyPair = @@ -57,9 +59,9 @@ await voter.Vote.SendAsync(new VoteMinerInput var headerInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggers[minerInRound.Pubkey] .ToBytesValue())).ToConsensusHeaderInformation(); - + randomNumber = await GenerateRandomProveAsync(currentKeyPair); // Update consensus information. - var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey); + var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey, ByteString.CopyFrom(randomNumber)); await tester.UpdateValue.SendAsync(toUpdate); } @@ -74,25 +76,26 @@ await voter.Vote.SendAsync(new VoteMinerInput Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); var nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); - // TODO: Set random hash. - nextTermInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); + randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + nextTermInput.RandomNumber = ByteString.CopyFrom(randomNumber); await AEDPoSContractStub.NextTerm.SendAsync(nextTermInput); // First candidate cheat others with in value. var oneCandidate = GetAEDPoSContractStub(ValidationDataCenterKeyPairs[0]); var anotherCandidate = GetAEDPoSContractStub(ValidationDataCenterKeyPairs[1]); - var randomHash = HashHelper.ComputeFrom("hash5"); + var inValue = HashHelper.ComputeFrom("hash5"); var informationOfSecondRound = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( new AElfConsensusTriggerInformation { Behaviour = AElfConsensusBehaviour.UpdateValue, PreviousInValue = Hash.Empty, - InValue = randomHash, + InValue = inValue, Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); + randomNumber = await GenerateRandomProveAsync(ValidationDataCenterKeyPairs[0]); var updateResult = await oneCandidate.UpdateValue.SendAsync( informationOfSecondRound.Round.ExtractInformationToUpdateConsensus(ValidationDataCenterKeyPairs[0] - .PublicKey.ToHex())); + .PublicKey.ToHex(), ByteString.CopyFrom(randomNumber))); var thirdRoundStartTime = changeTermTime.AddMinutes(AEDPoSContractTestConstants.PeriodSeconds + 2); BlockTimeProvider.SetBlockTime(thirdRoundStartTime.ToTimestamp()); @@ -103,21 +106,22 @@ await voter.Vote.SendAsync(new VoteMinerInput Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation().Round; var nextRoundInput = NextRoundInput.Parser.ParseFrom(thirdRound.ToByteArray()); - // TODO: Set random hash. - nextRoundInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); + randomNumber = await GenerateRandomProveAsync(ValidationDataCenterKeyPairs[0]); + nextRoundInput.RandomNumber = ByteString.CopyFrom(randomNumber); await oneCandidate.NextRound.SendAsync(nextRoundInput); var cheatInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync( new AElfConsensusTriggerInformation { Behaviour = AElfConsensusBehaviour.UpdateValue, - PreviousInValue = HashHelper.ComputeFrom(randomHash), // Not same as before. + PreviousInValue = HashHelper.ComputeFrom(inValue), // Not same as before. InValue = HashHelper.ComputeFrom("InValue"), // Don't care this value in current test case. Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); + randomNumber = await GenerateRandomProveAsync(ValidationDataCenterKeyPairs[0]); await oneCandidate.UpdateValue.SendAsync( cheatInformation.Round.ExtractInformationToUpdateConsensus(ValidationDataCenterKeyPairs[0].PublicKey - .ToHex())); + .ToHex(), ByteString.CopyFrom(randomNumber))); } [Fact] @@ -136,8 +140,7 @@ public async Task Update_TinyBlockInformation_Test() RoundId = roundInfo.RoundId, ProducedBlocks = 4, ActualMiningTime = BlockTimeProvider.GetBlockTime(), - // TODO: Set random hash. - RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()) + RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(BootMinerKeyPair)) }; var transactionResult = await AEDPoSContractStub.UpdateTinyBlockInformation.SendAsync(input); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs index 83d405bc97..ff97e556ec 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Threading.Tasks; +using AElf.Cryptography; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -28,8 +29,8 @@ public async Task Query_RoundInformation_Test() }.ToBytesValue())).ToConsensusHeaderInformation(); var nextRoundInput = NextRoundInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); - // TODO: Set random hash. - nextRoundInput.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); + var randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + nextRoundInput.RandomNumber = ByteString.CopyFrom(randomNumber); var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs index 4fcff801d6..6f6acaf2bf 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round.cs @@ -86,8 +86,9 @@ public int TotalMilliseconds(int miningInterval = 0) /// will record this purpose to their FinalOrderOfNextRound field. /// /// + /// /// - public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) + public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey, ByteString randomNumber) { if (!RealTimeMinersInformation.ContainsKey(pubkey)) return null; @@ -119,8 +120,7 @@ public UpdateValueInput ExtractInformationToUpdateConsensus(string pubkey) EncryptedPieces = { minerInRound.EncryptedPieces }, DecryptedPieces = { decryptedPreviousInValues }, MinersPreviousInValues = { minersPreviousInValues }, - // TODO: Set random hash. - RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()) + RandomNumber = randomNumber }; } diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs index 9a7b3833e4..6965e4c874 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/Types/Round_Generation.cs @@ -9,7 +9,7 @@ namespace AElf.Contracts.Consensus.AEDPoS; internal partial class Round { - public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, + public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, ByteString randomNumber, out NextRoundInput nextRound) { nextRound = new NextRoundInput(); @@ -67,9 +67,7 @@ public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timest nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; else expectedExtraBlockProducer.IsExtraBlockProducer = true; - - // TODO: Set random hash. - nextRound.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); + nextRound.RandomNumber = randomNumber; return true; } diff --git a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestBase.cs b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestBase.cs index 60a5a0d350..b4f5419397 100644 --- a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestBase.cs +++ b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestBase.cs @@ -3,6 +3,7 @@ using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.Kernel; +using AElf.Kernel.Blockchain.Application; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; @@ -13,6 +14,9 @@ public partial class EconomicContractsTestBase : ContractTestBase Application.ServiceProvider.GetRequiredService(); + + protected IBlockchainService BlockchainService => + Application.ServiceProvider.GetRequiredService(); protected Timestamp StartTimestamp => TimestampHelper.GetUtcNow(); diff --git a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs index d9618cef7a..8ffb5334ce 100644 --- a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs +++ b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; +using AElf.Cryptography; using AElf.Cryptography.ECDSA; using AElf.Types; using Google.Protobuf; @@ -25,9 +26,10 @@ protected async Task NextTerm(ECKeyPair keyPair) victories.Value } }; + var randomNumber = await GenerateRandomProveAsync(keyPair); var firstRoundOfNextTerm = miners.GenerateFirstRoundOfNewTerm(EconomicContractsTestConstants.MiningInterval, - BlockTimeProvider.GetBlockTime(), round.RoundNumber, round.TermNumber); + randomNumber, BlockTimeProvider.GetBlockTime(), round.RoundNumber, round.TermNumber); var executionResult = (await miner.NextTerm.SendAsync(firstRoundOfNextTerm)).TransactionResult; executionResult.Error.ShouldBeNullOrEmpty(); executionResult.Status.ShouldBe(TransactionResultStatus.Mined); @@ -37,9 +39,10 @@ protected async Task NextRound(ECKeyPair keyPair) { var miner = GetConsensusContractTester(keyPair); var round = await miner.GetCurrentRoundInformation.CallAsync(new Empty()); + var randomNumber = await GenerateRandomProveAsync(keyPair); round.GenerateNextRoundInformation( StartTimestamp.ToDateTime().AddMilliseconds(round.TotalMilliseconds()).ToTimestamp(), StartTimestamp, - out var nextRound); + ByteString.CopyFrom(randomNumber), out var nextRound); await miner.NextRound.SendAsync(nextRound); } @@ -58,8 +61,7 @@ await miner.UpdateValue.SendAsync(new UpdateValueInput ProducedBlocks = minerInRound.ProducedBlocks + 1, ActualMiningTime = minerInRound.ExpectedMiningTime, SupposedOrderOfNextRound = 1, - // TODO: Set random hash. - RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()) + RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(keyPair)) }); } @@ -97,6 +99,16 @@ protected async Task GetVoteTokenBalance(byte[] publicKey) return balance; } + + protected async Task GenerateRandomProveAsync(ECKeyPair keyPair) + { + var consensusContractStub = GetConsensusContractTester(keyPair); + var blockHeight = (await BlockchainService.GetChainAsync()).BestChainHeight; + var previousRandomHash = + await consensusContractStub.GetRandomHash.CallAsync(new Int64Value + { Value = blockHeight == 0 ? 1 : blockHeight }); + return CryptoHelper.ECVrfProve(keyPair, previousRandomHash.ToByteArray()); + } #endregion } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs b/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs index 087d283ce8..800ef0cb5a 100644 --- a/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs +++ b/test/AElf.Contracts.Economic.TestBase/Types/MinerList.cs @@ -42,8 +42,8 @@ orderby obj.Value descending return round; } - public NextTermInput GenerateFirstRoundOfNewTerm(int miningInterval, - Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0, byte[] randomNumber= null) + public NextTermInput GenerateFirstRoundOfNewTerm(int miningInterval, byte[] randomNumber, + Timestamp currentBlockTime, long currentRoundNumber = 0, long currentTermNumber = 0) { var sortedMiners = (from obj in Pubkeys @@ -72,7 +72,6 @@ orderby obj.Value descending input.RoundNumber = currentRoundNumber + 1; input.TermNumber = currentTermNumber + 1; input.IsMinerListJustChanged = true; - // TODO: Set random hash. input.RandomNumber = ByteString.CopyFrom(randomNumber); return input; diff --git a/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs b/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs index c57db52769..f195933fff 100644 --- a/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs +++ b/test/AElf.Contracts.Economic.TestBase/Types/Round_Generation.cs @@ -9,7 +9,7 @@ namespace AElf.Contracts.Consensus.AEDPoS; internal partial class Round { - public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, + public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, ByteString randomNumber, out NextRoundInput nextRound) { nextRound = new NextRoundInput(); @@ -64,9 +64,7 @@ public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timest nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; else expectedExtraBlockProducer.IsExtraBlockProducer = true; - - // TODO: Set random hash. - nextRound.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); + nextRound.RandomNumber = randomNumber; return true; } diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs index ca4e882201..79c3300b82 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs @@ -8,9 +8,12 @@ using AElf.Contracts.Referendum; using AElf.ContractTestBase.ContractTestKit; using AElf.CrossChain; +using AElf.Cryptography; +using AElf.Cryptography.ECDSA; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; using AElf.Kernel; +using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract; @@ -61,6 +64,8 @@ public class MultiTokenContractCrossChainTestBase : ContractTestBase SideChainTestKit; internal TokenContractImplContainer.TokenContractImplStub SideChainTokenContractStub; + protected readonly IBlockchainService BlockchainService; + protected Address SideConsensusAddress; @@ -103,6 +108,8 @@ public MultiTokenContractCrossChainTestBase() ResourceTokenSymbolList = Application.ServiceProvider .GetRequiredService>() .Value.ContextVariables["SymbolListToPayRental"].Split(",").ToList(); + + BlockchainService = Application.ServiceProvider.GetRequiredService(); } protected Timestamp BlockchainStartTimestamp => TimestampHelper.GetUtcNow(); @@ -318,10 +325,11 @@ internal async Task BootMinerChangeRoundAsync(AEDPoSContractContainer.AEDPoSCont { if (isMainChain) { + var randomNumber = await GenerateRandomProveAsync(aedPoSContractStub, DefaultAccount.KeyPair); var currentRound = await aedPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); var expectedStartTime = TimestampHelper.GetUtcNow(); currentRound.GenerateNextRoundInformation(expectedStartTime, BlockchainStartTimestamp, - out var nextRound); + ByteString.CopyFrom(randomNumber), out var nextRound); nextRound.RealTimeMinersInformation[DefaultAccount.KeyPair.PublicKey.ToHex()] .ExpectedMiningTime = expectedStartTime; await aedPoSContractStub.NextRound.SendAsync(nextRound); @@ -329,13 +337,14 @@ internal async Task BootMinerChangeRoundAsync(AEDPoSContractContainer.AEDPoSCont if (!isMainChain) { + var randomNumber = CryptoHelper.ECVrfProve(DefaultAccount.KeyPair, Hash.Empty.ToByteArray()); var currentRound = await aedPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); var expectedStartTime = BlockchainStartTimestamp.ToDateTime() .AddMilliseconds( ((long)currentRound.TotalMilliseconds(4000)).Mul( nextRoundNumber.Sub(1))); currentRound.GenerateNextRoundInformation(expectedStartTime.ToTimestamp(), BlockchainStartTimestamp, - out var nextRound); + ByteString.CopyFrom(randomNumber), out var nextRound); if (currentRound.RoundNumber >= 3) { @@ -353,6 +362,16 @@ internal async Task BootMinerChangeRoundAsync(AEDPoSContractContainer.AEDPoSCont } } + private async Task GenerateRandomProveAsync(AEDPoSContractContainer.AEDPoSContractStub aedPoSContractStub, + ECKeyPair keyPair) + { + var blockHeight = (await BlockchainService.GetChainAsync()).BestChainHeight; + var previousRandomHash = + await aedPoSContractStub.GetRandomHash.CallAsync(new Int64Value + { Value = blockHeight == 0 ? 1 : blockHeight }); + return CryptoHelper.ECVrfProve(keyPair, previousRandomHash.ToByteArray()); + } + private async Task ApproveBalanceAsync(long amount) { await TokenContractStub.Approve.SendAsync(new ApproveInput diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs index 9a7b3833e4..63ca824cd6 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/Types/Round_Generation.cs @@ -10,7 +10,7 @@ namespace AElf.Contracts.Consensus.AEDPoS; internal partial class Round { public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timestamp blockchainStartTimestamp, - out NextRoundInput nextRound) + ByteString randomNumber, out NextRoundInput nextRound) { nextRound = new NextRoundInput(); @@ -67,9 +67,7 @@ public bool GenerateNextRoundInformation(Timestamp currentBlockTimestamp, Timest nextRound.RealTimeMinersInformation.Values.First().IsExtraBlockProducer = true; else expectedExtraBlockProducer.IsExtraBlockProducer = true; - - // TODO: Set random hash. - nextRound.RandomNumber = ByteString.CopyFrom(Hash.Empty.ToByteArray()); + nextRound.RandomNumber = randomNumber; return true; } From 036f5d0913e3284621b2d9b6c2f6412d25c4bbde Mon Sep 17 00:00:00 2001 From: zhxymh Date: Mon, 19 Jun 2023 11:01:46 +0800 Subject: [PATCH 059/139] feat: remove random hash from first round --- contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs index 8249961a4a..c4043e3d49 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs @@ -80,7 +80,6 @@ public override Empty FirstRound(Round input) State.CurrentTermNumber.Value = 1; State.CurrentRoundNumber.Value = 1; State.FirstRoundNumberOfEachTerm[1] = 1; - State.RandomHashes[Context.CurrentHeight] = Context.PreviousBlockHash; State.MiningInterval.Value = input.GetMiningInterval(); SetMinerList(input.GetMinerList(), 1); From f391715faafb499d0956ce40489e7eed421f0e74 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Mon, 19 Jun 2023 11:17:08 +0800 Subject: [PATCH 060/139] feat: upgrade Secp256k1.Net 1.2.0 --- src/AElf.Cryptography/AElf.Cryptography.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AElf.Cryptography/AElf.Cryptography.csproj b/src/AElf.Cryptography/AElf.Cryptography.csproj index 22d264f402..65f0ded71e 100644 --- a/src/AElf.Cryptography/AElf.Cryptography.csproj +++ b/src/AElf.Cryptography/AElf.Cryptography.csproj @@ -7,7 +7,7 @@ Cryptographic primitives used in AElf. - + From 9d266b8b39ba6fa24c7fa4bb9b660bffb5000e92 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 19 Jun 2023 14:29:27 +0800 Subject: [PATCH 061/139] feat: add ut for vote and withdraw --- AElf.All.sln | 7 ++ .../ElectionContract_Elector.cs | 1 - protobuf/test_election_vote_contract.proto | 25 ++++++ .../AElf.Contracts.Economic.TestBase.csproj | 34 +++++--- .../Contracts.cs | 3 +- .../ContractsPreparation.cs | 15 +++- .../AElf.Contracts.Election.Tests.csproj | 12 +++ .../BVT/ElectionTests.cs | 85 +++++++++++++++++++ .../ElectionContractTestBase.cs | 17 ++++ ...Elf.Contracts.TestContract.TestVote.csproj | 41 +++++++++ .../Action.cs | 29 +++++++ .../ReferenceState.cs | 8 ++ .../State.cs | 8 ++ 13 files changed, 269 insertions(+), 16 deletions(-) create mode 100644 protobuf/test_election_vote_contract.proto create mode 100644 test/AElf.Contracts.TestContract.TestVote/AElf.Contracts.TestContract.TestVote.csproj create mode 100644 test/AElf.Contracts.TestContract.TestVote/Action.cs create mode 100644 test/AElf.Contracts.TestContract.TestVote/ReferenceState.cs create mode 100644 test/AElf.Contracts.TestContract.TestVote/State.cs diff --git a/AElf.All.sln b/AElf.All.sln index 7554592ce4..d1cda27137 100644 --- a/AElf.All.sln +++ b/AElf.All.sln @@ -369,6 +369,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps.UnitTes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract.csproj", "{AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.TestVote", "test\AElf.Contracts.TestContract.TestVote\AElf.Contracts.TestContract.TestVote.csproj", "{64498F8C-B827-4E1C-B5FB-4B9188C839A8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1059,6 +1061,10 @@ Global {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}.Debug|Any CPU.Build.0 = Debug|Any CPU {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}.Release|Any CPU.ActiveCfg = Release|Any CPU {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}.Release|Any CPU.Build.0 = Release|Any CPU + {64498F8C-B827-4E1C-B5FB-4B9188C839A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {64498F8C-B827-4E1C-B5FB-4B9188C839A8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {64498F8C-B827-4E1C-B5FB-4B9188C839A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {64498F8C-B827-4E1C-B5FB-4B9188C839A8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1245,5 +1251,6 @@ Global {1B44277E-74EB-49B2-B8FD-05C29EE51985} = {4E54480A-D155-43ED-9736-1A5BE7957211} {D1A00CD6-958E-4E9F-8325-354309E3029E} = {4E54480A-D155-43ED-9736-1A5BE7957211} {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {64498F8C-B827-4E1C-B5FB-4B9188C839A8} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} EndGlobalSection EndGlobal diff --git a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs index 233cacaa80..28d38baa2d 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs @@ -506,7 +506,6 @@ private void UpdateElectorInformation(byte[] recoveredPublicKey, long amount, Ha voterVotes = new ElectorVote { Address = Context.Sender, - Pubkey = recoveredPublicKey != null ? ByteString.CopyFrom(recoveredPublicKey) : null, ActiveVotingRecordIds = { voteId }, ActiveVotedVotesAmount = amount, AllVotedVotesAmount = amount diff --git a/protobuf/test_election_vote_contract.proto b/protobuf/test_election_vote_contract.proto new file mode 100644 index 0000000000..41305215c6 --- /dev/null +++ b/protobuf/test_election_vote_contract.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; + +import "aelf/options.proto"; +import "aelf/core.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/wrappers.proto"; +import "acs1.proto"; + +option csharp_namespace = "AElf.Contracts.TestContract.TestVote"; + +service TestVoteContract { + option (aelf.csharp_state) = "AElf.Contracts.TestContract.TestVote.State"; + option (aelf.base) = "acs1.proto"; + + rpc VirtualAddressVote(VirtualAddressVoteInput) returns (google.protobuf.Empty); +} + +message VirtualAddressVoteInput { + string pub_key = 1; + int64 amount = 2; + google.protobuf.Timestamp end_timestamp = 3; + // Used to generate vote id. + aelf.Hash token = 4; +} \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj b/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj index 95287fb207..3b5bc18baa 100644 --- a/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj +++ b/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj @@ -13,16 +13,16 @@ runtime; build; native; contentfiles; analyzers - + - all - runtime; build; native; contentfiles; analyzers - + all + runtime; build; native; contentfiles; analyzers + - all - runtime; build; native; contentfiles; analyzers - + all + runtime; build; native; contentfiles; analyzers + @@ -71,9 +71,9 @@ Contract PreserveNewest - - - + + + false Contract @@ -99,8 +99,13 @@ Contract PreserveNewest - - + + false + Contract + PreserveNewest + + + @@ -179,8 +184,11 @@ Protobuf\Proto\parliament_contract_impl.proto + + Protobuf\Proto\test_election_vote_contract.proto + - + diff --git a/test/AElf.Contracts.Economic.TestBase/Contracts.cs b/test/AElf.Contracts.Economic.TestBase/Contracts.cs index 3e32bdd1cd..c1e9b344ac 100644 --- a/test/AElf.Contracts.Economic.TestBase/Contracts.cs +++ b/test/AElf.Contracts.Economic.TestBase/Contracts.cs @@ -26,7 +26,8 @@ public enum TestContracts BasicSecurity, BasicUpdate, MethodCallThreshold, - ResourceSpender + ResourceSpender, + TestVote } public enum ProfitType diff --git a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs index 04437a46a8..7d25a2d7a9 100644 --- a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs +++ b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs @@ -10,6 +10,7 @@ using AElf.Contracts.Parliament; using AElf.Contracts.Profit; using AElf.Contracts.TestContract.MethodCallThreshold; +using AElf.Contracts.TestContract.TestVote; using AElf.Contracts.TestContract.TransactionFeeCharging; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; @@ -102,6 +103,9 @@ public partial class EconomicContractsTestBase protected Address ConfigurationAddress => GetOrDeployContract(Contracts.Configuration, ref _configurationAddress); + + private Address _testVoteContractAddress; + protected Address TestVoteContractAddress => GetOrDeployContract(TestContracts.TestVote, ref _testVoteContractAddress); #endregion @@ -144,6 +148,9 @@ internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractS internal ConfigurationContainer.ConfigurationStub ConfigurationStub => GetConfigurationContractTester(BootMinerKeyPair); + + internal TestVoteContractContainer.TestVoteContractStub TestVoteContractStub => + GetTestVoteContractTester(BootMinerKeyPair); #endregion @@ -223,6 +230,11 @@ internal ConfigurationContainer.ConfigurationStub GetConfigurationContractTester { return GetTester(ConfigurationAddress, keyPair); } + + internal TestVoteContractContainer.TestVoteContractStub GetTestVoteContractTester(ECKeyPair keyPair) + { + return GetTester(TestVoteContractAddress, keyPair); + } #endregion @@ -257,7 +269,7 @@ private Address GetOrDeployContract(TestContracts contract, ref Address address) private async Task
DeployContract(Contracts contract) { - var code = Codes.Single(kv => kv.Key.Contains(contract.ToString())).Value; + var code = Codes.FirstOrDefault(kv => kv.Key.Contains(contract.ToString())).Value; Hash hash; switch (contract) { @@ -308,6 +320,7 @@ protected void DeployAllContracts() _ = TokenContractAddress; _ = TokenHolderContractAddress; _ = AssociationContractAddress; + _ = TestVoteContractAddress; } #endregion diff --git a/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj b/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj index 4f04ca5c83..4aaa89f9ca 100644 --- a/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj +++ b/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj @@ -40,6 +40,11 @@ Contract PreserveNewest + + false + Contract + PreserveNewest + @@ -52,6 +57,13 @@ Protobuf\Proto\transaction_fee.proto + + + + Protobuf\Proto\test_election_vote_contract.proto + + + diff --git a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs index ce2fac0ff9..24b8b69860 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs @@ -6,6 +6,7 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Contracts.Profit; +using AElf.Contracts.TestContract.TestVote; using AElf.Contracts.Vote; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core; @@ -1900,4 +1901,88 @@ private async Task ResetMinerCount(int count) } #endregion + + // [Fact] + // public async Task VirtualAddress_Vote_Test() + // { + // var amount = 100; + // const int lockTime = 100 * 60 * 60 * 24; + // var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); + // var candidateKeyPair = candidatesKeyPairs[0]; + // await TestVoteContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput + // { + // PubKey = candidateKeyPair.PublicKey.ToHex(), + // Amount = amount, + // EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(lockTime), + // Token = HashHelper.ComputeFrom("token A") + // }); + // } + + [Fact] + public async Task Vote_Test() + { + var amount = 100; + const int lockTime = 100 * 60 * 60 * 24; + var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); + var candidateKeyPair = candidatesKeyPairs[0]; + + var voteRet = await ElectionContractStub.Vote.SendAsync(new VoteMinerInput + { + CandidatePubkey = candidateKeyPair.PublicKey.ToHex(), + Amount = amount, + EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(lockTime), + Token = HashHelper.ComputeFrom("token A") + }); + voteRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var result = await ElectionContractStub.GetElectorVote.CallAsync(new StringValue + { + Value = BootMinerKeyPair.PublicKey.ToHex() + }); + result.ActiveVotedVotesAmount.ShouldBe(amount); + result = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue + { + Value = BootMinerKeyPair.PublicKey.ToHex() + }); + result.ActiveVotedVotesAmount.ShouldBe(amount); + result = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync(new StringValue + { + Value = BootMinerKeyPair.PublicKey.ToHex() + }); + result.AllVotedVotesAmount.ShouldBe(amount); + + return result.ActiveVotingRecords.First().VoteId; + } + + [Fact] + public async Task Withdraw_Test() + { + var voteId = await Vote_Test(); + + BlockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddDays(101)); + + await ElectionContractStub.Withdraw.SendAsync(new Hash + { + Value = voteId.Value + }); + + var result = await ElectionContractStub.GetElectorVote.CallAsync(new StringValue + { + Value = BootMinerKeyPair.PublicKey.ToHex() + }); + result.ActiveVotedVotesAmount.ShouldBe(0); + result = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue + { + Value = BootMinerKeyPair.PublicKey.ToHex() + }); + result.ActiveVotedVotesAmount.ShouldBe(0); + result = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync(new StringValue + { + Value = BootMinerKeyPair.PublicKey.ToHex() + }); + + result.ActiveVotedVotesAmount.ShouldBe(0); + result.WithdrawnVotesRecords.Count().ShouldBe(1); + result.AllVotedVotesAmount.ShouldBe(100); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs b/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs index 4375a2c352..74d0a5ff2f 100644 --- a/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs +++ b/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs @@ -5,9 +5,11 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Contracts.Profit; +using AElf.Contracts.TestContract.TestVote; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; using AElf.Contracts.Vote; +using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.Types; using Google.Protobuf.WellKnownTypes; @@ -17,6 +19,13 @@ namespace AElf.Contracts.Election; public class ElectionContractTestBase : EconomicContractsTestBase { + protected readonly IBlockTimeProvider BlockTimeProvider; + + protected ElectionContractTestBase() + { + BlockTimeProvider = GetRequiredService(); + } + protected Hash MinerElectionVotingItemId; internal BasicContractZeroImplContainer.BasicContractZeroImplStub BasicContractZeroStub => @@ -48,6 +57,9 @@ public class ElectionContractTestBase : EconomicContractsTestBase internal EconomicContractImplContainer.EconomicContractImplStub EconomicContractStub => GetEconomicContractTester(BootMinerKeyPair); + internal TestVoteContractContainer.TestVoteContractStub TestVoteContractStub => + GetTestVoteContractTester(BootMinerKeyPair); + private new void DeployAllContracts() { _ = TokenContractAddress; @@ -135,4 +147,9 @@ internal EconomicContractImplContainer.EconomicContractImplStub GetEconomicContr { return GetTester(EconomicContractAddress, keyPair); } + + internal TestVoteContractContainer.TestVoteContractStub GetTestVoteContractTester(ECKeyPair keyPair) + { + return GetTester(TestVoteContractAddress, keyPair); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TestVote/AElf.Contracts.TestContract.TestVote.csproj b/test/AElf.Contracts.TestContract.TestVote/AElf.Contracts.TestContract.TestVote.csproj new file mode 100644 index 0000000000..b6b5047064 --- /dev/null +++ b/test/AElf.Contracts.TestContract.TestVote/AElf.Contracts.TestContract.TestVote.csproj @@ -0,0 +1,41 @@ + + + + net6.0 + AElf.Contracts.TestContract.TestVote + AElf.Contracts.TestContract.TestVote + false + + + + + + + + + Protobuf\Proto\authority_info.proto + + + + + + Protobuf\Proto\reference\election_contract.proto + + + Protobuf\Proto\reference\election_contract_impl.proto + + + + + + Protobuf\Proto\acs1.proto + + + + + + Protobuf\Proto\test_election_vote_contract.proto + + + + diff --git a/test/AElf.Contracts.TestContract.TestVote/Action.cs b/test/AElf.Contracts.TestContract.TestVote/Action.cs new file mode 100644 index 0000000000..7a3355856e --- /dev/null +++ b/test/AElf.Contracts.TestContract.TestVote/Action.cs @@ -0,0 +1,29 @@ +using AElf.Contracts.Election; +using AElf.Sdk.CSharp; +using Google.Protobuf.WellKnownTypes; + +namespace AElf.Contracts.TestContract.TestVote; + +public class Action : TestVoteContractContainer.TestVoteContractBase +{ + public override Empty VirtualAddressVote(VirtualAddressVoteInput input) + { + Initialize(); + + Context.SendVirtualInline(HashHelper.ComputeFrom("test"), State.ElectionContract.Value, "Vote", new VoteMinerInput + { + CandidatePubkey = input.PubKey, + Amount = input.Amount, + EndTimestamp = input.EndTimestamp, + Token = input.Token + }); + + return new Empty(); + } + + private void Initialize() + { + State.ElectionContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + } +} \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TestVote/ReferenceState.cs b/test/AElf.Contracts.TestContract.TestVote/ReferenceState.cs new file mode 100644 index 0000000000..f69a59fc48 --- /dev/null +++ b/test/AElf.Contracts.TestContract.TestVote/ReferenceState.cs @@ -0,0 +1,8 @@ +using AElf.Contracts.Election; + +namespace AElf.Contracts.TestContract.TestVote; + +public partial class State +{ + internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } +} \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TestVote/State.cs b/test/AElf.Contracts.TestContract.TestVote/State.cs new file mode 100644 index 0000000000..38d131befb --- /dev/null +++ b/test/AElf.Contracts.TestContract.TestVote/State.cs @@ -0,0 +1,8 @@ +using AElf.Sdk.CSharp.State; + +namespace AElf.Contracts.TestContract.TestVote; + +public partial class State : ContractState +{ + +} \ No newline at end of file From 64d746dff31542acaa98a1e34f192d7e4621e8de Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Mon, 19 Jun 2023 18:27:59 +0800 Subject: [PATCH 062/139] feat: mutiToken method fee set 0 --- .../TokenContract_ACS1_MethodFeeProvider.cs | 14 ----------- .../TokenContract_Actions.cs | 1 - .../TokenContract_NFT_Actions.cs | 25 ++----------------- 3 files changed, 2 insertions(+), 38 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs index ff15f9a9c6..a20737c76d 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS1_MethodFeeProvider.cs @@ -47,20 +47,6 @@ public override MethodFees GetMethodFee(StringValue input) IsSizeFeeFree = true }; var fees = State.TransactionFees[input.Value]; - if (input.Value == nameof(Create) && fees == null) - return new MethodFees - { - MethodName = input.Value, - Fees = - { - new MethodFee - { - Symbol = Context.Variables.NativeSymbol, - BasicFee = 10000_00000000 - } - } - }; - return fees; } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index f627b867a7..c8fabd2d18 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -35,7 +35,6 @@ public override Empty Create(CreateInput input) // can not call create on side chain Assert(State.SideChainCreator.Value == null, "Failed to create token if side chain creator already set."); var inputSymbolType = GetCreateInputSymbolType(input.Symbol); - ChargeCreateFees(); return inputSymbolType switch { SymbolType.NftCollection => CreateNFTCollection(input), diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 8d52fba4bd..de155b6de0 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -25,23 +25,7 @@ private Empty CreateNFTInfo(CreateInput input) return CreateToken(input, SymbolType.Nft); } - private void ChargeCreateFees() - { - if (Context.Sender == Context.Origin) return; - if (IsAddressInCreateWhiteList(Context.Sender)) return; - - var fee = GetCreateMethodFee(); - Assert(fee != null, "not enough balance for create"); - DoTransferFrom(Context.Sender, Context.Self, Context.Self, fee.Symbol, fee.BasicFee, ""); - - ModifyBalance(Context.Self, fee.Symbol, -fee.BasicFee); - Context.Fire(new TransactionFeeCharged() - { - Symbol = fee.Symbol, - Amount = fee.BasicFee, - ChargingAddress = Context.Self - }); - } + private void DoTransferFrom(Address from, Address to, Address spender, string symbol, long amount, string memo) { @@ -66,12 +50,7 @@ private void DoTransferFrom(Address from, Address to, Address spender, string sy State.Allowances[from][spender][symbol] = allowance.Sub(amount); } - private MethodFee GetCreateMethodFee() - { - var fee = State.TransactionFees[nameof(Create)]; - if (fee == null || fee.Fees.Count <= 0) return new MethodFee { Symbol = Context.Variables.NativeSymbol, BasicFee = 10000_00000000 }; - return fee.Fees.FirstOrDefault(f => GetBalance(Context.Sender, f.Symbol) >= f.BasicFee); - } + private string GetNftCollectionSymbol(string inputSymbol) { From 75f13a5d97d518a1ee34bd8c4e4bf5cf869070ef Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 19 Jun 2023 18:36:32 +0800 Subject: [PATCH 063/139] fix: cr --- .../TokenContract_ACS2_StatePathsProvider.cs | 31 ++++++-- .../TokenContract_Fees.cs | 73 ++++++++++--------- .../TokenContract_Helper.cs | 4 +- .../AElf.Contracts.Profit/ProfitContract.cs | 10 --- .../ProfitContractState.cs | 2 - protobuf/profit_contract.proto | 4 - 6 files changed, 65 insertions(+), 59 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index bd194a5ddf..1dda625f98 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -21,19 +21,20 @@ public override ResourceInfo GetResourceInfo(Transaction txn) WritePaths = { GetPath(nameof(TokenContractState.Balances), txn.From.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowances), txn.From.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesLastRefreshTimes), txn.From.ToString(), args.Symbol) + GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol) }, ReadPaths = { GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)), - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesSymbolList)) + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesSymbolList)), + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesConfigMap)) } }; AddPathForTransactionFee(resourceInfo, txn.From.ToString()); AddPathForDelegatees(resourceInfo, txn.From, args.Symbol); + AddPathForTransactionFeeFreeAllowance(resourceInfo, txn.From); + return resourceInfo; } @@ -48,19 +49,20 @@ public override ResourceInfo GetResourceInfo(Transaction txn) args.Symbol), GetPath(nameof(TokenContractState.Balances), args.From.ToString(), args.Symbol), GetPath(nameof(TokenContractState.Balances), args.To.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.LockWhiteLists), args.Symbol, txn.From.ToString()), - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowances), txn.From.ToString(), args.Symbol), - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesLastRefreshTimes), txn.From.ToString(), args.Symbol) + GetPath(nameof(TokenContractState.LockWhiteLists), args.Symbol, txn.From.ToString()) }, ReadPaths = { GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)), - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesSymbolList)) + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesSymbolList)), + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesConfigMap)) } }; AddPathForTransactionFee(resourceInfo, txn.From.ToString()); AddPathForDelegatees(resourceInfo, txn.From, args.Symbol); + AddPathForTransactionFeeFreeAllowance(resourceInfo, txn.From); + return resourceInfo; } @@ -113,4 +115,17 @@ private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from, strin } } } + + private void AddPathForTransactionFeeFreeAllowance(ResourceInfo resourceInfo, Address from) + { + var symbols = State.TransactionFeeFreeAllowancesSymbolList.Value?.Symbols; + if (symbols != null) + { + foreach (var symbol in symbols) + { + resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowances), from.ToBase58(), symbol)); + resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesLastRefreshTimes), from.ToBase58(), symbol)); + } + } + } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 89eaff04a5..e1b91132ee 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -166,7 +166,8 @@ private bool ChargeFromDelegations(ChargeTransactionFeesInput input, ref Address // Try to charge delegatees // Get delegatee list according to the delegator var delegationInfo = - State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][input.MethodName]?.Delegatees ?? + State.TransactionFeeDelegateInfoMap[delegatorAddress][input.ContractAddress][input.MethodName] + ?.Delegatees ?? State.TransactionFeeDelegateesMap[delegatorAddress]?.Delegatees; if (delegationInfo == null) @@ -219,7 +220,7 @@ private void ModifyDelegation(TransactionFeeBill bill, TransactionFreeFeeAllowan foreach (var (symbol, amount) in allowanceBill.FreeFeeAllowancesMap) { if (amount <= 0) continue; - var delegateInfo = + var delegateInfo = State.TransactionFeeDelegateInfoMap[delegatorAddress][contractAddress][methodName] ?? State.TransactionFeeDelegateesMap[delegatorAddress]; delegateInfo.Delegatees[delegateeAddress.ToBase58()].Delegations[symbol] = @@ -298,7 +299,8 @@ private void SetOrRefreshTransactionFeeFreeAllowances(Address address) foreach (var symbol in config.Symbols) { - if (State.Balances[address][symbol] < State.TransactionFeeFreeAllowancesConfigMap[symbol].Threshold) continue; + if (State.Balances[address][symbol] < + State.TransactionFeeFreeAllowancesConfigMap[symbol].Threshold) continue; var lastRefreshTime = State.TransactionFeeFreeAllowancesLastRefreshTimes[address][symbol]; if (lastRefreshTime != null && State.TransactionFeeFreeAllowancesConfigMap[symbol].RefreshSeconds > @@ -325,12 +327,14 @@ private Dictionary GetUserContractFeeDictionary(UserContractMethod } private bool ChargeBaseFee(Dictionary methodFeeMap, Address fromAddress, ref TransactionFeeBill bill, - TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, ref TransactionFreeFeeAllowanceBill allowanceBill, + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, + ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { // Fail to charge if (!ChargeFirstSufficientToken(methodFeeMap, fromAddress, out var symbolToChargeBaseFee, - out var amountToChargeBaseFee, out var existingBalance, out var existingAllowance, transactionFeeFreeAllowancesMap, + out var amountToChargeBaseFee, out var existingBalance, out var existingAllowance, + transactionFeeFreeAllowancesMap, delegations)) { Context.LogDebug(() => "Failed to charge first sufficient token."); @@ -360,7 +364,8 @@ private bool ChargeBaseFee(Dictionary methodFeeMap, Address fromAd } private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress, ref TransactionFeeBill bill, - TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, ref TransactionFreeFeeAllowanceBill allowanceBill, + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, + ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { //If delegation != null,from address->delegateeAddress @@ -434,28 +439,23 @@ private void GetAvailableBalance(string symbolToPayTxFee, Address fromAddress, T ? GetBalance(fromAddress, symbolToPayTxFee).Sub(amountChargedForBaseFee) : GetBalance(fromAddress, symbolToPayTxFee); availableAllowance = symbolChargedForBaseFee == symbolToPayTxFee - ? GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbolToPayTxFee).Sub(amountChargedForBaseAllowance) + ? GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbolToPayTxFee) + .Sub(amountChargedForBaseAllowance) : GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbolToPayTxFee); } private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List allSymbolToTxFee, Address fromAddress, long txSizeFeeAmount, TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, - string symbolChargedForBaseFee, long amountChargedForBaseFee, long amountChargedForBaseAllowance, - TransactionFeeDelegations delegations = null) + string symbolChargedForBaseFee, long amountChargedForBaseFee, long amountChargedForBaseAllowance, TransactionFeeDelegations delegations = null) { SymbolToPayTxSizeFee availableSymbol = null; SymbolToPayTxSizeFee availableSymbolWithAnything = null; - SymbolToPayTxSizeFee availableSymbolWithBalancePlusAllowanceEnoughToPayTxFee = null; + SymbolToPayTxSizeFee availableSymbolWithEnoughBalancePlusAllowance = null; SymbolToPayTxSizeFee availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; // get 1st Allowance > size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) { - var allowance = GetAllowanceCalculatedBaseOnPrimaryToken(symbolToPlayTxSizeFee, - transactionFeeFreeAllowancesMap, symbolChargedForBaseFee, amountChargedForBaseAllowance); - var balancePlusAllowance = GetBalancePlusAllowanceCalculatedBaseOnPrimaryToken(fromAddress, - symbolToPlayTxSizeFee, symbolChargedForBaseFee, amountChargedForBaseFee, - transactionFeeFreeAllowancesMap, amountChargedForBaseAllowance); if (delegations != null) { var delegationEnough = IsDelegationEnoughBaseOnPrimaryToken(symbolToPlayTxSizeFee, @@ -463,7 +463,13 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List= txSizeFeeAmount) { availableSymbol = symbolToPlayTxSizeFee; @@ -476,14 +482,14 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List symbolToAmountM return chargeResult; } - chargeResult = TryToChargeUserBaseFee(symbolToAmountMap, fromAddress, transactionFeeFreeAllowancesMap, out amount, + chargeResult = TryToChargeUserBaseFee(symbolToAmountMap, fromAddress, transactionFeeFreeAllowancesMap, + out amount, out symbol, out existingBalance, out existingAllowance); - + if (symbol != null) { existingBalance = GetBalance(fromAddress, symbol); @@ -717,12 +724,13 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM } private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, Address fromAddress, - TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, out long amount, out string symbolOfValidBalance, + TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, out long amount, + out string symbolOfValidBalance, out long existingBalance, out long existingAllowance) { symbolOfValidBalance = null; string symbolWithAnything = null; - string symbolWithBalancePlusAllowanceEnoughToPayTxFee = null; + string symbolWithEnoughBalancePlusAllowance = null; string symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; amount = 0; @@ -747,13 +755,13 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, symbolWithAnything ??= symbol; if (existingBalance.Add(existingAllowance) < amount) continue; - symbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbol; + symbolWithEnoughBalancePlusAllowance ??= symbol; if (existingAllowance <= 0) continue; symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbol; } - if (symbolWithBalancePlusAllowanceEnoughToPayTxFee == null) + if (symbolWithEnoughBalancePlusAllowance == null) { symbolOfValidBalance = symbolWithAnything; @@ -761,7 +769,7 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, } symbolOfValidBalance = symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? - symbolWithBalancePlusAllowanceEnoughToPayTxFee; + symbolWithEnoughBalancePlusAllowance; return true; } @@ -785,7 +793,8 @@ private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountM existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); // is unlimited delegate is true || is unlimited delegate is false and delegation is enough if (delegations.IsUnlimitedDelegate || (!delegations.IsUnlimitedDelegate && - delegations.Delegations.ContainsKey(symbol) && delegations.Delegations[symbol] >= amount)) + delegations.Delegations.ContainsKey(symbol) && + delegations.Delegations[symbol] >= amount)) { //If allowance is enough,return true if (existingAllowance >= amount) @@ -1163,7 +1172,8 @@ public override Empty ConfigTransactionFeeFreeAllowances(ConfigTransactionFeeFre { ValidateToken(allowances.Symbol); Assert( - allowances.TransactionFeeFreeAllowances?.Value != null && allowances.TransactionFeeFreeAllowances.Value.Count > 0, + allowances.TransactionFeeFreeAllowances?.Value != null && + allowances.TransactionFeeFreeAllowances.Value.Count > 0, "Invalid input allowances"); Assert(allowances.Threshold >= 0, "Invalid input threshold"); Assert(allowances.RefreshSeconds >= 0, "Invalid input refresh seconds"); @@ -1258,12 +1268,9 @@ private TransactionFeeFreeAllowancesMap CalculateTransactionFeeFreeAllowances(Ad if (freeAllowances == null) { - if (balance >= State.TransactionFeeFreeAllowancesConfigMap[symbol].Threshold) - { - transactionFeeFreeAllowancesMap.Map.Add(symbol, - State.TransactionFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone()); - continue; - } + transactionFeeFreeAllowancesMap.Map.Add(symbol, + State.TransactionFeeFreeAllowancesConfigMap[symbol].FreeAllowances.Clone()); + continue; } if (lastRefreshTime == null) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 22d50a496c..47b6af9f84 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -135,13 +135,13 @@ private long GetBalance(Address address, string symbol) private long GetFreeFeeAllowanceAmount(TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, string symbol) { var allowance = 0L; - var map = transactionFeeFreeAllowancesMap?.Map; + var map = transactionFeeFreeAllowancesMap.Map; if (map == null) return allowance; foreach (var freeAllowances in map.Values) { - var freeAllowance = freeAllowances.Map.Values.FirstOrDefault(t => t.Symbol == symbol); + freeAllowances.Map.TryGetValue(symbol, out var freeAllowance); allowance = allowance.Add(freeAllowance?.Amount ?? 0L); } diff --git a/contract/AElf.Contracts.Profit/ProfitContract.cs b/contract/AElf.Contracts.Profit/ProfitContract.cs index 5cd5514a71..c3c09b3aba 100644 --- a/contract/AElf.Contracts.Profit/ProfitContract.cs +++ b/contract/AElf.Contracts.Profit/ProfitContract.cs @@ -719,16 +719,6 @@ public override Empty ContributeProfits(ContributeProfitsInput input) return new Empty(); } - - public override Empty IncreaseBackupSubsidyTotalShare(Hash schemeId) - { - Assert(!State.BackupSubsidyTotalShareIncreased.Value, "Already increased"); - State.BackupSubsidyTotalShareIncreased.Value = true; - var scheme = State.SchemeInfos[schemeId]; - scheme.TotalShares = scheme.TotalShares.Add(1); - State.SchemeInfos[schemeId] = scheme; - return new Empty(); - } public override Empty ResetManager(ResetManagerInput input) { diff --git a/contract/AElf.Contracts.Profit/ProfitContractState.cs b/contract/AElf.Contracts.Profit/ProfitContractState.cs index 1648619f80..7a525e3ff6 100644 --- a/contract/AElf.Contracts.Profit/ProfitContractState.cs +++ b/contract/AElf.Contracts.Profit/ProfitContractState.cs @@ -17,6 +17,4 @@ public partial class ProfitContractState : ContractState public MappedState TransactionFees { get; set; } public SingletonState MethodFeeController { get; set; } - - public BoolState BackupSubsidyTotalShareIncreased { get; set; } } \ No newline at end of file diff --git a/protobuf/profit_contract.proto b/protobuf/profit_contract.proto index b2fa18e712..1326da62ff 100644 --- a/protobuf/profit_contract.proto +++ b/protobuf/profit_contract.proto @@ -60,10 +60,6 @@ service ProfitContract { rpc RemoveSubScheme (RemoveSubSchemeInput) returns (google.protobuf.Empty) { } - // Increase backup subsidy TotalShare - rpc IncreaseBackupSubsidyTotalShare (aelf.Hash) returns (google.protobuf.Empty) { - } - // Reset the manager of a scheme. rpc ResetManager (ResetManagerInput) returns (google.protobuf.Empty) { } From 541deadafa64ada8ae81c0f28a47eb033ecd7bcb Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Mon, 19 Jun 2023 20:43:04 +0800 Subject: [PATCH 064/139] feat: nftCollection,token cannot use same symbol prefix --- .../AElf.Contracts.MultiToken/TokenContractConstants.cs | 3 ++- .../AElf.Contracts.MultiToken/TokenContract_Helper.cs | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs index 2f407988d3..b9d2184ebd 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs @@ -17,5 +17,6 @@ public static class TokenContractConstants public const int DELEGATEE_MAX_COUNT = 128; public const char NFTSymbolSeparator = '-'; public const int NFTSymbolMaxLength = 30; - public const string UserContractMethodFeeKey = "UserContractMethodFee"; + public const string UserContractMethodFeeKey = "UserContractMethodFee"; + public const string CollectionId = "0"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index d11e25b7de..c45ebc0a70 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -143,8 +143,15 @@ private void AssertCrossChainTransaction(Transaction originalTransaction, Addres private void RegisterTokenInfo(TokenInfo tokenInfo) { + var symbols = tokenInfo.Symbol.Split(TokenContractConstants.NFTSymbolSeparator); + var duplicatedToken = State.TokenInfos[symbols.First()]; + var empty = new TokenInfo(); + Assert( duplicatedToken == null || duplicatedToken.Equals(empty),"Token name prefix can not be duplicated"); + var duplicatedNftCollection = State.TokenInfos[symbols.First() + TokenContractConstants.NFTSymbolSeparator + TokenContractConstants.CollectionId]; + Assert( duplicatedNftCollection == null ||duplicatedNftCollection.Equals(empty),"Token name prefix can not be duplicated"); + var existing = State.TokenInfos[tokenInfo.Symbol]; - Assert(existing == null || existing.Equals(new TokenInfo()), "Token already exists."); + Assert(existing == null || existing.Equals(empty), "Token already exists."); Assert(!string.IsNullOrEmpty(tokenInfo.Symbol) && tokenInfo.Symbol.All(IsValidSymbolChar), "Invalid symbol."); Assert(!string.IsNullOrEmpty(tokenInfo.TokenName), "Token name can neither be null nor empty."); From 96e2c180537704a92e370c568f101a193c5a7c06 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 19 Jun 2023 21:07:42 +0800 Subject: [PATCH 065/139] fix: adjust Lock and Unlock for Election Contract --- .../TokenContract_Actions.cs | 12 ++++++-- .../BVT/ElectionTests.cs | 30 +++++++++---------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index f627b867a7..3e9833c9b8 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -151,7 +151,11 @@ public override Empty Transfer(TransferInput input) public override Empty Lock(LockInput input) { AssertSystemContractOrLockWhiteListAddress(input.Symbol); - Assert(Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); + + // For Election Contract + var electionAddress = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + Assert(Context.Sender == electionAddress || Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); + var allowance = State.Allowances[input.Address][Context.Sender][input.Symbol]; if (allowance >= input.Amount) State.Allowances[input.Address][Context.Sender][input.Symbol] = allowance.Sub(input.Amount); @@ -175,7 +179,11 @@ public override Empty Lock(LockInput input) public override Empty Unlock(UnlockInput input) { AssertSystemContractOrLockWhiteListAddress(input.Symbol); - Assert(Context.Origin == input.Address, "Unlock behaviour should be initialed by origin address."); + + // For Election Contract + var electionAddress = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + Assert(Context.Sender == electionAddress || Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); + AssertValidToken(input.Symbol, input.Amount); var fromVirtualAddress = HashHelper.ComputeFrom(Context.Sender.Value.Concat(input.Address.Value) .Concat(input.LockId.Value).ToArray()); diff --git a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs index 24b8b69860..76c291a487 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs @@ -1902,21 +1902,21 @@ private async Task ResetMinerCount(int count) #endregion - // [Fact] - // public async Task VirtualAddress_Vote_Test() - // { - // var amount = 100; - // const int lockTime = 100 * 60 * 60 * 24; - // var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); - // var candidateKeyPair = candidatesKeyPairs[0]; - // await TestVoteContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput - // { - // PubKey = candidateKeyPair.PublicKey.ToHex(), - // Amount = amount, - // EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(lockTime), - // Token = HashHelper.ComputeFrom("token A") - // }); - // } + [Fact] + public async Task VirtualAddress_Vote_Test() + { + var amount = 100; + const int lockTime = 100 * 60 * 60 * 24; + var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); + var candidateKeyPair = candidatesKeyPairs[0]; + await TestVoteContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput + { + PubKey = candidateKeyPair.PublicKey.ToHex(), + Amount = amount, + EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(lockTime), + Token = HashHelper.ComputeFrom("token A") + }); + } [Fact] public async Task Vote_Test() From 5835e3de339fdfc1fa273ea46b2d70ce8ed73bbd Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 20 Jun 2023 11:06:23 +0800 Subject: [PATCH 066/139] fix: cr --- .../TokenContract_ACS2_StatePathsProvider.cs | 10 +-- .../TokenContract_Fees.cs | 71 +++++++++++-------- .../ProfitTests.cs | 13 ---- 3 files changed, 48 insertions(+), 46 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index 1dda625f98..32e629382a 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -27,8 +27,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) { GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)), - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesSymbolList)), - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesConfigMap)) + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesSymbolList)) } }; AddPathForTransactionFee(resourceInfo, txn.From.ToString()); @@ -55,8 +54,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) { GetPath(nameof(TokenContractState.TokenInfos), args.Symbol), GetPath(nameof(TokenContractState.ChainPrimaryTokenSymbol)), - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesSymbolList)), - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesConfigMap)) + GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesSymbolList)) } }; AddPathForTransactionFee(resourceInfo, txn.From.ToString()); @@ -71,7 +69,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) } } - private void AddPathForTransactionFee(ResourceInfo resourceInfo, String from) + private void AddPathForTransactionFee(ResourceInfo resourceInfo, string from) { var symbols = GetMethodFeeSymbols(); var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; @@ -110,6 +108,7 @@ private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from, strin if (delegations == null) return; var add = Address.FromBase58(delegations).ToString(); AddPathForTransactionFee(resourceInfo, add); + AddPathForTransactionFeeFreeAllowance(resourceInfo, Address.FromBase58(delegations)); resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowances), add, symbol)); resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesLastRefreshTimes), add, symbol)); } @@ -125,6 +124,7 @@ private void AddPathForTransactionFeeFreeAllowance(ResourceInfo resourceInfo, Ad { resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowances), from.ToBase58(), symbol)); resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesLastRefreshTimes), from.ToBase58(), symbol)); + resourceInfo.ReadPaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesConfigMap), symbol)); } } } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index e1b91132ee..e3fb3439de 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -446,12 +446,13 @@ private void GetAvailableBalance(string symbolToPayTxFee, Address fromAddress, T private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List allSymbolToTxFee, Address fromAddress, long txSizeFeeAmount, TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, - string symbolChargedForBaseFee, long amountChargedForBaseFee, long amountChargedForBaseAllowance, TransactionFeeDelegations delegations = null) + string symbolChargedForBaseFee, long amountChargedForBaseFee, long amountChargedForBaseAllowance, + TransactionFeeDelegations delegations = null) { SymbolToPayTxSizeFee availableSymbol = null; SymbolToPayTxSizeFee availableSymbolWithAnything = null; + SymbolToPayTxSizeFee availableSymbolWithEnoughBalance = null; SymbolToPayTxSizeFee availableSymbolWithEnoughBalancePlusAllowance = null; - SymbolToPayTxSizeFee availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; // get 1st Allowance > size fee, else, get 1st Balance + Allowance > 0, else get 1st > 0 foreach (var symbolToPlayTxSizeFee in allSymbolToTxFee) @@ -463,13 +464,14 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List= txSizeFeeAmount) { availableSymbol = symbolToPlayTxSizeFee; @@ -482,14 +484,19 @@ private SymbolToPayTxSizeFee GetAvailableSymbolToPayTxFee(List 0) + { + availableSymbolWithEnoughBalancePlusAllowance ??= symbolToPlayTxSizeFee; + } + else + { + availableSymbolWithEnoughBalance ??= symbolToPlayTxSizeFee; + } } - availableSymbol ??= availableSymbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? - availableSymbolWithEnoughBalancePlusAllowance ?? availableSymbolWithAnything; + availableSymbol ??= availableSymbolWithEnoughBalancePlusAllowance ?? + availableSymbolWithEnoughBalance ?? availableSymbolWithAnything; return availableSymbol; } @@ -725,13 +732,12 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, Address fromAddress, TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, out long amount, - out string symbolOfValidBalance, - out long existingBalance, out long existingAllowance) + out string symbolOfValidBalance, out long existingBalance, out long existingAllowance) { symbolOfValidBalance = null; string symbolWithAnything = null; + string symbolWithEnoughBalance = null; string symbolWithEnoughBalancePlusAllowance = null; - string symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; amount = 0; existingBalance = 0; @@ -755,21 +761,25 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, symbolWithAnything ??= symbol; if (existingBalance.Add(existingAllowance) < amount) continue; - symbolWithEnoughBalancePlusAllowance ??= symbol; - if (existingAllowance <= 0) continue; - symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbol; + if (existingAllowance > 0) + { + symbolWithEnoughBalancePlusAllowance ??= symbol; + } + else + { + symbolWithEnoughBalance ??= symbol; + } } - if (symbolWithEnoughBalancePlusAllowance == null) + if (symbolWithEnoughBalancePlusAllowance == null && symbolWithEnoughBalance == null) { symbolOfValidBalance = symbolWithAnything; return false; } - symbolOfValidBalance = symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? - symbolWithEnoughBalancePlusAllowance; + symbolOfValidBalance = symbolWithEnoughBalancePlusAllowance ?? symbolWithEnoughBalance; return true; } @@ -782,8 +792,8 @@ private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountM amount = 0; existingBalance = 0; existingAllowance = 0; - string symbolWithBalancePlusAllowanceEnoughToPayTxFee = null; - string symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance = null; + string symbolWithEnoughBalance = null; + string symbolWithEnoughBalancePlusAllowance = null; //Find the token that satisfies the delegate limit and satisfies the balance of the fee foreach (var (symbol, value) in symbolToAmountMap) { @@ -805,15 +815,20 @@ private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountM //Find symbol which balance+allowance >= amount if (existingBalance.Add(existingAllowance) < amount) continue; - symbolWithBalancePlusAllowanceEnoughToPayTxFee ??= symbol; - //If balance+allowance is enough,priority find the symbol which allowance > 0 - if (existingAllowance <= 0) continue; - symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ??= symbol; + + if (existingAllowance > 0) + { + //If balance+allowance is enough,priority find the symbol which allowance > 0 + symbolWithEnoughBalancePlusAllowance ??= symbol; + } + else + { + symbolWithEnoughBalance ??= symbol; + } } } - symbolOfValidBalance = symbolWithBalancePlusAllowanceEnoughToPayTxFeeWithAllowance ?? - symbolWithBalancePlusAllowanceEnoughToPayTxFee; + symbolOfValidBalance = symbolWithEnoughBalancePlusAllowance ?? symbolWithEnoughBalance; return symbolOfValidBalance != null; } diff --git a/test/AElf.Contracts.Profit.Tests/ProfitTests.cs b/test/AElf.Contracts.Profit.Tests/ProfitTests.cs index 71d52660e0..34979069da 100644 --- a/test/AElf.Contracts.Profit.Tests/ProfitTests.cs +++ b/test/AElf.Contracts.Profit.Tests/ProfitTests.cs @@ -1679,19 +1679,6 @@ await ProfitContractStub.ClaimProfits.SendAsync(new ClaimProfitsInput details.Details.First().LastProfitPeriod.ShouldBe(scheme.CurrentPeriod); } } - - [Fact] - public async Task IncreaseBackupSubsidyTotalShare_Test() - { - var schemeId = await CreateSchemeAsync(); - var scheme = await ProfitContractStub.GetScheme.CallAsync(schemeId); - scheme.TotalShares.ShouldBe(0); - await ProfitContractStub.IncreaseBackupSubsidyTotalShare.SendAsync(schemeId); - scheme = await ProfitContractStub.GetScheme.CallAsync(schemeId); - scheme.TotalShares.ShouldBe(1); - var result = await ProfitContractStub.IncreaseBackupSubsidyTotalShare.SendWithExceptionAsync(schemeId); - result.TransactionResult.Error.ShouldContain("Already increased"); - } private async Task ContributeProfits(Hash schemeId, long amount = 100) { From a8a23594a1c5f51292bee52acfddd7fcfd6411a1 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 20 Jun 2023 11:56:59 +0800 Subject: [PATCH 067/139] fix: chargeBaseFee logic and ut --- .../AElf.Contracts.MultiToken/TokenContract_Fees.cs | 4 ++-- ...cutePluginTransactionDirectlyTest_FreeAllowance.cs | 11 ++++++----- .../ExecutionPluginForMethodFeeTest.cs | 4 ++-- .../ExecutionPluginForUserContractMethodFeeTest.cs | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index e3fb3439de..eec49bbaaf 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -706,13 +706,13 @@ private bool ChargeFirstSufficientToken(Dictionary symbolToAmountM } chargeResult = TryToChargeUserBaseFee(symbolToAmountMap, fromAddress, transactionFeeFreeAllowancesMap, - out amount, - out symbol, out existingBalance, out existingAllowance); + out amount, out symbol, out existingBalance, out existingAllowance); if (symbol != null) { existingBalance = GetBalance(fromAddress, symbol); existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); + amount = symbolToAmountMap[symbol]; } //For user, if charge failed and delegation is null, priority charge primary token diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index ce504dd6f5..e4794f513b 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -1557,7 +1557,8 @@ public async Task ChargeTransactionFee_MultipleTxFeeTokens_Test(long initialELFB await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -1629,7 +1630,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, BasicFee = secondBaseFeeAmount }); } - + await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); @@ -1673,7 +1674,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(firstFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(firstFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(firstFreeAmountUSDT); - + freeAllowances.Map.Values.Last().Map.Keys.Last().ShouldBe(secondFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.Last().Symbol.ShouldBe(secondFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.Last().Amount.ShouldBe(secondFreeAmountUSDT); @@ -1686,7 +1687,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, TransactionSizeFee = sizeFee, }; chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(chargeFeeResult); @@ -1709,7 +1710,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.Last().Map.Keys.First().ShouldBe(firstFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.First().Symbol.ShouldBe(firstFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.First().Amount.ShouldBe(newFirstFreeAmountUSDT); - + freeAllowances.Map.Values.Last().Map.Keys.Last().ShouldBe(secondFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.Last().Symbol.ShouldBe(secondFreeSymbolUSDT); freeAllowances.Map.Values.Last().Map.Values.Last().Amount.ShouldBe(newSecondFreeAmountUSDT); diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs index 6940935f4d..0c1237863d 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs @@ -335,9 +335,9 @@ await tokenContractStub.Transfer.SendAsync(new TransferInput } [Theory] - [InlineData(100000000, 0, 3, 10, 1, 2, "ELF", 20260002, true)] + [InlineData(100000000, 0, 3, 10, 1, 2, "ELF", 20260010, true)] [InlineData(9, 0, 1, 10, 1, 2, "ELF", 9, false)] - [InlineData(100000000, 2, 2, 0, 1, 2, "TSA", 2, true)] + [InlineData(100000000, 2, 2, 0, 1, 2, "TSA", 1, true)] [InlineData(100000000, 2, 2, 0, 13, 2, "TSB", 2, true)] [InlineData(100000000, 2, 2, 0, 20, 20, "TSA", 2, false)] [InlineData(1, 0, 1, 0, 1, 2, "TSB", 1, false)] diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs index 2a12cde602..d115a517cc 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs @@ -151,9 +151,9 @@ public async Task GetPreTransactions_None_PreTransaction_Test() } [Theory] - [InlineData(100000000, 0, 3, 10, 1, 2, "ELF", 20135002, true)] + [InlineData(100000000, 0, 3, 10, 1, 2, "ELF", 20135010, true)] [InlineData(9, 0, 1, 10, 1, 2, "ELF", 9, false)] - [InlineData(100000000, 2, 2, 0, 1, 2, "TSA", 2, true)] + [InlineData(100000000, 2, 2, 0, 1, 2, "TSA", 1, true)] [InlineData(100000000, 2, 2, 0, 13, 2, "TSB", 2, true)] [InlineData(100000000, 2, 2, 0, 20, 20, "TSA", 2, false)] [InlineData(1, 0, 1, 0, 1, 2, "TSB", 1, false)] From 18b9ecf067292eb3b8331b2d7b745d68fb08b6f0 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 20 Jun 2023 13:53:26 +0800 Subject: [PATCH 068/139] feat: add ut case --- .../ExecutePluginTransactionDirectlyTest_FreeAllowance.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index e4794f513b..4300646d96 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -1535,6 +1535,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, [InlineData(10000, 10000, 1000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, NativeTokenSymbol, 1000, 300, 100, 0, 0, 0, 0, 0, 10000, 0, 0, 3000, 5, 3, NativeTokenSymbol, 15000, USDT, 20000, false)] // case 33 [InlineData(5000, 10000, 0, 0, Token1, 1000, Token1, 1000, 600, 100, Token2, 1000, Token2, 1000, 300, 100, 0, 0, 1000, 1000, 0, 8000, 0, 0, 10000, 1, 5, USDT, 2000, NativeTokenSymbol, 0, false)] + [InlineData(2000, 0, 0, 0, Token1, 0, NativeTokenSymbol, 0, 0, 10000, Token2, 0, Token2, 0, 0, 10000, 0, 0, 0, 0, 500, 0, 0, 0, 0, 1, 1, NativeTokenSymbol, 1500, USDT, 100, true)] public async Task ChargeTransactionFee_MultipleTxFeeTokens_Test(long initialELFBalance, long initialUSDTBalance, long initialToken1Balance, long initialToken2Balance, string firstFreeSymbolELF, long firstFreeAmountELF, string secondFreeSymbolELF, long secondFreeAmountELF, long refreshSecondsELF, long thresholdELF, From 13aa5c9a9a532e1fdb5ae73a4dc3e69b5b20f0f3 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Tue, 20 Jun 2023 13:56:02 +0800 Subject: [PATCH 069/139] fix: charge delegatee base fee. --- contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index eec49bbaaf..defd7d1cde 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -830,6 +830,13 @@ private bool TryToChargeDelegateBaseFee(Dictionary symbolToAmountM symbolOfValidBalance = symbolWithEnoughBalancePlusAllowance ?? symbolWithEnoughBalance; + if (symbolOfValidBalance != null) + { + existingBalance = GetBalance(fromAddress, symbolOfValidBalance); + existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbolOfValidBalance); + amount = symbolToAmountMap[symbolOfValidBalance]; + } + return symbolOfValidBalance != null; } From 5494fbd957056afd5ec2f6601e1052076d35d41d Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 20 Jun 2023 15:18:47 +0800 Subject: [PATCH 070/139] feat: add ut --- .../TokenContractState_ChargeFee.cs | 1 + .../TokenContract_Actions.cs | 8 +- .../TokenContract_Helper.cs | 9 ++ protobuf/test_election_vote_contract.proto | 5 + .../BVT/ElectionTests.cs | 140 +++++++++++++++++- .../Action.cs | 22 ++- 6 files changed, 177 insertions(+), 8 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs index 9fdf6cbe0c..5c61f668c4 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs @@ -35,6 +35,7 @@ public partial class TokenContractState /// public MappedState OwningRental { get; set; } + public SingletonState
ElectionContractAddress { get; set; } public SingletonState MethodFeeFreeAllowancesConfig { get; set; } public MappedState MethodFeeFreeAllowancesMap { get; set; } public MappedState MethodFeeFreeAllowancesLastRefreshTimeMap { get; set; } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 3e9833c9b8..6a5cdd9b77 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -153,8 +153,8 @@ public override Empty Lock(LockInput input) AssertSystemContractOrLockWhiteListAddress(input.Symbol); // For Election Contract - var electionAddress = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); - Assert(Context.Sender == electionAddress || Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); + var electionContractAddress = GetElectionContractAddress(); ; + Assert(Context.Sender == electionContractAddress || Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); var allowance = State.Allowances[input.Address][Context.Sender][input.Symbol]; if (allowance >= input.Amount) @@ -181,8 +181,8 @@ public override Empty Unlock(UnlockInput input) AssertSystemContractOrLockWhiteListAddress(input.Symbol); // For Election Contract - var electionAddress = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); - Assert(Context.Sender == electionAddress || Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); + var electionContractAddress = GetElectionContractAddress(); + Assert(Context.Sender == electionContractAddress || Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); AssertValidToken(input.Symbol, input.Amount); var fromVirtualAddress = HashHelper.ComputeFrom(Context.Sender.Value.Concat(input.Address.Value) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index d11e25b7de..90270fa95c 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -265,4 +265,13 @@ private void FireExternalLogEvent(TokenInfo tokenInfo, TransferFromInput input) NonIndexed = input.ToByteString() }); } + + private Address GetElectionContractAddress() + { + if (State.ElectionContractAddress.Value == null) + State.ElectionContractAddress.Value = + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + + return State.ElectionContractAddress.Value; + } } \ No newline at end of file diff --git a/protobuf/test_election_vote_contract.proto b/protobuf/test_election_vote_contract.proto index 41305215c6..ee0f5330cd 100644 --- a/protobuf/test_election_vote_contract.proto +++ b/protobuf/test_election_vote_contract.proto @@ -14,6 +14,11 @@ service TestVoteContract { option (aelf.base) = "acs1.proto"; rpc VirtualAddressVote(VirtualAddressVoteInput) returns (google.protobuf.Empty); + rpc VirtualAddressWithdraw(aelf.Hash) returns (google.protobuf.Empty); + + rpc GetVirtualAddress(google.protobuf.Empty) returns (aelf.Address) { + option (aelf.is_view) = true; + } } message VirtualAddressVoteInput { diff --git a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs index 76c291a487..70f3d330ef 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs @@ -300,7 +300,7 @@ await VoteToCandidates( { Value = voterKeyPair.PublicKey.ToHex() }); - voterVotes.Pubkey.ShouldBe(ByteString.CopyFrom(voterKeyPair.PublicKey)); + voterVotes.Address.ShouldBe(Address.FromPublicKey(voterKeyPair.PublicKey)); voterVotes.ActiveVotingRecordIds.Count.ShouldBe(19); voterVotes.AllVotedVotesAmount.ShouldBe(actualVotedAmount); voterVotes.ActiveVotedVotesAmount.ShouldBe(actualVotedAmount); @@ -1903,12 +1903,56 @@ private async Task ResetMinerCount(int count) #endregion [Fact] - public async Task VirtualAddress_Vote_Test() + public async Task VirtualAddress_Vote_Test() { var amount = 100; const int lockTime = 100 * 60 * 60 * 24; var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); var candidateKeyPair = candidatesKeyPairs[0]; + + var address = await TestVoteContractStub.GetVirtualAddress.CallAsync(new Empty()); + var initBalance = 100000; + + await TokenContractStub.Transfer.SendAsync(new TransferInput + { + Amount = initBalance, + Symbol = "ELF", + To = address, + Memo = "test" + }); + + CheckBalance(address, "ELF", initBalance); + CheckBalance(address, "SHARE", 0); + CheckBalance(address, "VOTE", 0); + + await TestVoteContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput + { + PubKey = candidateKeyPair.PublicKey.ToHex(), + Amount = amount, + EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(lockTime), + Token = HashHelper.ComputeFrom("token A") + }); + + var result = await ElectionContractStub.GetElectorVote.CallAsync(new StringValue + { + Value = address.ToBase58() + }); + result.ActiveVotedVotesAmount.ShouldBe(amount); + result = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue + { + Value = address.ToBase58() + }); + result.ActiveVotedVotesAmount.ShouldBe(amount); + result = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync(new StringValue + { + Value = address.ToBase58() + }); + result.AllVotedVotesAmount.ShouldBe(amount); + + CheckBalance(address, "ELF", initBalance - amount); + CheckBalance(address, "SHARE", amount); + CheckBalance(address, "VOTE", amount); + await TestVoteContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput { PubKey = candidateKeyPair.PublicKey.ToHex(), @@ -1916,6 +1960,69 @@ await TestVoteContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteIn EndTimestamp = TimestampHelper.GetUtcNow().AddSeconds(lockTime), Token = HashHelper.ComputeFrom("token A") }); + + result = await ElectionContractStub.GetElectorVote.CallAsync(new StringValue + { + Value = address.ToBase58() + }); + result.ActiveVotedVotesAmount.ShouldBe(amount + amount); + result = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue + { + Value = address.ToBase58() + }); + result.ActiveVotedVotesAmount.ShouldBe(amount + amount); + result = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync(new StringValue + { + Value = address.ToBase58() + }); + result.AllVotedVotesAmount.ShouldBe(amount + amount); + + CheckBalance(address, "ELF", initBalance - amount - amount); + CheckBalance(address, "SHARE", amount + amount); + CheckBalance(address, "VOTE", amount + amount); + + return result.ActiveVotingRecords.First().VoteId; + } + + [Fact] + public async Task VirtualAddress_Withdraw_Test() + { + var amount = 100; + const int lockTime = 100 * 60 * 60 * 24; + + var address = await TestVoteContractStub.GetVirtualAddress.CallAsync(new Empty()); + var initBalance = 100000; + + var voteId = await VirtualAddress_Vote_Test(); + BlockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddDays(101)); + + await TestVoteContractStub.VirtualAddressWithdraw.SendAsync(new Hash + { + Value = voteId.Value + }); + + var result = await ElectionContractStub.GetElectorVote.CallAsync(new StringValue + { + Value = address.ToBase58() + }); + result.ActiveVotedVotesAmount.ShouldBe(amount); + result = await ElectionContractStub.GetElectorVoteWithRecords.CallAsync(new StringValue + { + Value = address.ToBase58() + }); + result.ActiveVotedVotesAmount.ShouldBe(amount); + result = await ElectionContractStub.GetElectorVoteWithAllRecords.CallAsync(new StringValue + { + Value = address.ToBase58() + }); + + result.ActiveVotedVotesAmount.ShouldBe(amount); + result.WithdrawnVotesRecords.Count().ShouldBe(1); + result.AllVotedVotesAmount.ShouldBe(amount + amount); + + CheckBalance(address, "ELF", initBalance - amount); + CheckBalance(address, "SHARE", amount); + CheckBalance(address, "VOTE", amount); } [Fact] @@ -1926,6 +2033,13 @@ public async Task Vote_Test() var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); var candidateKeyPair = candidatesKeyPairs[0]; + var address = Address.FromPublicKey(BootMinerKeyPair.PublicKey); + var initBalance = 100000000000000; + + CheckBalance(address, "ELF", initBalance); + CheckBalance(address, "SHARE", 0); + CheckBalance(address, "VOTE", 0); + var voteRet = await ElectionContractStub.Vote.SendAsync(new VoteMinerInput { CandidatePubkey = candidateKeyPair.PublicKey.ToHex(), @@ -1951,6 +2065,10 @@ public async Task Vote_Test() }); result.AllVotedVotesAmount.ShouldBe(amount); + CheckBalance(address, "ELF", initBalance - amount); + CheckBalance(address, "SHARE", amount); + CheckBalance(address, "VOTE", amount); + return result.ActiveVotingRecords.First().VoteId; } @@ -1984,5 +2102,23 @@ await ElectionContractStub.Withdraw.SendAsync(new Hash result.ActiveVotedVotesAmount.ShouldBe(0); result.WithdrawnVotesRecords.Count().ShouldBe(1); result.AllVotedVotesAmount.ShouldBe(100); + + var address = Address.FromPublicKey(BootMinerKeyPair.PublicKey); + var initBalance = 100000000000000; + + CheckBalance(address, "ELF", initBalance); + CheckBalance(address, "SHARE", 0); + CheckBalance(address, "VOTE", 0); + } + + private void CheckBalance(Address address, string symbol, long amount) + { + var balance = TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Owner = address, + Symbol = symbol + }).Result; + + balance.Balance.ShouldBe(amount); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TestVote/Action.cs b/test/AElf.Contracts.TestContract.TestVote/Action.cs index 7a3355856e..f076f4ce21 100644 --- a/test/AElf.Contracts.TestContract.TestVote/Action.cs +++ b/test/AElf.Contracts.TestContract.TestVote/Action.cs @@ -1,5 +1,6 @@ using AElf.Contracts.Election; using AElf.Sdk.CSharp; +using AElf.Types; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.TestContract.TestVote; @@ -21,9 +22,26 @@ public override Empty VirtualAddressVote(VirtualAddressVoteInput input) return new Empty(); } + public override Empty VirtualAddressWithdraw(Hash input) + { + Initialize(); + + Context.SendVirtualInline(HashHelper.ComputeFrom("test"), State.ElectionContract.Value, "Withdraw", input); + + return new Empty(); + } + + public override Address GetVirtualAddress(Empty input) + { + return Context.ConvertVirtualAddressToContractAddress(HashHelper.ComputeFrom("test")); + } + private void Initialize() { - State.ElectionContract.Value = - Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + if (State.ElectionContract.Value == null) + { + State.ElectionContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + } } } \ No newline at end of file From 1383a721c6d1e45ea097deb2992731c516bac49c Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 20 Jun 2023 15:24:32 +0800 Subject: [PATCH 071/139] fix: duplicate readPath --- .../TokenContract_ACS2_StatePathsProvider.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index 32e629382a..8578edfc5e 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -124,7 +124,12 @@ private void AddPathForTransactionFeeFreeAllowance(ResourceInfo resourceInfo, Ad { resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowances), from.ToBase58(), symbol)); resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesLastRefreshTimes), from.ToBase58(), symbol)); - resourceInfo.ReadPaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesConfigMap), symbol)); + + var path = GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesConfigMap), symbol); + if (!resourceInfo.ReadPaths.Contains(path)) + { + resourceInfo.ReadPaths.Add(path); + } } } } From 2989869842d6a398ead5daf4d22fb90dd9eb3e1e Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 20 Jun 2023 18:18:55 +0800 Subject: [PATCH 072/139] feat: add log --- .../TokenContract_Fees.cs | 10 ++++++++++ .../AElf.Contracts.MultiToken.Tests.csproj | 16 ++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index defd7d1cde..fec7f867e2 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -22,6 +22,7 @@ public partial class TokenContract /// public override ChargeTransactionFeesOutput ChargeTransactionFees(ChargeTransactionFeesInput input) { + Context.LogDebug(() => "ChargeTransactionFees Start"); AssertPermissionAndInput(input); // Primary token not created yet. if (State.ChainPrimaryTokenSymbol.Value == null) @@ -83,6 +84,7 @@ private ChargeTransactionFeesOutput TryToChargeTransactionFee(ChargeTransactionF TransactionFeeBill bill, TransactionFreeFeeAllowanceBill allowanceBill, Dictionary fee, bool isSizeFeeFree) { + Context.LogDebug(() => "TryToChargeTransactionFee Start"); var chargingResult = ChargeTransactionFeesToBill(input, fromAddress, ref bill, ref allowanceBill, fee, isSizeFeeFree); if (!chargingResult) @@ -116,6 +118,9 @@ private ChargeTransactionFeesOutput TryToChargeTransactionFee(ChargeTransactionF var chargingOutput = new ChargeTransactionFeesOutput { Success = chargingResult }; if (!chargingResult) chargingOutput.ChargingInformation = "Transaction fee not enough."; + + Context.LogDebug(() => "TryToChargeTransactionFee End"); + Context.LogDebug(() => "ChargeTransactionFees End"); return chargingOutput; } @@ -331,6 +336,7 @@ private bool ChargeBaseFee(Dictionary methodFeeMap, Address fromAd ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { + Context.LogDebug(() => "ChargeBaseFee Start"); // Fail to charge if (!ChargeFirstSufficientToken(methodFeeMap, fromAddress, out var symbolToChargeBaseFee, out var amountToChargeBaseFee, out var existingBalance, out var existingAllowance, @@ -360,6 +366,7 @@ private bool ChargeBaseFee(Dictionary methodFeeMap, Address fromAd bill.FeesMap.Add(symbolToChargeBaseFee, amountToChargeBaseFee.Sub(existingAllowance)); } + Context.LogDebug(() => "ChargeBaseFee End"); return true; } @@ -368,6 +375,7 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress ref TransactionFreeFeeAllowanceBill allowanceBill, TransactionFeeDelegations delegations = null) { + Context.LogDebug(() => "ChargeSizeFee Start"); //If delegation != null,from address->delegateeAddress // Size Fee is charged in primary token, elf. var symbolToPayTxFee = State.ChainPrimaryTokenSymbol.Value; @@ -415,6 +423,8 @@ private bool ChargeSizeFee(ChargeTransactionFeesInput input, Address fromAddress GenerateBill(txSizeFeeAmount, symbolToPayTxFee, symbolChargedForBaseFee, availableBalance, availableAllowance, ref bill, ref allowanceBill); + + Context.LogDebug(() => "ChargeSizeFee End"); return chargeResult; } diff --git a/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj b/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj index 08ec6e2c33..51995933ec 100644 --- a/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj +++ b/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj @@ -63,17 +63,17 @@ all runtime; build; native; contentfiles; analyzers - + - + - all - runtime; build; native; contentfiles; analyzers - + all + runtime; build; native; contentfiles; analyzers + - all - runtime; build; native; contentfiles; analyzers - + all + runtime; build; native; contentfiles; analyzers + From 761efd37cdac41c47bd8dba91ef55c6a83067268 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 21 Jun 2023 11:40:44 +0800 Subject: [PATCH 073/139] fix: TokenContract_ACS2_StatePathsProvider.cs --- .../TokenContract_ACS2_StatePathsProvider.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index ec92464fd5..98d7dd0ff6 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -1,6 +1,4 @@ -using System; -using System.Data.SqlTypes; -using System.Linq; +using System.Linq; using AElf.Standards.ACS2; using AElf.Types; using Google.Protobuf.WellKnownTypes; @@ -68,7 +66,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) } } - private void AddPathForTransactionFee(ResourceInfo resourceInfo, String from, string methodName) + private void AddPathForTransactionFee(ResourceInfo resourceInfo, string from, string methodName) { var symbols = GetTransactionFeeSymbols(methodName); var primaryTokenSymbol = GetPrimaryTokenSymbol(new Empty()).Value; From 1a730f10f6c941529a3902aea07facf2aaafe0c5 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Wed, 21 Jun 2023 17:04:07 +0800 Subject: [PATCH 074/139] feat: mutiToken add seed nft --- .../TokenContractConstants.cs | 1 + .../TokenContractState.cs | 1 + .../TokenContract_Actions.cs | 30 +++++++++++++++++++ .../TokenContract_Helper.cs | 19 ++++++++---- .../TokenContract_NFT_Actions.cs | 9 ++++++ 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs index b9d2184ebd..3810302e5f 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs @@ -19,4 +19,5 @@ public static class TokenContractConstants public const int NFTSymbolMaxLength = 30; public const string UserContractMethodFeeKey = "UserContractMethodFee"; public const string CollectionId = "0"; + public const string SeedCollectionId = "SEED-0"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState.cs b/contract/AElf.Contracts.MultiToken/TokenContractState.cs index cac95c40af..672c55a076 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState.cs @@ -9,6 +9,7 @@ public partial class TokenContractState : ContractState public StringState ChainPrimaryTokenSymbol { get; set; } public MappedState TokenInfos { get; set; } + public MappedState SymbolSeedMap { get; set; } public MappedState Balances { get; set; } public MappedState Allowances { get; set; } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index c8fabd2d18..9facd0d728 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -46,6 +46,21 @@ public override Empty Create(CreateInput input) private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType.Token) { AssertValidCreateInput(input, symbolType); + if (symbolType == SymbolType.Token || symbolType == SymbolType.NftCollection) + { + if (!IsAddressInCreateWhiteList(Context.Sender)) + { + var symbolSeed = State.SymbolSeedMap[input.Symbol]; + CheckSeedNft(symbolSeed, input.Symbol); + // seed nft for one-time use only + long balance = State.Balances[Context.Sender][symbolSeed]; + DoTransferFrom(Context.Sender, Context.Self, Context.Self, input.Symbol, balance,""); + Burn(new BurnInput { + Symbol = input.Symbol, + Amount = balance}); + } + } + var tokenInfo = new TokenInfo { Symbol = input.Symbol, @@ -85,6 +100,21 @@ private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType. return new Empty(); } + + private void CheckSeedNft(string symbolSeed,String symbol) + { + Assert(!string.IsNullOrEmpty(symbolSeed),"Seed NFT is not exist"); + var tokenInfo = State.TokenInfos[symbolSeed]; + Assert(tokenInfo != null,"Seed NFT is not exist"); + Assert(State.Balances[Context.Sender][symbolSeed] > 0,"owner doesn't own enough balance"); + Assert(tokenInfo.ExternalInfo != null ,"seed_owned_symbol is empty "); + tokenInfo.ExternalInfo.Value.TryGetValue("__seed_owned_symbol",out var ownedSymbol); + Assert(ownedSymbol == symbol ,"seed_owned_symbol and input_symbol is inconsistent "); + tokenInfo.ExternalInfo.Value.TryGetValue("__seed_exp_time",out var expirationTime); + Assert(!string.IsNullOrEmpty(expirationTime) + && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime),"seed_owned_symbol is expired "); + } + /// /// Set primary token symbol. diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index c45ebc0a70..f0269d98f1 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -143,13 +143,7 @@ private void AssertCrossChainTransaction(Transaction originalTransaction, Addres private void RegisterTokenInfo(TokenInfo tokenInfo) { - var symbols = tokenInfo.Symbol.Split(TokenContractConstants.NFTSymbolSeparator); - var duplicatedToken = State.TokenInfos[symbols.First()]; var empty = new TokenInfo(); - Assert( duplicatedToken == null || duplicatedToken.Equals(empty),"Token name prefix can not be duplicated"); - var duplicatedNftCollection = State.TokenInfos[symbols.First() + TokenContractConstants.NFTSymbolSeparator + TokenContractConstants.CollectionId]; - Assert( duplicatedNftCollection == null ||duplicatedNftCollection.Equals(empty),"Token name prefix can not be duplicated"); - var existing = State.TokenInfos[tokenInfo.Symbol]; Assert(existing == null || existing.Equals(empty), "Token already exists."); Assert(!string.IsNullOrEmpty(tokenInfo.Symbol) && tokenInfo.Symbol.All(IsValidSymbolChar), @@ -202,10 +196,23 @@ private void AssertValidCreateInput(CreateInput input, SymbolType symbolType) && input.Symbol.Length > 0 && input.Decimals >= 0 && input.Decimals <= TokenContractConstants.MaxDecimals, "Invalid input."); + var symbols = input.Symbol.Split(TokenContractConstants.NFTSymbolSeparator); + var empty = new TokenInfo(); if (symbolType == SymbolType.Token) + { Assert(input.Symbol.Length <= TokenContractConstants.SymbolMaxLength, "Invalid token symbol length"); + var duplicatedNftCollection = State.TokenInfos[symbols.First() + TokenContractConstants.NFTSymbolSeparator + TokenContractConstants.CollectionId]; + Assert( duplicatedNftCollection == null ||duplicatedNftCollection.Equals(empty),"Token name prefix can not be duplicated"); + } if (symbolType == SymbolType.Nft || symbolType == SymbolType.NftCollection) + { Assert(input.Symbol.Length <= TokenContractConstants.NFTSymbolMaxLength, "Invalid NFT symbol length"); + var duplicatedToken = State.TokenInfos[symbols.First()]; + Assert( duplicatedToken == null || duplicatedToken.Equals(empty),"Token name prefix can not be duplicated"); + } + + + } private void CheckCrossChainTokenContractRegistrationControllerAuthority() diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index de155b6de0..aaf3ea27f2 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -22,6 +22,15 @@ private Empty CreateNFTInfo(CreateInput input) input.IssueChainId = input.IssueChainId == 0 ? nftCollectionInfo.IssueChainId : input.IssueChainId; Assert(input.IssueChainId == nftCollectionInfo.IssueChainId, "NFT create ChainId must be collection's issue chainId"); Assert(Context.Sender == nftCollectionInfo.Issuer && nftCollectionInfo.Issuer == input.Issuer, "NFT issuer must be collection's issuer"); + if (nftCollectionInfo.Symbol == TokenContractConstants.SeedCollectionId) + { + input.ExternalInfo.Value.TryGetValue("__seed_owned_symbol",out var ownerSymbol); + input.ExternalInfo.Value.TryGetValue("__seed_exp_time",out var expirationTime); + Assert(!string.IsNullOrEmpty(ownerSymbol) && State.TokenInfos[ownerSymbol] == null,"seed_owned_symbol is empty "); + Assert(!string.IsNullOrEmpty(expirationTime) + && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime),"seed_owned_symbol is expired "); + State.SymbolSeedMap[input.Symbol] = ownerSymbol; + } return CreateToken(input, SymbolType.Nft); } From 976628270b7a6fce7dd31a31928edbd061b0f134 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 21 Jun 2023 18:43:13 +0800 Subject: [PATCH 075/139] fix: ut --- AElf.All.sln | 2 +- .../ElectionContract_Elector.cs | 8 +++---- .../TokenContract_Actions.cs | 10 ++++---- ...o => test_virtual_function_contract.proto} | 6 ++--- ...lf.Contracts.Consensus.AEDPoS.Tests.csproj | 19 +++++++++------ .../AElf.Contracts.Economic.TestBase.csproj | 6 ++--- .../Contracts.cs | 2 +- .../ContractsPreparation.cs | 18 +++++++-------- ...AElf.Contracts.EconomicSystem.Tests.csproj | 23 +++++++++++-------- .../AElf.Contracts.Election.Tests.csproj | 6 ++--- .../BVT/ElectionTests.cs | 12 +++++----- .../ElectionContractTestBase.cs | 10 ++++---- ...racts.TestContract.VirtualFunction.csproj} | 14 +++++------ .../Action.cs | 4 ++-- .../ReferenceState.cs | 2 +- .../State.cs | 2 +- 16 files changed, 77 insertions(+), 67 deletions(-) rename protobuf/{test_election_vote_contract.proto => test_virtual_function_contract.proto} (78%) rename test/{AElf.Contracts.TestContract.TestVote/AElf.Contracts.TestContract.TestVote.csproj => AElf.Contracts.TestContract.VirtualFunction/AElf.Contracts.TestContract.VirtualFunction.csproj} (77%) rename test/{AElf.Contracts.TestContract.TestVote => AElf.Contracts.TestContract.VirtualFunction}/Action.cs (89%) rename test/{AElf.Contracts.TestContract.TestVote => AElf.Contracts.TestContract.VirtualFunction}/ReferenceState.cs (74%) rename test/{AElf.Contracts.TestContract.TestVote => AElf.Contracts.TestContract.VirtualFunction}/State.cs (59%) diff --git a/AElf.All.sln b/AElf.All.sln index d1cda27137..e4ded9d7ef 100644 --- a/AElf.All.sln +++ b/AElf.All.sln @@ -369,7 +369,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps.UnitTes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract.csproj", "{AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.TestVote", "test\AElf.Contracts.TestContract.TestVote\AElf.Contracts.TestContract.TestVote.csproj", "{64498F8C-B827-4E1C-B5FB-4B9188C839A8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.VirtualFunction", "test\AElf.Contracts.TestContract.VirtualFunction\AElf.Contracts.TestContract.VirtualFunction.csproj", "{64498F8C-B827-4E1C-B5FB-4B9188C839A8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs index 28d38baa2d..8961baacdb 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs @@ -3,12 +3,10 @@ using System.Linq; using AElf.Contracts.MultiToken; using AElf.Contracts.Profit; -using AElf.Contracts.Treasury; using AElf.Contracts.Vote; using AElf.CSharp.Core; using AElf.Sdk.CSharp; using AElf.Types; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.Election; @@ -532,7 +530,7 @@ private ElectorVote GetElectorVote(byte[] recoveredPublicKey) var publicKey = recoveredPublicKey.ToHex(); voteVotes = State.ElectorVotes[publicKey]?.Clone(); - + if (voteVotes != null) { State.ElectorVotes.Remove(publicKey); @@ -640,7 +638,7 @@ public override Empty Withdraw(Hash input) var claimedLockDays = State.LockTimeMap[input]; Assert(actualLockedTime >= claimedLockDays, $"Still need {claimedLockDays.Sub(actualLockedTime).Div(86400)} days to unlock your token."); - + var voterPublicKey = Context.RecoverPublicKey(); var voterVotes = GetElectorVote(voterPublicKey); @@ -656,7 +654,7 @@ public override Empty Withdraw(Hash input) // Update Candidate's Votes information. var newestPubkey = GetNewestPubkey(votingRecord.Option); var candidateVotes = State.CandidateVotes[newestPubkey]; - + Assert(candidateVotes != null, $"Newest pubkey {newestPubkey} is invalid. Old pubkey is {votingRecord.Option}"); candidateVotes!.ObtainedActiveVotingRecordIds.Remove(input); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 6a5cdd9b77..a6edd365dd 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -153,8 +153,9 @@ public override Empty Lock(LockInput input) AssertSystemContractOrLockWhiteListAddress(input.Symbol); // For Election Contract - var electionContractAddress = GetElectionContractAddress(); ; - Assert(Context.Sender == electionContractAddress || Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); + var electionContractAddress = GetElectionContractAddress(); + Assert(Context.Sender == electionContractAddress || Context.Origin == input.Address, + "Lock behaviour should be initialed by origin address."); var allowance = State.Allowances[input.Address][Context.Sender][input.Symbol]; if (allowance >= input.Amount) @@ -179,10 +180,11 @@ public override Empty Lock(LockInput input) public override Empty Unlock(UnlockInput input) { AssertSystemContractOrLockWhiteListAddress(input.Symbol); - + // For Election Contract var electionContractAddress = GetElectionContractAddress(); - Assert(Context.Sender == electionContractAddress || Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); + Assert(Context.Sender == electionContractAddress || Context.Origin == input.Address, + "Unlock behaviour should be initialed by origin address."); AssertValidToken(input.Symbol, input.Amount); var fromVirtualAddress = HashHelper.ComputeFrom(Context.Sender.Value.Concat(input.Address.Value) diff --git a/protobuf/test_election_vote_contract.proto b/protobuf/test_virtual_function_contract.proto similarity index 78% rename from protobuf/test_election_vote_contract.proto rename to protobuf/test_virtual_function_contract.proto index ee0f5330cd..f5b10b5e1f 100644 --- a/protobuf/test_election_vote_contract.proto +++ b/protobuf/test_virtual_function_contract.proto @@ -7,10 +7,10 @@ import "google/protobuf/empty.proto"; import "google/protobuf/wrappers.proto"; import "acs1.proto"; -option csharp_namespace = "AElf.Contracts.TestContract.TestVote"; +option csharp_namespace = "AElf.Contracts.TestContract.VirtualFunction"; -service TestVoteContract { - option (aelf.csharp_state) = "AElf.Contracts.TestContract.TestVote.State"; +service VirtualFunctionContract { + option (aelf.csharp_state) = "AElf.Contracts.TestContract.VirtualFunction.State"; option (aelf.base) = "acs1.proto"; rpc VirtualAddressVote(VirtualAddressVoteInput) returns (google.protobuf.Empty); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj index 0a1b7fb34b..ad1d5e89fb 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj @@ -17,7 +17,7 @@ runtime; build; native; contentfiles; analyzers - + all @@ -29,10 +29,10 @@ - - - - + + + + false Contract @@ -43,7 +43,12 @@ Contract PreserveNewest - + + false + Contract + PreserveNewest + + @@ -116,5 +121,5 @@ - + diff --git a/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj b/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj index 3b5bc18baa..70a01de0e0 100644 --- a/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj +++ b/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj @@ -99,7 +99,7 @@ Contract PreserveNewest - + false Contract PreserveNewest @@ -184,8 +184,8 @@ Protobuf\Proto\parliament_contract_impl.proto - - Protobuf\Proto\test_election_vote_contract.proto + + Protobuf\Proto\test_virtual_function_contract.proto diff --git a/test/AElf.Contracts.Economic.TestBase/Contracts.cs b/test/AElf.Contracts.Economic.TestBase/Contracts.cs index c1e9b344ac..6990378a99 100644 --- a/test/AElf.Contracts.Economic.TestBase/Contracts.cs +++ b/test/AElf.Contracts.Economic.TestBase/Contracts.cs @@ -27,7 +27,7 @@ public enum TestContracts BasicUpdate, MethodCallThreshold, ResourceSpender, - TestVote + VirtualFunction } public enum ProfitType diff --git a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs index 7d25a2d7a9..e383e2d9ba 100644 --- a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs +++ b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs @@ -10,7 +10,7 @@ using AElf.Contracts.Parliament; using AElf.Contracts.Profit; using AElf.Contracts.TestContract.MethodCallThreshold; -using AElf.Contracts.TestContract.TestVote; +using AElf.Contracts.TestContract.VirtualFunction; using AElf.Contracts.TestContract.TransactionFeeCharging; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; @@ -104,8 +104,8 @@ public partial class EconomicContractsTestBase protected Address ConfigurationAddress => GetOrDeployContract(Contracts.Configuration, ref _configurationAddress); - private Address _testVoteContractAddress; - protected Address TestVoteContractAddress => GetOrDeployContract(TestContracts.TestVote, ref _testVoteContractAddress); + private Address _virtualFunctionContractAddress; + protected Address VirtualFunctionContractAddress => GetOrDeployContract(TestContracts.VirtualFunction, ref _virtualFunctionContractAddress); #endregion @@ -149,8 +149,8 @@ internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractS internal ConfigurationContainer.ConfigurationStub ConfigurationStub => GetConfigurationContractTester(BootMinerKeyPair); - internal TestVoteContractContainer.TestVoteContractStub TestVoteContractStub => - GetTestVoteContractTester(BootMinerKeyPair); + internal VirtualFunctionContractContainer.VirtualFunctionContractStub VirtualFunctionContractStub => + GetVirtualFunctionContractTester(BootMinerKeyPair); #endregion @@ -231,9 +231,9 @@ internal ConfigurationContainer.ConfigurationStub GetConfigurationContractTester return GetTester(ConfigurationAddress, keyPair); } - internal TestVoteContractContainer.TestVoteContractStub GetTestVoteContractTester(ECKeyPair keyPair) + internal VirtualFunctionContractContainer.VirtualFunctionContractStub GetVirtualFunctionContractTester(ECKeyPair keyPair) { - return GetTester(TestVoteContractAddress, keyPair); + return GetTester(VirtualFunctionContractAddress, keyPair); } #endregion @@ -269,7 +269,7 @@ private Address GetOrDeployContract(TestContracts contract, ref Address address) private async Task
DeployContract(Contracts contract) { - var code = Codes.FirstOrDefault(kv => kv.Key.Contains(contract.ToString())).Value; + var code = Codes.Single(kv => kv.Key.Contains(contract.ToString())).Value; Hash hash; switch (contract) { @@ -320,7 +320,7 @@ protected void DeployAllContracts() _ = TokenContractAddress; _ = TokenHolderContractAddress; _ = AssociationContractAddress; - _ = TestVoteContractAddress; + _ = VirtualFunctionContractAddress; } #endregion diff --git a/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj b/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj index c5333b816b..06df4dd4d9 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj +++ b/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj @@ -13,7 +13,7 @@ runtime; build; native; contentfiles; analyzers - + all @@ -75,10 +75,10 @@ Contract PreserveNewest - - - - + + + + false Contract @@ -99,9 +99,14 @@ Contract PreserveNewest - - - + + false + Contract + PreserveNewest + + + + @@ -222,5 +227,5 @@ - + diff --git a/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj b/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj index 4aaa89f9ca..81a2c1de7f 100644 --- a/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj +++ b/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj @@ -40,7 +40,7 @@ Contract PreserveNewest - + false Contract PreserveNewest @@ -59,8 +59,8 @@ - - Protobuf\Proto\test_election_vote_contract.proto + + Protobuf\Proto\test_virtual_function_contract.proto diff --git a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs index 70f3d330ef..f8c0b46469 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs @@ -6,7 +6,7 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Contracts.Profit; -using AElf.Contracts.TestContract.TestVote; +using AElf.Contracts.TestContract.VirtualFunction; using AElf.Contracts.Vote; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core; @@ -1910,7 +1910,7 @@ public async Task VirtualAddress_Vote_Test() var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); var candidateKeyPair = candidatesKeyPairs[0]; - var address = await TestVoteContractStub.GetVirtualAddress.CallAsync(new Empty()); + var address = await VirtualFunctionContractStub.GetVirtualAddress.CallAsync(new Empty()); var initBalance = 100000; await TokenContractStub.Transfer.SendAsync(new TransferInput @@ -1925,7 +1925,7 @@ await TokenContractStub.Transfer.SendAsync(new TransferInput CheckBalance(address, "SHARE", 0); CheckBalance(address, "VOTE", 0); - await TestVoteContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput + await VirtualFunctionContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput { PubKey = candidateKeyPair.PublicKey.ToHex(), Amount = amount, @@ -1953,7 +1953,7 @@ await TestVoteContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteIn CheckBalance(address, "SHARE", amount); CheckBalance(address, "VOTE", amount); - await TestVoteContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput + await VirtualFunctionContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput { PubKey = candidateKeyPair.PublicKey.ToHex(), Amount = amount, @@ -1990,13 +1990,13 @@ public async Task VirtualAddress_Withdraw_Test() var amount = 100; const int lockTime = 100 * 60 * 60 * 24; - var address = await TestVoteContractStub.GetVirtualAddress.CallAsync(new Empty()); + var address = await VirtualFunctionContractStub.GetVirtualAddress.CallAsync(new Empty()); var initBalance = 100000; var voteId = await VirtualAddress_Vote_Test(); BlockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddDays(101)); - await TestVoteContractStub.VirtualAddressWithdraw.SendAsync(new Hash + await VirtualFunctionContractStub.VirtualAddressWithdraw.SendAsync(new Hash { Value = voteId.Value }); diff --git a/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs b/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs index 74d0a5ff2f..0d1de742b4 100644 --- a/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs +++ b/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs @@ -5,7 +5,7 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Contracts.Profit; -using AElf.Contracts.TestContract.TestVote; +using AElf.Contracts.TestContract.VirtualFunction; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; using AElf.Contracts.Vote; @@ -57,8 +57,8 @@ protected ElectionContractTestBase() internal EconomicContractImplContainer.EconomicContractImplStub EconomicContractStub => GetEconomicContractTester(BootMinerKeyPair); - internal TestVoteContractContainer.TestVoteContractStub TestVoteContractStub => - GetTestVoteContractTester(BootMinerKeyPair); + internal VirtualFunctionContractContainer.VirtualFunctionContractStub VirtualFunctionContractStub => + GetVirtualFunctionContractTester(BootMinerKeyPair); private new void DeployAllContracts() { @@ -148,8 +148,8 @@ internal EconomicContractImplContainer.EconomicContractImplStub GetEconomicContr return GetTester(EconomicContractAddress, keyPair); } - internal TestVoteContractContainer.TestVoteContractStub GetTestVoteContractTester(ECKeyPair keyPair) + internal VirtualFunctionContractContainer.VirtualFunctionContractStub GetVirtualFunctionContractTester(ECKeyPair keyPair) { - return GetTester(TestVoteContractAddress, keyPair); + return GetTester(VirtualFunctionContractAddress, keyPair); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.TestVote/AElf.Contracts.TestContract.TestVote.csproj b/test/AElf.Contracts.TestContract.VirtualFunction/AElf.Contracts.TestContract.VirtualFunction.csproj similarity index 77% rename from test/AElf.Contracts.TestContract.TestVote/AElf.Contracts.TestContract.TestVote.csproj rename to test/AElf.Contracts.TestContract.VirtualFunction/AElf.Contracts.TestContract.VirtualFunction.csproj index b6b5047064..d1a4faf28d 100644 --- a/test/AElf.Contracts.TestContract.TestVote/AElf.Contracts.TestContract.TestVote.csproj +++ b/test/AElf.Contracts.TestContract.VirtualFunction/AElf.Contracts.TestContract.VirtualFunction.csproj @@ -2,15 +2,15 @@ net6.0 - AElf.Contracts.TestContract.TestVote - AElf.Contracts.TestContract.TestVote + AElf.Contracts.TestContract.VirtualFunction + AElf.Contracts.TestContract.VirtualFunction false - + Protobuf\Proto\authority_info.proto @@ -31,11 +31,11 @@ Protobuf\Proto\acs1.proto - + - - Protobuf\Proto\test_election_vote_contract.proto + + Protobuf\Proto\test_virtual_function_contract.proto - + diff --git a/test/AElf.Contracts.TestContract.TestVote/Action.cs b/test/AElf.Contracts.TestContract.VirtualFunction/Action.cs similarity index 89% rename from test/AElf.Contracts.TestContract.TestVote/Action.cs rename to test/AElf.Contracts.TestContract.VirtualFunction/Action.cs index f076f4ce21..2812c8688a 100644 --- a/test/AElf.Contracts.TestContract.TestVote/Action.cs +++ b/test/AElf.Contracts.TestContract.VirtualFunction/Action.cs @@ -3,9 +3,9 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.TestVote; +namespace AElf.Contracts.TestContract.VirtualFunction; -public class Action : TestVoteContractContainer.TestVoteContractBase +public class Action : VirtualFunctionContractContainer.VirtualFunctionContractBase { public override Empty VirtualAddressVote(VirtualAddressVoteInput input) { diff --git a/test/AElf.Contracts.TestContract.TestVote/ReferenceState.cs b/test/AElf.Contracts.TestContract.VirtualFunction/ReferenceState.cs similarity index 74% rename from test/AElf.Contracts.TestContract.TestVote/ReferenceState.cs rename to test/AElf.Contracts.TestContract.VirtualFunction/ReferenceState.cs index f69a59fc48..b908032f82 100644 --- a/test/AElf.Contracts.TestContract.TestVote/ReferenceState.cs +++ b/test/AElf.Contracts.TestContract.VirtualFunction/ReferenceState.cs @@ -1,6 +1,6 @@ using AElf.Contracts.Election; -namespace AElf.Contracts.TestContract.TestVote; +namespace AElf.Contracts.TestContract.VirtualFunction; public partial class State { diff --git a/test/AElf.Contracts.TestContract.TestVote/State.cs b/test/AElf.Contracts.TestContract.VirtualFunction/State.cs similarity index 59% rename from test/AElf.Contracts.TestContract.TestVote/State.cs rename to test/AElf.Contracts.TestContract.VirtualFunction/State.cs index 38d131befb..4feff66a06 100644 --- a/test/AElf.Contracts.TestContract.TestVote/State.cs +++ b/test/AElf.Contracts.TestContract.VirtualFunction/State.cs @@ -1,6 +1,6 @@ using AElf.Sdk.CSharp.State; -namespace AElf.Contracts.TestContract.TestVote; +namespace AElf.Contracts.TestContract.VirtualFunction; public partial class State : ContractState { From 75bc916546ca83282a2a61016050e829e95e41b0 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 21 Jun 2023 18:49:30 +0800 Subject: [PATCH 076/139] fix: GetTransactionFeeFreeAllowancesConfig --- contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index fec7f867e2..fbd68c30e9 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -1261,7 +1261,9 @@ public override Empty RemoveTransactionFeeFreeAllowancesConfig(RemoveTransaction public override GetTransactionFeeFreeAllowancesConfigOutput GetTransactionFeeFreeAllowancesConfig(Empty input) { - var symbols = State.TransactionFeeFreeAllowancesSymbolList.Value.Symbols; + var symbols = State.TransactionFeeFreeAllowancesSymbolList.Value?.Symbols; + if (symbols == null) return new GetTransactionFeeFreeAllowancesConfigOutput(); + var output = new GetTransactionFeeFreeAllowancesConfigOutput(); foreach (var symbol in symbols) From 855d28caec6fd6df1c30274970e8510f3608bca7 Mon Sep 17 00:00:00 2001 From: kevin Date: Sun, 25 Jun 2023 10:42:09 +0800 Subject: [PATCH 077/139] feat: add comments --- contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs | 7 +++++++ contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs | 1 + 2 files changed, 8 insertions(+) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index fbd68c30e9..95af5ec2c3 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -744,6 +744,7 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, TransactionFeeFreeAllowancesMap transactionFeeFreeAllowancesMap, out long amount, out string symbolOfValidBalance, out long existingBalance, out long existingAllowance) { + // priority: enough allowance -> symbolWithEnoughBalancePlusAllowance -> symbolWithEnoughBalance -> symbolWithAnything symbolOfValidBalance = null; string symbolWithAnything = null; string symbolWithEnoughBalance = null; @@ -761,6 +762,8 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, existingBalance = GetBalance(fromAddress, symbol); existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); + + // allowance is enough to cover the base fee if (existingAllowance >= amount) { symbolOfValidBalance = symbol; @@ -768,16 +771,20 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, } if (existingBalance.Add(existingAllowance) <= 0) continue; + + // find symbol: balance + allowance > 0 symbolWithAnything ??= symbol; if (existingBalance.Add(existingAllowance) < amount) continue; if (existingAllowance > 0) { + // find symbol: balance plus allowance is enough to cover the base fee and allowance is greater than 0 symbolWithEnoughBalancePlusAllowance ??= symbol; } else { + // find symbol: balance is enough to cover the base fee and no allowance symbolWithEnoughBalance ??= symbol; } } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 47b6af9f84..d50e8e83ca 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -94,6 +94,7 @@ private void ModifyFreeFeeAllowanceAmount(Address fromAddress, $"Insufficient amount of {symbol} for free fee allowance. Need amount: {-addAmount}; Current amount: {freeAllowanceAmount}"); } + // Sort symbols by expiration time var symbolList = GetSymbolListSortedByExpirationTime(transactionFeeFreeAllowancesMap, fromAddress); foreach (var s in symbolList) From dcdc751b38b8c14cf9552eca06e024713d74220d Mon Sep 17 00:00:00 2001 From: zhxymh Date: Sun, 25 Jun 2023 10:54:45 +0800 Subject: [PATCH 078/139] fix: file name --- .../Application/{IRandomHashProvider.cs => IRandomProvider.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/AElf.Kernel.Consensus.AEDPoS/Application/{IRandomHashProvider.cs => IRandomProvider.cs} (100%) diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomProvider.cs similarity index 100% rename from src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomHashProvider.cs rename to src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomProvider.cs From df7fd171efc47acf52c9bd1a53e1f8fa4b40e14d Mon Sep 17 00:00:00 2001 From: zhxymh Date: Sun, 25 Jun 2023 11:50:23 +0800 Subject: [PATCH 079/139] feat: add default gennesis block random hash --- .../Application/IRandomProvider.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomProvider.cs index cc6d15617e..bb891b4e20 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomProvider.cs @@ -23,8 +23,9 @@ public RandomProvider(IAEDPoSInformationProvider aedPoSInformationProvider, IAcc public async Task GenerateRandomProveAsync(IChainContext chainContext) { - var previousRandomHash = - await _aedPoSInformationProvider.GetRandomHashAsync(chainContext, chainContext.BlockHeight); + var previousRandomHash = chainContext.BlockHeight == AElfConstants.GenesisBlockHeight + ? Hash.Empty + : await _aedPoSInformationProvider.GetRandomHashAsync(chainContext, chainContext.BlockHeight); return await _accountService.ECVrfProveAsync(previousRandomHash.ToByteArray()); } } From 874a1008ef7e06ce99b6fd0d50c1bf2bbd79d489 Mon Sep 17 00:00:00 2001 From: kevin Date: Sun, 25 Jun 2023 14:14:07 +0800 Subject: [PATCH 080/139] fix: cr --- AElf.All.sln | 2 +- .../ElectionContractState.cs | 3 -- .../ElectionContract_Elector.cs | 11 +++---- .../AElf.Contracts.Election/ViewMethods.cs | 29 +++++++++++-------- .../AElf.Contracts.MultiToken.csproj | 3 ++ .../TokenContractReferenceState.cs | 2 ++ .../TokenContractState_ChargeFee.cs | 3 +- .../TokenContract_Helper.cs | 8 +++-- ...to => test_virtual_address_contract.proto} | 6 ++-- ...lf.Contracts.Consensus.AEDPoS.Tests.csproj | 2 +- .../AElf.Contracts.Economic.TestBase.csproj | 6 ++-- .../Contracts.cs | 2 +- .../ContractsPreparation.cs | 16 +++++----- ...AElf.Contracts.EconomicSystem.Tests.csproj | 2 +- .../AElf.Contracts.Election.Tests.csproj | 6 ++-- .../BVT/ElectionTests.cs | 12 ++++---- .../ElectionContractTestBase.cs | 10 +++---- ...tracts.TestContract.VirtualAddress.csproj} | 8 ++--- .../Action.cs | 4 +-- .../ReferenceState.cs | 2 +- .../State.cs | 2 +- 21 files changed, 74 insertions(+), 65 deletions(-) rename protobuf/{test_virtual_function_contract.proto => test_virtual_address_contract.proto} (85%) rename test/{AElf.Contracts.TestContract.VirtualFunction/AElf.Contracts.TestContract.VirtualFunction.csproj => AElf.Contracts.TestContract.VirtualAddress/AElf.Contracts.TestContract.VirtualAddress.csproj} (77%) rename test/{AElf.Contracts.TestContract.VirtualFunction => AElf.Contracts.TestContract.VirtualAddress}/Action.cs (89%) rename test/{AElf.Contracts.TestContract.VirtualFunction => AElf.Contracts.TestContract.VirtualAddress}/ReferenceState.cs (74%) rename test/{AElf.Contracts.TestContract.VirtualFunction => AElf.Contracts.TestContract.VirtualAddress}/State.cs (59%) diff --git a/AElf.All.sln b/AElf.All.sln index e4ded9d7ef..5e6703a3c2 100644 --- a/AElf.All.sln +++ b/AElf.All.sln @@ -369,7 +369,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps.UnitTes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract.csproj", "{AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.VirtualFunction", "test\AElf.Contracts.TestContract.VirtualFunction\AElf.Contracts.TestContract.VirtualFunction.csproj", "{64498F8C-B827-4E1C-B5FB-4B9188C839A8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.VirtualAddress", "test\AElf.Contracts.TestContract.VirtualAddress\AElf.Contracts.TestContract.VirtualAddress.csproj", "{64498F8C-B827-4E1C-B5FB-4B9188C839A8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/contract/AElf.Contracts.Election/ElectionContractState.cs b/contract/AElf.Contracts.Election/ElectionContractState.cs index fa6ebc6089..7e3a85731f 100644 --- a/contract/AElf.Contracts.Election/ElectionContractState.cs +++ b/contract/AElf.Contracts.Election/ElectionContractState.cs @@ -17,9 +17,6 @@ public partial class ElectionContractState : ContractState // Pubkey -> ElectorVote public MappedState ElectorVotes { get; set; } - - // Address -> ElectorVote - public MappedState ElectorVotesByAddress { get; set; } public MappedState CandidateVotes { get; set; } diff --git a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs index 8961baacdb..4b8762c8c1 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs @@ -514,15 +514,14 @@ private void UpdateElectorInformation(byte[] recoveredPublicKey, long amount, Ha voterVotes.ActiveVotingRecordIds.Add(voteId); voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Add(amount); voterVotes.AllVotedVotesAmount = voterVotes.AllVotedVotesAmount.Add(amount); - voterVotes.Address ??= Context.Sender; } - State.ElectorVotesByAddress[Context.Sender.ToBase58()] = voterVotes; + State.ElectorVotes[Context.Sender.ToBase58()] = voterVotes; } private ElectorVote GetElectorVote(byte[] recoveredPublicKey) { - var voteVotes = State.ElectorVotesByAddress[Context.Sender.ToBase58()]; + var voteVotes = State.ElectorVotes[Context.Sender.ToBase58()]; if (voteVotes != null) return voteVotes; if (recoveredPublicKey != null) @@ -533,6 +532,8 @@ private ElectorVote GetElectorVote(byte[] recoveredPublicKey) if (voteVotes != null) { + voteVotes.Address ??= Context.Sender; + State.ElectorVotes.Remove(publicKey); return voteVotes; } @@ -648,8 +649,8 @@ public override Empty Withdraw(Hash input) voterVotes!.ActiveVotingRecordIds.Remove(input); voterVotes.WithdrawnVotingRecordIds.Add(input); voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Sub(votingRecord.Amount); - voterVotes.Address ??= Context.Sender; - State.ElectorVotesByAddress[Context.Sender.ToBase58()] = voterVotes; + + State.ElectorVotes[Context.Sender.ToBase58()] = voterVotes; // Update Candidate's Votes information. var newestPubkey = GetNewestPubkey(votingRecord.Option); diff --git a/contract/AElf.Contracts.Election/ViewMethods.cs b/contract/AElf.Contracts.Election/ViewMethods.cs index 85315fbbd7..4535fb63b3 100644 --- a/contract/AElf.Contracts.Election/ViewMethods.cs +++ b/contract/AElf.Contracts.Election/ViewMethods.cs @@ -161,22 +161,12 @@ private TermSnapshot GetPreviousTermSnapshotWithNewestPubkey() public override ElectorVote GetElectorVote(StringValue input) { - Assert(input.Value != null && input.Value.Length > 1, "Invalid input."); - - var voterVotes = AddressHelper.VerifyFormattedAddress(input.Value) ? State.ElectorVotesByAddress[input.Value] : State.ElectorVotes[input.Value]; - - if (voterVotes == null) - { - voterVotes = State.ElectorVotesByAddress[ - Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(input.Value)).ToBase58()]; - } - - return voterVotes ?? new ElectorVote(); + return GetElectorVote(input.Value); } public override ElectorVote GetElectorVoteWithRecords(StringValue input) { - var votes = GetElectorVote(input); + var votes = GetElectorVote(input.Value); if (votes.Address == null && votes.Pubkey == null) return votes; @@ -195,6 +185,21 @@ public override ElectorVote GetElectorVoteWithRecords(StringValue input) return votes; } + private ElectorVote GetElectorVote(string value) + { + Assert(value != null && value.Length > 1, "Invalid input."); + + var voterVotes = State.ElectorVotes[value]; + + if (voterVotes == null) + { + voterVotes = State.ElectorVotes[ + Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(value)).ToBase58()]; + } + + return voterVotes ?? new ElectorVote(); + } + public override ElectorVote GetElectorVoteWithAllRecords(StringValue input) { var votes = GetElectorVoteWithRecords(input); diff --git a/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj b/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj index 44d6ef3422..6bf48ead5a 100644 --- a/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj +++ b/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj @@ -55,6 +55,9 @@ Protobuf\Proto\acs12.proto + + Protobuf\Proto\reference\election_contract.proto + diff --git a/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs b/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs index 05021eabd2..77d86f98f2 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs @@ -1,6 +1,7 @@ using AElf.Contracts.Association; using AElf.Contracts.Configuration; using AElf.Contracts.Consensus.AEDPoS; +using AElf.Contracts.Election; using AElf.Contracts.Parliament; using AElf.Contracts.Referendum; using AElf.Standards.ACS10; @@ -16,4 +17,5 @@ public partial class TokenContractState internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract { get; set; } internal ConfigurationContainer.ConfigurationReferenceState ConfigurationContract { get; set; } + internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs index 5c61f668c4..095c5417c1 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState_ChargeFee.cs @@ -34,8 +34,7 @@ public partial class TokenContractState /// Symbol -> Amount ///
public MappedState OwningRental { get; set; } - - public SingletonState
ElectionContractAddress { get; set; } + public SingletonState MethodFeeFreeAllowancesConfig { get; set; } public MappedState MethodFeeFreeAllowancesMap { get; set; } public MappedState MethodFeeFreeAllowancesLastRefreshTimeMap { get; set; } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 90270fa95c..e1cf3e871c 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -268,10 +268,12 @@ private void FireExternalLogEvent(TokenInfo tokenInfo, TransferFromInput input) private Address GetElectionContractAddress() { - if (State.ElectionContractAddress.Value == null) - State.ElectionContractAddress.Value = + if (State.ElectionContract.Value == null) + { + State.ElectionContract.Value = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); + } - return State.ElectionContractAddress.Value; + return State.ElectionContract.Value; } } \ No newline at end of file diff --git a/protobuf/test_virtual_function_contract.proto b/protobuf/test_virtual_address_contract.proto similarity index 85% rename from protobuf/test_virtual_function_contract.proto rename to protobuf/test_virtual_address_contract.proto index f5b10b5e1f..b8f9a561aa 100644 --- a/protobuf/test_virtual_function_contract.proto +++ b/protobuf/test_virtual_address_contract.proto @@ -7,10 +7,10 @@ import "google/protobuf/empty.proto"; import "google/protobuf/wrappers.proto"; import "acs1.proto"; -option csharp_namespace = "AElf.Contracts.TestContract.VirtualFunction"; +option csharp_namespace = "AElf.Contracts.TestContract.VirtualAddress"; -service VirtualFunctionContract { - option (aelf.csharp_state) = "AElf.Contracts.TestContract.VirtualFunction.State"; +service VirtualAddressContract { + option (aelf.csharp_state) = "AElf.Contracts.TestContract.VirtualAddress.State"; option (aelf.base) = "acs1.proto"; rpc VirtualAddressVote(VirtualAddressVoteInput) returns (google.protobuf.Empty); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj index ad1d5e89fb..f9397a21b3 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AElf.Contracts.Consensus.AEDPoS.Tests.csproj @@ -43,7 +43,7 @@ Contract PreserveNewest - + false Contract PreserveNewest diff --git a/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj b/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj index 70a01de0e0..c0b204fe14 100644 --- a/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj +++ b/test/AElf.Contracts.Economic.TestBase/AElf.Contracts.Economic.TestBase.csproj @@ -99,7 +99,7 @@ Contract PreserveNewest - + false Contract PreserveNewest @@ -184,8 +184,8 @@ Protobuf\Proto\parliament_contract_impl.proto - - Protobuf\Proto\test_virtual_function_contract.proto + + Protobuf\Proto\test_virtual_address_contract.proto diff --git a/test/AElf.Contracts.Economic.TestBase/Contracts.cs b/test/AElf.Contracts.Economic.TestBase/Contracts.cs index 6990378a99..2bd259d94a 100644 --- a/test/AElf.Contracts.Economic.TestBase/Contracts.cs +++ b/test/AElf.Contracts.Economic.TestBase/Contracts.cs @@ -27,7 +27,7 @@ public enum TestContracts BasicUpdate, MethodCallThreshold, ResourceSpender, - VirtualFunction + VirtualAddress } public enum ProfitType diff --git a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs index e383e2d9ba..15477b851a 100644 --- a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs +++ b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs @@ -10,7 +10,7 @@ using AElf.Contracts.Parliament; using AElf.Contracts.Profit; using AElf.Contracts.TestContract.MethodCallThreshold; -using AElf.Contracts.TestContract.VirtualFunction; +using AElf.Contracts.TestContract.VirtualAddress; using AElf.Contracts.TestContract.TransactionFeeCharging; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; @@ -104,8 +104,8 @@ public partial class EconomicContractsTestBase protected Address ConfigurationAddress => GetOrDeployContract(Contracts.Configuration, ref _configurationAddress); - private Address _virtualFunctionContractAddress; - protected Address VirtualFunctionContractAddress => GetOrDeployContract(TestContracts.VirtualFunction, ref _virtualFunctionContractAddress); + private Address _virtualAddressContractAddress; + protected Address VirtualAddressContractAddress => GetOrDeployContract(TestContracts.VirtualAddress, ref _virtualAddressContractAddress); #endregion @@ -149,8 +149,8 @@ internal TransactionFeeChargingContractContainer.TransactionFeeChargingContractS internal ConfigurationContainer.ConfigurationStub ConfigurationStub => GetConfigurationContractTester(BootMinerKeyPair); - internal VirtualFunctionContractContainer.VirtualFunctionContractStub VirtualFunctionContractStub => - GetVirtualFunctionContractTester(BootMinerKeyPair); + internal VirtualAddressContractContainer.VirtualAddressContractStub VirtualAddressContractStub => + GetVirtualAddressContractTester(BootMinerKeyPair); #endregion @@ -231,9 +231,9 @@ internal ConfigurationContainer.ConfigurationStub GetConfigurationContractTester return GetTester(ConfigurationAddress, keyPair); } - internal VirtualFunctionContractContainer.VirtualFunctionContractStub GetVirtualFunctionContractTester(ECKeyPair keyPair) + internal VirtualAddressContractContainer.VirtualAddressContractStub GetVirtualAddressContractTester(ECKeyPair keyPair) { - return GetTester(VirtualFunctionContractAddress, keyPair); + return GetTester(VirtualAddressContractAddress, keyPair); } #endregion @@ -320,7 +320,7 @@ protected void DeployAllContracts() _ = TokenContractAddress; _ = TokenHolderContractAddress; _ = AssociationContractAddress; - _ = VirtualFunctionContractAddress; + _ = VirtualAddressContractAddress; } #endregion diff --git a/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj b/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj index 06df4dd4d9..dbad41ec40 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj +++ b/test/AElf.Contracts.EconomicSystem.Tests/AElf.Contracts.EconomicSystem.Tests.csproj @@ -99,7 +99,7 @@ Contract PreserveNewest - + false Contract PreserveNewest diff --git a/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj b/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj index 81a2c1de7f..e472065cfe 100644 --- a/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj +++ b/test/AElf.Contracts.Election.Tests/AElf.Contracts.Election.Tests.csproj @@ -40,7 +40,7 @@ Contract PreserveNewest - + false Contract PreserveNewest @@ -59,8 +59,8 @@ - - Protobuf\Proto\test_virtual_function_contract.proto + + Protobuf\Proto\test_virtual_address_contract.proto diff --git a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs index f8c0b46469..2ba363f220 100644 --- a/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs +++ b/test/AElf.Contracts.Election.Tests/BVT/ElectionTests.cs @@ -6,7 +6,7 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Contracts.Profit; -using AElf.Contracts.TestContract.VirtualFunction; +using AElf.Contracts.TestContract.VirtualAddress; using AElf.Contracts.Vote; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core; @@ -1910,7 +1910,7 @@ public async Task VirtualAddress_Vote_Test() var candidatesKeyPairs = await ElectionContract_AnnounceElection_Test(); var candidateKeyPair = candidatesKeyPairs[0]; - var address = await VirtualFunctionContractStub.GetVirtualAddress.CallAsync(new Empty()); + var address = await VirtualAddressContractStub.GetVirtualAddress.CallAsync(new Empty()); var initBalance = 100000; await TokenContractStub.Transfer.SendAsync(new TransferInput @@ -1925,7 +1925,7 @@ await TokenContractStub.Transfer.SendAsync(new TransferInput CheckBalance(address, "SHARE", 0); CheckBalance(address, "VOTE", 0); - await VirtualFunctionContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput + await VirtualAddressContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput { PubKey = candidateKeyPair.PublicKey.ToHex(), Amount = amount, @@ -1953,7 +1953,7 @@ await VirtualFunctionContractStub.VirtualAddressVote.SendAsync(new VirtualAddres CheckBalance(address, "SHARE", amount); CheckBalance(address, "VOTE", amount); - await VirtualFunctionContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput + await VirtualAddressContractStub.VirtualAddressVote.SendAsync(new VirtualAddressVoteInput { PubKey = candidateKeyPair.PublicKey.ToHex(), Amount = amount, @@ -1990,13 +1990,13 @@ public async Task VirtualAddress_Withdraw_Test() var amount = 100; const int lockTime = 100 * 60 * 60 * 24; - var address = await VirtualFunctionContractStub.GetVirtualAddress.CallAsync(new Empty()); + var address = await VirtualAddressContractStub.GetVirtualAddress.CallAsync(new Empty()); var initBalance = 100000; var voteId = await VirtualAddress_Vote_Test(); BlockTimeProvider.SetBlockTime(TimestampHelper.GetUtcNow().AddDays(101)); - await VirtualFunctionContractStub.VirtualAddressWithdraw.SendAsync(new Hash + await VirtualAddressContractStub.VirtualAddressWithdraw.SendAsync(new Hash { Value = voteId.Value }); diff --git a/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs b/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs index 0d1de742b4..6ba094c35d 100644 --- a/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs +++ b/test/AElf.Contracts.Election.Tests/ElectionContractTestBase.cs @@ -5,7 +5,7 @@ using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Contracts.Profit; -using AElf.Contracts.TestContract.VirtualFunction; +using AElf.Contracts.TestContract.VirtualAddress; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; using AElf.Contracts.Vote; @@ -57,8 +57,8 @@ protected ElectionContractTestBase() internal EconomicContractImplContainer.EconomicContractImplStub EconomicContractStub => GetEconomicContractTester(BootMinerKeyPair); - internal VirtualFunctionContractContainer.VirtualFunctionContractStub VirtualFunctionContractStub => - GetVirtualFunctionContractTester(BootMinerKeyPair); + internal VirtualAddressContractContainer.VirtualAddressContractStub VirtualAddressContractStub => + GetVirtualAddressContractTester(BootMinerKeyPair); private new void DeployAllContracts() { @@ -148,8 +148,8 @@ internal EconomicContractImplContainer.EconomicContractImplStub GetEconomicContr return GetTester(EconomicContractAddress, keyPair); } - internal VirtualFunctionContractContainer.VirtualFunctionContractStub GetVirtualFunctionContractTester(ECKeyPair keyPair) + internal VirtualAddressContractContainer.VirtualAddressContractStub GetVirtualAddressContractTester(ECKeyPair keyPair) { - return GetTester(VirtualFunctionContractAddress, keyPair); + return GetTester(VirtualAddressContractAddress, keyPair); } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.VirtualFunction/AElf.Contracts.TestContract.VirtualFunction.csproj b/test/AElf.Contracts.TestContract.VirtualAddress/AElf.Contracts.TestContract.VirtualAddress.csproj similarity index 77% rename from test/AElf.Contracts.TestContract.VirtualFunction/AElf.Contracts.TestContract.VirtualFunction.csproj rename to test/AElf.Contracts.TestContract.VirtualAddress/AElf.Contracts.TestContract.VirtualAddress.csproj index d1a4faf28d..d480fbc720 100644 --- a/test/AElf.Contracts.TestContract.VirtualFunction/AElf.Contracts.TestContract.VirtualFunction.csproj +++ b/test/AElf.Contracts.TestContract.VirtualAddress/AElf.Contracts.TestContract.VirtualAddress.csproj @@ -2,8 +2,8 @@ net6.0 - AElf.Contracts.TestContract.VirtualFunction - AElf.Contracts.TestContract.VirtualFunction + AElf.Contracts.TestContract.VirtualAddress + AElf.Contracts.TestContract.VirtualAddress false @@ -33,8 +33,8 @@ - - Protobuf\Proto\test_virtual_function_contract.proto + + Protobuf\Proto\test_virtual_address_contract.proto diff --git a/test/AElf.Contracts.TestContract.VirtualFunction/Action.cs b/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs similarity index 89% rename from test/AElf.Contracts.TestContract.VirtualFunction/Action.cs rename to test/AElf.Contracts.TestContract.VirtualAddress/Action.cs index 2812c8688a..2ce59acaed 100644 --- a/test/AElf.Contracts.TestContract.VirtualFunction/Action.cs +++ b/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs @@ -3,9 +3,9 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.VirtualFunction; +namespace AElf.Contracts.TestContract.VirtualAddress; -public class Action : VirtualFunctionContractContainer.VirtualFunctionContractBase +public class Action : VirtualAddressContractContainer.VirtualAddressContractBase { public override Empty VirtualAddressVote(VirtualAddressVoteInput input) { diff --git a/test/AElf.Contracts.TestContract.VirtualFunction/ReferenceState.cs b/test/AElf.Contracts.TestContract.VirtualAddress/ReferenceState.cs similarity index 74% rename from test/AElf.Contracts.TestContract.VirtualFunction/ReferenceState.cs rename to test/AElf.Contracts.TestContract.VirtualAddress/ReferenceState.cs index b908032f82..677e3c5e4c 100644 --- a/test/AElf.Contracts.TestContract.VirtualFunction/ReferenceState.cs +++ b/test/AElf.Contracts.TestContract.VirtualAddress/ReferenceState.cs @@ -1,6 +1,6 @@ using AElf.Contracts.Election; -namespace AElf.Contracts.TestContract.VirtualFunction; +namespace AElf.Contracts.TestContract.VirtualAddress; public partial class State { diff --git a/test/AElf.Contracts.TestContract.VirtualFunction/State.cs b/test/AElf.Contracts.TestContract.VirtualAddress/State.cs similarity index 59% rename from test/AElf.Contracts.TestContract.VirtualFunction/State.cs rename to test/AElf.Contracts.TestContract.VirtualAddress/State.cs index 4feff66a06..75d9d72646 100644 --- a/test/AElf.Contracts.TestContract.VirtualFunction/State.cs +++ b/test/AElf.Contracts.TestContract.VirtualAddress/State.cs @@ -1,6 +1,6 @@ using AElf.Sdk.CSharp.State; -namespace AElf.Contracts.TestContract.VirtualFunction; +namespace AElf.Contracts.TestContract.VirtualAddress; public partial class State : ContractState { From 39d8163bf00aa36297637fc334bbe280dede3aee Mon Sep 17 00:00:00 2001 From: kevin Date: Sun, 25 Jun 2023 14:42:51 +0800 Subject: [PATCH 081/139] fix: cr --- .../ElectionContract_Elector.cs | 12 ++++++------ contract/AElf.Contracts.Election/ViewMethods.cs | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs index 4b8762c8c1..d524390f92 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs @@ -521,21 +521,21 @@ private void UpdateElectorInformation(byte[] recoveredPublicKey, long amount, Ha private ElectorVote GetElectorVote(byte[] recoveredPublicKey) { - var voteVotes = State.ElectorVotes[Context.Sender.ToBase58()]; - if (voteVotes != null) return voteVotes; + var voterVotes = State.ElectorVotes[Context.Sender.ToBase58()]; + if (voterVotes != null) return voterVotes; if (recoveredPublicKey != null) { var publicKey = recoveredPublicKey.ToHex(); - voteVotes = State.ElectorVotes[publicKey]?.Clone(); + voterVotes = State.ElectorVotes[publicKey]?.Clone(); - if (voteVotes != null) + if (voterVotes != null) { - voteVotes.Address ??= Context.Sender; + voterVotes.Address ??= Context.Sender; State.ElectorVotes.Remove(publicKey); - return voteVotes; + return voterVotes; } } diff --git a/contract/AElf.Contracts.Election/ViewMethods.cs b/contract/AElf.Contracts.Election/ViewMethods.cs index 4535fb63b3..f1996fa4cb 100644 --- a/contract/AElf.Contracts.Election/ViewMethods.cs +++ b/contract/AElf.Contracts.Election/ViewMethods.cs @@ -193,6 +193,8 @@ private ElectorVote GetElectorVote(string value) if (voterVotes == null) { + if (AddressHelper.VerifyFormattedAddress(value)) return new ElectorVote(); + voterVotes = State.ElectorVotes[ Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(value)).ToBase58()]; } From 15df0a01ea50d0971919958593e669e9729409da Mon Sep 17 00:00:00 2001 From: kevin Date: Sun, 25 Jun 2023 14:55:39 +0800 Subject: [PATCH 082/139] fix: cr --- contract/AElf.Contracts.Election/ViewMethods.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contract/AElf.Contracts.Election/ViewMethods.cs b/contract/AElf.Contracts.Election/ViewMethods.cs index f1996fa4cb..ef8735b3d5 100644 --- a/contract/AElf.Contracts.Election/ViewMethods.cs +++ b/contract/AElf.Contracts.Election/ViewMethods.cs @@ -191,10 +191,8 @@ private ElectorVote GetElectorVote(string value) var voterVotes = State.ElectorVotes[value]; - if (voterVotes == null) + if (voterVotes == null && !AddressHelper.VerifyFormattedAddress(value)) { - if (AddressHelper.VerifyFormattedAddress(value)) return new ElectorVote(); - voterVotes = State.ElectorVotes[ Address.FromPublicKey(ByteArrayHelper.HexStringToByteArray(value)).ToBase58()]; } From cd8b84feff5c5b4221e02bfaa19711e4a8e91082 Mon Sep 17 00:00:00 2001 From: kevin Date: Sun, 25 Jun 2023 17:10:25 +0800 Subject: [PATCH 083/139] fix: TryToChargeUserBaseFee --- contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 95af5ec2c3..365702b256 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -762,6 +762,8 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, existingBalance = GetBalance(fromAddress, symbol); existingAllowance = GetFreeFeeAllowanceAmount(transactionFeeFreeAllowancesMap, symbol); + var existingBalancePlusAllowance = existingBalance.Add(existingAllowance); + // allowance is enough to cover the base fee if (existingAllowance >= amount) @@ -770,12 +772,12 @@ private bool TryToChargeUserBaseFee(Dictionary symbolToAmountMap, return true; } - if (existingBalance.Add(existingAllowance) <= 0) continue; + if (existingBalancePlusAllowance <= 0) continue; // find symbol: balance + allowance > 0 symbolWithAnything ??= symbol; - if (existingBalance.Add(existingAllowance) < amount) continue; + if (existingBalancePlusAllowance < amount) continue; if (existingAllowance > 0) { From 0a2a19de9a329c5d38fbdf26b16b1ebce7c9e12e Mon Sep 17 00:00:00 2001 From: zhxymh Date: Sun, 25 Jun 2023 18:14:45 +0800 Subject: [PATCH 084/139] feat: improve TransactionFeeClaimed event --- contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 0aa309fe12..9d33414e2d 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -674,13 +674,14 @@ public override Empty ClaimTransactionFees(TotalTransactionFeesMap input) var symbol = bill.Key; var amount = bill.Value; ModifyBalance(Context.Self, symbol, amount); - TransferTransactionFeesToFeeReceiver(symbol, amount); Context.Fire(new TransactionFeeClaimed { Symbol = symbol, Amount = amount, Receiver = Context.Self }); + + TransferTransactionFeesToFeeReceiver(symbol, amount); } Context.LogDebug(() => "Finish claim transaction fee."); From 4541e4a9f883e219f3f70161835875dc55a844d1 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Sun, 25 Jun 2023 20:41:59 +0800 Subject: [PATCH 085/139] feat: cr. --- .../TokenContract_Delegation.cs | 14 +++++++------- .../TokenContract_Helper.cs | 5 ----- protobuf/token_contract_impl.proto | 4 ++-- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs index 6f9cae0ae9..6607479b3a 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs @@ -207,8 +207,8 @@ public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateIn //If isUnlimitedDelegate is false,delegate info list should > 0. Assert(delegateInfo.IsUnlimitedDelegate || delegateInfo.Delegations.Count > 0, "Delegation cannot be null."); - Assert(delegateInfo.ContractAddress != null && !string.IsNullOrEmpty(delegateInfo.MethodName) && - delegateInfo.MethodName.All(IsValidMethodNameChar), "Invalid contract address and method name."); + Assert(delegateInfo.ContractAddress != null && !string.IsNullOrEmpty(delegateInfo.MethodName), + "Invalid contract address and method name."); var existDelegateeInfoList = State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateInfo.ContractAddress] [delegateInfo.MethodName] ?? new TransactionFeeDelegatees(); @@ -221,7 +221,7 @@ public override Empty SetTransactionFeeDelegateInfos(SetTransactionFeeDelegateIn } //else,add new delegate info. else { - Assert(existDelegateeList.Count <= TokenContractConstants.DELEGATEE_MAX_COUNT, + Assert(existDelegateeList.Count < TokenContractConstants.DELEGATEE_MAX_COUNT, "The quantity of delegatee has reached its limit"); existDelegateeList.Add(delegateeAddress, new TransactionFeeDelegations()); var transactionFeeDelegations = existDelegateeList[delegateeAddress]; @@ -371,8 +371,8 @@ private void RemoveTransactionFeeDelegateInfo(List delegate var toCancelTransactionList = new DelegateTransactionList(); foreach (var delegateTransaction in delegateTransactionList.Distinct()) { - Assert(delegateTransaction.ContractAddress != null && !string.IsNullOrEmpty(delegateTransaction.MethodName) && - delegateTransaction.MethodName.All(IsValidMethodNameChar), "Invalid contract address and method name."); + Assert(delegateTransaction.ContractAddress != null && !string.IsNullOrEmpty(delegateTransaction.MethodName), + "Invalid contract address and method name."); var delegateeInfo = State.TransactionFeeDelegateInfoMap[delegatorAddress][delegateTransaction.ContractAddress][ delegateTransaction.MethodName]; @@ -414,8 +414,8 @@ public override GetTransactionFeeDelegateeListOutput GetTransactionFeeDelegateeL }; } - public override TransactionFeeDelegations GetTransactionFeeDelegateInfosOfADelegatee( - GetTransactionFeeDelegateInfosOfADelegateeInput input) + public override TransactionFeeDelegations GetTransactionFeeDelegateInfo( + GetTransactionFeeDelegateInfoInput input) { var allDelegatees = State.TransactionFeeDelegateInfoMap[input.DelegatorAddress][input.ContractAddress][input.MethodName]; diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index ad6f8d5fb1..d11e25b7de 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -27,11 +27,6 @@ private bool IsValidCreateSymbolChar(char character) { return character >= 'A' && character <= 'Z'; } - - private bool IsValidMethodNameChar(char character) - { - return (character >= 'A' && character <= 'Z') || (character >= 'a' && character <= 'z') || (character >= '0' && character <= '9'); - } private TokenInfo AssertValidToken(string symbol, long amount) { diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index ce5346b9b3..fe2d898d9c 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -146,7 +146,7 @@ service TokenContractImpl { option (aelf.is_view) = true; } // Get delegation according to the delegator,transaction and delegatee. - rpc GetTransactionFeeDelegateInfosOfADelegatee(GetTransactionFeeDelegateInfosOfADelegateeInput) returns (token.TransactionFeeDelegations){ + rpc GetTransactionFeeDelegateInfo(GetTransactionFeeDelegateInfoInput) returns (token.TransactionFeeDelegations){ option (aelf.is_view) = true; } } @@ -302,7 +302,7 @@ message RemoveTransactionFeeDelegateeInfosInput { repeated DelegateTransaction delegate_transaction_list = 2; } -message GetTransactionFeeDelegateInfosOfADelegateeInput { +message GetTransactionFeeDelegateInfoInput { aelf.Address delegator_address = 1; aelf.Address delegatee_address = 2; aelf.Address contract_address = 3; From ee2f7885fe740e80fe2cc9091d9ad32501b4f666 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Sun, 25 Jun 2023 21:21:43 +0800 Subject: [PATCH 086/139] feat: failed ut. --- .../BVT/TokenDelegationTest.cs | 211 +++++++----------- .../ExecutePluginTransactionDirectlyTest.cs | 108 ++++----- 2 files changed, 131 insertions(+), 188 deletions(-) diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs index a257a763ed..4d6b1bb937 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs @@ -360,8 +360,8 @@ public async Task SetDelegateInfos_NewDelegate_Success_Test() DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo3 } }); { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -374,8 +374,8 @@ public async Task SetDelegateInfos_NewDelegate_Success_Test() delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -387,8 +387,8 @@ public async Task SetDelegateInfos_NewDelegate_Success_Test() delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -454,8 +454,8 @@ public async Task SetDelegateInfos_NewOrUpdateDelegate_Success_Test() DelegateInfoList = { delegateInfo1,delegateInfo2 } }); { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicContractZeroAddress, DelegatorAddress = User1Address, @@ -468,8 +468,8 @@ public async Task SetDelegateInfos_NewOrUpdateDelegate_Success_Test() delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -554,8 +554,8 @@ await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransact DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo3,delegateInfo4 } }); { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -569,8 +569,8 @@ await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransact delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -582,8 +582,8 @@ await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransact delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -596,8 +596,8 @@ await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransact delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicContractZeroAddress, DelegatorAddress = User1Address, @@ -665,8 +665,8 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test( DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo3 } }); { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -680,8 +680,8 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test( delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -694,8 +694,8 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegation_Success_Test( delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicContractZeroAddress, DelegatorAddress = User1Address, @@ -772,8 +772,8 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegateInfo_Success_Tes delegateeAddress.DelegateeAddresses.Count.ShouldBe(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -793,8 +793,8 @@ public async Task SetDelegateInfos_UpdateDelegate_RemoveDelegateInfo_Success_Tes delegateeAddress.DelegateeAddresses.Count.ShouldBe(1); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -877,8 +877,8 @@ public async Task SetDelegateInfos_AddOrUpdateOrRemoveDelegate_Success_Test() DelegateInfoList = { delegateInfo1,delegateInfo2,delegateInfo4,delegateInfo5 } }); { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -892,8 +892,8 @@ public async Task SetDelegateInfos_AddOrUpdateOrRemoveDelegate_Success_Test() delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -905,8 +905,8 @@ public async Task SetDelegateInfos_AddOrUpdateOrRemoveDelegate_Success_Test() delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -918,8 +918,8 @@ public async Task SetDelegateInfos_AddOrUpdateOrRemoveDelegate_Success_Test() delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicContractZeroAddress, DelegatorAddress = User1Address, @@ -990,8 +990,8 @@ await TokenContractStubDelegate.SetTransactionFeeDelegateInfos.SendAsync(new Set DelegateInfoList = { delegateInfo1 } }); { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -1004,8 +1004,8 @@ await TokenContractStubDelegate.SetTransactionFeeDelegateInfos.SendAsync(new Set delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -1064,8 +1064,8 @@ await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransact DelegateInfoList = { delegateInfo1 } }); { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -1078,8 +1078,8 @@ await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransact delegateInfoOfADelegatee.BlockHeight.ShouldBeGreaterThan(0); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User2Address, @@ -1156,8 +1156,8 @@ await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransact }); } { - var transactionFeeDelegation = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionFeeDelegation = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, MethodName = "test1", @@ -1207,64 +1207,7 @@ await TokenContractStub.SetTransactionFeeDelegateInfos.SendAsync(new SetTransact executionResult.TransactionResult.Error.ShouldContain("Delegator address and delegate info cannot be null."); } } - - [Fact] - public async Task SetDelegateInfos_InvalidMethodName_Failed_Test() - { - await Initialize(); - var delegations1 = new Dictionary - { - [NativeToken] = 1000, - [BasicFeeSymbol] = 500, - [SizeFeeSymbol] = 100 - }; - var delegateInfo = new DelegateInfo - { - ContractAddress = BasicFunctionContractAddress, - MethodName = "test1-0", - Delegations = { delegations1 }, - IsUnlimitedDelegate = false - }; - var delegateInfo1 = new DelegateInfo - { - ContractAddress = BasicFunctionContractAddress, - MethodName = "test1@0", - Delegations = { delegations1 }, - IsUnlimitedDelegate = false - }; - var delegateInfo2 = new DelegateInfo - { - ContractAddress = BasicFunctionContractAddress, - MethodName = "@#¥%Z……", - Delegations = { delegations1 }, - IsUnlimitedDelegate = false - }; - { - var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = User1Address, - DelegateInfoList = { delegateInfo } - }); - executionResult.TransactionResult.Error.ShouldContain("Invalid contract address and method name."); - } - { - var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = User1Address, - DelegateInfoList = { delegateInfo1 } - }); - executionResult.TransactionResult.Error.ShouldContain("Invalid contract address and method name."); - } - { - var executionResult = await TokenContractStub.SetTransactionFeeDelegateInfos.SendWithExceptionAsync(new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = User1Address, - DelegateInfoList = { delegateInfo2 } - }); - executionResult.TransactionResult.Error.ShouldContain("Invalid contract address and method name."); - } - - } + [Fact] public async Task RemoveTransactionFeeDelegateeInfos_Success_Test() { @@ -1290,8 +1233,8 @@ await TokenContractStubDelegate.SetTransactionFeeDelegateInfos.SendAsync(new Set DelegateInfoList = { delegateInfo1 } }); { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -1322,8 +1265,8 @@ await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new Rem DelegateTransactionList = { delegationTransactionList } }); { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -1333,8 +1276,8 @@ await TokenContractStubUser.RemoveTransactionFeeDelegateeInfos.SendAsync(new Rem delegateInfoOfADelegatee.ShouldBe(new TransactionFeeDelegations()); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -1375,8 +1318,8 @@ public async Task RemoveTransactionFeeDelegateeInfos_SingleTransaction_Success_T DelegateTransactionList = { delegationTransactionList } }); { - var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, MethodName = "test1", @@ -1428,8 +1371,8 @@ public async Task RemoveTransactionFeeDelegateeInfos_MultiTransaction_Success_Te DelegateTransactionList = { delegationTransactionList } }); { - var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, MethodName = "test1", @@ -1439,8 +1382,8 @@ public async Task RemoveTransactionFeeDelegateeInfos_MultiTransaction_Success_Te transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); } { - var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicContractZeroAddress, MethodName = "test1", @@ -1504,8 +1447,8 @@ public async Task RemoveTransactionFeeDelegateeInfos_NotExistTransaction_Success DelegateTransactionList = { delegationTransactionList } }); { - var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = TokenContractAddress, MethodName = "transfer", @@ -1525,8 +1468,8 @@ public async Task RemoveTransactionFeeDelegateeInfos_NotExistTransaction_Success delegateeList.DelegateeAddresses.Count.ShouldBe(0); } { - var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = TokenContractAddress, MethodName = "transfer", @@ -1616,8 +1559,8 @@ await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendAsync(new RemoveT DelegateTransactionList = { delegationTransactionList } }); { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -1627,8 +1570,8 @@ await TokenContractStub.RemoveTransactionFeeDelegatorInfos.SendAsync(new RemoveT delegateInfoOfADelegatee.ShouldBe(new TransactionFeeDelegations()); } { - var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegateInfoOfADelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, DelegatorAddress = User1Address, @@ -1668,8 +1611,8 @@ public async Task RemoveTransactionFeeDelegatorInfos_SingleTransaction_Success_T DelegateTransactionList = { delegationTransactionList } }); { - var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, MethodName = "test1", @@ -1721,8 +1664,8 @@ public async Task RemoveTransactionFeeDelegatorInfos_MultiTransaction_Success_Te DelegateTransactionList = { delegationTransactionList } }); { - var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicFunctionContractAddress, MethodName = "test1", @@ -1732,8 +1675,8 @@ public async Task RemoveTransactionFeeDelegatorInfos_MultiTransaction_Success_Te transactionDelegatee.ShouldBe(new TransactionFeeDelegations()); } { - var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = BasicContractZeroAddress, MethodName = "test1", @@ -1797,8 +1740,8 @@ public async Task RemoveTransactionFeeDelegatorInfos_NotExistTransaction_Success DelegateTransactionList = { delegationTransactionList } }); { - var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = TokenContractAddress, MethodName = "transfer", @@ -1818,8 +1761,8 @@ public async Task RemoveTransactionFeeDelegatorInfos_NotExistTransaction_Success delegateeList.DelegateeAddresses.Count.ShouldBe(0); } { - var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var transactionDelegatee = await TokenContractStub.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { ContractAddress = TokenContractAddress, MethodName = "transfer", diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 04b3d8c760..48c31ceb32 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -1089,8 +1089,8 @@ public async Task ChargeTransactionFee_DelegateNew_First( DelegateInfoList = { delegateInfo4 } }); { - var result = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var result = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, @@ -1101,8 +1101,8 @@ public async Task ChargeTransactionFee_DelegateNew_First( result.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); } - var delegationsBefore = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegationsBefore = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = userAddress, @@ -1113,8 +1113,8 @@ public async Task ChargeTransactionFee_DelegateNew_First( delegationsBefore.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); - var delegationBefore2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegationBefore2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = userAddress, @@ -1125,8 +1125,8 @@ public async Task ChargeTransactionFee_DelegateNew_First( delegationBefore2.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); { - var result = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var result = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = UserTomSender, @@ -1208,8 +1208,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }); afterBalance.Balance.ShouldBe(0); } - var delegationsAfter = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegationsAfter = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = userAddress, @@ -1220,8 +1220,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, delegationsAfter.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); - var delegationAfter2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegationAfter2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, @@ -1232,8 +1232,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, delegationAfter2.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); { var delegationResult = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, @@ -1259,8 +1259,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call Owner = DelegateeAddress }); afterDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, @@ -1273,8 +1273,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call { chargeFeeRetDefault.Output.Success.ShouldBe(false); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, @@ -1364,8 +1364,8 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( }; chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); var delegationResult = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, @@ -1373,8 +1373,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); var delegationResult2 = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -1409,8 +1409,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call Owner = Delegatee2Address }); afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -1423,8 +1423,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call { chargeFeeRetDefault.Output.Success.ShouldBe(false); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, @@ -1432,8 +1432,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); delegation.Delegations[NativeTokenSymbol].ShouldBe(5); - var delegation2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -1522,8 +1522,8 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( }; chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); var delegationResult = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = DelegateeAddress, DelegatorAddress = DefaultSender, @@ -1531,8 +1531,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); var delegationResult2 = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -1569,8 +1569,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call Owner = Delegatee2Address }); afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -1687,8 +1687,8 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( Owner = Delegatee2Address }); afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -1800,8 +1800,8 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( Owner = Delegatee2Address }); afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -1889,8 +1889,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAs DelegatorAddress = DefaultSender }); var delegationResult2 = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -1925,8 +1925,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call Owner = Delegatee2Address }); afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -1946,8 +1946,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call DelegatorAddress = DefaultSender }); delegation.Delegations[NativeTokenSymbol].ShouldBe(5); - var delegation2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -2028,8 +2028,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAs DelegatorAddress = DefaultSender }); var delegationResult2 = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = Delegatee2Address, DelegatorAddress = DelegateeAddress, @@ -2245,8 +2245,8 @@ await TokenContractStubSecondaryDelegate6.SetTransactionFeeDelegateInfos.SendAsy await CheckUserBalanceAsync(basicFeeSymbol, SecondaryDelegatee5Address, 120); await CheckUserBalanceAsync(NativeTokenSymbol, SecondaryDelegatee6Address, 100); var delegateInfo = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = SecondaryDelegatee5Address, DelegatorAddress = Delegatee2Address, @@ -2254,8 +2254,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); delegateInfo.Delegations[basicFeeSymbol].ShouldBe(20); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = SecondaryDelegatee3Address, DelegatorAddress = DelegateeAddress, @@ -2269,8 +2269,8 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.Call { chargeFeeRetDefault.Output.Success.ShouldBe(false); var delegateInfo = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = SecondaryDelegatee5Address, DelegatorAddress = Delegatee2Address, @@ -2296,8 +2296,8 @@ private async Task GetSetDelegationResultAsync(List<(Address, Address)> de foreach (var (delegateeAddress, delegatorAddress) in delegateAddressList) { var delegateInfo = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput + await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { DelegateeAddress = delegateeAddress, DelegatorAddress = delegatorAddress, From 8518639a57d7ffca3b2b2ccd489ea38cd385b434 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Mon, 26 Jun 2023 13:54:48 +0800 Subject: [PATCH 087/139] feat: update ut base --- .../TokenContract_Actions.cs | 19 ++- .../TokenContract_NFT_Actions.cs | 8 +- .../AElf.Contracts.MultiToken.Tests.csproj | 6 +- .../BVT/ACS1_ImplementTest.cs | 2 +- .../BVT/NftApplicationTests.cs | 32 ++--- .../BVT/TokenApplicationTests.cs | 14 -- .../BVT/TokenManagementTests.cs | 2 +- .../MultiTokenContractTestBase.cs | 134 +++++++++++++++++- ...ContractWithCustomSystemTransactionTest.cs | 6 +- 9 files changed, 173 insertions(+), 50 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 9facd0d728..ae1a447d8b 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -48,16 +48,16 @@ private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType. AssertValidCreateInput(input, symbolType); if (symbolType == SymbolType.Token || symbolType == SymbolType.NftCollection) { - if (!IsAddressInCreateWhiteList(Context.Sender)) + if (!IsAddressInCreateWhiteList(Context.Sender) && input.Symbol != TokenContractConstants.SeedCollectionId) { var symbolSeed = State.SymbolSeedMap[input.Symbol]; CheckSeedNft(symbolSeed, input.Symbol); // seed nft for one-time use only long balance = State.Balances[Context.Sender][symbolSeed]; - DoTransferFrom(Context.Sender, Context.Self, Context.Self, input.Symbol, balance,""); - Burn(new BurnInput { - Symbol = input.Symbol, - Amount = balance}); + DoTransferFrom(Context.Sender, Context.Self, Context.Self, symbolSeed, balance,""); + BurnWithAddress(new BurnInput { + Symbol = symbolSeed, + Amount = balance},Context.Self); } } @@ -264,15 +264,20 @@ public override Empty UnApprove(UnApproveInput input) } public override Empty Burn(BurnInput input) + { + return BurnWithAddress(input,Context.Sender); + } + + private Empty BurnWithAddress(BurnInput input,Address address) { var tokenInfo = AssertValidToken(input.Symbol, input.Amount); Assert(tokenInfo.IsBurnable, "The token is not burnable."); - ModifyBalance(Context.Sender, input.Symbol, -input.Amount); + ModifyBalance(address, input.Symbol, -input.Amount); tokenInfo.Supply = tokenInfo.Supply.Sub(input.Amount); Context.Fire(new Burned { - Burner = Context.Sender, + Burner = address, Symbol = input.Symbol, Amount = input.Amount }); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index aaf3ea27f2..e061667d23 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -1,7 +1,5 @@ using System.Linq; using AElf.CSharp.Core; -using AElf.Sdk.CSharp; -using AElf.Standards.ACS1; using AElf.Types; using Google.Protobuf.WellKnownTypes; @@ -29,7 +27,11 @@ private Empty CreateNFTInfo(CreateInput input) Assert(!string.IsNullOrEmpty(ownerSymbol) && State.TokenInfos[ownerSymbol] == null,"seed_owned_symbol is empty "); Assert(!string.IsNullOrEmpty(expirationTime) && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime),"seed_owned_symbol is expired "); - State.SymbolSeedMap[input.Symbol] = ownerSymbol; + var oldSymbolSeed = State.SymbolSeedMap[ownerSymbol]; + State.TokenInfos[oldSymbolSeed].ExternalInfo.Value.TryGetValue("__seed_exp_time",out var oldSymbolSeedExpireTime); + Assert(oldSymbolSeed == null || string.IsNullOrEmpty(expirationTime) + || Context.CurrentBlockTime.Seconds > long.Parse(expirationTime),"seed_owned_symbol has been created"); + State.SymbolSeedMap[ownerSymbol] = input.Symbol; } return CreateToken(input, SymbolType.Nft); } diff --git a/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj b/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj index 08ec6e2c33..8bab7776f7 100644 --- a/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj +++ b/test/AElf.Contracts.MultiToken.Tests/AElf.Contracts.MultiToken.Tests.csproj @@ -64,7 +64,7 @@ runtime; build; native; contentfiles; analyzers - + all @@ -134,6 +134,6 @@ Protobuf\Proto\base\acs11.proto - - + + diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs index d50f4ad89d..0c1032a23b 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs @@ -212,7 +212,7 @@ public async Task SetMethodFee_Fail_Test() // token is not profitable { var tokenNotProfitable = "DLS"; - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = tokenNotProfitable, TokenName = "name", diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs index ce5e3c2c8e..cd0dd1faf2 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs @@ -113,8 +113,7 @@ public partial class MultiTokenContractTests private async Task> CreateNftCollectionAsync(TokenInfo collectionInfo) { - await CreateNativeTokenAsync(); - return await TokenContractStub.Create.SendAsync(new CreateInput + return await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = $"{collectionInfo.Symbol}0", TokenName = collectionInfo.TokenName, @@ -208,11 +207,10 @@ public async Task MultiTokenContract_Create_721Nft_Test() [Fact(DisplayName = "[MultiToken_Nft] Create nft collection input check")] public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() { - await CreateNativeTokenAsync(); var input = NftCollection721Info; // Decimals check { - var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = $"{input.Symbol}0", TokenName = input.TokenName, @@ -227,7 +225,7 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() } // Symbol check { - var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = "ABC123", TokenName = input.TokenName, @@ -242,7 +240,7 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() } // Symbol length check { - var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = "ABCDEFGHIJKLMNOPQRSTUVWXYZABC-0", TokenName = input.TokenName, @@ -257,9 +255,9 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() } // Issue chain Id check { - var result = await TokenContractStubUser.Create.SendAsync(new CreateInput + var result = await CreateMutiTokenAsync(TokenContractStub, new CreateInput { - Symbol = $"{input.Symbol}0", + Symbol = $"{input.Symbol}0", TokenName = input.TokenName, TotalSupply = input.TotalSupply, Decimals = input.Decimals, @@ -267,6 +265,7 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() IssueChainId = ChainHelper.ConvertBase58ToChainId("tDVV"), ExternalInfo = input.ExternalInfo }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } } @@ -279,7 +278,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() // Decimals check { - var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -294,7 +293,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Symbol check { - var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput { Symbol = "ABC-ABC", TokenName = input.TokenName, @@ -309,7 +308,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Symbol check { - var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput { Symbol = "ABC-", TokenName = input.TokenName, @@ -324,7 +323,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Symbol check { - var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput { Symbol = "ABC-ABC-1", TokenName = input.TokenName, @@ -339,7 +338,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Issue check { - var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -353,7 +352,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() result.TransactionResult.Error.ShouldContain("NFT issuer must be collection's issuer"); } { - var result = await TokenContractStubUser.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -371,9 +370,8 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() [Fact(DisplayName = "[MultiToken_Nft] Collection not exist")] public async Task MultiTokenContract_Create_NFT_Collection_NotExist() { - await CreateNativeTokenAsync(); var input = Nft721Info; - var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -392,7 +390,7 @@ public async Task MultiTokenContract_Create_NFT_Already_Exist() { await CreateNftCollectionAndNft(false); var input = Nft721Info; - var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index 137c034a2d..8adc01d712 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -1260,20 +1260,6 @@ await TokenContractStub.Issue.SendAsync(new IssueInput }; var result = await BasicFunctionContractStub.CreateTokenThroughMultiToken.SendAsync(createTokenInput); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var logs = result.TransactionResult.Logs.First(l => l.Name.Equals("TransactionFeeCharged")); - var transactionFeeCharged = TransactionFeeCharged.Parser.ParseFrom(logs.NonIndexed); - transactionFeeCharged.Amount.ShouldBe(fee.Fees.First().BasicFee); - transactionFeeCharged.Symbol.ShouldBe(fee.Fees.First().Symbol); - - var tokenBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { Owner = TokenContractAddress, Symbol = NativeToken }); - tokenBalance.Balance.ShouldBe(0); - - var functionBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { Owner = BasicFunctionContractAddress, Symbol = NativeToken }); - functionBalance.Balance.ShouldBe(0); - var checkTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { Symbol = "TEST" }); checkTokenInfo.Decimals.ShouldBe(createTokenInput.Decimals); checkTokenInfo.Issuer.ShouldBe(createTokenInput.Issuer); diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs index b132b14184..f850283ca1 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs @@ -111,7 +111,7 @@ public MultiTokenContractTests() private async Task CreateNativeTokenAsync() { - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = NativeTokenInfo.Symbol, TokenName = NativeTokenInfo.TokenName, diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs index 819e5f825d..8c0b4f7439 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs @@ -1,13 +1,22 @@ using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using AElf.Contracts.Parliament; using AElf.Contracts.TestContract.BasicFunction; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; using AElf.ContractTestBase.ContractTestKit; using AElf.Cryptography.ECDSA; +using AElf.CSharp.Core; +using AElf.CSharp.Core.Extension; +using AElf.Kernel; using AElf.Standards.ACS2; +using AElf.Standards.ACS3; using AElf.Types; +using Google.Protobuf; +using Google.Protobuf.WellKnownTypes; +using Volo.Abp.Threading; namespace AElf.Contracts.MultiToken; @@ -27,12 +36,13 @@ public class MultiTokenContractTestBase : ContractTestBase(TokenContractAddress, DefaultKeyPair); - TokenContractStubUser = + + TokenContractStubUser = GetTester(TokenContractAddress, User1KeyPair); Acs2BaseStub = GetTester(TokenContractAddress, DefaultKeyPair); @@ -54,6 +64,24 @@ public MultiTokenContractTestBase() ParliamentContractStub = GetTester( ParliamentContractAddress, DefaultKeyPair); + // EconomicContractStub = GetTester( + // SystemContractAddresses[EconomicContractName], + // DefaultKeyPair); + + // AsyncHelper.RunSync(()=>InitializeEconomicContract()) ; + AsyncHelper.RunSync(() => SubmitAndApproveProposalOfDefaultParliament(TokenContractAddress, + nameof(TokenContractStub.Create), new CreateInput() + { + Symbol = "ELF", + Decimals = 0, + IsBurnable = true, + TokenName = "ELF2", + TotalSupply = 1, + Issuer = DefaultAddress, + ExternalInfo = new ExternalInfo() + })); + + AsyncHelper.RunSync(()=>CreateSeedNftCollection(TokenContractStub)) ; } protected long AliceCoinTotalAmount => 1_000_000_000_0000000L; @@ -64,6 +92,9 @@ public MultiTokenContractTestBase() protected Address User1Address => Accounts[10].Address; protected Address User2Address => Accounts[11].Address; + protected int SeedNum = 0; + protected string SeedNFTSymbolPre = "SEED-"; + protected List InitialCoreDataCenterKeyPairs => Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); @@ -73,6 +104,7 @@ public MultiTokenContractTestBase() protected Hash OtherBasicFunctionContractName => HashHelper.ComputeFrom("AElf.TestContractNames.OtherBasicFunction"); + protected Address OtherBasicFunctionContractAddress { get; set; } internal BasicFunctionContractContainer.BasicFunctionContractStub OtherBasicFunctionContractStub { get; set; } @@ -83,4 +115,102 @@ internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamen return GetTester(ParliamentContractAddress, keyPair); } + + private async Task SubmitAndApproveProposalOfDefaultParliament(Address contractAddress, string methodName, + IMessage message) + { + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalId = await CreateProposalAsync(TokenContractAddress, + defaultParliamentAddress, methodName, message); + await ApproveWithMinersAsync(proposalId); + var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); + + } + + private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, + string methodName, IMessage input) + { + var proposal = new CreateProposalInput + { + OrganizationAddress = organizationAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contractAddress + }; + + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; + + return proposalId; + } + + private async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) + { + var tester = GetParliamentContractTester(bp); + var approveResult = await tester.Approve.SendAsync(proposalId); + } + } + + internal async Task CreateSeedNftCollection(TokenContractImplContainer.TokenContractImplStub stub) + { + var input = new CreateInput + { + Symbol = SeedNFTSymbolPre + SeedNum, + Decimals = 0, + IsBurnable = true, + TokenName = "seed Collection", + TotalSupply = 1, + Issuer = DefaultAddress, + ExternalInfo = new ExternalInfo() + }; + await stub.Create.SendAsync(input); + } + + + internal async Task CreateSeedNftAsync(TokenContractImplContainer.TokenContractImplStub stub, + CreateInput createInput) + { + Interlocked.Increment(ref SeedNum); + var input = new CreateInput + { + Symbol = SeedNFTSymbolPre + SeedNum, + Decimals = 0, + IsBurnable = true, + TokenName = "seed token" + SeedNum, + TotalSupply = 1, + Issuer = createInput.Issuer, + ExternalInfo = new ExternalInfo(), + LockWhiteList = { TokenContractAddress } + + }; + input.ExternalInfo.Value["__seed_owned_symbol"] = createInput.Symbol; + input.ExternalInfo.Value["__seed_exp_time"] = TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString(); + await stub.Create.SendAsync(input); + var result = await stub.Issue.SendAsync(new IssueInput + { + + Symbol = input.Symbol, + Amount = 1, + Memo = "ddd", + To = createInput.Issuer + }); + } + + internal async Task> CreateMutiTokenAsync(TokenContractImplContainer.TokenContractImplStub stub, + CreateInput createInput) + { + await CreateSeedNftAsync(stub, createInput); + return await stub.Create.SendAsync(createInput); + } + + internal async Task> CreateMutiTokenWithExceptionAsync( + TokenContractImplContainer.TokenContractImplStub stub, CreateInput createInput) + { + await CreateSeedNftAsync(stub, createInput); + return await stub.Create.SendWithExceptionAsync(createInput); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs index 12a2888fba..73df45294a 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs @@ -20,7 +20,7 @@ public MultiTokenContractWithCustomSystemTransactionTest() private async Task InitializeAsync() { - await TokenContractStub.Create.SendAsync(new CreateInput + var input = new CreateInput { Symbol = DefaultSymbol, Decimals = 2, @@ -28,7 +28,9 @@ await TokenContractStub.Create.SendAsync(new CreateInput TokenName = "elf token", TotalSupply = _totalSupply, Issuer = DefaultAddress - }); + }; + + await CreateMutiTokenAsync(TokenContractStub, input); await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput { Symbol = DefaultSymbol From 5b0a9078549feb2d217a60599777b9f047b1b6d8 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Mon, 26 Jun 2023 14:21:42 +0800 Subject: [PATCH 088/139] feat: use partial class --- ...tract_ACS4_ConsensusInformationProvider.cs | 30 +------------- ...PoSContract_ProcessConsensusInformation.cs | 28 +------------ .../AElf.Contracts.Consensus.AEDPoS.csproj | 2 +- .../Types/NextRoundInput.cs | 41 +++++++++++++++++++ .../Types/NextTermInput.cs | 41 +++++++++++++++++++ protobuf/aedpos_contract.proto | 2 + 6 files changed, 89 insertions(+), 55 deletions(-) create mode 100644 contract/AElf.Contracts.Consensus.AEDPoS/Types/NextRoundInput.cs create mode 100644 contract/AElf.Contracts.Consensus.AEDPoS/Types/NextTermInput.cs diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs index 45fd241277..9c059c426b 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ACS4_ConsensusInformationProvider.cs @@ -166,20 +166,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn { Transactions = { - GenerateTransaction(nameof(NextRound), new NextRoundInput - { - RoundNumber = round.RoundNumber, - RealTimeMinersInformation = { round.RealTimeMinersInformation }, - ExtraBlockProducerOfPreviousRound = round.ExtraBlockProducerOfPreviousRound, - BlockchainAge = round.BlockchainAge, - TermNumber = round.TermNumber, - ConfirmedIrreversibleBlockHeight = round.ConfirmedIrreversibleBlockHeight, - ConfirmedIrreversibleBlockRoundNumber = round.ConfirmedIrreversibleBlockRoundNumber, - IsMinerListJustChanged = round.IsMinerListJustChanged, - RoundIdForValidation = round.RoundIdForValidation, - MainChainMinersRoundNumber = round.MainChainMinersRoundNumber, - RandomNumber = randomNumber - }) + GenerateTransaction(nameof(NextRound), NextRoundInput.Create(round,randomNumber)) } }; case AElfConsensusBehaviour.NextTerm: @@ -187,20 +174,7 @@ private TransactionList GenerateTransactionListByExtraData(AElfConsensusHeaderIn { Transactions = { - GenerateTransaction(nameof(NextTerm), new NextTermInput - { - RoundNumber = round.RoundNumber, - RealTimeMinersInformation = { round.RealTimeMinersInformation }, - ExtraBlockProducerOfPreviousRound = round.ExtraBlockProducerOfPreviousRound, - BlockchainAge = round.BlockchainAge, - TermNumber = round.TermNumber, - ConfirmedIrreversibleBlockHeight = round.ConfirmedIrreversibleBlockHeight, - ConfirmedIrreversibleBlockRoundNumber = round.ConfirmedIrreversibleBlockRoundNumber, - IsMinerListJustChanged = round.IsMinerListJustChanged, - RoundIdForValidation = round.RoundIdForValidation, - MainChainMinersRoundNumber = round.MainChainMinersRoundNumber, - RandomNumber = randomNumber - }) + GenerateTransaction(nameof(NextTerm), NextTermInput.Create(round,randomNumber)) } }; default: diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs index c4b204c12d..af089676b8 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs @@ -106,19 +106,7 @@ private Hash GetLatestSignature(Round currentRound) private void ProcessNextRound(NextRoundInput input) { - var nextRound = new Round - { - RoundNumber = input.RoundNumber, - RealTimeMinersInformation = { input.RealTimeMinersInformation }, - ExtraBlockProducerOfPreviousRound = input.ExtraBlockProducerOfPreviousRound, - BlockchainAge = input.BlockchainAge, - TermNumber = input.TermNumber, - ConfirmedIrreversibleBlockHeight = input.ConfirmedIrreversibleBlockHeight, - ConfirmedIrreversibleBlockRoundNumber = input.ConfirmedIrreversibleBlockRoundNumber, - IsMinerListJustChanged = input.IsMinerListJustChanged, - RoundIdForValidation = input.RoundIdForValidation, - MainChainMinersRoundNumber = input.MainChainMinersRoundNumber - }; + var nextRound = input.ToRound(); RecordMinedMinerListOfCurrentRound(); @@ -169,19 +157,7 @@ private void ProcessNextRound(NextRoundInput input) private void ProcessNextTerm(NextTermInput input) { - var nextRound = new Round - { - RoundNumber = input.RoundNumber, - RealTimeMinersInformation = { input.RealTimeMinersInformation }, - ExtraBlockProducerOfPreviousRound = input.ExtraBlockProducerOfPreviousRound, - BlockchainAge = input.BlockchainAge, - TermNumber = input.TermNumber, - ConfirmedIrreversibleBlockHeight = input.ConfirmedIrreversibleBlockHeight, - ConfirmedIrreversibleBlockRoundNumber = input.ConfirmedIrreversibleBlockRoundNumber, - IsMinerListJustChanged = input.IsMinerListJustChanged, - RoundIdForValidation = input.RoundIdForValidation, - MainChainMinersRoundNumber = input.MainChainMinersRoundNumber - }; + var nextRound = input.ToRound(); RecordMinedMinerListOfCurrentRound(); diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AElf.Contracts.Consensus.AEDPoS.csproj b/contract/AElf.Contracts.Consensus.AEDPoS/AElf.Contracts.Consensus.AEDPoS.csproj index 13ae50e26c..e197019f68 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AElf.Contracts.Consensus.AEDPoS.csproj +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AElf.Contracts.Consensus.AEDPoS.csproj @@ -1,5 +1,5 @@ - + net6.0 diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/NextRoundInput.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/NextRoundInput.cs new file mode 100644 index 0000000000..e3240dc417 --- /dev/null +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/NextRoundInput.cs @@ -0,0 +1,41 @@ +using Google.Protobuf; + +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class NextRoundInput +{ + public static NextRoundInput Create(Round round, ByteString randomNumber) + { + return new NextRoundInput + { + RoundNumber = round.RoundNumber, + RealTimeMinersInformation = { round.RealTimeMinersInformation }, + ExtraBlockProducerOfPreviousRound = round.ExtraBlockProducerOfPreviousRound, + BlockchainAge = round.BlockchainAge, + TermNumber = round.TermNumber, + ConfirmedIrreversibleBlockHeight = round.ConfirmedIrreversibleBlockHeight, + ConfirmedIrreversibleBlockRoundNumber = round.ConfirmedIrreversibleBlockRoundNumber, + IsMinerListJustChanged = round.IsMinerListJustChanged, + RoundIdForValidation = round.RoundIdForValidation, + MainChainMinersRoundNumber = round.MainChainMinersRoundNumber, + RandomNumber = randomNumber + }; + } + + public Round ToRound() + { + return new Round + { + RoundNumber = RoundNumber, + RealTimeMinersInformation = { RealTimeMinersInformation }, + ExtraBlockProducerOfPreviousRound = ExtraBlockProducerOfPreviousRound, + BlockchainAge = BlockchainAge, + TermNumber = TermNumber, + ConfirmedIrreversibleBlockHeight = ConfirmedIrreversibleBlockHeight, + ConfirmedIrreversibleBlockRoundNumber = ConfirmedIrreversibleBlockRoundNumber, + IsMinerListJustChanged = IsMinerListJustChanged, + RoundIdForValidation = RoundIdForValidation, + MainChainMinersRoundNumber = MainChainMinersRoundNumber + }; + } +} \ No newline at end of file diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/Types/NextTermInput.cs b/contract/AElf.Contracts.Consensus.AEDPoS/Types/NextTermInput.cs new file mode 100644 index 0000000000..74afc3daac --- /dev/null +++ b/contract/AElf.Contracts.Consensus.AEDPoS/Types/NextTermInput.cs @@ -0,0 +1,41 @@ +using Google.Protobuf; + +namespace AElf.Contracts.Consensus.AEDPoS; + +public partial class NextTermInput +{ + public static NextTermInput Create(Round round, ByteString randomNumber) + { + return new NextTermInput + { + RoundNumber = round.RoundNumber, + RealTimeMinersInformation = { round.RealTimeMinersInformation }, + ExtraBlockProducerOfPreviousRound = round.ExtraBlockProducerOfPreviousRound, + BlockchainAge = round.BlockchainAge, + TermNumber = round.TermNumber, + ConfirmedIrreversibleBlockHeight = round.ConfirmedIrreversibleBlockHeight, + ConfirmedIrreversibleBlockRoundNumber = round.ConfirmedIrreversibleBlockRoundNumber, + IsMinerListJustChanged = round.IsMinerListJustChanged, + RoundIdForValidation = round.RoundIdForValidation, + MainChainMinersRoundNumber = round.MainChainMinersRoundNumber, + RandomNumber = randomNumber + }; + } + + public Round ToRound() + { + return new Round + { + RoundNumber = RoundNumber, + RealTimeMinersInformation = { RealTimeMinersInformation }, + ExtraBlockProducerOfPreviousRound = ExtraBlockProducerOfPreviousRound, + BlockchainAge = BlockchainAge, + TermNumber = TermNumber, + ConfirmedIrreversibleBlockHeight = ConfirmedIrreversibleBlockHeight, + ConfirmedIrreversibleBlockRoundNumber = ConfirmedIrreversibleBlockRoundNumber, + IsMinerListJustChanged = IsMinerListJustChanged, + RoundIdForValidation = RoundIdForValidation, + MainChainMinersRoundNumber = MainChainMinersRoundNumber + }; + } +} \ No newline at end of file diff --git a/protobuf/aedpos_contract.proto b/protobuf/aedpos_contract.proto index 4f2719a70c..d06f5d5ccf 100644 --- a/protobuf/aedpos_contract.proto +++ b/protobuf/aedpos_contract.proto @@ -454,6 +454,7 @@ message RecordCandidateReplacementInput { string new_pubkey = 2; } +// For compatibility, it is the same as the Round with the addition of the random_number property. message NextRoundInput { // The round number. int64 round_number = 1; @@ -479,6 +480,7 @@ message NextRoundInput { bytes random_number = 11; } +// For compatibility, it is the same as the Round with the addition of the random_number property. message NextTermInput { // The round number. int64 round_number = 1; From 10c309213f3d193223a69e4844720a950fa75c1f Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Mon, 26 Jun 2023 15:02:02 +0800 Subject: [PATCH 089/139] feat: add param check --- .../TokenContract_NFT_Actions.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index e061667d23..4195437ea2 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -28,9 +28,13 @@ private Empty CreateNFTInfo(CreateInput input) Assert(!string.IsNullOrEmpty(expirationTime) && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime),"seed_owned_symbol is expired "); var oldSymbolSeed = State.SymbolSeedMap[ownerSymbol]; - State.TokenInfos[oldSymbolSeed].ExternalInfo.Value.TryGetValue("__seed_exp_time",out var oldSymbolSeedExpireTime); - Assert(oldSymbolSeed == null || string.IsNullOrEmpty(expirationTime) - || Context.CurrentBlockTime.Seconds > long.Parse(expirationTime),"seed_owned_symbol has been created"); + var oldSymbolSeedExpireTime =""; + if (oldSymbolSeed !=null) + { + State.TokenInfos[oldSymbolSeed].ExternalInfo.Value.TryGetValue("__seed_exp_time",out oldSymbolSeedExpireTime); + } + Assert(oldSymbolSeed == null || string.IsNullOrEmpty(oldSymbolSeedExpireTime) + || Context.CurrentBlockTime.Seconds > long.Parse(oldSymbolSeedExpireTime),"seed_owned_symbol has been created"); State.SymbolSeedMap[ownerSymbol] = input.Symbol; } return CreateToken(input, SymbolType.Nft); From 200d6be4b1535e03014fd634b1962544f39fe166 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Mon, 26 Jun 2023 15:28:34 +0800 Subject: [PATCH 090/139] refactor: add constant --- .../AElf.Contracts.MultiToken/TokenContractConstants.cs | 2 ++ contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs | 4 ++-- .../AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs index 3810302e5f..4c0118d40b 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs @@ -20,4 +20,6 @@ public static class TokenContractConstants public const string UserContractMethodFeeKey = "UserContractMethodFee"; public const string CollectionId = "0"; public const string SeedCollectionId = "SEED-0"; + public const string SeedExternalInfoOwnerSymbol= "__seed_owned_symbol"; + public const string SeedExternalInfoExpireTime = "__seed_exp_time"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index ae1a447d8b..323a66e3df 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -108,9 +108,9 @@ private void CheckSeedNft(string symbolSeed,String symbol) Assert(tokenInfo != null,"Seed NFT is not exist"); Assert(State.Balances[Context.Sender][symbolSeed] > 0,"owner doesn't own enough balance"); Assert(tokenInfo.ExternalInfo != null ,"seed_owned_symbol is empty "); - tokenInfo.ExternalInfo.Value.TryGetValue("__seed_owned_symbol",out var ownedSymbol); + tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoOwnerSymbol,out var ownedSymbol); Assert(ownedSymbol == symbol ,"seed_owned_symbol and input_symbol is inconsistent "); - tokenInfo.ExternalInfo.Value.TryGetValue("__seed_exp_time",out var expirationTime); + tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoExpireTime,out var expirationTime); Assert(!string.IsNullOrEmpty(expirationTime) && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime),"seed_owned_symbol is expired "); } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 4195437ea2..70ff104bc3 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -22,8 +22,8 @@ private Empty CreateNFTInfo(CreateInput input) Assert(Context.Sender == nftCollectionInfo.Issuer && nftCollectionInfo.Issuer == input.Issuer, "NFT issuer must be collection's issuer"); if (nftCollectionInfo.Symbol == TokenContractConstants.SeedCollectionId) { - input.ExternalInfo.Value.TryGetValue("__seed_owned_symbol",out var ownerSymbol); - input.ExternalInfo.Value.TryGetValue("__seed_exp_time",out var expirationTime); + input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoOwnerSymbol,out var ownerSymbol); + input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoExpireTime,out var expirationTime); Assert(!string.IsNullOrEmpty(ownerSymbol) && State.TokenInfos[ownerSymbol] == null,"seed_owned_symbol is empty "); Assert(!string.IsNullOrEmpty(expirationTime) && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime),"seed_owned_symbol is expired "); @@ -31,7 +31,7 @@ private Empty CreateNFTInfo(CreateInput input) var oldSymbolSeedExpireTime =""; if (oldSymbolSeed !=null) { - State.TokenInfos[oldSymbolSeed].ExternalInfo.Value.TryGetValue("__seed_exp_time",out oldSymbolSeedExpireTime); + State.TokenInfos[oldSymbolSeed].ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoExpireTime,out oldSymbolSeedExpireTime); } Assert(oldSymbolSeed == null || string.IsNullOrEmpty(oldSymbolSeedExpireTime) || Context.CurrentBlockTime.Seconds > long.Parse(oldSymbolSeedExpireTime),"seed_owned_symbol has been created"); From 940a9b531af4ed99f78a32427439d73b3e70e5a7 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 26 Jun 2023 16:27:37 +0800 Subject: [PATCH 091/139] fix: conflict --- .../ExecutePluginTransactionDirectlyTest.cs | 1421 +---------------- 1 file changed, 28 insertions(+), 1393 deletions(-) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 72fdaee4b0..2a931d1251 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -1159,39 +1159,46 @@ public async Task ChargeTransactionFee_DelegateNew_First( } await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput { - FreeAllowances = new MethodFeeFreeAllowances + Value = { - Value = + new ConfigTransactionFeeFreeAllowance { - new MethodFeeFreeAllowance - { - Symbol = basicFeeSymbol, - Amount = baseFeeFreeAmount - }, - new MethodFeeFreeAllowance + Symbol = NativeTokenSymbol, + RefreshSeconds = 100, + Threshold = threshold, + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances { - Symbol = sizeFeeSymbol, - Amount = sizeFeeFreeAmount + Value = + { + new TransactionFeeFreeAllowance + { + Symbol = basicFeeSymbol, + Amount = baseFeeFreeAmount + }, + new TransactionFeeFreeAllowance + { + Symbol = sizeFeeSymbol, + Amount = sizeFeeFreeAmount + } + } } } - }, - RefreshSeconds = 100, - Threshold = threshold + } }); { - var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(userAddress); + var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(userAddress); if (threshold <= initialBalance) { - freeAllowances.Value.First().Symbol.ShouldBe(basicFeeSymbol); - freeAllowances.Value.First().Amount.ShouldBe(baseFeeFreeAmount); - freeAllowances.Value.Last().Symbol.ShouldBe(sizeFeeSymbol); - freeAllowances.Value.Last().Amount.ShouldBe(sizeFeeFreeAmount); + freeAllowances.Map.First().Value.Map.Values.First().Symbol.ShouldBe(basicFeeSymbol); + freeAllowances.Map.First().Value.Map.Values.First().Amount.ShouldBe(baseFeeFreeAmount); + freeAllowances.Map.First().Value.Map.Values.Last().Symbol.ShouldBe(sizeFeeSymbol); + freeAllowances.Map.First().Value.Map.Values.Last().Amount.ShouldBe(sizeFeeFreeAmount); } else { - freeAllowances.Value.ShouldBeEmpty(); + freeAllowances.Map.ShouldBeEmpty(); } } var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); @@ -1833,7 +1840,7 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( } [Theory] - [InlineData(10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] + [InlineData( 10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, @@ -2383,1378 +2390,6 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } - private async Task GetTokenSupplyAmount(string tokenSymbol) - { - var basicFeeSymbol = "BASIC"; - var sizeFeeSymbol = "SIZE"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, basicFeeSymbol); - await CreateTokenAsync(DefaultSender, sizeFeeSymbol); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); - await IssueTokenToUserAsync(NativeTokenSymbol, initialUserBalance, userAddress); - await IssueTokenToUserAsync(NativeTokenSymbol, initialUserBalance, UserTomSender); - if (baseFeeBalance != 0 && sizeFeeBalance != 0 && - baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && - baseFeeUserBalance != 0 && sizeFeeUserBalance != 0) - { - await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); - await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeUserBalance, userAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeUserBalance, userAddress); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeUserBalance, UserTomSender); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeUserBalance, UserTomSender); - } - - var delegations = new Dictionary - { - [NativeTokenSymbol] = delegateeAmountNativeToken, - [basicFeeSymbol] = delegateeAmountBasic, - [sizeFeeSymbol] = delegateeAmountSize - }; - var delegations1 = new Dictionary - { - [NativeTokenSymbol] = 5, - }; - var delegateInfo1 = new DelegateInfo - { - Delegations = { delegations }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - var delegateInfo2 = new DelegateInfo - { - Delegations = { delegations }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.TransferFrom), - ContractAddress = TokenContractAddress, - }; - var delegateInfo3 = new DelegateInfo - { - Delegations = { delegations }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.TransferFrom), - ContractAddress = ConsensusContractAddress, - }; - var delegateInfo4 = new DelegateInfo - { - Delegations = { delegations1 }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - var transactionResult = await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DefaultSender, - DelegateInfoList = { delegateInfo1 } - }); - //delegate User transferFrom method - var transactionResult1 = await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = userAddress, - DelegateInfoList = { delegateInfo2 } - }); - //delegate User ConsensusContract - var transactionResult2 = await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = userAddress, - DelegateInfoList = { delegateInfo3 } - }); - var transactionResult3 = await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = UserTomSender, - DelegateInfoList = { delegateInfo4 } - }); - { - var result = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - result.BlockHeight.ShouldBe(transactionResult.TransactionResult.BlockNumber); - result.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); - } - - var delegationsBefore = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = userAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.TransferFrom) - }); - delegationsBefore.BlockHeight.ShouldBe(transactionResult1.TransactionResult.BlockNumber); - delegationsBefore.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); - - - var delegationBefore2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = userAddress, - ContractAddress = ConsensusContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.TransferFrom) - }); - delegationBefore2.BlockHeight.ShouldBe(transactionResult2.TransactionResult.BlockNumber); - delegationBefore2.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); - - { - var result = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = UserTomSender, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - result.BlockHeight.ShouldBe(transactionResult3.TransactionResult.BlockNumber); - result.Delegations[NativeTokenSymbol].ShouldBe(5); - } - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput - { - Value = - { - new ConfigTransactionFeeFreeAllowance - { - Symbol = NativeTokenSymbol, - RefreshSeconds = 100, - Threshold = threshold, - TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances - { - Value = - { - new TransactionFeeFreeAllowance - { - Symbol = basicFeeSymbol, - Amount = baseFeeFreeAmount - }, - new TransactionFeeFreeAllowance - { - Symbol = sizeFeeSymbol, - Amount = sizeFeeFreeAmount - } - } - } - } - } - }); - { - var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(userAddress); - if (threshold <= initialBalance) - { - freeAllowances.Map.First().Value.Map.Values.First().Symbol.ShouldBe(basicFeeSymbol); - freeAllowances.Map.First().Value.Map.Values.First().Amount.ShouldBe(baseFeeFreeAmount); - freeAllowances.Map.First().Value.Map.Values.Last().Symbol.ShouldBe(sizeFeeSymbol); - freeAllowances.Map.First().Value.Map.Values.Last().Amount.ShouldBe(sizeFeeFreeAmount); - } - else - { - freeAllowances.Map.ShouldBeEmpty(); - } - } - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - { - var chargeFeeRetUser = await TokenContractStubA.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRetUser.Output.Success.ShouldBe(false); - chargeFeeRetUser.Output.ChargingInformation.ShouldBe("Transaction fee not enough."); - - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = userAddress - }); - afterBalance.Balance.ShouldBe(0); - } - { - var chargeFeeRetUser = - await TokenContractStubDelegator.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRetUser.Output.Success.ShouldBe(false); - chargeFeeRetUser.Output.ChargingInformation.ShouldBe("Transaction fee not enough."); - - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = UserTomSender - }); - afterBalance.Balance.ShouldBe(0); - } - var delegationsAfter = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = userAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.TransferFrom) - }); - delegationsAfter.BlockHeight.ShouldBe(transactionResult1.TransactionResult.BlockNumber); - delegationsAfter.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); - - - var delegationAfter2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegationAfter2.BlockHeight.ShouldBe(transactionResult.TransactionResult.BlockNumber); - delegationAfter2.Delegations[NativeTokenSymbol].ShouldBe(delegateeAmountNativeToken); - { - var delegationResult = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - var chargeFeeRetDefault = - await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2) - { - chargeFeeRetDefault.Output.Success.ShouldBe(true); - - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DefaultSender - }); - afterBalance.Balance.ShouldBe(afterBalanceDefault); - - var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DelegateeAddress - }); - afterDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); - } - else - { - chargeFeeRetDefault.Output.Success.ShouldBe(false); - - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); - } - } - } - - [Theory] - [InlineData(10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] - public async Task ChargeTransactionFee_DelegationNew_Second_Success( - long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, - long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, - long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, - long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, - long basicFee, long sizeFee, long afterBalanceDelegatee, long afterDelegateeAmount) - { - var basicFeeSymbol = "BASIC"; - var sizeFeeSymbol = "SIZE"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, basicFeeSymbol); - await CreateTokenAsync(DefaultSender, sizeFeeSymbol); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); - if (baseFeeBalance != 0 && sizeFeeBalance != 0 && - baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && - baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) - { - await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); - await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); - } - - var delegations = new Dictionary - { - [NativeTokenSymbol] = 5, - }; - var delegations2 = new Dictionary - { - [NativeTokenSymbol] = delegateeAmountNativeToken, - [basicFeeSymbol] = delegateeAmountBasic, - [sizeFeeSymbol] = delegateeAmountSize - }; - var delegateInfo1 = new DelegateInfo - { - Delegations = { delegations }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - var delegateInfo2 = new DelegateInfo - { - Delegations = { delegations2 }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DefaultSender, - DelegateInfoList = { delegateInfo1 } - }); - await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DelegateeAddress, - DelegateInfoList = { delegateInfo2 } - }); - - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - var delegationResult = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - var delegationResult2 = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && - chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) - { - chargeFeeRetDefault.Output.Success.ShouldBe(true); - - //no change - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DefaultSender - }); - afterBalance.Balance.ShouldBe(10); - - //no change - var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DelegateeAddress - }); - afterDelegateeBalance.Balance.ShouldBe(20); - - var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = Delegatee2Address - }); - afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); - } - else - { - chargeFeeRetDefault.Output.Success.ShouldBe(false); - - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation.Delegations[NativeTokenSymbol].ShouldBe(5); - var delegation2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation2.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); - } - } - - [Theory] - [InlineData(10, 20, 70, 1000, 1000, 1000, 10, 10, 20, 20, 70, 70, 80, 80, 70, 1000)] - public async Task ChargeTransactionFee_DelegationNew_Second_Failed_DelegateeBalanceIsNotEnough( - long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, - long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, - long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, - long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, - long basicFee, long sizeFee, long afterBalanceDelegatee, long afterDelegateeAmount) - { - var basicFeeSymbol = "BASIC"; - var sizeFeeSymbol = "SIZE"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, basicFeeSymbol); - await CreateTokenAsync(DefaultSender, sizeFeeSymbol); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); - if (baseFeeBalance != 0 && sizeFeeBalance != 0 && - baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && - baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) - { - await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); - await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); - } - - var delegations = new Dictionary - { - [NativeTokenSymbol] = 5, - }; - var delegations2 = new Dictionary - { - [NativeTokenSymbol] = delegateeAmountNativeToken, - [basicFeeSymbol] = delegateeAmountBasic, - [sizeFeeSymbol] = delegateeAmountSize - }; - var delegateInfo1 = new DelegateInfo - { - Delegations = { delegations }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - var delegateInfo2 = new DelegateInfo - { - Delegations = { delegations2 }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DefaultSender, - DelegateInfoList = { delegateInfo1 } - }); - await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DelegateeAddress, - DelegateInfoList = { delegateInfo2 } - }); - - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - var delegationResult = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - var delegationResult2 = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && - chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) - { - chargeFeeRetDefault.Output.Success.ShouldBe(false); - chargeFeeRetDefault.Output.ChargingInformation.ShouldBe("Transaction fee not enough."); - - //all in - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DefaultSender - }); - afterBalance.Balance.ShouldBe(0); - - //no change - var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DelegateeAddress - }); - afterDelegateeBalance.Balance.ShouldBe(20); - - //no change - var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = Delegatee2Address - }); - afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); - } - else - { - chargeFeeRetDefault.Output.Success.ShouldBe(false); - } - } - - [Theory] - [InlineData(10, 20, 100, 30, 30, 30, 10, 10, 20, 20, 100, 100, 80, 80, 100, 30)] - public async Task ChargeTransactionFee_DelegationNew_Second_Failed_DelegationIsNotEnough( - long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, - long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, - long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, - long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, - long basicFee, long sizeFee, long afterBalanceDelegatee, long afterDelegateeAmount) - { - var basicFeeSymbol = "BASIC"; - var sizeFeeSymbol = "SIZE"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, basicFeeSymbol); - await CreateTokenAsync(DefaultSender, sizeFeeSymbol); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); - if (baseFeeBalance != 0 && sizeFeeBalance != 0 && - baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && - baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) - { - await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); - await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); - } - - var delegations = new Dictionary - { - [NativeTokenSymbol] = 5, - }; - var delegations2 = new Dictionary - { - [NativeTokenSymbol] = delegateeAmountNativeToken, - [basicFeeSymbol] = delegateeAmountBasic, - [sizeFeeSymbol] = delegateeAmountSize - }; - var delegateInfo1 = new DelegateInfo - { - Delegations = { delegations }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - var delegateInfo2 = new DelegateInfo - { - Delegations = { delegations2 }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DefaultSender, - DelegateInfoList = { delegateInfo1 } - }); - await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DelegateeAddress, - DelegateInfoList = { delegateInfo2 } - }); - - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRetDefault.Output.Success.ShouldBe(false); - - //no change - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DefaultSender - }); - afterBalance.Balance.ShouldBe(0); - - //no change - var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DelegateeAddress - }); - afterDelegateeBalance.Balance.ShouldBe(20); - - var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = Delegatee2Address - }); - afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); - } - - [Theory] - [InlineData(10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 100, 1000)] - public async Task ChargeTransactionFee_DelegationNew_Second_Failed_DelegateIsNotExist( - long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, - long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, - long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, - long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, - long basicFee, long sizeFee, long afterBalanceDelegatee, long afterDelegateeAmount) - { - var basicFeeSymbol = "BASIC"; - var sizeFeeSymbol = "SIZE"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, basicFeeSymbol); - await CreateTokenAsync(DefaultSender, sizeFeeSymbol); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); - if (baseFeeBalance != 0 && sizeFeeBalance != 0 && - baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && - baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) - { - await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); - await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); - } - - var delegations = new Dictionary - { - [NativeTokenSymbol] = 5, - }; - var delegations2 = new Dictionary - { - [NativeTokenSymbol] = delegateeAmountNativeToken, - [basicFeeSymbol] = delegateeAmountBasic, - [sizeFeeSymbol] = delegateeAmountSize - }; - var delegateInfo1 = new DelegateInfo - { - Delegations = { delegations }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - var delegateInfo2 = new DelegateInfo - { - Delegations = { delegations2 }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = ConsensusContractAddress, - }; - await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DefaultSender, - DelegateInfoList = { delegateInfo1 } - }); - await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DelegateeAddress, - DelegateInfoList = { delegateInfo2 } - }); - - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,basicFee); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - chargeFeeRetDefault.Output.Success.ShouldBe(false); - - //no change - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DefaultSender - }); - afterBalance.Balance.ShouldBe(0); - - //no change - var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DelegateeAddress - }); - afterDelegateeBalance.Balance.ShouldBe(20); - - var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = Delegatee2Address - }); - afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = ConsensusContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); - } - - [Theory] - [InlineData( 10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] - public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( - long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, - long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, - long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, - long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, - long basicFee, long sizeFee, long afterBalanceDelegatee, long afterDelegateeAmount) - { - var basicFeeSymbol = "BASIC"; - var sizeFeeSymbol = "SIZE"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, basicFeeSymbol); - await CreateTokenAsync(DefaultSender, sizeFeeSymbol); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); - if (baseFeeBalance != 0 && sizeFeeBalance != 0 && - baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && - baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) - { - await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); - await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); - } - - var delegations = new Dictionary - { - [NativeTokenSymbol] = 5, - }; - var delegations2 = new Dictionary - { - [NativeTokenSymbol] = delegateeAmountNativeToken, - [basicFeeSymbol] = delegateeAmountBasic, - [sizeFeeSymbol] = delegateeAmountSize - }; - var delegateInfo2 = new DelegateInfo - { - Delegations = { delegations2 }, - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - await TokenContractStubDelegate1.SetTransactionFeeDelegations.SendAsync( - new SetTransactionFeeDelegationsInput - { - DelegatorAddress = DefaultSender, - Delegations = { delegations } - }); - await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DelegateeAddress, - DelegateInfoList = { delegateInfo2 } - }); - - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,basicFee); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - var delegationResult = - await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( - new GetTransactionFeeDelegationsOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender - }); - var delegationResult2 = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && - chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) - { - chargeFeeRetDefault.Output.Success.ShouldBe(true); - - //no change - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DefaultSender - }); - afterBalance.Balance.ShouldBe(10); - - //no change - var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DelegateeAddress - }); - afterDelegateeBalance.Balance.ShouldBe(20); - - var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = Delegatee2Address - }); - afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); - } - else - { - chargeFeeRetDefault.Output.Success.ShouldBe(false); - - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( - new GetTransactionFeeDelegationsOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender - }); - delegation.Delegations[NativeTokenSymbol].ShouldBe(5); - var delegation2 = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation2.Delegations[basicFeeSymbol].ShouldBe(delegateeAmountBasic); - } - } - - [Theory] - [InlineData(10, 20, 100, 10, 10, 20, 20, 100, 100, 80, 80, 20)] - public async Task ChargeTransactionFee_DelegationNew_UnlimitedDelegate_Success( - long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, - long baseFeeBalance, long sizeFeeBalance, long baseFeeDelegateBalance, long sizeFeeDelegateBalance, - long baseFeeDelegate2Balance, long sizeFeeDelegate2Balance, - long basicFee, long sizeFee, long afterBalanceDelegatee) - { - var basicFeeSymbol = "BASIC"; - var sizeFeeSymbol = "SIZE"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, basicFeeSymbol); - await CreateTokenAsync(DefaultSender, sizeFeeSymbol); - - await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegateeBalance, DelegateeAddress); - await IssueTokenToUserAsync(NativeTokenSymbol, initialDelegatee2Balance, Delegatee2Address); - if (baseFeeBalance != 0 && sizeFeeBalance != 0 && - baseFeeDelegateBalance != 0 && sizeFeeDelegateBalance != 0 && - baseFeeDelegate2Balance != 0 && sizeFeeDelegate2Balance != 0) - { - await IssueTokenToDefaultSenderAsync(basicFeeSymbol, baseFeeBalance); - await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); - await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegate2Balance, Delegatee2Address); - await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegate2Balance, Delegatee2Address); - } - - var delegations = new Dictionary - { - [NativeTokenSymbol] = 5, - }; - var delegateInfo2 = new DelegateInfo - { - IsUnlimitedDelegate = true, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - }; - await TokenContractStubDelegate1.SetTransactionFeeDelegations.SendAsync( - new SetTransactionFeeDelegationsInput - { - DelegatorAddress = DefaultSender, - Delegations = { delegations } - }); - await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DelegateeAddress, - DelegateInfoList = { delegateInfo2 } - }); - - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,basicFee); - - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = sizeFee, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - var delegationResult = - await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( - new GetTransactionFeeDelegationsOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender - }); - var delegationResult2 = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - if (chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult.BlockHeight + 2 && - chargeFeeRetDefault.Transaction.RefBlockNumber >= delegationResult2.BlockHeight + 2) - { - chargeFeeRetDefault.Output.Success.ShouldBe(true); - - //no change - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DefaultSender - }); - afterBalance.Balance.ShouldBe(10); - - //no change - var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DelegateeAddress - }); - afterDelegateeBalance.Balance.ShouldBe(20); - - var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = Delegatee2Address - }); - afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - } - else - { - chargeFeeRetDefault.Output.Success.ShouldBe(false); - - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegationsOfADelegatee.CallAsync( - new GetTransactionFeeDelegationsOfADelegateeInput - { - DelegateeAddress = DelegateeAddress, - DelegatorAddress = DefaultSender - }); - delegation.Delegations[NativeTokenSymbol].ShouldBe(5); - } - } - - [Fact] - public async Task ChargeTransactionFee_DelegationNew_MultiDelegate_Success() - { - var basicFeeSymbol = "BASIC"; - var sizeFeeSymbol = "SIZE"; - - await SetPrimaryTokenSymbolAsync(); - await CreateTokenAsync(DefaultSender, basicFeeSymbol); - await CreateTokenAsync(DefaultSender, sizeFeeSymbol); - - var tokenList = new List { NativeTokenSymbol, basicFeeSymbol, sizeFeeSymbol }; - await IssueTokenListToUserAsync(tokenList, 10, DefaultSender); - await IssueTokenListToUserAsync(tokenList, 20, DelegateeAddress); - await IssueTokenListToUserAsync(tokenList, 100, Delegatee2Address); - await IssueTokenListToUserAsync(tokenList, 20, Delegatee3Address); - await IssueTokenListToUserAsync(tokenList, 20, SecondaryDelegatee1Address); - await IssueTokenListToUserAsync(tokenList, 100, SecondaryDelegatee2Address); - await IssueTokenListToUserAsync(tokenList, 20, SecondaryDelegatee3Address); - await IssueTokenListToUserAsync(tokenList, 20, SecondaryDelegatee4Address); - await IssueTokenListToUserAsync(tokenList, 200, SecondaryDelegatee5Address); - await IssueTokenListToUserAsync(tokenList, 100, SecondaryDelegatee6Address); - - //first delegate - //delegatee1 -> default sender, balance is not enough - //delegatee2 -> default sender, delegation is not enough - //delegatee3 -> default sender, balance and delegation is not enough - var delegations1 = new Dictionary - { - [NativeTokenSymbol] = 100, - [basicFeeSymbol] = 100, - [sizeFeeSymbol] = 100, - }; - var delegations2 = new Dictionary - { - [NativeTokenSymbol] = 10 - }; - var delegations3 = new Dictionary - { - [NativeTokenSymbol] = 30, - [basicFeeSymbol] = 100 - }; - var delegateInfo1 = new DelegateInfo - { - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - Delegations = { delegations1 } - }; - var delegateInfo2 = new DelegateInfo - { - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - Delegations = { delegations2 } - }; - var delegateInfo3 = new DelegateInfo - { - IsUnlimitedDelegate = false, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - Delegations = { delegations3 } - }; - await TokenContractStubDelegate1.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DefaultSender, - DelegateInfoList = { delegateInfo1 }, - }); - await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DefaultSender, - DelegateInfoList = { delegateInfo2 } - }); - await TokenContractStubDelegate3.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DefaultSender, - DelegateInfoList = { delegateInfo3 } - }); - //second delegate - //secondary delegatee1 -> delegatee1, balance is not enough - //secondary delegatee2 -> delegatee1, delegation is not enough - //secondary delegatee3 -> delegatee1, balance and delegation is not enough - //secondary delegatee4 -> delegatee2, balance is not enough - //secondary delegatee5 -> delegatee2, success - //secondary delegatee6 -> delegatee3 - await TokenContractStubSecondaryDelegate1.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DelegateeAddress, - DelegateInfoList = { delegateInfo1 } - }); - await TokenContractStubSecondaryDelegate2.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DelegateeAddress, - DelegateInfoList = { delegateInfo2 } - }); - await TokenContractStubSecondaryDelegate3.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = DelegateeAddress, - DelegateInfoList = { delegateInfo3 } - }); - await TokenContractStubSecondaryDelegate4.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = Delegatee2Address, - DelegateInfoList = { delegateInfo1 } - }); - await TokenContractStubSecondaryDelegate5.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = Delegatee2Address, - DelegateInfoList = { delegateInfo1 } - }); - await TokenContractStubSecondaryDelegate6.SetTransactionFeeDelegateInfos.SendAsync( - new SetTransactionFeeDelegateInfosInput - { - DelegatorAddress = Delegatee3Address, - DelegateInfoList = { delegateInfo3 } - }); - - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol, sizeFeeSymbol, 80); - var chargeTransactionFeesInput = new ChargeTransactionFeesInput - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - ContractAddress = TokenContractAddress, - TransactionSizeFee = 80, - }; - chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - - var delegateList = new List<(Address, Address)> - { - (DelegateeAddress, DefaultSender), - (Delegatee2Address, DefaultSender), - (Delegatee3Address, DefaultSender), - (SecondaryDelegatee1Address, DelegateeAddress), - (SecondaryDelegatee2Address, DelegateeAddress), - (SecondaryDelegatee3Address, DelegateeAddress), - (SecondaryDelegatee4Address, Delegatee2Address), - (SecondaryDelegatee5Address, Delegatee2Address), - (SecondaryDelegatee6Address, Delegatee3Address), - (DelegateeAddress, DefaultSender), - (DelegateeAddress, DefaultSender), - (DelegateeAddress, DefaultSender) - }; - - var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); - var result = await GetSetDelegationResultAsync(delegateList, chargeFeeRetDefault.Transaction.RefBlockNumber); - if (result) - { - chargeFeeRetDefault.Output.Success.ShouldBe(true); - await CheckUserBalanceAsync(NativeTokenSymbol, DefaultSender, 10); - await CheckUserBalanceAsync(basicFeeSymbol, DelegateeAddress, 20); - await CheckUserBalanceAsync(basicFeeSymbol, Delegatee2Address, 100); - await CheckUserBalanceAsync(NativeTokenSymbol, Delegatee3Address, 20); - await CheckUserBalanceAsync(basicFeeSymbol, SecondaryDelegatee1Address, 20); - await CheckUserBalanceAsync(basicFeeSymbol, SecondaryDelegatee2Address, 100); - await CheckUserBalanceAsync(NativeTokenSymbol, SecondaryDelegatee3Address, 20); - await CheckUserBalanceAsync(NativeTokenSymbol, SecondaryDelegatee4Address, 20); - //change - await CheckUserBalanceAsync(basicFeeSymbol, SecondaryDelegatee5Address, 120); - await CheckUserBalanceAsync(NativeTokenSymbol, SecondaryDelegatee6Address, 100); - var delegateInfo = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = SecondaryDelegatee5Address, - DelegatorAddress = Delegatee2Address, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegateInfo.Delegations[basicFeeSymbol].ShouldBe(20); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = SecondaryDelegatee3Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation.Delegations[NativeTokenSymbol].ShouldBe(30); - delegation.Delegations[basicFeeSymbol].ShouldBe(100); - } - else - { - chargeFeeRetDefault.Output.Success.ShouldBe(false); - var delegateInfo = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = SecondaryDelegatee5Address, - DelegatorAddress = Delegatee2Address, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegateInfo.Delegations[basicFeeSymbol].ShouldBe(100); - } - } - - private async Task IssueTokenListToUserAsync(List symbols, long amount, Address address) - { - foreach (var symbol in symbols) - { - await IssueTokenToUserAsync(symbol, amount, address); - } - } - - private async Task GetSetDelegationResultAsync(List<(Address, Address)> delegateAddressList, - long refBlockHeight) - { - var result = true; - foreach (var (delegateeAddress, delegatorAddress) in delegateAddressList) - { - var delegateInfo = - await TokenContractStubDelegate1.GetTransactionFeeDelegateInfosOfADelegatee.CallAsync( - new GetTransactionFeeDelegateInfosOfADelegateeInput - { - DelegateeAddress = delegateeAddress, - DelegatorAddress = delegatorAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - result = result && refBlockHeight >= delegateInfo.BlockHeight + 2; - } - - return result; - } - - private async Task CheckUserBalanceAsync(string symbol, Address owner, long balance) - { - var userBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = symbol, - Owner = owner - }); - userBalance.Balance.ShouldBe(balance); - } - - private async Task SetMethodOrSizeFeeAsync(string basicFeeSymbol, string sizeFeeSymbol, - long basicFee) - { - var methodFee = new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = - { - new MethodFee - { - Symbol = basicFeeSymbol, - BasicFee = basicFee - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); - - var sizeFeeSymbolList = new SymbolListToPayTxSizeFee - { - SymbolsToPayTxSizeFee = - { - new SymbolToPayTxSizeFee - { - TokenSymbol = sizeFeeSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - }, - new SymbolToPayTxSizeFee - { - TokenSymbol = NativeTokenSymbol, - AddedTokenWeight = 1, - BaseTokenWeight = 1 - } - } - }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - return sizeFeeSymbolList; - } - - private async Task GetTokenSupplyAmount(string tokenSymbol) { var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput From 32c238d64da9128429ed1041f2b35c1cc7eaf83a Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Mon, 26 Jun 2023 20:48:10 +0800 Subject: [PATCH 092/139] feat: add ut --- .../TokenContract_Helper.cs | 35 +++-- .../TokenContract_NFT_Actions.cs | 4 +- .../BVT/NftApplicationTests.cs | 123 ++++++++++++++++++ .../MultiTokenContractTestBase.cs | 45 ++++--- 4 files changed, 177 insertions(+), 30 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index f0269d98f1..f93f2716b2 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -196,23 +196,36 @@ private void AssertValidCreateInput(CreateInput input, SymbolType symbolType) && input.Symbol.Length > 0 && input.Decimals >= 0 && input.Decimals <= TokenContractConstants.MaxDecimals, "Invalid input."); - var symbols = input.Symbol.Split(TokenContractConstants.NFTSymbolSeparator); + + + TokenSymBolNameCheck(input.Symbol); + } + + private void TokenSymBolNameCheck( string symbol) + { + var symbols = symbol.Split(TokenContractConstants.NFTSymbolSeparator); + var inputSymbolType = GetCreateInputSymbolType(symbol); var empty = new TokenInfo(); - if (symbolType == SymbolType.Token) + if (inputSymbolType == SymbolType.Token) { - Assert(input.Symbol.Length <= TokenContractConstants.SymbolMaxLength, "Invalid token symbol length"); - var duplicatedNftCollection = State.TokenInfos[symbols.First() + TokenContractConstants.NFTSymbolSeparator + TokenContractConstants.CollectionId]; - Assert( duplicatedNftCollection == null ||duplicatedNftCollection.Equals(empty),"Token name prefix can not be duplicated"); + Assert(symbol.Length <= TokenContractConstants.SymbolMaxLength, "Invalid token symbol length"); + var duplicatedNftCollection = + State.TokenInfos[ + symbols.First() + TokenContractConstants.NFTSymbolSeparator + TokenContractConstants.CollectionId]; + Assert(duplicatedNftCollection == null || duplicatedNftCollection.Equals(empty), + "Token name prefix can not be duplicated"); } - if (symbolType == SymbolType.Nft || symbolType == SymbolType.NftCollection) + + if (inputSymbolType == SymbolType.Nft || inputSymbolType == SymbolType.NftCollection) { - Assert(input.Symbol.Length <= TokenContractConstants.NFTSymbolMaxLength, "Invalid NFT symbol length"); + Assert(symbol.Length <= TokenContractConstants.NFTSymbolMaxLength, "Invalid NFT symbol length"); var duplicatedToken = State.TokenInfos[symbols.First()]; - Assert( duplicatedToken == null || duplicatedToken.Equals(empty),"Token name prefix can not be duplicated"); + Assert(duplicatedToken == null || duplicatedToken.Equals(empty), "Token name prefix can not be duplicated"); } - - - + var existing = State.TokenInfos[symbol]; + Assert(existing == null || existing.Equals(empty), "Token already exists."); + Assert(!string.IsNullOrEmpty(symbol) && symbol.All(IsValidSymbolChar), + "Invalid symbol."); } private void CheckCrossChainTokenContractRegistrationControllerAuthority() diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 70ff104bc3..9d8b1a2d40 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -24,7 +24,9 @@ private Empty CreateNFTInfo(CreateInput input) { input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoOwnerSymbol,out var ownerSymbol); input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoExpireTime,out var expirationTime); - Assert(!string.IsNullOrEmpty(ownerSymbol) && State.TokenInfos[ownerSymbol] == null,"seed_owned_symbol is empty "); + + Assert(!string.IsNullOrEmpty(ownerSymbol),"seed_owned_symbol is empty "); + TokenSymBolNameCheck(ownerSymbol); Assert(!string.IsNullOrEmpty(expirationTime) && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime),"seed_owned_symbol is expired "); var oldSymbolSeed = State.SymbolSeedMap[ownerSymbol]; diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs index cd0dd1faf2..acfcc0d357 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Threading.Tasks; using AElf.CSharp.Core; +using AElf.CSharp.Core.Extension; +using AElf.Kernel; using AElf.Types; using Google.Protobuf.WellKnownTypes; using Shouldly; @@ -667,4 +669,125 @@ public async Task NftIssue_Approve_TransferFrom() }); ownerBalanceOutput.Balance.ShouldBe(90); } + + [Fact(DisplayName = "[seed-nft] ResetExternalInfo Test")] + public async Task ResetExternalInfoInputTest() + { + var createInput = await CreateSeedNftAsync(TokenContractStub,new CreateInput + { + Issuer = DefaultAddress, + Symbol = "XYZ" + }); + + var symbol = createInput.Symbol; + createInput.ExternalInfo.Value["__seed_exp_time"] = "1234"; + // permission check + var exceptionRes = await TokenContractStubUser.ResetExternalInfo.SendWithExceptionAsync(new ResetExternalInfoInput + { + Symbol = createInput.Symbol, + ExternalInfo = createInput.ExternalInfo + }); + exceptionRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + exceptionRes.TransactionResult.Error.ShouldContain("No permission to reset external info"); + var result = await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + { + Symbol = createInput.Symbol, + ExternalInfo = createInput.ExternalInfo + }); + var tokenInfoRs = await TokenContractStub.GetTokenInfo.SendAsync(new GetTokenInfoInput + { + Symbol = symbol, + }); + tokenInfoRs.Output.ExternalInfo.Value["__seed_exp_time"].ShouldBe("1234"); + + + } + + [Fact(DisplayName = "[token] create Test")] + public async Task CreateTokenTest() + { + var res = await CreateMutiTokenAsync(TokenContractStub,new CreateInput + { + Symbol = "XYZ", + TokenName = "Trump Digital Trading Cards #1155", + TotalSupply = TotalSupply, + Decimals = 0, + Issuer = DefaultAddress, + IssueChainId = _chainId, + }); + res.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + // check symbol repeat + var exceptionRes = await CreateSeedNftWithExceptionAsync(TokenContractStub,new CreateInput + { + Symbol = "XYZ", + TokenName = "Trump Digital Trading Cards #1155", + TotalSupply = TotalSupply, + Decimals = 0, + Issuer = DefaultAddress, + IssueChainId = _chainId, + }); + exceptionRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + exceptionRes.TransactionResult.Error.ShouldContain("Token already exists"); + // check collection symbol prefix duplicated + var failCollection = await CreateSeedNftWithExceptionAsync(TokenContractStub,new CreateInput + { + TokenName = "Trump Digital Trading Cards #1155", + TotalSupply = TotalSupply, + Decimals = 0, + Issuer = DefaultAddress, + IssueChainId = _chainId, + Symbol = "XYZ-0" + }); + failCollection.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + failCollection.TransactionResult.Error.ShouldContain("Token name prefix can not be duplicated"); + + var successCollection = await CreateMutiTokenAsync(TokenContractStub,new CreateInput + { + TokenName = "Trump Digital Trading Cards #1155", + TotalSupply = TotalSupply, + Decimals = 0, + Issuer = DefaultAddress, + IssueChainId = _chainId, + Symbol = "GHJ-0" + }); + successCollection.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + // check ft symbol prefix duplicated + var fTokenAsync = await CreateSeedNftWithExceptionAsync(TokenContractStub,new CreateInput + { + TokenName = "Trump Digital Trading Cards #1155", + TotalSupply = TotalSupply, + Decimals = 0, + Issuer = DefaultAddress, + IssueChainId = _chainId, + Symbol = "GHJ" + }); + fTokenAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + fTokenAsync.TransactionResult.Error.ShouldContain("Token name prefix can not be duplicated"); + + var nftAsync = await CreateMutiTokenAsync(TokenContractStub,new CreateInput + { + TokenName = "Trump Digital Trading Cards #1155", + TotalSupply = TotalSupply, + Decimals = 0, + Issuer = DefaultAddress, + IssueChainId = _chainId, + Symbol = "GHJ-1" + }); + fTokenAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + fTokenAsync.TransactionResult.Error.ShouldContain("Token name prefix can not be duplicated"); + var createInput = BuildSeedCreateInput(new CreateInput() + { + Symbol = "GHJ-2" + }); + createInput.ExternalInfo.Value["__seed_owned_symbol"] = ""; + var ownError = await TokenContractStub.Create.SendWithExceptionAsync(createInput); + ownError.TransactionResult.Error.ShouldContain("seed_owned_symbol is empty"); + var createInputExpire = BuildSeedCreateInput(new CreateInput() + { + Symbol = "GHJ-3" + }); + createInputExpire.ExternalInfo.Value["__seed_exp_time"] = "1234"; + var expireError = await TokenContractStub.Create.SendWithExceptionAsync(createInputExpire); + expireError.TransactionResult.Error.ShouldContain("seed_owned_symbol is expired"); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs index 8c0b4f7439..4ab8455a0b 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs @@ -64,12 +64,7 @@ public MultiTokenContractTestBase() ParliamentContractStub = GetTester( ParliamentContractAddress, DefaultKeyPair); - // EconomicContractStub = GetTester( - // SystemContractAddresses[EconomicContractName], - // DefaultKeyPair); - - // AsyncHelper.RunSync(()=>InitializeEconomicContract()) ; - AsyncHelper.RunSync(() => SubmitAndApproveProposalOfDefaultParliament(TokenContractAddress, + AsyncHelper.RunSync(() => SubmitAndApproveProposalOfDefaultParliament(TokenContractAddress, nameof(TokenContractStub.Create), new CreateInput() { Symbol = "ELF", @@ -171,8 +166,31 @@ internal async Task CreateSeedNftCollection(TokenContractImplContainer.TokenCont } - internal async Task CreateSeedNftAsync(TokenContractImplContainer.TokenContractImplStub stub, + internal async Task CreateSeedNftAsync(TokenContractImplContainer.TokenContractImplStub stub, CreateInput createInput) + { + var input = BuildSeedCreateInput(createInput); + await stub.Create.SendAsync(input); + await stub.Issue.SendAsync(new IssueInput + { + + Symbol = input.Symbol, + Amount = 1, + Memo = "ddd", + To = createInput.Issuer + }); + return input; + } + + internal async Task> CreateSeedNftWithExceptionAsync(TokenContractImplContainer.TokenContractImplStub stub, + CreateInput createInput) + { + var input = BuildSeedCreateInput(createInput); + return await stub.Create.SendWithExceptionAsync(input); + + } + + internal CreateInput BuildSeedCreateInput(CreateInput createInput) { Interlocked.Increment(ref SeedNum); var input = new CreateInput @@ -182,22 +200,13 @@ internal async Task CreateSeedNftAsync(TokenContractImplContainer.TokenContractI IsBurnable = true, TokenName = "seed token" + SeedNum, TotalSupply = 1, - Issuer = createInput.Issuer, + Issuer = DefaultAddress, ExternalInfo = new ExternalInfo(), LockWhiteList = { TokenContractAddress } - }; input.ExternalInfo.Value["__seed_owned_symbol"] = createInput.Symbol; input.ExternalInfo.Value["__seed_exp_time"] = TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString(); - await stub.Create.SendAsync(input); - var result = await stub.Issue.SendAsync(new IssueInput - { - - Symbol = input.Symbol, - Amount = 1, - Memo = "ddd", - To = createInput.Issuer - }); + return input; } internal async Task> CreateMutiTokenAsync(TokenContractImplContainer.TokenContractImplStub stub, From ddaf71e95e42f69ff03d035aee6b43efc1055006 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Tue, 27 Jun 2023 11:56:39 +0800 Subject: [PATCH 093/139] fix: update nft create check --- contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index f93f2716b2..5cb750ed2d 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -219,9 +219,14 @@ private void TokenSymBolNameCheck( string symbol) if (inputSymbolType == SymbolType.Nft || inputSymbolType == SymbolType.NftCollection) { Assert(symbol.Length <= TokenContractConstants.NFTSymbolMaxLength, "Invalid NFT symbol length"); + } + + if (inputSymbolType == SymbolType.NftCollection) + { var duplicatedToken = State.TokenInfos[symbols.First()]; Assert(duplicatedToken == null || duplicatedToken.Equals(empty), "Token name prefix can not be duplicated"); } + var existing = State.TokenInfos[symbol]; Assert(existing == null || existing.Equals(empty), "Token already exists."); Assert(!string.IsNullOrEmpty(symbol) && symbol.All(IsValidSymbolChar), From 8e4c94d4de8fd7e1bd3406c6f2b3beb56555a9d2 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Tue, 27 Jun 2023 13:51:47 +0800 Subject: [PATCH 094/139] feat: change delegate suport parallel. --- .../TokenContractConstants.cs | 2 +- .../TokenContractState.cs | 2 +- .../TokenContract_ACS2_StatePathsProvider.cs | 53 ++++++++++++------ .../BVT/ACS2_TokenResourceTests.cs | 54 +++++++++++++++++++ .../MultiTokenContractTestBase.cs | 13 ++++- 5 files changed, 105 insertions(+), 19 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs index 2f407988d3..89b44c2dee 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs @@ -14,7 +14,7 @@ public static class TokenContractConstants public const string LockCallbackExternalInfoKey = "aelf_lock_callback"; public const string UnlockCallbackExternalInfoKey = "aelf_unlock_callback"; public const string LogEventExternalInfoKey = "aelf_log_event"; - public const int DELEGATEE_MAX_COUNT = 128; + public const int DELEGATEE_MAX_COUNT = 24; public const char NFTSymbolSeparator = '-'; public const int NFTSymbolMaxLength = 30; public const string UserContractMethodFeeKey = "UserContractMethodFee"; diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState.cs b/contract/AElf.Contracts.MultiToken/TokenContractState.cs index 4e5dddc488..eb0c54807e 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState.cs @@ -58,5 +58,5 @@ public partial class TokenContractState : ContractState /// /// delegator address -> contract address -> method name -> delegatee info /// - public MappedState TransactionFeeDelegateInfoMap { get; set; } + public MappedState TransactionFeeDelegateInfoMap { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index 304886f51f..15c5fd4971 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Linq; using AElf.Standards.ACS2; using AElf.Types; @@ -30,7 +31,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) }; AddPathForTransactionFee(resourceInfo, txn.From.ToString(), txn.MethodName); - AddPathForDelegatees(resourceInfo, txn.From, args.Symbol, txn.MethodName); + AddPathForDelegatees(resourceInfo, txn.From, txn.To, txn.MethodName); AddPathForTransactionFeeFreeAllowance(resourceInfo, txn.From); return resourceInfo; @@ -58,7 +59,7 @@ public override ResourceInfo GetResourceInfo(Transaction txn) }; AddPathForTransactionFee(resourceInfo, txn.From.ToString(), txn.MethodName); - AddPathForDelegatees(resourceInfo, txn.From, args.Symbol, txn.MethodName); + AddPathForDelegatees(resourceInfo, txn.From, txn.To, txn.MethodName); AddPathForTransactionFeeFreeAllowance(resourceInfo, txn.From); return resourceInfo; @@ -99,24 +100,44 @@ private ScopedStatePath GetPath(params string[] parts) }; } - private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from, string symbol, string methodName) + private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from, Address to, string methodName) { - var allDelegatees = State.TransactionFeeDelegateesMap[from]; + var delegateeList = new List(); + //get and add first-level delegatee list + delegateeList.AddRange(GetDelegateeList(from, to, methodName)); + var secondDelegateeList = new List(); + //get and add second-level delegatee list + foreach (var delegateeAddress in delegateeList.Select(Address.FromBase58)) + { + //delegatee of the first-level delegate is delegator of the second-level delegate + secondDelegateeList.AddRange(GetDelegateeList(delegateeAddress, to, methodName)); + } + delegateeList.AddRange(secondDelegateeList); + + foreach (var delegatee in delegateeList) + { + AddPathForTransactionFee(resourceInfo, delegatee, methodName); + AddPathForTransactionFeeFreeAllowance(resourceInfo, Address.FromBase58(delegatee)); + } + } + + private List GetDelegateeList(Address delegator, Address to, string methodName) + { + var delegateeList = new List(); + var allDelegatees = State.TransactionFeeDelegateesMap[delegator]; + var allDelegateInfos = State.TransactionFeeDelegateInfoMap[delegator][to][methodName]; + if (allDelegatees != null) { - foreach (var delegations in allDelegatees.Delegatees.Keys) - { - if (delegations == null) return; - var add = Address.FromBase58(delegations).ToString(); - - AddPathForTransactionFee(resourceInfo, add, methodName); - AddPathForTransactionFeeFreeAllowance(resourceInfo, Address.FromBase58(delegations)); - resourceInfo.WritePaths.Add(GetPath(nameof(TokenContractState.TransactionFeeFreeAllowances), add, - symbol)); - resourceInfo.WritePaths.Add( - GetPath(nameof(TokenContractState.TransactionFeeFreeAllowancesLastRefreshTimes), add, symbol)); - } + delegateeList.AddRange(allDelegatees.Delegatees.Keys.ToList()); } + + if (allDelegateInfos != null) + { + delegateeList.AddRange(allDelegateInfos.Delegatees.Keys.ToList()); + } + + return delegateeList; } private void AddPathForTransactionFeeFreeAllowance(ResourceInfo resourceInfo, Address from) diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs index c7dd514896..815f43da3d 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Threading.Tasks; using AElf.CSharp.Core.Extension; using AElf.Kernel; @@ -129,7 +130,60 @@ public async Task ACS2_GetResourceInfo_Transfer_MultiToken_Test() result1.NonParallelizable.ShouldBeFalse(); result1.WritePaths.Count.ShouldBeGreaterThan(0); } + + [Fact] + public async Task ACS2_GetResourceInfo_TransferFrom_WithDelegate_Test() + { + await CreateNativeTokenAsync(); + var delegations1 = new Dictionary + { + [NativeToken] = 1000, + }; + var delegateInfo1 = new DelegateInfo + { + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractStub.TransferFrom), + Delegations = + { + delegations1 + }, + IsUnlimitedDelegate = false + }; + await TokenContractStubUser.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = Accounts[0].Address, + DelegateInfoList = { delegateInfo1 } + }); + await TokenContractStubDelegate.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = Accounts[0].Address, + DelegateInfoList = { delegateInfo1 } + }); + await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User1Address, + DelegateInfoList = { delegateInfo1 } + }); + await TokenContractStubDelegate3.SetTransactionFeeDelegateInfos.SendAsync(new SetTransactionFeeDelegateInfosInput + { + DelegatorAddress = User2Address, + DelegateInfoList = { delegateInfo1 } + }); + var transaction = GenerateTokenTransaction(Accounts[0].Address, nameof(TokenContractStub.TransferFrom), + new TransferFromInput + { + Amount = 100, + Symbol = NativeToken, + From = Accounts[1].Address, + To = Accounts[2].Address, + Memo = "Test get resource" + }); + var result = await Acs2BaseStub.GetResourceInfo.CallAsync(transaction); + result.NonParallelizable.ShouldBeFalse(); + result.WritePaths.Count.ShouldBe(9); + + } [Fact] public async Task ACS2_GetResourceInfo_DonateResourceToken_Test() { diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs index 427167bfef..e0ab84e6fd 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs @@ -25,6 +25,10 @@ public class MultiTokenContractTestBase : ContractTestBase(TokenContractAddress, User1KeyPair); TokenContractStubDelegate = GetTester(TokenContractAddress, User2KeyPair); + TokenContractStubDelegate2 = + GetTester(TokenContractAddress, User3KeyPair); + TokenContractStubDelegate3 = + GetTester(TokenContractAddress, User4KeyPair); Acs2BaseStub = GetTester(TokenContractAddress, DefaultKeyPair); TreasuryContractStub = GetTester( @@ -67,7 +75,10 @@ public MultiTokenContractTestBase() protected Address User1Address => Accounts[10].Address; protected ECKeyPair User2KeyPair => Accounts[11].KeyPair; protected Address User2Address => Accounts[11].Address; - + protected ECKeyPair User3KeyPair => Accounts[12].KeyPair; + protected Address User3Address => Accounts[12].Address; + protected ECKeyPair User4KeyPair => Accounts[13].KeyPair; + protected Address User4Address => Accounts[13].Address; protected List InitialCoreDataCenterKeyPairs => Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); From 8dcaedf1cd452869563d8a05db833af0d17b2eef Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Tue, 27 Jun 2023 15:37:15 +0800 Subject: [PATCH 095/139] feat: add seedNft ut --- .../TokenContract_Actions.cs | 39 ++-- .../TokenContract_Helper.cs | 2 +- .../BVT/NftApplicationTests.cs | 173 ++++++++++++++---- .../MultiTokenContractTestBase.cs | 51 +++--- 4 files changed, 182 insertions(+), 83 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 323a66e3df..be0063261d 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -45,7 +45,7 @@ public override Empty Create(CreateInput input) private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType.Token) { - AssertValidCreateInput(input, symbolType); + AssertValidCreateInput(input); if (symbolType == SymbolType.Token || symbolType == SymbolType.NftCollection) { if (!IsAddressInCreateWhiteList(Context.Sender) && input.Symbol != TokenContractConstants.SeedCollectionId) @@ -54,10 +54,12 @@ private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType. CheckSeedNft(symbolSeed, input.Symbol); // seed nft for one-time use only long balance = State.Balances[Context.Sender][symbolSeed]; - DoTransferFrom(Context.Sender, Context.Self, Context.Self, symbolSeed, balance,""); - BurnWithAddress(new BurnInput { + DoTransferFrom(Context.Sender, Context.Self, Context.Self, symbolSeed, balance, ""); + BurnWithAddress(new BurnInput + { Symbol = symbolSeed, - Amount = balance},Context.Self); + Amount = balance + }, Context.Self); } } @@ -100,19 +102,22 @@ private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType. return new Empty(); } - - private void CheckSeedNft(string symbolSeed,String symbol) + + private void CheckSeedNft(string symbolSeed, String symbol) { - Assert(!string.IsNullOrEmpty(symbolSeed),"Seed NFT is not exist"); + Assert(!string.IsNullOrEmpty(symbolSeed), "Seed NFT is not exist"); var tokenInfo = State.TokenInfos[symbolSeed]; - Assert(tokenInfo != null,"Seed NFT is not exist"); - Assert(State.Balances[Context.Sender][symbolSeed] > 0,"owner doesn't own enough balance"); - Assert(tokenInfo.ExternalInfo != null ,"seed_owned_symbol is empty "); - tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoOwnerSymbol,out var ownedSymbol); - Assert(ownedSymbol == symbol ,"seed_owned_symbol and input_symbol is inconsistent "); - tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoExpireTime,out var expirationTime); - Assert(!string.IsNullOrEmpty(expirationTime) - && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime),"seed_owned_symbol is expired "); + Assert(tokenInfo != null, "Seed NFT is not exist"); + Assert(State.Balances[Context.Sender][symbolSeed] > 0, "owner doesn't own enough balance"); + Assert(tokenInfo.ExternalInfo != null && !tokenInfo.ExternalInfo.Equals(new ExternalInfo()), + "seed_owned_symbol is empty "); + tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoOwnerSymbol, + out var ownedSymbol); + Assert(ownedSymbol == symbol, "seed_owned_symbol and input_symbol is inconsistent "); + tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoExpireTime, + out var expirationTime); + Assert(!string.IsNullOrEmpty(expirationTime) + && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime), "seed_owned_symbol is expired "); } @@ -265,10 +270,10 @@ public override Empty UnApprove(UnApproveInput input) public override Empty Burn(BurnInput input) { - return BurnWithAddress(input,Context.Sender); + return BurnWithAddress(input, Context.Sender); } - private Empty BurnWithAddress(BurnInput input,Address address) + private Empty BurnWithAddress(BurnInput input, Address address) { var tokenInfo = AssertValidToken(input.Symbol, input.Amount); Assert(tokenInfo.IsBurnable, "The token is not burnable."); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 5cb750ed2d..c5dd22bdd3 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -190,7 +190,7 @@ private int GetIssueChainId(string symbol) return tokenInfo.IssueChainId; } - private void AssertValidCreateInput(CreateInput input, SymbolType symbolType) + private void AssertValidCreateInput(CreateInput input) { Assert(input.TokenName.Length <= TokenContractConstants.TokenNameLength && input.Symbol.Length > 0 diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs index acfcc0d357..fe11a7639b 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs @@ -267,7 +267,7 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() IssueChainId = ChainHelper.ConvertBase58ToChainId("tDVV"), ExternalInfo = input.ExternalInfo }); - + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } } @@ -280,7 +280,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() // Decimals check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -295,7 +295,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Symbol check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = "ABC-ABC", TokenName = input.TokenName, @@ -310,7 +310,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Symbol check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = "ABC-", TokenName = input.TokenName, @@ -325,7 +325,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Symbol check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = "ABC-ABC-1", TokenName = input.TokenName, @@ -340,7 +340,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Issue check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -354,7 +354,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() result.TransactionResult.Error.ShouldContain("NFT issuer must be collection's issuer"); } { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -373,7 +373,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() public async Task MultiTokenContract_Create_NFT_Collection_NotExist() { var input = Nft721Info; - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -392,7 +392,7 @@ public async Task MultiTokenContract_Create_NFT_Already_Exist() { await CreateNftCollectionAndNft(false); var input = Nft721Info; - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput + var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -669,24 +669,25 @@ public async Task NftIssue_Approve_TransferFrom() }); ownerBalanceOutput.Balance.ShouldBe(90); } - + [Fact(DisplayName = "[seed-nft] ResetExternalInfo Test")] public async Task ResetExternalInfoInputTest() { - var createInput = await CreateSeedNftAsync(TokenContractStub,new CreateInput + var createInput = await CreateSeedNftAsync(TokenContractStub, new CreateInput { Issuer = DefaultAddress, Symbol = "XYZ" }); - + var symbol = createInput.Symbol; createInput.ExternalInfo.Value["__seed_exp_time"] = "1234"; // permission check - var exceptionRes = await TokenContractStubUser.ResetExternalInfo.SendWithExceptionAsync(new ResetExternalInfoInput - { - Symbol = createInput.Symbol, - ExternalInfo = createInput.ExternalInfo - }); + var exceptionRes = await TokenContractStubUser.ResetExternalInfo.SendWithExceptionAsync( + new ResetExternalInfoInput + { + Symbol = createInput.Symbol, + ExternalInfo = createInput.ExternalInfo + }); exceptionRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); exceptionRes.TransactionResult.Error.ShouldContain("No permission to reset external info"); var result = await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() @@ -699,14 +700,12 @@ public async Task ResetExternalInfoInputTest() Symbol = symbol, }); tokenInfoRs.Output.ExternalInfo.Value["__seed_exp_time"].ShouldBe("1234"); - - } - + [Fact(DisplayName = "[token] create Test")] public async Task CreateTokenTest() { - var res = await CreateMutiTokenAsync(TokenContractStub,new CreateInput + var res = await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = "XYZ", TokenName = "Trump Digital Trading Cards #1155", @@ -717,7 +716,7 @@ public async Task CreateTokenTest() }); res.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); // check symbol repeat - var exceptionRes = await CreateSeedNftWithExceptionAsync(TokenContractStub,new CreateInput + var exceptionRes = await CreateSeedNftWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = "XYZ", TokenName = "Trump Digital Trading Cards #1155", @@ -729,7 +728,7 @@ public async Task CreateTokenTest() exceptionRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); exceptionRes.TransactionResult.Error.ShouldContain("Token already exists"); // check collection symbol prefix duplicated - var failCollection = await CreateSeedNftWithExceptionAsync(TokenContractStub,new CreateInput + var failCollection = await CreateSeedNftWithExceptionAsync(TokenContractStub, new CreateInput { TokenName = "Trump Digital Trading Cards #1155", TotalSupply = TotalSupply, @@ -741,7 +740,7 @@ public async Task CreateTokenTest() failCollection.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); failCollection.TransactionResult.Error.ShouldContain("Token name prefix can not be duplicated"); - var successCollection = await CreateMutiTokenAsync(TokenContractStub,new CreateInput + var successCollection = await CreateMutiTokenAsync(TokenContractStub, new CreateInput { TokenName = "Trump Digital Trading Cards #1155", TotalSupply = TotalSupply, @@ -752,7 +751,7 @@ public async Task CreateTokenTest() }); successCollection.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); // check ft symbol prefix duplicated - var fTokenAsync = await CreateSeedNftWithExceptionAsync(TokenContractStub,new CreateInput + var fTokenAsync = await CreateSeedNftWithExceptionAsync(TokenContractStub, new CreateInput { TokenName = "Trump Digital Trading Cards #1155", TotalSupply = TotalSupply, @@ -763,31 +762,127 @@ public async Task CreateTokenTest() }); fTokenAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); fTokenAsync.TransactionResult.Error.ShouldContain("Token name prefix can not be duplicated"); - - var nftAsync = await CreateMutiTokenAsync(TokenContractStub,new CreateInput - { - TokenName = "Trump Digital Trading Cards #1155", - TotalSupply = TotalSupply, - Decimals = 0, - Issuer = DefaultAddress, - IssueChainId = _chainId, - Symbol = "GHJ-1" - }); - fTokenAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - fTokenAsync.TransactionResult.Error.ShouldContain("Token name prefix can not be duplicated"); + + var createInput = BuildSeedCreateInput(new CreateInput() { - Symbol = "GHJ-2" + Symbol = "GH" }); createInput.ExternalInfo.Value["__seed_owned_symbol"] = ""; var ownError = await TokenContractStub.Create.SendWithExceptionAsync(createInput); ownError.TransactionResult.Error.ShouldContain("seed_owned_symbol is empty"); var createInputExpire = BuildSeedCreateInput(new CreateInput() { - Symbol = "GHJ-3" + Symbol = "GHT" }); createInputExpire.ExternalInfo.Value["__seed_exp_time"] = "1234"; var expireError = await TokenContractStub.Create.SendWithExceptionAsync(createInputExpire); expireError.TransactionResult.Error.ShouldContain("seed_owned_symbol is expired"); + // create nft + var nftSuccessAsync = await TokenContractStub.Create.SendAsync(new CreateInput + { + TokenName = "Trump Digital Trading Cards #1155", + TotalSupply = TotalSupply, + Decimals = 0, + Issuer = DefaultAddress, + IssueChainId = _chainId, + Symbol = "GHJ-1" + }); + nftSuccessAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + } + + [Fact(DisplayName = "[feed nft] create Test")] + public async Task FeedNftCreateTest() + { + // symbol expire reCreate success + var createInput = await CreateSeedNftAsync(TokenContractStub, new CreateInput + { + Issuer = DefaultAddress, + Symbol = "XYZ" + }); + + createInput.ExternalInfo.Value["__seed_exp_time"] = "1234"; + await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + { + Symbol = createInput.Symbol, + ExternalInfo = createInput.ExternalInfo + }); + + var input = BuildSeedCreateInput(new CreateInput + { + Issuer = DefaultAddress, + Symbol = "XYZ" + }); + var seedRes = await TokenContractStub.Create.SendAsync(input); + seedRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + // owner doesn't own enough balance + var nftAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); + nftAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + nftAsync.TransactionResult.Error.ShouldContain("owner doesn't own enough balance"); + // ExternalInfo check + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = input.Symbol, + Amount = 1, + Memo = "ddd", + To = DefaultAddress + }); + input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; + + await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + { + Symbol = input.Symbol, + ExternalInfo = input.ExternalInfo + }); + var inconsistentExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); + inconsistentExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + inconsistentExceptionAsync.TransactionResult.Error.ShouldContain( + "seed_owned_symbol and input_symbol is inconsistent"); + + input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ"; + input.ExternalInfo.Value["__seed_exp_time"] = ""; + await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + { + Symbol = input.Symbol, + ExternalInfo = input.ExternalInfo + }); + var expireExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync( + GetCreateInput()); + expireExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + expireExceptionAsync.TransactionResult.Error.ShouldContain("seed_owned_symbol is expired"); + + input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ"; + input.ExternalInfo.Value["__seed_exp_time"] = "1234"; + await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + { + Symbol = input.Symbol, + ExternalInfo = input.ExternalInfo + }); + var expireExceptionAsync1 = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); + expireExceptionAsync1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + expireExceptionAsync1.TransactionResult.Error.ShouldContain("seed_owned_symbol is expired"); + + var s = await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + { + Symbol = input.Symbol, + ExternalInfo = new ExternalInfo() + }); + var emptyExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); + emptyExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + emptyExceptionAsync.TransactionResult.Error.ShouldContain("seed_owned_symbol is empty"); + } + + private CreateInput GetCreateInput() + { + return new CreateInput + { + TokenName = "Trump Digital Trading Cards #1155", + TotalSupply = TotalSupply, + Decimals = 0, + Issuer = DefaultAddress, + IssueChainId = _chainId, + Symbol = "XYZ" + }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs index 4ab8455a0b..4adb393235 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs @@ -36,7 +36,7 @@ public class MultiTokenContractTestBase : ContractTestBase( ParliamentContractAddress, DefaultKeyPair); AsyncHelper.RunSync(() => SubmitAndApproveProposalOfDefaultParliament(TokenContractAddress, - nameof(TokenContractStub.Create), new CreateInput() - { - Symbol = "ELF", - Decimals = 0, - IsBurnable = true, - TokenName = "ELF2", - TotalSupply = 1, - Issuer = DefaultAddress, - ExternalInfo = new ExternalInfo() - })); - - AsyncHelper.RunSync(()=>CreateSeedNftCollection(TokenContractStub)) ; + nameof(TokenContractStub.Create), new CreateInput() + { + Symbol = "ELF", + Decimals = 0, + IsBurnable = true, + TokenName = "ELF2", + TotalSupply = 1, + Issuer = DefaultAddress, + ExternalInfo = new ExternalInfo() + })); + + AsyncHelper.RunSync(() => CreateSeedNftCollection(TokenContractStub)); } protected long AliceCoinTotalAmount => 1_000_000_000_0000000L; @@ -99,7 +99,7 @@ public MultiTokenContractTestBase() protected Hash OtherBasicFunctionContractName => HashHelper.ComputeFrom("AElf.TestContractNames.OtherBasicFunction"); - + protected Address OtherBasicFunctionContractAddress { get; set; } internal BasicFunctionContractContainer.BasicFunctionContractStub OtherBasicFunctionContractStub { get; set; } @@ -110,7 +110,7 @@ internal ParliamentContractImplContainer.ParliamentContractImplStub GetParliamen return GetTester(ParliamentContractAddress, keyPair); } - + private async Task SubmitAndApproveProposalOfDefaultParliament(Address contractAddress, string methodName, IMessage message) { @@ -120,9 +120,8 @@ private async Task SubmitAndApproveProposalOfDefaultParliament(Address contractA defaultParliamentAddress, methodName, message); await ApproveWithMinersAsync(proposalId); var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); - } - + private async Task CreateProposalAsync(Address contractAddress, Address organizationAddress, string methodName, IMessage input) { @@ -140,7 +139,7 @@ private async Task CreateProposalAsync(Address contractAddress, Address or return proposalId; } - + private async Task ApproveWithMinersAsync(Hash proposalId) { foreach (var bp in InitialCoreDataCenterKeyPairs) @@ -164,7 +163,7 @@ internal async Task CreateSeedNftCollection(TokenContractImplContainer.TokenCont }; await stub.Create.SendAsync(input); } - + internal async Task CreateSeedNftAsync(TokenContractImplContainer.TokenContractImplStub stub, CreateInput createInput) @@ -173,7 +172,6 @@ internal async Task CreateSeedNftAsync(TokenContractImplContainer.T await stub.Create.SendAsync(input); await stub.Issue.SendAsync(new IssueInput { - Symbol = input.Symbol, Amount = 1, Memo = "ddd", @@ -181,13 +179,13 @@ await stub.Issue.SendAsync(new IssueInput }); return input; } - - internal async Task> CreateSeedNftWithExceptionAsync(TokenContractImplContainer.TokenContractImplStub stub, + + internal async Task> CreateSeedNftWithExceptionAsync( + TokenContractImplContainer.TokenContractImplStub stub, CreateInput createInput) { var input = BuildSeedCreateInput(createInput); - return await stub.Create.SendWithExceptionAsync(input); - + return await stub.Create.SendWithExceptionAsync(input); } internal CreateInput BuildSeedCreateInput(CreateInput createInput) @@ -209,13 +207,14 @@ internal CreateInput BuildSeedCreateInput(CreateInput createInput) return input; } - internal async Task> CreateMutiTokenAsync(TokenContractImplContainer.TokenContractImplStub stub, + internal async Task> CreateMutiTokenAsync( + TokenContractImplContainer.TokenContractImplStub stub, CreateInput createInput) { await CreateSeedNftAsync(stub, createInput); return await stub.Create.SendAsync(createInput); } - + internal async Task> CreateMutiTokenWithExceptionAsync( TokenContractImplContainer.TokenContractImplStub stub, CreateInput createInput) { From 3935762cadfaf3ee043f579502c33acfd7e053d9 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 27 Jun 2023 18:49:04 +0800 Subject: [PATCH 096/139] fix: ut --- AElf.All.sln | 7 ++ protobuf/test_mock_parliament_contract.proto | 24 ++++ .../AElf.ContractTestBase.csproj | 14 +++ .../ContractTestKit/ContractTestBase.cs | 36 ++++++ src/AElf.ContractTestKit/ContractTestBase.cs | 42 +++++++ .../ReferendumContractTest.cs | 42 +++++++ .../AElf.Contracts.TestBase/ContractTester.cs | 2 +- ...ntracts.TestContract.MockParliament.csproj | 31 ++++++ .../Contract.cs | 19 ++++ .../State.cs | 9 ++ ...t.ExecutionPluginForMethodFee.Tests.csproj | 8 ++ .../ExecutePluginTransactionDirectlyTest.cs | 104 ++++++++---------- .../ExecutionPluginForMethodFeeTestBase.cs | 79 +++++++++---- ...ExecutionPluginForMethodFeeWithForkTest.cs | 62 ++++++----- ...utionPluginForUserContractMethodFeeTest.cs | 40 ++----- ...ExecutionPluginForResourceFee.Tests.csproj | 17 ++- .../ExecutionPluginForResourceFeeTestBase.cs | 57 +++++----- ...ExecutionPluginForResourceFeeTestModule.cs | 1 + 18 files changed, 414 insertions(+), 180 deletions(-) create mode 100644 protobuf/test_mock_parliament_contract.proto create mode 100644 test/AElf.Contracts.TestContract.MockParliament/AElf.Contracts.TestContract.MockParliament.csproj create mode 100644 test/AElf.Contracts.TestContract.MockParliament/Contract.cs create mode 100644 test/AElf.Contracts.TestContract.MockParliament/State.cs diff --git a/AElf.All.sln b/AElf.All.sln index 7554592ce4..bb49705c13 100644 --- a/AElf.All.sln +++ b/AElf.All.sln @@ -369,6 +369,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps.UnitTes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract.csproj", "{AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.MockParliament", "test\AElf.Contracts.TestContract.MockParliament\AElf.Contracts.TestContract.MockParliament.csproj", "{C7EDD0EB-CCE7-4B06-BF1E-F9CA7F149097}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1059,6 +1061,10 @@ Global {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}.Debug|Any CPU.Build.0 = Debug|Any CPU {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}.Release|Any CPU.ActiveCfg = Release|Any CPU {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}.Release|Any CPU.Build.0 = Release|Any CPU + {C7EDD0EB-CCE7-4B06-BF1E-F9CA7F149097}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7EDD0EB-CCE7-4B06-BF1E-F9CA7F149097}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7EDD0EB-CCE7-4B06-BF1E-F9CA7F149097}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7EDD0EB-CCE7-4B06-BF1E-F9CA7F149097}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1245,5 +1251,6 @@ Global {1B44277E-74EB-49B2-B8FD-05C29EE51985} = {4E54480A-D155-43ED-9736-1A5BE7957211} {D1A00CD6-958E-4E9F-8325-354309E3029E} = {4E54480A-D155-43ED-9736-1A5BE7957211} {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {C7EDD0EB-CCE7-4B06-BF1E-F9CA7F149097} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} EndGlobalSection EndGlobal diff --git a/protobuf/test_mock_parliament_contract.proto b/protobuf/test_mock_parliament_contract.proto new file mode 100644 index 0000000000..1024e5cd7d --- /dev/null +++ b/protobuf/test_mock_parliament_contract.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; + +import "aelf/options.proto"; +import "aelf/core.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/wrappers.proto"; + +option csharp_namespace = "AElf.Contracts.TestContract.MockParliament"; + +service MockParliamentContract { + option (aelf.csharp_state) = "AElf.Contracts.TestContract.MockParliament.MockParliamentContractState"; + + rpc Initialize(InitializeInput) returns (google.protobuf.Empty) { + } + + rpc GetDefaultOrganizationAddress (google.protobuf.Empty) returns (aelf.Address) { + option (aelf.is_view) = true; + } +} + +message InitializeInput{ + aelf.Address privileged_proposer = 1; + bool proposer_authority_required = 2; +} diff --git a/src/AElf.ContractTestBase/AElf.ContractTestBase.csproj b/src/AElf.ContractTestBase/AElf.ContractTestBase.csproj index 40a637defe..cb38e8bf85 100644 --- a/src/AElf.ContractTestBase/AElf.ContractTestBase.csproj +++ b/src/AElf.ContractTestBase/AElf.ContractTestBase.csproj @@ -18,6 +18,11 @@ + + false + Contract + PreserveNewest + @@ -39,6 +44,15 @@ Protobuf\Proto\basic_contract_zero.proto + + Protobuf\Proto\parliament_contract.proto + + + Protobuf\Proto\parliament_contract_impl.proto + + + Protobuf\Proto\acs3.proto + diff --git a/src/AElf.ContractTestBase/ContractTestKit/ContractTestBase.cs b/src/AElf.ContractTestBase/ContractTestKit/ContractTestBase.cs index 765afaa90e..f9c435327f 100644 --- a/src/AElf.ContractTestBase/ContractTestKit/ContractTestBase.cs +++ b/src/AElf.ContractTestBase/ContractTestKit/ContractTestBase.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using AElf.Contracts.Parliament; using AElf.CrossChain; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core; @@ -16,7 +17,9 @@ using AElf.Kernel.SmartContract.Application; using AElf.Kernel.Token; using AElf.Standards.ACS0; +using AElf.Standards.ACS3; using AElf.Types; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Volo.Abp; @@ -45,6 +48,9 @@ public ContractTestBase() protected IReadOnlyList Accounts => SampleAccount.Accounts; protected int InitialCoreDataCenterCount => 5; + + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(InitialCoreDataCenterCount).Select(a => a.KeyPair).ToList(); protected Dictionary SystemContractAddresses { get; } = new(); @@ -155,4 +161,34 @@ private IAbpApplication CreateApplication(ChainInitializationDto dto) where T application.Initialize(); return application; } + + protected async Task SubmitAndApproveProposalOfDefaultParliament(Address contractAddress, string methodName, + IMessage message) + { + var parliamentContractStub = GetTester(ParliamentContractAddress, DefaultAccount.KeyPair); + var defaultParliamentAddress = + await parliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + + var proposal = new CreateProposalInput + { + OrganizationAddress = defaultParliamentAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = message.ToByteString(), + ToAddress = contractAddress + }; + var createResult = await parliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; + await ApproveWithMinersAsync(proposalId); + await parliamentContractStub.Release.SendAsync(proposalId); + } + + private async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) + { + var tester = GetTester(ParliamentContractAddress, bp); + await tester.Approve.SendAsync(proposalId); + } + } } \ No newline at end of file diff --git a/src/AElf.ContractTestKit/ContractTestBase.cs b/src/AElf.ContractTestKit/ContractTestBase.cs index 21c26e6aff..5ea3f85012 100644 --- a/src/AElf.ContractTestKit/ContractTestBase.cs +++ b/src/AElf.ContractTestKit/ContractTestBase.cs @@ -1,18 +1,24 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using AElf.ContractDeployer; using AElf.Contracts.Genesis; +using AElf.Contracts.Parliament; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core; +using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Blockchain.Application; using AElf.Kernel.Blockchain.Domain; using AElf.Kernel.Infrastructure; +using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract.Application; using AElf.Standards.ACS0; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; +using Google.Protobuf.WellKnownTypes; using MartinCostello.Logging.XUnit; using Microsoft.Extensions.DependencyInjection; using Volo.Abp; @@ -123,4 +129,40 @@ protected IReadOnlyDictionary GetPatchedCodes(string dir) // ? File.ReadAllBytes(path) // : throw new FileNotFoundException("Contract DLL cannot be found. " + path); // } + + protected async Task SubmitAndApproveProposalOfDefaultParliament(ECKeyPair senderKeyPair, Address parliamentAddress, + Address contractAddress, string methodName, IMessage message) + { + // var parliamentContractStub = + // GetTester(parliamentAddress, senderKeyPair); + // // await parliamentContractStub.Initialize.SendAsync(new AElf.Contracts.Parliament.InitializeInput + // // { + // // PrivilegedProposer = DefaultAccount.Address, + // // ProposerAuthorityRequired = false + // // }); + // var defaultParliamentAddress = + // await parliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + // + // var proposal = new CreateProposalInput + // { + // OrganizationAddress = defaultParliamentAddress, + // ContractMethodName = methodName, + // ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + // Params = message.ToByteString(), + // ToAddress = contractAddress + // }; + // var createResult = await parliamentContractStub.CreateProposal.SendAsync(proposal); + // var proposalId = createResult.Output; + // await ApproveWithMinersAsync(proposalId, parliamentAddress); + // await parliamentContractStub.Release.SendAsync(proposalId); + } + + private async Task ApproveWithMinersAsync(Hash proposalId, Address parliamentAddress) + { + // foreach (var bp in InitialCoreDataCenterKeyPairs) + // { + // var tester = GetTester(parliamentAddress, bp); + // await tester.Approve.SendAsync(proposalId); + // } + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs index e4e87910a0..ba8ca9b78f 100644 --- a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs +++ b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs @@ -1290,6 +1290,48 @@ private CreateProposalInput GetValidCreateProposalInput(Address organizationAddr private async Task CreateProposalAsync(ECKeyPair proposalKeyPair, Address organizationAddress, Timestamp timestamp = null) { + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, TokenContractAddress, + nameof(TokenContractStub.Create), new CreateInput + { + Symbol = "SEED-" + "0", + Decimals = 0, + IsBurnable = true, + TokenName = "seed Collection", + TotalSupply = 1, + Issuer = defaultParliamentAddress, + ExternalInfo = new ExternalInfo() + }); + await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, TokenContractAddress, + nameof(TokenContractStub.Create), new CreateInput + { + Symbol = "SEED-" + "1", + Decimals = 0, + IsBurnable = true, + TokenName = "seed token" + 1, + TotalSupply = 1, + Issuer = defaultParliamentAddress, + ExternalInfo = new ExternalInfo + { + Value = + { + {"__seed_owned_symbol", "NEW"}, + {"__seed_exp_time", TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString()} + } + }, + LockWhiteList = { TokenContractAddress } + }); + + await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, TokenContractAddress, + nameof(TokenContractStub.Issue), new IssueInput + { + Symbol = "SEED-1", + Amount = 1, + Memo = "ddd", + To = organizationAddress + }); + var createInput = new CreateInput { Symbol = "NEW", diff --git a/test/AElf.Contracts.TestBase/ContractTester.cs b/test/AElf.Contracts.TestBase/ContractTester.cs index 2ac2ea3092..8d091c28b4 100644 --- a/test/AElf.Contracts.TestBase/ContractTester.cs +++ b/test/AElf.Contracts.TestBase/ContractTester.cs @@ -186,7 +186,7 @@ public ContractTester(int chainId) public byte[] CrossChainContractCode => GetContractCodeByName(SmartContractTestConstants.CrossChain); - public byte[] ParliamentContractCode => GetContractCodeByName(SmartContractTestConstants.Parliament); + public byte[] ParliamentContractCode => GetContractCodeByName("MockParliament"); public byte[] ConfigurationContractCode => GetContractCodeByName(SmartContractTestConstants.Configuration); diff --git a/test/AElf.Contracts.TestContract.MockParliament/AElf.Contracts.TestContract.MockParliament.csproj b/test/AElf.Contracts.TestContract.MockParliament/AElf.Contracts.TestContract.MockParliament.csproj new file mode 100644 index 0000000000..b9228e40c9 --- /dev/null +++ b/test/AElf.Contracts.TestContract.MockParliament/AElf.Contracts.TestContract.MockParliament.csproj @@ -0,0 +1,31 @@ + + + + net6.0 + 1.2.0 + AElf.Contracts.TestContract.MockParliament + AElf.Contracts.TestContract.MockParliament + + + + + + + + + Protobuf\Proto\authority_info.proto + + + + + + Protobuf\Proto\test_mock_parliament_contract.proto + + + + + + + + + diff --git a/test/AElf.Contracts.TestContract.MockParliament/Contract.cs b/test/AElf.Contracts.TestContract.MockParliament/Contract.cs new file mode 100644 index 0000000000..046457ca88 --- /dev/null +++ b/test/AElf.Contracts.TestContract.MockParliament/Contract.cs @@ -0,0 +1,19 @@ +using AElf.Types; +using Google.Protobuf.WellKnownTypes; + +namespace AElf.Contracts.TestContract.MockParliament; + +public class Contract : MockParliamentContractContainer.MockParliamentContractBase +{ + public override Address GetDefaultOrganizationAddress(Empty input) + { + return State.DefaultOrganizationAddress.Value ?? new Address(); + } + + public override Empty Initialize(InitializeInput input) + { + State.DefaultOrganizationAddress.Value = input.PrivilegedProposer; + + return new Empty(); + } +} \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.MockParliament/State.cs b/test/AElf.Contracts.TestContract.MockParliament/State.cs new file mode 100644 index 0000000000..07fa208914 --- /dev/null +++ b/test/AElf.Contracts.TestContract.MockParliament/State.cs @@ -0,0 +1,9 @@ +using AElf.Sdk.CSharp.State; +using AElf.Types; + +namespace AElf.Contracts.TestContract.MockParliament; + +public partial class MockParliamentContractState : ContractState +{ + public SingletonState
DefaultOrganizationAddress { get; set; } +} \ No newline at end of file diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj index 17473c3736..be41c73b32 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj @@ -85,6 +85,11 @@ Contract PreserveNewest + + false + Contract + PreserveNewest + @@ -107,6 +112,9 @@ Protobuf\Proto\token_contract.proto + + Protobuf\Proto\token_contract_impl.proto + Protobuf\Proto\acs1_plugin_test_contract.proto diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index a72b124533..2c82d25c07 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -79,8 +79,7 @@ public async Task Set_Repeat_Token_Test() } }; var sizeFee = 0; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var beforeChargeBalance = await GetBalanceAsync(address, NativeTokenSymbol); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -129,8 +128,7 @@ public async Task ChargeTransactionFees_With_Different_Transaction_Size_Fee_Toke } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var tokenSymbolList = new[] { NativeTokenSymbol, "CWJ", "YPA" }; var tokenCount = 3; var orderedSymbolList = new string[tokenCount]; @@ -155,9 +153,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, BaseTokenWeight = baseWeight[i] }); } - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var beforeBalanceList = await GetDefaultBalancesAsync(orderedSymbolList); var chargeTransactionFeesInput = new ChargeTransactionFeesInput @@ -214,12 +211,10 @@ public async Task DonateResourceToken_Test(long[] initialBalances, long[] tokenF if (!isMainChain) { var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain), - new InitializeFromParentChainInput - { - Creator = defaultParliament - }); + await TokenContractStub.InitializeFromParentChain.SendAsync(new InitializeFromParentChainInput + { + Creator = defaultParliament + }); } await TokenContractStub.DonateResourceToken.SendAsync(feeMap); @@ -266,10 +261,8 @@ public async Task ClaimTransactionFee_Balance_With_Receiver_Test() { Creator = receiver }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.InitializeFromParentChain), input); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetFeeReceiver), receiver); + await TokenContractImplStub.InitializeFromParentChain.SendAsync(input); + await TokenContractImplStub.SetFeeReceiver.SendAsync(receiver); var beforeBurned = await GetTokenSupplyAmount(tokenSymbol); var beforeBalance = await GetBalanceAsync(receiver, tokenSymbol); var claimFeeInput = new TotalTransactionFeesMap @@ -301,8 +294,7 @@ public async Task FreeAllowancesTest(long threshold, long initialBalance, long f await SetPrimaryTokenSymbolAsync(); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFreeAllowancesConfig { FreeAllowances = new MethodFeeFreeAllowances { @@ -331,8 +323,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); { var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); @@ -359,8 +350,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -425,8 +415,7 @@ public async Task FreeAllowances_MultToken_Test( await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); } - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFreeAllowancesConfig { FreeAllowances = new MethodFeeFreeAllowances { @@ -461,8 +450,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -482,8 +470,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); { var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(DefaultSender); @@ -608,28 +595,28 @@ public async Task ChargeTransactionFee_Delegate( await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeUserBalance, userAddress); } - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFreeAllowancesConfig + { + FreeAllowances = new MethodFeeFreeAllowances { - FreeAllowances = new MethodFeeFreeAllowances + Value = { - Value = + new MethodFeeFreeAllowance { - new MethodFeeFreeAllowance - { - Symbol = basicFeeSymbol, - Amount = baseFeeFreeAmount - }, - new MethodFeeFreeAllowance - { - Symbol = sizeFeeSymbol, - Amount = sizeFeeFreeAmount - } + Symbol = basicFeeSymbol, + Amount = baseFeeFreeAmount + }, + new MethodFeeFreeAllowance + { + Symbol = sizeFeeSymbol, + Amount = sizeFeeFreeAmount } - }, - RefreshSeconds = 100, - Threshold = threshold - }); + } + }, + RefreshSeconds = 100, + Threshold = threshold + }); + { var freeAllowances = await TokenContractStub.GetMethodFeeFreeAllowances.CallAsync(userAddress); if (threshold <= initialBalance) @@ -657,8 +644,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -678,10 +665,9 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); - + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); + var chargeTransactionFeesInput = new ChargeTransactionFeesInput { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), @@ -805,9 +791,8 @@ await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransacti await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, delegateeAddress); await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, delegateeAddress); } - - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + + await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFreeAllowancesConfig { FreeAllowances = new MethodFeeFreeAllowances { @@ -841,8 +826,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -862,8 +846,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var chargeTransactionFeesInput = new ChargeTransactionFeesInput @@ -951,8 +934,7 @@ await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransacti } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index 33fff08c64..ebcb9263fa 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -29,6 +29,44 @@ namespace AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests; public class ExecutionPluginForMethodFeeTestBase : ContractTestBase { + internal Address ParliamentAddress; + internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub; + protected ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; + protected Address DefaultAddress => Accounts[0].Address; + + protected ExecutionPluginForMethodFeeTestBase() + { + AsyncHelper.RunSync(InitializeContracts); + } + + private async Task InitializeContracts() + { + await DeployContractsAsync(); + await InitializedParliament(); + } + + private async Task DeployContractsAsync() + { + const int category = KernelConstants.CodeCoverageRunnerCategory; + // Parliament + { + var code = Codes.Single(kv => kv.Key.Contains("MockParliament")).Value; + ParliamentAddress = await DeploySystemSmartContract(category, code, + ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + ParliamentContractStub = + GetTester(ParliamentAddress, + DefaultSenderKeyPair); + } + } + + private async Task InitializedParliament() + { + await ParliamentContractStub.Initialize.SendAsync(new InitializeInput + { + ProposerAuthorityRequired = false, + PrivilegedProposer = DefaultAddress + }); + } } public class ExecutionPluginForUserContractMethodFeeTestBase : ContractTestBase @@ -115,7 +153,7 @@ private async Task DeployContractsAsync() } // Parliament { - var code = Codes.Single(kv => kv.Key.Contains("Parliament")).Value; + var code = Codes.Single(kv => kv.Key.Contains("MockParliament")).Value; ParliamentAddress = await DeploySystemSmartContract(category, code, ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); ParliamentContractStub = @@ -219,23 +257,23 @@ await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, }); } - protected async Task SetMethodFeeWithProposalAsync(ByteString methodFee) - { - var proposal = await Tester.ExecuteContractWithMiningAsync(_parliamentAddress, - nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), - new CreateProposalInput - { - ContractMethodName = - nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.SetMethodFee), - ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - Params = methodFee, - ToAddress = TokenContractAddress, - OrganizationAddress = await GetParliamentDefaultOrganizationAddressAsync() - }); - var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); - await ApproveWithMinersAsync(proposalId); - await ReleaseProposalAsync(proposalId); - } + // protected async Task SetMethodFeeWithProposalAsync(ByteString methodFee) + // { + // var proposal = await Tester.ExecuteContractWithMiningAsync(_parliamentAddress, + // nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), + // new CreateProposalInput + // { + // ContractMethodName = + // nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.SetMethodFee), + // ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + // Params = methodFee, + // ToAddress = TokenContractAddress, + // OrganizationAddress = await GetParliamentDefaultOrganizationAddressAsync() + // }); + // var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); + // await ApproveWithMinersAsync(proposalId); + // await ReleaseProposalAsync(proposalId); + // } private async Task
GetParliamentDefaultOrganizationAddressAsync() { @@ -295,6 +333,7 @@ protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub2 { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub3 { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractImplStub { get; set; } internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; @@ -349,11 +388,13 @@ private async Task DeployContractsAsync() GetTester(TokenContractAddress, UserKeyPair); TokenContractStubA = GetTester(TokenContractAddress, UserKeyPair); + TokenContractImplStub = + GetTester(TokenContractAddress, DefaultSenderKeyPair); } // Parliament { - var code = Codes.Single(kv => kv.Key.Contains("Parliament")).Value; + var code = Codes.Single(kv => kv.Key.Contains("MockParliament")).Value; var parliamentContractAddress = await DeploySystemSmartContract(category, code, ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); ParliamentContractStub = diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs index e6bebf3081..3d0daac6b9 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs @@ -33,19 +33,20 @@ private async Task> GetTransactionFeesMapAsync(IChainC public async Task ChargeFee_With_Fork_Test() { var amount = 100000; - - await SetMethodFeeWithProposalAsync(new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = + + var r = await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), new MethodFees { - new MethodFee + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = { - Symbol = "ELF", - BasicFee = 100000 + new MethodFee + { + Symbol = "ELF", + BasicFee = 100000 + } } - } - }.ToByteString()); + }); var result = await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput @@ -74,19 +75,20 @@ await SetMethodFeeWithProposalAsync(new MethodFees BlockHash = branchOneBlock.GetHash(), BlockHeight = branchOneBlock.Height }); transactionFeesMap.ShouldBeNull(); - await SetMethodFeeWithProposalAsync(new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = + await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), new MethodFees { - new MethodFee + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = { - Symbol = "ELF", - BasicFee = 200000 + new MethodFee + { + Symbol = "ELF", + BasicFee = 200000 + } } - } - }.ToByteString()); - + }); + result = await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput { @@ -128,18 +130,20 @@ await SetMethodFeeWithProposalAsync(new MethodFees public async Task Claim_Fee_Send_By_User_Fail_Test() { var amount = 100000; - await SetMethodFeeWithProposalAsync(new MethodFees - { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = + + await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, + nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), new MethodFees { - new MethodFee + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = { - Symbol = "ELF", - BasicFee = amount + new MethodFee + { + Symbol = "ELF", + BasicFee = amount + } } - } - }.ToByteString()); + }); await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs index f10baf828c..594a8d03c7 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs @@ -184,14 +184,8 @@ await TokenContractStub.Transfer.SendAsync(new TransferInput Key = ConfigurationKey, Value = transactionFee.ToByteString() }; - { - var organizationAddress = await GetParliamentDefaultOrganizationAddressAsync(); - var proposalId = - await CreateProposalAsync(organizationAddress, createProposalInput, "SetConfiguration"); - await ParliamentContractStub.Approve.SendAsync(proposalId); - var releaseRet = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + + await ConfigurationStub.SetConfiguration.SendAsync(createProposalInput); var originBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { @@ -250,14 +244,7 @@ public async Task ChargeFee_SizeFeeIsFree() Key = ConfigurationKey, Value = transactionFee.ToByteString() }; - { - var organizationAddress = await GetParliamentDefaultOrganizationAddressAsync(); - var proposalId = - await CreateProposalAsync(organizationAddress, createProposalInput, "SetConfiguration"); - await ParliamentContractStub.Approve.SendAsync(proposalId); - var releaseRet = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + await ConfigurationStub.SetConfiguration.SendAsync(createProposalInput); var beforeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = DefaultAddress, @@ -298,14 +285,7 @@ public async Task ChargeFee_SpecConfigurationFee() Key = $"{ConfigurationKey}_{_testContractAddress}_{nameof(TestContractContainer.TestContractStub.TestMethod)}", Value = transactionFee.ToByteString() }; - { - var organizationAddress = await GetParliamentDefaultOrganizationAddressAsync(); - var proposalId = - await CreateProposalAsync(organizationAddress, createProposalInput, "SetConfiguration"); - await ParliamentContractStub.Approve.SendAsync(proposalId); - var releaseRet = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } + await ConfigurationStub.SetConfiguration.SendAsync(createProposalInput); var beforeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = DefaultAddress, @@ -363,10 +343,7 @@ private async Task Initialize() await DeployTestContractAsync(); { - var proposalId = await SetUserContractFeeAsync(1_00000000); - await ParliamentContractStub.Approve.SendAsync(proposalId); - var releaseRet = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + await SetUserContractFeeAsync(1_00000000); var configuration = await ConfigurationStub.GetConfiguration.CallAsync(new StringValue { Value = ConfigurationKey @@ -390,13 +367,10 @@ private async Task CheckTransactionFeesMapAsync(Dictionary transac transactionFeesMap.Value[transactionFee.Key].ShouldBe(transactionFee.Value); } - private async Task SetUserContractFeeAsync(int amount) + private async Task SetUserContractFeeAsync(int amount) { var createProposalInput = SetUserContractFee(amount); - var organizationAddress = await GetParliamentDefaultOrganizationAddressAsync(); - var proposalId = - await CreateProposalAsync(organizationAddress, createProposalInput, "SetConfiguration"); - return proposalId; + await ConfigurationStub.SetConfiguration.SendAsync(createProposalInput); } private async Task
GetParliamentDefaultOrganizationAddressAsync() diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj index 360e3a5f34..4defe6144f 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj @@ -9,7 +9,7 @@ runtime; build; native; contentfiles; analyzers - + all @@ -21,11 +21,11 @@ - - - - - + + + + + @@ -63,6 +63,11 @@ Contract PreserveNewest + + false + Contract + PreserveNewest + diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs index 7d73b285db..99519ddefa 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs @@ -119,6 +119,7 @@ public class ExecutionPluginForResourceFeeTestBase : ContractTestBase kv.Key.Contains("TestContract")).Value; + var code = Codes.Single(kv => kv.Key.Contains("ExecutionPluginForResourceFee.Tests.TestContract")).Value; TestContractAddress = await DeployContractAsync(category, code, HashHelper.ComputeFrom("TestContract"), DefaultSenderKeyPair); TestContractStub = @@ -196,11 +197,11 @@ await DeploySystemSmartContract(category, code, // Parliament { - var code = Codes.Single(kv => kv.Key.Contains("Parliament")).Value; - var parliamentContractAddress = await DeploySystemSmartContract(category, code, + var code = Codes.Single(kv => kv.Key.Contains("MockParliament")).Value; + ParliamentContractAddress = await DeploySystemSmartContract(category, code, ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); ParliamentContractStub = - GetTester(parliamentContractAddress, + GetTester(ParliamentContractAddress, DefaultSenderKeyPair); } @@ -222,18 +223,16 @@ private async Task InitializeTokenAsync() const long issueAmountToConverter = 100_000_000_00000000; //init elf token { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = "ELF", - Decimals = 8, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = totalSupply, - Issuer = DefaultSender, - LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } - }); - - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + await TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = "ELF", + Decimals = 8, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = totalSupply, + Issuer = DefaultSender, + LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } + }); { var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput @@ -258,7 +257,7 @@ private async Task InitializeTokenAsync() //init resource token - CPU { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput + await TokenContractStub.Create.SendAsync(new CreateInput { Symbol = "READ", Decimals = 2, @@ -269,8 +268,6 @@ private async Task InitializeTokenAsync() LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } }); - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { Symbol = "READ", @@ -283,7 +280,7 @@ private async Task InitializeTokenAsync() //init resource token - STO { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput + await TokenContractStub.Create.SendAsync(new CreateInput { Symbol = "STORAGE", Decimals = 2, @@ -294,8 +291,6 @@ private async Task InitializeTokenAsync() LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } }); - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { Symbol = "STORAGE", @@ -308,7 +303,7 @@ private async Task InitializeTokenAsync() //init resource token - NET { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput + await TokenContractStub.Create.SendAsync(new CreateInput { Symbol = "TRAFFIC", Decimals = 2, @@ -319,8 +314,6 @@ private async Task InitializeTokenAsync() LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } }); - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { Symbol = "TRAFFIC", @@ -332,7 +325,7 @@ private async Task InitializeTokenAsync() } //init resource token - WRITE { - var createResult = await TokenContractStub.Create.SendAsync(new CreateInput + await TokenContractStub.Create.SendAsync(new CreateInput { Symbol = "WRITE", Decimals = 2, @@ -343,8 +336,6 @@ private async Task InitializeTokenAsync() LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } }); - createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput { Symbol = "WRITE", @@ -390,7 +381,11 @@ await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync( private async Task InitializeParliament() { - await ParliamentContractStub.Initialize.SendAsync(new Contracts.Parliament.InitializeInput()); + await ParliamentContractStub.Initialize.SendAsync(new Contracts.Parliament.InitializeInput + { + ProposerAuthorityRequired = false, + PrivilegedProposer = DefaultSender + }); } private async Task InitializeAElfConsensus() diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestModule.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestModule.cs index 22d634ad0b..3fb9d1c466 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestModule.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestModule.cs @@ -1,4 +1,5 @@ using AElf.ContractTestKit; +using AElf.Kernel.Consensus.AEDPoS; using AElf.Kernel.FeeCalculation; using AElf.Kernel.FeeCalculation.Infrastructure; using AElf.Kernel.SmartContract.Application; From eee91f75654f825616c029de7d4e03f7785b8a80 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 27 Jun 2023 19:12:11 +0800 Subject: [PATCH 097/139] fix:ut --- ...ecutionPluginForCallThreshold.Tests.csproj | 19 ++++++++++++++ ...ExecutionPluginForCallThresholdTestBase.cs | 26 ++++++++++++++++++- .../ExecutionPluginForMethodFeeTestBase.cs | 1 - 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.csproj index 2577e808ad..572810cff3 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.csproj @@ -47,6 +47,16 @@ Contract PreserveNewest + + false + Contract + PreserveNewest + + + false + Contract + PreserveNewest + @@ -72,6 +82,15 @@ Protobuf\Proto\acs5_plugin_test_contract.proto + + Protobuf\Proto\parliament_contract.proto + + + Protobuf\Proto\parliament_contract_impl.proto + + + Protobuf\Proto\acs3.proto + diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs index 62a7a04a85..196ef5f109 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs @@ -1,14 +1,17 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.MultiToken; +using AElf.Contracts.Parliament; using AElf.Contracts.TokenConverter; using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.EconomicSystem; +using AElf.Kernel.Proposal; using AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests.TestContract; using AElf.Kernel.Token; using AElf.Types; using Shouldly; +using InitializeInput = AElf.Contracts.TokenConverter.InitializeInput; namespace AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests; @@ -39,6 +42,8 @@ public class ExecutionPluginForCallThresholdTestBase : ContractTestBase Accounts[0].KeyPair; internal ECKeyPair OtherTester => Accounts[1].KeyPair; @@ -51,6 +56,7 @@ public class ExecutionPluginForCallThresholdTestBase : ContractTestBase kv.Key.Contains("TestContract")).Value; + var code = Codes.Single(kv => kv.Key.Contains("ExecutionPluginForCallThreshold.Tests.TestContract")).Value; TestContractAddress = await DeployContractAsync(category, code, HashHelper.ComputeFrom("TestContract"), DefaultSenderKeyPair); DefaultTester = GetTester(TestContractAddress, DefaultSenderKeyPair); } + // Parliament + { + var code = Codes.Single(kv => kv.Key.Contains("MockParliament")).Value; + ParliamentAddress = await DeploySystemSmartContract(category, code, + ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); + ParliamentContractStub = + GetTester(ParliamentAddress, + DefaultSenderKeyPair); + } + } + + private async Task InitializedParliament() + { + await ParliamentContractStub.Initialize.SendAsync(new AElf.Contracts.Parliament.InitializeInput + { + ProposerAuthorityRequired = false, + PrivilegedProposer = DefaultSender + }); } private async Task InitializeTokenAsync() diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index 8cce4429ed..c763bd0662 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -159,7 +159,6 @@ private async Task DeployContractsAsync() ParliamentContractStub = GetTester(ParliamentAddress, DefaultSenderKeyPair); - } //Consensus { From aeb63ce0b953fd6f2e922e01881d76372cf409b6 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Tue, 27 Jun 2023 19:53:58 +0800 Subject: [PATCH 098/139] feat: handle tx result deserialization exception --- AElf.All.sln | 7 ++ protobuf/test_fake_vote_contract.proto | 21 ++++ .../Services/TransactionResultAppService.cs | 78 ++++++------- ...Elf.Contracts.TestContract.FakeVote.csproj | 29 +++++ .../FakeVoteContract.cs | 11 ++ .../VoteContractState.cs | 10 ++ ...AElf.WebApp.Application.Chain.Tests.csproj | 5 + .../BlockChainAppServiceTest.cs | 103 +++++++++++++++++- 8 files changed, 225 insertions(+), 39 deletions(-) create mode 100644 protobuf/test_fake_vote_contract.proto create mode 100644 test/AElf.Contracts.TestContract.FakeVote/AElf.Contracts.TestContract.FakeVote.csproj create mode 100644 test/AElf.Contracts.TestContract.FakeVote/FakeVoteContract.cs create mode 100644 test/AElf.Contracts.TestContract.FakeVote/VoteContractState.cs diff --git a/AElf.All.sln b/AElf.All.sln index 7554592ce4..bd58022b63 100644 --- a/AElf.All.sln +++ b/AElf.All.sln @@ -369,6 +369,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps.UnitTes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract.csproj", "{AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.FakeVote", "test\AElf.Contracts.TestContract.FakeVote\AElf.Contracts.TestContract.FakeVote.csproj", "{860947CF-F081-4A3B-BE65-199ECE793616}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1059,6 +1061,10 @@ Global {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}.Debug|Any CPU.Build.0 = Debug|Any CPU {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}.Release|Any CPU.ActiveCfg = Release|Any CPU {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}.Release|Any CPU.Build.0 = Release|Any CPU + {860947CF-F081-4A3B-BE65-199ECE793616}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {860947CF-F081-4A3B-BE65-199ECE793616}.Debug|Any CPU.Build.0 = Debug|Any CPU + {860947CF-F081-4A3B-BE65-199ECE793616}.Release|Any CPU.ActiveCfg = Release|Any CPU + {860947CF-F081-4A3B-BE65-199ECE793616}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1245,5 +1251,6 @@ Global {1B44277E-74EB-49B2-B8FD-05C29EE51985} = {4E54480A-D155-43ED-9736-1A5BE7957211} {D1A00CD6-958E-4E9F-8325-354309E3029E} = {4E54480A-D155-43ED-9736-1A5BE7957211} {AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C} = {4E54480A-D155-43ED-9736-1A5BE7957211} + {860947CF-F081-4A3B-BE65-199ECE793616} = {D3950CC9-808F-4ED8-946A-79A992F3F8EF} EndGlobalSection EndGlobal diff --git a/protobuf/test_fake_vote_contract.proto b/protobuf/test_fake_vote_contract.proto new file mode 100644 index 0000000000..27f9c956ae --- /dev/null +++ b/protobuf/test_fake_vote_contract.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +import "aelf/core.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/wrappers.proto"; +import "acs1.proto"; + +option csharp_namespace = "AElf.Contracts.TestContract.FakeVote"; + +service FakeVoteContract { + option (aelf.csharp_state) = "AElf.Contracts.TestContract.FakeVote.VoteContractState"; + option (aelf.base) = "acs1.proto"; + + rpc AddOption (AddOptionInput) returns (google.protobuf.Empty) { + } +} + +message AddOptionInput { + aelf.Hash voting_item_id = 1; + aelf.Hash option = 2; +} \ No newline at end of file diff --git a/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs b/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs index 1c5fdabe4c..f8bb29f461 100644 --- a/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs +++ b/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs @@ -101,19 +101,9 @@ public async Task GetTransactionResultAsync(string transac return output; } - - var methodDescriptor = - await GetContractMethodDescriptorAsync(transaction!.To, transaction.MethodName, false); - - if (methodDescriptor != null) - { - var parameters = methodDescriptor.InputType.Parser.ParseFrom(transaction.Params); - if (!IsValidMessage(parameters)) - throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString()); - - output.Transaction.Params = JsonFormatter.ToDiagnosticString(parameters); - } - + + await FormatTransactionParamsAsync(output.Transaction, transaction.Params); + return output; } @@ -244,17 +234,7 @@ private async Task GetTransactionResultDto(Hash transactio transactionResultDto.Transaction = _objectMapper.Map(transaction); transactionResultDto.TransactionSize = transaction.CalculateSize(); - var methodDescriptor = - await GetContractMethodDescriptorAsync(transaction.To, transaction.MethodName, false); - - if (methodDescriptor != null) - { - var parameters = methodDescriptor.InputType.Parser.ParseFrom(transaction.Params); - if (!IsValidMessage(parameters)) - throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString()); - - transactionResultDto.Transaction.Params = JsonFormatter.ToDiagnosticString(parameters); - } + await FormatTransactionParamsAsync(transactionResultDto.Transaction, transaction.Params); return transactionResultDto; } @@ -304,20 +284,6 @@ private Hash GetHashCombiningTransactionAndStatus(Hash txId, return HashHelper.ComputeFrom(rawBytes); } - private bool IsValidMessage(IMessage message) - { - try - { - JsonFormatter.ToDiagnosticString(message); - } - catch - { - return false; - } - - return true; - } - private async Task GetContractMethodDescriptorAsync(Address contractAddress, string methodName, bool throwException = true) { @@ -331,4 +297,40 @@ private async Task GetContractMethodDescriptorAsync(Address co return await _transactionReadOnlyExecutionService.GetContractMethodDescriptorAsync(chainContext, contractAddress, methodName, throwException); } + + private async Task FormatTransactionParamsAsync(TransactionDto transaction, ByteString @params) + { + var methodDescriptor = + await GetContractMethodDescriptorAsync(Address.FromBase58(transaction.To), transaction.MethodName, false); + + if (methodDescriptor == null) + return; + + try + { + var parameters = methodDescriptor.InputType.Parser.ParseFrom(@params); + if (!TryFormatToJsonString(parameters, out var paramsJson)) + throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString()); + transaction.Params = paramsJson; + } + catch (Exception exception) when (exception is not UserFriendlyException) + { + Logger.LogError(exception, "Failed to parse transaction params: {params}", transaction.Params); + } + } + + private bool TryFormatToJsonString(IMessage message, out string json) + { + try + { + json = JsonFormatter.ToDiagnosticString(message); + } + catch + { + json = string.Empty; + return false; + } + + return true; + } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.FakeVote/AElf.Contracts.TestContract.FakeVote.csproj b/test/AElf.Contracts.TestContract.FakeVote/AElf.Contracts.TestContract.FakeVote.csproj new file mode 100644 index 0000000000..6d608c91f8 --- /dev/null +++ b/test/AElf.Contracts.TestContract.FakeVote/AElf.Contracts.TestContract.FakeVote.csproj @@ -0,0 +1,29 @@ + + + + net6.0 + 1.1.0 + + + + true + + + + + + + + + Protobuf\Proto\authority_info.proto + + + + + Protobuf\Proto\acs1.proto + + + Protobuf\Proto\test_fake_vote_contract.proto + + + diff --git a/test/AElf.Contracts.TestContract.FakeVote/FakeVoteContract.cs b/test/AElf.Contracts.TestContract.FakeVote/FakeVoteContract.cs new file mode 100644 index 0000000000..81c7c77eed --- /dev/null +++ b/test/AElf.Contracts.TestContract.FakeVote/FakeVoteContract.cs @@ -0,0 +1,11 @@ +using Google.Protobuf.WellKnownTypes; + +namespace AElf.Contracts.TestContract.FakeVote; + +public class FakeVoteContract : FakeVoteContractContainer.FakeVoteContractBase +{ + public override Empty AddOption(AddOptionInput input) + { + return new Empty(); + } +} \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.FakeVote/VoteContractState.cs b/test/AElf.Contracts.TestContract.FakeVote/VoteContractState.cs new file mode 100644 index 0000000000..9ff9ea2e3d --- /dev/null +++ b/test/AElf.Contracts.TestContract.FakeVote/VoteContractState.cs @@ -0,0 +1,10 @@ +using AElf.Sdk.CSharp.State; +using AElf.Types; +using Google.Protobuf.WellKnownTypes; + +namespace AElf.Contracts.TestContract.FakeVote; + +public class VoteContractState : ContractState +{ + public MappedState State { get; set; } +} \ No newline at end of file diff --git a/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj b/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj index f4907935f6..8b24ca8d0b 100644 --- a/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj +++ b/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj @@ -28,6 +28,11 @@ Contract PreserveNewest + + false + Contract + PreserveNewest + diff --git a/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs b/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs index 6755b238ee..466c35f4d8 100644 --- a/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs +++ b/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs @@ -66,7 +66,8 @@ public BlockChainAppServiceTest(ITestOutputHelper outputHelper) : base(outputHel _codes ?? (_codes = ContractsDeployer.GetContractCodes()); private byte[] TestContractCode => Codes.Single(kv => kv.Key.Contains("TestContract.BasicFunction")).Value; - private byte[] VoteContractCode => Codes.Single(kv => kv.Key.Contains("Vote")).Value; + private byte[] VoteContractCode => Codes.Single(kv => kv.Key.Contains("Contracts.Vote")).Value; + private byte[] FakeVoteContractCode => Codes.Single(kv => kv.Key.Contains("TestContract.FakeVote")).Value; [Fact] public async Task Deploy_Contract_Success_Test() @@ -1720,5 +1721,105 @@ await PostResponseAsObjectAsync("/api/blockChain/CalculateT response.Error.Message.ShouldBe(Error.Message[Error.InvalidParams]); } + [Fact] + public async Task Transaction_Params_Changed_Test() + { + var accountAddress = await _accountService.GetAccountAsync(); + var chain = await _blockchainService.GetChainAsync(); + var deployTransaction = new Transaction + { + From = accountAddress, + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(BasicContractZero.DeploySmartContract), + Params = ByteString.CopyFrom(new ContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(VoteContractCode) + }.ToByteArray()), + RefBlockNumber = chain.BestChainHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) + }; + deployTransaction.Signature = + ByteString.CopyFrom(await _accountService.SignAsync(deployTransaction.GetHash().ToByteArray())); + + var parameters = new Dictionary + { + { "rawTransaction", deployTransaction.ToByteArray().ToHex() } + }; + + var sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters); + + sendTransactionResponse.TransactionId.ShouldBe(deployTransaction.GetHash().ToHex()); + await _osTestHelper.MinedOneBlock(); + var transactionResult = await _osTestHelper.GetTransactionResultsAsync(deployTransaction.GetHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var address = Address.Parser.ParseFrom(transactionResult.ReturnValue); + var transaction = new Transaction + { + From = accountAddress, + To = address, + MethodName = nameof(VoteContractContainer.VoteContractStub.AddOption), + Params = ByteString.CopyFrom(new AddOptionInput() + { + VotingItemId = HashHelper.ComputeFrom("VotingItemId"), + Option = "Option" + }.ToByteArray()), + RefBlockNumber = chain.BestChainHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) + }; + transaction.Signature = + ByteString.CopyFrom(await _accountService.SignAsync(transaction.GetHash().ToByteArray())); + + parameters = new Dictionary + { + { "rawTransaction", transaction.ToByteArray().ToHex() } + }; + + sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters); + + sendTransactionResponse.TransactionId.ShouldBe(transaction.GetHash().ToHex()); + await _osTestHelper.MinedOneBlock(); + var response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={transaction.GetHash().ToHex()}"); + response.Transaction.Params.ShouldBe(AddOptionInput.Parser.ParseFrom(transaction.Params).ToString()); + + var updateTransaction = new Transaction + { + From = accountAddress, + To = _smartContractAddressService.GetZeroSmartContractAddress(), + MethodName = nameof(BasicContractZero.UpdateSmartContract), + Params = ByteString.CopyFrom(new ContractUpdateInput + { + Address = address, + Code = ByteString.CopyFrom(FakeVoteContractCode) + }.ToByteArray()), + RefBlockNumber = chain.BestChainHeight, + RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) + }; + updateTransaction.Signature = + ByteString.CopyFrom(await _accountService.SignAsync(updateTransaction.GetHash().ToByteArray())); + + parameters = new Dictionary + { + { "rawTransaction", updateTransaction.ToByteArray().ToHex() } + }; + sendTransactionResponse = + await PostResponseAsObjectAsync("/api/blockChain/sendTransaction", + parameters); + + sendTransactionResponse.TransactionId.ShouldBe(updateTransaction.GetHash().ToHex()); + await _osTestHelper.MinedOneBlock(); + transactionResult = await _osTestHelper.GetTransactionResultsAsync(updateTransaction.GetHash()); + transactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + response = await GetResponseAsObjectAsync( + $"/api/blockChain/transactionResult?transactionId={transaction.GetHash().ToHex()}"); + response.Transaction.Params.ShouldBe(transaction.Params.ToBase64()); + response.Transaction.Params.ShouldNotBe( + AddOptionInput.Parser.ParseFrom(transaction.Params).ToString()); + } } \ No newline at end of file From 88cdad198cffd2138e8855d6074bb0f3801c5d5c Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Tue, 27 Jun 2023 23:02:48 +0800 Subject: [PATCH 099/139] feat: change get delegatee list and distinct list. --- .../TokenContract_ACS2_StatePathsProvider.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs index 15c5fd4971..8d12f604e1 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_ACS2_StatePathsProvider.cs @@ -105,6 +105,7 @@ private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from, Addre var delegateeList = new List(); //get and add first-level delegatee list delegateeList.AddRange(GetDelegateeList(from, to, methodName)); + if (delegateeList.Count <= 0) return; var secondDelegateeList = new List(); //get and add second-level delegatee list foreach (var delegateeAddress in delegateeList.Select(Address.FromBase58)) @@ -113,8 +114,7 @@ private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from, Addre secondDelegateeList.AddRange(GetDelegateeList(delegateeAddress, to, methodName)); } delegateeList.AddRange(secondDelegateeList); - - foreach (var delegatee in delegateeList) + foreach (var delegatee in delegateeList.Distinct()) { AddPathForTransactionFee(resourceInfo, delegatee, methodName); AddPathForTransactionFeeFreeAllowance(resourceInfo, Address.FromBase58(delegatee)); @@ -124,18 +124,13 @@ private void AddPathForDelegatees(ResourceInfo resourceInfo, Address from, Addre private List GetDelegateeList(Address delegator, Address to, string methodName) { var delegateeList = new List(); - var allDelegatees = State.TransactionFeeDelegateesMap[delegator]; - var allDelegateInfos = State.TransactionFeeDelegateInfoMap[delegator][to][methodName]; + var allDelegatees = State.TransactionFeeDelegateInfoMap[delegator][to][methodName] + ?? State.TransactionFeeDelegateesMap[delegator]; if (allDelegatees != null) { delegateeList.AddRange(allDelegatees.Delegatees.Keys.ToList()); - } - - if (allDelegateInfos != null) - { - delegateeList.AddRange(allDelegateInfos.Delegatees.Keys.ToList()); - } + } return delegateeList; } From 82c84446a6efafa5e5b3668546fdd73ebed6f88c Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 28 Jun 2023 10:15:34 +0800 Subject: [PATCH 100/139] fix: ut --- .../ContractsPreparation.cs | 32 +++- .../BVT/DonateTests.cs | 11 +- .../BVT/TreasuryBasicTests.cs | 7 +- .../AElf.Contracts.Genesis.Tests.csproj | 5 + .../ParliamentContractTestBase.cs | 15 +- .../AElf.Contracts.TestBase/ContractTester.cs | 2 +- .../AElf.Contracts.TokenHolder.Tests.csproj | 23 +-- .../TokenHolderContractTestBase.cs | 145 +++++++++++++++--- ...ExecutionPluginForResourceFee.Tests.csproj | 8 - 9 files changed, 192 insertions(+), 56 deletions(-) diff --git a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs index 04437a46a8..42de61e783 100644 --- a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs +++ b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs @@ -509,12 +509,34 @@ protected async Task InitializeTransactionFeeChargingContract() { await ExecuteProposalForParliamentTransaction(TokenContractAddress, nameof(TokenContractStub.AddAddressToCreateTokenWhiteList), TransactionFeeChargingContractAddress); - var result = await TransactionFeeChargingContractStub.InitializeTransactionFeeChargingContract.SendAsync( - new InitializeTransactionFeeChargingContractInput + + await ExecuteProposalForParliamentTransaction(TokenContractAddress, nameof(TokenContractStub.Create), new CreateInput + { + Symbol = EconomicContractsTestConstants.TransactionFeeChargingContractTokenSymbol, + TokenName = "Token of Transaction Fee Charging Contract", + Decimals = 2, + Issuer = BootMinerAddress, + IsBurnable = true, + TotalSupply = 1_000_000_000, + LockWhiteList = { - Symbol = EconomicContractsTestConstants.TransactionFeeChargingContractTokenSymbol - }); - CheckResult(result.TransactionResult); + TokenConverterContractAddress, + TreasuryContractAddress + } + }); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = EconomicContractsTestConstants.TransactionFeeChargingContractTokenSymbol, + Amount = 100_000, + To = TokenConverterContractAddress + }); + + // var result = await TransactionFeeChargingContractStub.InitializeTransactionFeeChargingContract.SendAsync( + // new InitializeTransactionFeeChargingContractInput + // { + // Symbol = EconomicContractsTestConstants.TransactionFeeChargingContractTokenSymbol + // }); + // CheckResult(result.TransactionResult); { var approveResult = await TokenContractStub.Approve.SendAsync(new ApproveInput diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/DonateTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/DonateTests.cs index db05af1544..4c3a80ae96 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/DonateTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/DonateTests.cs @@ -118,13 +118,14 @@ private async Task InitialBuildConnector(string symbol) TokenSymbol = symbol, AmountToTokenConvert = 0 }; - var issueRet = (await TransactionFeeChargingContractStub.IssueToTokenConvert.SendAsync( - new IssueAmount + await TokenContractStub.Issue.SendAsync( + new IssueInput { Symbol = symbol, - Amount = token.TotalSupply - token.Supply - })).TransactionResult; - issueRet.Status.ShouldBe(TransactionResultStatus.Mined); + Amount = token.TotalSupply - token.Supply, + To = TokenConverterContractAddress, + Memo = "test" + }); var buildConnector = (await TokenConverterContractStub.EnableConnector.SendAsync(tokenInfo)).TransactionResult; buildConnector.Status.ShouldBe(TransactionResultStatus.Mined); } diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs index 44fa2b131a..57d3d0b778 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs @@ -283,8 +283,8 @@ public async Task Treasury_SetSymbolList_With_Invalid_Token_Test() Issuer = BootMinerAddress, IsBurnable = true }; - var createTokenRet = await TokenContractStub.Create.SendAsync(tokenCreateInput); - createTokenRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + await ExecuteProposalForParliamentTransactionWithException(Tester, TokenContractAddress, nameof(TokenContractStub.Create), + tokenCreateInput); // without native token { var newSymbolList = new SymbolList @@ -330,7 +330,8 @@ public async Task Treasury_SetSymbolList_Success_Test() Issuer = BootMinerAddress, IsBurnable = true }; - await TokenContractStub.Create.SendAsync(tokenCreateInput); + await ExecuteProposalForParliamentTransaction(TokenContractAddress, nameof(TokenContractStub.Create), + tokenCreateInput); var newSymbolList = new SymbolList { Value = diff --git a/test/AElf.Contracts.Genesis.Tests/AElf.Contracts.Genesis.Tests.csproj b/test/AElf.Contracts.Genesis.Tests/AElf.Contracts.Genesis.Tests.csproj index fc5f102700..c439d16de0 100644 --- a/test/AElf.Contracts.Genesis.Tests/AElf.Contracts.Genesis.Tests.csproj +++ b/test/AElf.Contracts.Genesis.Tests/AElf.Contracts.Genesis.Tests.csproj @@ -33,6 +33,11 @@ Contract PreserveNewest + + false + Contract + PreserveNewest + diff --git a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs index 4cc77daaa3..ce1efee793 100644 --- a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs +++ b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs @@ -8,6 +8,7 @@ using AElf.Contracts.TestBase; using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; +using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; @@ -36,7 +37,8 @@ public class ParliamentContractTestBase : ContractTestKit.ContractTestBase InitialMinersKeyPairs => Accounts.Take(MinersCount).Select(a => a.KeyPair).ToList(); protected Address DefaultSender => Accounts[10].Address; protected Address Tester => Accounts[MinersCount + 1].Address; - + protected List InitialCoreDataCenterKeyPairs => + Accounts.Take(1).Select(a => a.KeyPair).ToList(); protected Address TokenContractAddress { get; set; } protected Address ConsensusContractAddress { get; set; } protected Address ParliamentContractAddress { get; set; } @@ -66,6 +68,11 @@ protected void InitializeContracts() DefaultSenderKeyPair )); ParliamentContractStub = GetParliamentContractTester(DefaultSenderKeyPair); + AsyncHelper.RunSync(() => ParliamentContractStub.Initialize.SendAsync(new InitializeInput + { + ProposerAuthorityRequired = false, + PrivilegedProposer = DefaultSender + })); //deploy token contract TokenContractAddress = AsyncHelper.RunSync(() => DeploySystemSmartContract( @@ -144,7 +151,11 @@ await ConsensusContractStub.FirstRound.SendAsync( internal async Task InitializeParliamentContracts() { - await ParliamentContractStub.Initialize.SendAsync(new InitializeInput()); + await ParliamentContractStub.Initialize.SendAsync(new InitializeInput + { + ProposerAuthorityRequired = false, + PrivilegedProposer = DefaultSender + }); } } diff --git a/test/AElf.Contracts.TestBase/ContractTester.cs b/test/AElf.Contracts.TestBase/ContractTester.cs index 8d091c28b4..2ac2ea3092 100644 --- a/test/AElf.Contracts.TestBase/ContractTester.cs +++ b/test/AElf.Contracts.TestBase/ContractTester.cs @@ -186,7 +186,7 @@ public ContractTester(int chainId) public byte[] CrossChainContractCode => GetContractCodeByName(SmartContractTestConstants.CrossChain); - public byte[] ParliamentContractCode => GetContractCodeByName("MockParliament"); + public byte[] ParliamentContractCode => GetContractCodeByName(SmartContractTestConstants.Parliament); public byte[] ConfigurationContractCode => GetContractCodeByName(SmartContractTestConstants.Configuration); diff --git a/test/AElf.Contracts.TokenHolder.Tests/AElf.Contracts.TokenHolder.Tests.csproj b/test/AElf.Contracts.TokenHolder.Tests/AElf.Contracts.TokenHolder.Tests.csproj index ff8f4950ef..92957ed179 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/AElf.Contracts.TokenHolder.Tests.csproj +++ b/test/AElf.Contracts.TokenHolder.Tests/AElf.Contracts.TokenHolder.Tests.csproj @@ -15,7 +15,7 @@ runtime; build; native; contentfiles; analyzers - + all @@ -27,15 +27,15 @@ - - - - - - - - - + + + + + + + + + @@ -91,6 +91,9 @@ Protobuf\Proto\aedpos_contract_impl.proto + + Protobuf\Proto\acs3.proto + Protobuf\Proto\acs4.proto diff --git a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs index 2e4a17a843..440b952d63 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs @@ -91,6 +91,29 @@ protected void InitializeContracts() })).Output; TokenHolderContractStub = GetTokenHolderContractTester(StarterKeyPair); + //deploy parliament auth contract + ParliamentContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ParliamentContract).Assembly.Location)), + Name = ParliamentSmartContractAddressNameProvider.Name, + TransactionMethodCallList = GenerateParliamentInitializationCallList() + })).Output; + ParliamentContractStub = GetParliamentContractTester(StarterKeyPair); + + //deploy DApp contract + DAppContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) + .DeploySystemSmartContract.SendAsync( + new SystemContractDeploymentInput + { + Category = KernelConstants.CodeCoverageRunnerCategory, + Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(DAppContract).Assembly.Location)), + Name = DappSmartContractAddressNameProvider.Name + })).Output; + DAppContractStub = GetTester(DAppContractAddress, UserKeyPairs.First()); + //deploy token contract TokenContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) .DeploySystemSmartContract.SendAsync( @@ -102,18 +125,96 @@ protected void InitializeContracts() TransactionMethodCallList = GenerateTokenInitializationCallList() })).Output; TokenContractStub = GetTokenContractTester(StarterKeyPair); - - //deploy parliament auth contract - ParliamentContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput + + AsyncHelper.RunSync(() => TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = "SEED-1", + Decimals = 0, + IsBurnable = true, + TokenName = "collection", + TotalSupply = 1, + Issuer = Starter, + LockWhiteList = + { + TokenContractAddress + }, + ExternalInfo = new ExternalInfo + { + Value = { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(ParliamentContract).Assembly.Location)), - Name = ParliamentSmartContractAddressNameProvider.Name, - TransactionMethodCallList = GenerateParliamentInitializationCallList() - })).Output; - ParliamentContractStub = GetParliamentContractTester(StarterKeyPair); + { "__seed_owned_symbol", "APP" }, + { "__seed_exp_time", TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString() } + } + } + })); + + AsyncHelper.RunSync(() => TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = "SEED-2", + Decimals = 0, + IsBurnable = true, + TokenName = "collection", + TotalSupply = 1, + Issuer = Starter, + LockWhiteList = + { + TokenContractAddress + }, + ExternalInfo = new ExternalInfo + { + Value = + { + { "__seed_owned_symbol", "AUG" }, + { "__seed_exp_time", TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString() } + } + } + })); + + AsyncHelper.RunSync(() => TokenContractStub.Create.SendAsync(new CreateInput + { + Symbol = "SEED-3", + Decimals = 0, + IsBurnable = true, + TokenName = "collection", + TotalSupply = 1, + Issuer = Starter, + LockWhiteList = + { + TokenContractAddress + }, + ExternalInfo = new ExternalInfo + { + Value = + { + { "__seed_owned_symbol", "JUN" }, + { "__seed_exp_time", TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString() } + } + } + })); + + AsyncHelper.RunSync(() => TokenContractStub.Issue.SendAsync(new IssueInput + { + Amount = 1, + Memo = "test", + Symbol = "SEED-1", + To = DAppContractAddress + })); + + AsyncHelper.RunSync(() => TokenContractStub.Issue.SendAsync(new IssueInput + { + Amount = 1, + Memo = "test", + Symbol = "SEED-2", + To = Starter + })); + + AsyncHelper.RunSync(() => TokenContractStub.Issue.SendAsync(new IssueInput + { + Amount = 1, + Memo = "test", + Symbol = "SEED-3", + To = Starter + })); ConsensusContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) .DeploySystemSmartContract.SendAsync( @@ -126,16 +227,6 @@ protected void InitializeContracts() })).Output; AEDPoSContractStub = GetConsensusContractTester(StarterKeyPair); - //deploy DApp contract - DAppContractAddress = AsyncHelper.RunSync(() => GetContractZeroTester(StarterKeyPair) - .DeploySystemSmartContract.SendAsync( - new SystemContractDeploymentInput - { - Category = KernelConstants.CodeCoverageRunnerCategory, - Code = ByteString.CopyFrom(File.ReadAllBytes(typeof(DAppContract).Assembly.Location)), - Name = DappSmartContractAddressNameProvider.Name - })).Output; - DAppContractStub = GetTester(DAppContractAddress, UserKeyPairs.First()); AsyncHelper.RunSync(TransferToContract); AsyncHelper.RunSync(async () => { @@ -222,6 +313,16 @@ private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList To = Address.FromPublicKey(creatorKeyPair.PublicKey), Memo = "set voters few amount for voting." })); + + tokenContractCallList.Add(nameof(TokenContract.Create), new CreateInput + { + Symbol = "SEED-0", + Decimals = 0, + IsBurnable = true, + TokenName = "collection", + TotalSupply = 1, + Issuer = Starter + }); return tokenContractCallList; } @@ -286,7 +387,7 @@ protected async Task ApproveWithMinersAsync(Hash proposalId) approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } } - + private async Task TransferToContract() { await TokenContractStub.Transfer.SendAsync(new TransferInput diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj index 4defe6144f..7b783166f8 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj @@ -53,11 +53,6 @@ Contract PreserveNewest - - false - Contract - PreserveNewest - false Contract @@ -108,9 +103,6 @@ Protobuf\Proto\acs10.proto - - Protobuf\Proto\parliament_contract.proto - Protobuf\Proto\aedpos_contract.proto From a4afee068e807f20912b724d28dc92f3f916d607 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Wed, 28 Jun 2023 10:48:22 +0800 Subject: [PATCH 101/139] feat: naming --- AElf.All.sln | 2 +- ..._fake_vote_contract.proto => test_vote_contract.proto} | 6 +++--- .../AElf.Contracts.TestContract.Vote.csproj} | 4 ++-- .../VoteContract.cs} | 4 ++-- .../VoteContractState.cs | 2 +- .../AElf.WebApp.Application.Chain.Tests.csproj | 8 ++++---- .../BlockChainAppServiceTest.cs | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) rename protobuf/{test_fake_vote_contract.proto => test_vote_contract.proto} (65%) rename test/{AElf.Contracts.TestContract.FakeVote/AElf.Contracts.TestContract.FakeVote.csproj => AElf.Contracts.TestContract.Vote/AElf.Contracts.TestContract.Vote.csproj} (84%) rename test/{AElf.Contracts.TestContract.FakeVote/FakeVoteContract.cs => AElf.Contracts.TestContract.Vote/VoteContract.cs} (53%) rename test/{AElf.Contracts.TestContract.FakeVote => AElf.Contracts.TestContract.Vote}/VoteContractState.cs (80%) diff --git a/AElf.All.sln b/AElf.All.sln index bd58022b63..c426dee8f9 100644 --- a/AElf.All.sln +++ b/AElf.All.sln @@ -369,7 +369,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.CSharp.CodeOps.UnitTes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract", "test\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract\AElf.Kernel.SmartContract.ExecutionPluginForUserContractFee.Tests.TestContract.csproj", "{AB27298B-E6BE-4ACB-ADF1-64239E2A7A1C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.FakeVote", "test\AElf.Contracts.TestContract.FakeVote\AElf.Contracts.TestContract.FakeVote.csproj", "{860947CF-F081-4A3B-BE65-199ECE793616}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Contracts.TestContract.Vote", "test\AElf.Contracts.TestContract.Vote\AElf.Contracts.TestContract.Vote.csproj", "{860947CF-F081-4A3B-BE65-199ECE793616}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/protobuf/test_fake_vote_contract.proto b/protobuf/test_vote_contract.proto similarity index 65% rename from protobuf/test_fake_vote_contract.proto rename to protobuf/test_vote_contract.proto index 27f9c956ae..bc30611354 100644 --- a/protobuf/test_fake_vote_contract.proto +++ b/protobuf/test_vote_contract.proto @@ -5,10 +5,10 @@ import "google/protobuf/empty.proto"; import "google/protobuf/wrappers.proto"; import "acs1.proto"; -option csharp_namespace = "AElf.Contracts.TestContract.FakeVote"; +option csharp_namespace = "AElf.Contracts.TestContract.Vote"; -service FakeVoteContract { - option (aelf.csharp_state) = "AElf.Contracts.TestContract.FakeVote.VoteContractState"; +service VoteContract { + option (aelf.csharp_state) = "AElf.Contracts.TestContract.Vote.VoteContractState"; option (aelf.base) = "acs1.proto"; rpc AddOption (AddOptionInput) returns (google.protobuf.Empty) { diff --git a/test/AElf.Contracts.TestContract.FakeVote/AElf.Contracts.TestContract.FakeVote.csproj b/test/AElf.Contracts.TestContract.Vote/AElf.Contracts.TestContract.Vote.csproj similarity index 84% rename from test/AElf.Contracts.TestContract.FakeVote/AElf.Contracts.TestContract.FakeVote.csproj rename to test/AElf.Contracts.TestContract.Vote/AElf.Contracts.TestContract.Vote.csproj index 6d608c91f8..2924bb78db 100644 --- a/test/AElf.Contracts.TestContract.FakeVote/AElf.Contracts.TestContract.FakeVote.csproj +++ b/test/AElf.Contracts.TestContract.Vote/AElf.Contracts.TestContract.Vote.csproj @@ -22,8 +22,8 @@ Protobuf\Proto\acs1.proto - - Protobuf\Proto\test_fake_vote_contract.proto + + Protobuf\Proto\test_vote_contract.proto diff --git a/test/AElf.Contracts.TestContract.FakeVote/FakeVoteContract.cs b/test/AElf.Contracts.TestContract.Vote/VoteContract.cs similarity index 53% rename from test/AElf.Contracts.TestContract.FakeVote/FakeVoteContract.cs rename to test/AElf.Contracts.TestContract.Vote/VoteContract.cs index 81c7c77eed..4e7ae7c700 100644 --- a/test/AElf.Contracts.TestContract.FakeVote/FakeVoteContract.cs +++ b/test/AElf.Contracts.TestContract.Vote/VoteContract.cs @@ -1,8 +1,8 @@ using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.FakeVote; +namespace AElf.Contracts.TestContract.Vote; -public class FakeVoteContract : FakeVoteContractContainer.FakeVoteContractBase +public class VoteContract : VoteContractContainer.VoteContractBase { public override Empty AddOption(AddOptionInput input) { diff --git a/test/AElf.Contracts.TestContract.FakeVote/VoteContractState.cs b/test/AElf.Contracts.TestContract.Vote/VoteContractState.cs similarity index 80% rename from test/AElf.Contracts.TestContract.FakeVote/VoteContractState.cs rename to test/AElf.Contracts.TestContract.Vote/VoteContractState.cs index 9ff9ea2e3d..b7dbffd482 100644 --- a/test/AElf.Contracts.TestContract.FakeVote/VoteContractState.cs +++ b/test/AElf.Contracts.TestContract.Vote/VoteContractState.cs @@ -2,7 +2,7 @@ using AElf.Types; using Google.Protobuf.WellKnownTypes; -namespace AElf.Contracts.TestContract.FakeVote; +namespace AElf.Contracts.TestContract.Vote; public class VoteContractState : ContractState { diff --git a/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj b/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj index 8b24ca8d0b..f629badebd 100644 --- a/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj +++ b/test/AElf.WebApp.Application.Chain.Tests/AElf.WebApp.Application.Chain.Tests.csproj @@ -9,7 +9,7 @@ runtime; build; native; contentfiles; analyzers - + all @@ -20,15 +20,15 @@ runtime; build; native; contentfiles; analyzers - + - + false Contract PreserveNewest - + false Contract PreserveNewest diff --git a/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs b/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs index 466c35f4d8..b898977dc3 100644 --- a/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs +++ b/test/AElf.WebApp.Application.Chain.Tests/BlockChainAppServiceTest.cs @@ -67,7 +67,7 @@ public BlockChainAppServiceTest(ITestOutputHelper outputHelper) : base(outputHel private byte[] TestContractCode => Codes.Single(kv => kv.Key.Contains("TestContract.BasicFunction")).Value; private byte[] VoteContractCode => Codes.Single(kv => kv.Key.Contains("Contracts.Vote")).Value; - private byte[] FakeVoteContractCode => Codes.Single(kv => kv.Key.Contains("TestContract.FakeVote")).Value; + private byte[] TestVoteContractCode => Codes.Single(kv => kv.Key.Contains("TestContract.Vote")).Value; [Fact] public async Task Deploy_Contract_Success_Test() @@ -1795,7 +1795,7 @@ await PostResponseAsObjectAsync("/api/blockChain/sendTran Params = ByteString.CopyFrom(new ContractUpdateInput { Address = address, - Code = ByteString.CopyFrom(FakeVoteContractCode) + Code = ByteString.CopyFrom(TestVoteContractCode) }.ToByteArray()), RefBlockNumber = chain.BestChainHeight, RefBlockPrefix = BlockHelper.GetRefBlockPrefix(chain.BestChainHash) From 07d9344e78c90f6c5459e98dfe3ce3e8dcc30b7a Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Wed, 28 Jun 2023 12:37:17 +0800 Subject: [PATCH 102/139] feat: update mutiToken ut --- .../BVT/ACS1_ImplementTest.cs | 4 -- .../BVT/ACS2_TokenResourceTests.cs | 1 - .../BVT/NftApplicationTests.cs | 21 ++++--- .../BVT/TokenApplicationTests.cs | 25 +++----- .../BVT/TokenDelegationTest.cs | 3 +- .../BVT/TokenFeeTest.cs | 3 +- .../BVT/TokenManagementTests.cs | 58 ++++--------------- .../MultiTokenContractTestBase.cs | 6 +- ...ContractWithCustomSystemTransactionTest.cs | 11 ---- 9 files changed, 35 insertions(+), 97 deletions(-) diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs index 0c1032a23b..b5e4e25d46 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs @@ -129,7 +129,6 @@ public async Task SendInvalidTransactionsTest() [Fact] public async Task SetMethodFee_Success_Test() { - await CreateNativeTokenAsync(); var methodName = "Transfer"; var tokenSymbol = NativeTokenInfo.Symbol; var basicFee = 100; @@ -161,7 +160,6 @@ public async Task SetMethodFee_Success_Test() [Fact] public async Task SetMethodFee_Fail_Test() { - await CreateNativeTokenAsync(); var tokenSymbol = NativeTokenInfo.Symbol; var methodName = "Transfer"; // unauthorized @@ -239,7 +237,6 @@ public async Task GetMethodFee_No_Fee_Test(params string[] defaultSetMethodNames { var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); var proposalMethodName = nameof(TokenContractStub.SetMethodFee); - await CreateNativeTokenAsync(); var tokenSymbol = NativeTokenInfo.Symbol; var basicFee = 100; foreach (var methodName in defaultSetMethodNames) @@ -271,7 +268,6 @@ public async Task GetMethodFee_Fix_Fee_Test(params string[] defaultSetMethodName { var methodFeeController = await TokenContractStub.GetMethodFeeController.CallAsync(new Empty()); var proposalMethodName = nameof(TokenContractStub.SetMethodFee); - await CreateNativeTokenAsync(); var tokenSymbol = NativeTokenInfo.Symbol; var basicFee = 100; foreach (var methodName in defaultSetMethodNames) diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs index c7dd514896..43f4e4369d 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs @@ -60,7 +60,6 @@ public async Task ACS2_GetResourceInfo_Transfer_MultiToken_Test() { var theDefaultController = await GetDefaultParliamentAddressAsync(); var newSymbolList = new SymbolListToPayTxSizeFee(); - await CreateNativeTokenAsync(); await CreateTokenAsync(DefaultAddress, "CPU"); await CreateTokenAsync(DefaultAddress, "NET"); var methodName = "Transfer"; diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs index fe11a7639b..ac9924bc95 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs @@ -227,7 +227,7 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() } // Symbol check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput + var seedInput = BuildSeedCreateInput( new CreateInput { Symbol = "ABC123", TokenName = input.TokenName, @@ -237,12 +237,14 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() IssueChainId = input.IssueChainId, ExternalInfo = input.ExternalInfo }); + + var result = await TokenContractStub.Create.SendWithExceptionAsync(seedInput);; result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); result.TransactionResult.Error.ShouldContain("Invalid Symbol input"); } // Symbol length check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput + var seedInput = BuildSeedCreateInput( new CreateInput { Symbol = "ABCDEFGHIJKLMNOPQRSTUVWXYZABC-0", TokenName = input.TokenName, @@ -252,6 +254,7 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() IssueChainId = input.IssueChainId, ExternalInfo = input.ExternalInfo }); + var result = await TokenContractStub.Create.SendWithExceptionAsync(seedInput);; result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); result.TransactionResult.Error.ShouldContain("Invalid NFT symbol length"); } @@ -259,7 +262,7 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() { var result = await CreateMutiTokenAsync(TokenContractStub, new CreateInput { - Symbol = $"{input.Symbol}0", + Symbol = AliceCoinTokenInfo.Symbol, TokenName = input.TokenName, TotalSupply = input.TotalSupply, Decimals = input.Decimals, @@ -282,7 +285,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() { var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { - Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", + Symbol = "GHJ-0", TokenName = input.TokenName, TotalSupply = input.TotalSupply, Decimals = 8, @@ -295,7 +298,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Symbol check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput + var result = await CreateSeedNftWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = "ABC-ABC", TokenName = input.TokenName, @@ -310,7 +313,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Symbol check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput + var result = await CreateSeedNftWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = "ABC-", TokenName = input.TokenName, @@ -325,7 +328,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Symbol check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput + var result = await CreateSeedNftWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = "ABC-ABC-1", TokenName = input.TokenName, @@ -340,7 +343,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() } // Issue check { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput + var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -392,7 +395,7 @@ public async Task MultiTokenContract_Create_NFT_Already_Exist() { await CreateNftCollectionAndNft(false); var input = Nft721Info; - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput + var result = await CreateSeedNftWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index 8adc01d712..b07ac80237 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -15,6 +15,7 @@ namespace AElf.Contracts.MultiToken; public partial class MultiTokenContractTests { + protected const string SymbolForTest = "GHJ"; [Fact(DisplayName = "[MultiToken] Transfer token test")] public async Task MultiTokenContract_Transfer_Test() { @@ -372,7 +373,7 @@ private async Task CreateTokenAndIssue(List
whitelist = null, Address i OtherBasicFunctionContractAddress, TreasuryContractAddress }; - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = SymbolForTest, Decimals = 2, @@ -811,7 +812,7 @@ public async Task MultiTokenContract_Burn_Invalid_Token_Test() { await CreateAndIssueMultiTokensAsync(); var unburnedTokenSymbol = "UNBURNED"; - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = unburnedTokenSymbol, TokenName = "Name", @@ -944,8 +945,7 @@ await BasicFunctionContractStub.TransferTokenToContract.SendAsync( public async Task ChangeTokenIssuer_Test() { const string tokenSymbol = "PO"; - await CreateAndIssueMultiTokensAsync(); - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = tokenSymbol, TokenName = "Name", @@ -984,8 +984,7 @@ await tokenIssuerStub.ChangeTokenIssuer.SendAsync(new ChangeTokenIssuerInput public async Task ChangeTokenIssuer_Without_Authorization_Test() { const string tokenSymbol = "PO"; - await CreateAndIssueMultiTokensAsync(); - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = tokenSymbol, TokenName = "Name", @@ -1078,7 +1077,6 @@ public async Task Side_Chain_Creat_Token_Test() public async Task CheckThreshold_With_One_Token_Test(long totalSupply, long issueAmount, long ApproveAmount, long checkAmount, bool isCheckAllowance, bool isThrowException) { - await CreateNativeTokenAsync(); var tokenA = "AITA"; await CreateAndIssueCustomizeTokenAsync(DefaultAddress, tokenA, totalSupply, issueAmount); if (ApproveAmount > 0) @@ -1122,7 +1120,6 @@ await TokenContractStub.Approve.SendAsync(new ApproveInput public async Task CheckThreshold_With_Multiple_Token_Test(long tokenACheckAmount, long tokenAApporveAmount, long tokenBCheckAmount, long tokenBApporveAmount, bool isCheckAllowance, bool isThrowException) { - await CreateNativeTokenAsync(); var tokenA = "AITA"; await CreateAndIssueCustomizeTokenAsync(DefaultAddress, tokenA, 10000, 1000); var tokenB = "AITB"; @@ -1170,7 +1167,7 @@ private async Task CreateAndIssueCustomizeTokenAsync(Address creator, string sym long issueAmount, Address to = null, params string[] otherParameters) { - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = symbol, Issuer = creator, @@ -1189,8 +1186,7 @@ await TokenContractStub.Issue.SendAsync(new IssueInput [Fact] public async Task ValidateTokenInfoExists_ExternalInfo_Test() { - await CreateNativeTokenAsync(); - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = AliceCoinTokenInfo.Symbol, TokenName = AliceCoinTokenInfo.TokenName, @@ -1239,13 +1235,6 @@ await TokenContractStub.Create.SendAsync(new CreateInput [Fact] public async Task CrossContractCreateToken_Test() { - await CreateNativeTokenAsync(); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = NativeToken, - To = BasicFunctionContractAddress, - Amount = 10000_00000000 - }); var fee = await TokenContractStub.GetMethodFee.CallAsync(new StringValue { Value = "Create" }); var createTokenInput = new CreateTokenThroughMultiTokenInput diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs index 4d6b1bb937..f57f3e560f 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs @@ -158,14 +158,13 @@ public async Task SetTokenDelegation_addNotExistToken_Test() private async Task Initialize() { - await CreateBaseNativeTokenAsync(); await CreateTokenAsync(DefaultAddress, BasicFeeSymbol); await CreateTokenAsync(DefaultAddress, SizeFeeSymbol); } private async Task CreateTokenAsync(Address creator, string tokenSymbol, bool isBurned = true) { - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = tokenSymbol, TokenName = tokenSymbol + " name", diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs index 05cdb0efab..46d940c1d3 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs @@ -13,7 +13,7 @@ public partial class MultiTokenContractTests [Fact(DisplayName = "[MultiToken] advance token not exist in resource token")] public async Task AdvancedResourceToken_Test() { - await CreateNativeTokenAsync(); + // await CreateNativeTokenAsync(); long advanceAmount = 1000; { var tokenNotResrouce = "NORESOURCE"; @@ -51,7 +51,6 @@ public async Task AdvancedResourceToken_Test() [Fact(DisplayName = "[MultiToken] take more token than that of the contract address's balance")] public async Task TakeResourceTokenBack_Test() { - await CreateNativeTokenAsync(); var trafficToken = "TRAFFIC"; var advanceAmount = 1000; await CreateAndIssueCustomizeTokenAsync(DefaultAddress, trafficToken, 10000, 10000); diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs index f850283ca1..e01690b324 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs @@ -130,17 +130,8 @@ await CreateMutiTokenAsync(TokenContractStub,new CreateInput private async Task CreatePrimaryTokenAsync() { - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = NativeTokenInfo.Symbol, - TokenName = NativeTokenInfo.TokenName, - TotalSupply = NativeTokenInfo.TotalSupply, - Decimals = NativeTokenInfo.Decimals, - Issuer = NativeTokenInfo.Issuer, - IsBurnable = NativeTokenInfo.IsBurnable - }); - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Decimals = PrimaryTokenInfo.Decimals, IsBurnable = PrimaryTokenInfo.IsBurnable, @@ -169,7 +160,7 @@ private async Task CreateNormalTokenAsync() tokenInfo.ShouldBe(new TokenInfo()); } - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = AliceCoinTokenInfo.Symbol, TokenName = AliceCoinTokenInfo.TokenName, @@ -236,7 +227,7 @@ public async Task MultiTokenContract_Create_NotSame_Test() { await CreateAndIssueMultiTokensAsync(); - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = BobCoinTokenInfo.Symbol, TokenName = BobCoinTokenInfo.TokenName, @@ -259,13 +250,13 @@ await TokenContractStub.Create.SendAsync(new CreateInput [Fact(DisplayName = "[MultiToken] Create Token use custom address")] public async Task MultiTokenContract_Create_UseCustomAddress_Test() { - var transactionResult = (await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + var transactionResult = (await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput { - Symbol = NativeTokenInfo.Symbol, + Symbol = BobCoinTokenInfo.Symbol, Decimals = 2, IsBurnable = true, Issuer = DefaultAddress, - TokenName = NativeTokenInfo.TokenName, + TokenName = BobCoinTokenInfo.TokenName, TotalSupply = AliceCoinTotalAmount, LockWhiteList = { @@ -278,7 +269,6 @@ public async Task MultiTokenContract_Create_UseCustomAddress_Test() private async Task CreateAndIssueMultiTokensAsync() { - await CreateNativeTokenAsync(); await CreateNormalTokenAsync(); //issue AliceToken amount of 1000_00L to DefaultAddress { @@ -299,25 +289,6 @@ private async Task CreateAndIssueMultiTokensAsync() balance.ShouldBe(AliceCoinTotalAmount); } - //issue ELF amount of 1000_00L to DefaultAddress - { - var result = await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = "ELF", - Amount = AliceCoinTotalAmount, - To = DefaultAddress, - Memo = "first issue token." - }); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - var balance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Owner = DefaultAddress, - Symbol = "ELF" - })).Balance; - balance.ShouldBe(AliceCoinTotalAmount); - } - //issue AliceToken amount of 1000L to User1Address { var result = await TokenContractStub.Issue.SendAsync(new IssueInput @@ -375,7 +346,6 @@ public async Task MultiTokenContract_Issue_OutOfAmount_Test() [Fact] public async Task IssueToken_With_Invalid_Input() { - await CreateNativeTokenAsync(); await CreateNormalTokenAsync(); // to is null { @@ -420,7 +390,7 @@ public async Task IssueToken_With_Invalid_Input() //invalid chain id { var chainTokenSymbol = "CHAIN"; - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub ,new CreateInput { Symbol = chainTokenSymbol, TokenName = "chain token", @@ -443,9 +413,8 @@ await TokenContractStub.Create.SendAsync(new CreateInput [Fact] public async Task IssueToken_Test() { - await CreateNativeTokenAsync(); var newTokenSymbol = "AIN"; - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = newTokenSymbol, TokenName = "ain token", @@ -514,20 +483,17 @@ public async Task TokenCreate_Test() TreasuryContractAddress } }; - var createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(createTokenInfo); - createTokenRet.TransactionResult.Error.ShouldContain("Invalid native token input"); var createTokenInfoWithInvalidTokenName = new CreateInput(); createTokenInfoWithInvalidTokenName.MergeFrom(createTokenInfo); createTokenInfoWithInvalidTokenName.Symbol = "ITISAVERYLONGSYMBOLNAME"; - createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(createTokenInfoWithInvalidTokenName); + var createTokenRet = await CreateSeedNftWithExceptionAsync(TokenContractStub,createTokenInfoWithInvalidTokenName); createTokenRet.TransactionResult.Error.ShouldContain("Invalid token symbol length"); var createTokenInfoWithInvalidDecimal = new CreateInput(); createTokenInfoWithInvalidDecimal.MergeFrom(createTokenInfo); createTokenInfoWithInvalidDecimal.Decimals = 100; - createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(createTokenInfoWithInvalidDecimal); + createTokenRet = await CreateMutiTokenWithExceptionAsync(TokenContractStub,createTokenInfoWithInvalidDecimal); createTokenRet.TransactionResult.Error.ShouldContain("Invalid input"); - await CreateNativeTokenAsync(); - await TokenContractStub.Create.SendAsync(createTokenInfo); + await CreateMutiTokenAsync(TokenContractStub,createTokenInfo); var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { Symbol = AliceCoinTokenInfo.Symbol @@ -544,7 +510,6 @@ public async Task SetPrimaryToken_Test() Symbol = "NOTEXISTED" }); setPrimaryTokenRet.TransactionResult.Error.ShouldContain("Invalid input"); - await CreateNativeTokenAsync(); await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput { Symbol = NativeTokenInfo.Symbol @@ -562,7 +527,6 @@ await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbo [Fact] public async Task GetNativeToken_Test() { - await CreateNativeTokenAsync(); var tokenInfo = await TokenContractStub.GetNativeTokenInfo.CallAsync(new Empty()); tokenInfo.Symbol.ShouldBe(NativeTokenInfo.Symbol); } diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs index 9922564028..63954c5d51 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs @@ -24,8 +24,6 @@ public class MultiTokenContractTestBase : ContractTestBase> CreateSeedNftWithExceptionAsync( TokenContractImplContainer.TokenContractImplStub stub, diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs index 73df45294a..f9c91f87b1 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractWithCustomSystemTransactionTest.cs @@ -20,17 +20,6 @@ public MultiTokenContractWithCustomSystemTransactionTest() private async Task InitializeAsync() { - var input = new CreateInput - { - Symbol = DefaultSymbol, - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = _totalSupply, - Issuer = DefaultAddress - }; - - await CreateMutiTokenAsync(TokenContractStub, input); await TokenContractStub.SetPrimaryTokenSymbol.SendAsync(new SetPrimaryTokenSymbolInput { Symbol = DefaultSymbol From 3d88a764171cfb367378e4cadad0030deee13737 Mon Sep 17 00:00:00 2001 From: ssun0121 Date: Wed, 28 Jun 2023 14:01:29 +0800 Subject: [PATCH 103/139] feat: remove useless code. --- contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index d50e8e83ca..24bdc23aa6 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -29,11 +29,6 @@ private bool IsValidCreateSymbolChar(char character) { return character >= 'A' && character <= 'Z'; } - - private bool IsValidMethodNameChar(char character) - { - return (character >= 'A' && character <= 'Z') || (character >= 'a' && character <= 'z') || (character >= '0' && character <= '9'); - } private TokenInfo AssertValidToken(string symbol, long amount) { From d8f9c2bcc5c9c2ebb7ae5564e9e646cfa70b7506 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 28 Jun 2023 15:34:04 +0800 Subject: [PATCH 104/139] fix: ut --- .../AEDPoSExtensionDemoTestBase.cs | 13 +- .../AEDPoSExtensionTests.cs | 1 + .../SideChainConsensusInformationTest.cs | 1 + .../AssociationContractTests.cs | 22 +++- .../CrossChainContractTestBase.cs | 15 ++- .../ParliamentContractTest.cs | 123 +++++++----------- .../ParliamentContractTestBase.cs | 55 ++++++-- ...t.ExecutionPluginForMethodFee.Tests.csproj | 5 - .../ExecutePluginTransactionDirectlyTest.cs | 22 +++- .../ExecutionPluginForMethodFeeTestBase.cs | 34 ++--- ...ExecutionPluginForMethodFeeWithForkTest.cs | 43 +++--- ...ExecutionPluginForResourceFee.Tests.csproj | 3 + .../ExecutionPluginForResourceFeeTestBase.cs | 7 +- 13 files changed, 191 insertions(+), 153 deletions(-) diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs index 368cc56084..e755416f2b 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs @@ -81,8 +81,17 @@ internal void InitialContracts() internal void InitialAcs3Stubs() { foreach (var initialKeyPair in MissionedECKeyPairs.InitialKeyPairs) - ParliamentStubs.Add(GetTester( - ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], initialKeyPair)); + { + var parliamentStub = GetTester( + ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], initialKeyPair); + parliamentStub.Initialize.SendAsync(new AElf.Contracts.Parliament.InitializeInput + { + ProposerAuthorityRequired = false, + PrivilegedProposer = Address.FromPublicKey(initialKeyPair.PublicKey) + }); + + ParliamentStubs.Add(parliamentStub); + } } internal async Task diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs index 8840133e89..d8c6240394 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs @@ -23,6 +23,7 @@ public class AEDPoSExtensionTests : AEDPoSExtensionDemoTestBase public async Task Demo_Test() { InitialContracts(); + InitialAcs3Stubs(); // Check round information after initialization. { diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs index dd1ef0f753..793ac1ac41 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs @@ -31,6 +31,7 @@ public async Task UpdateInformationFromCrossChainTest() { SetToSideChain(); InitialContracts(); + InitialAcs3Stubs(); var mockedCrossChain = SampleAccount.Accounts.Last(); var mockedCrossChainStub = GetTester( diff --git a/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs b/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs index ad6ff414d9..f8c1c4079b 100644 --- a/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs +++ b/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs @@ -943,13 +943,21 @@ public async Task SetMethodFee_Fail_Test() var tokenSymbol = "DLS"; var invalidMethodFees = GetValidMethodFees(); invalidMethodFees.Fees[0].Symbol = tokenSymbol; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = tokenSymbol, - TokenName = "name", - Issuer = DefaultSender, - TotalSupply = 1000_000 - }); + + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + + var proposalId = await CreateFeeProposalAsync(TokenContractAddress, + defaultOrganization, nameof(TokenContractStub.Create), new CreateInput + { + Symbol = tokenSymbol, + TokenName = "name", + Issuer = DefaultSender, + TotalSupply = 1000_000 + }); + + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + var ret = await AssociationContractStub.SetMethodFee.SendWithExceptionAsync(invalidMethodFees); ret.TransactionResult.Error.ShouldContain($"Token {tokenSymbol} cannot set as method fee."); } diff --git a/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs b/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs index 11e08408eb..a47840028c 100644 --- a/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs +++ b/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs @@ -160,9 +160,11 @@ private async Task InitializeTokenAsync() { const string symbol = "ELF"; const long totalSupply = 100_000_000; - await MineAsync(new List - { - TokenContractStub.Create.GetTransaction(new CreateInput + + var parliamentOrganizationAddress = + (await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty())); + var approveProposalId = await CreateParliamentProposalAsync(nameof(TokenContractStub.Create), + parliamentOrganizationAddress, new CreateInput { Symbol = symbol, Decimals = 2, @@ -170,7 +172,12 @@ await MineAsync(new List TokenName = "elf token", TotalSupply = totalSupply, Issuer = DefaultSender - }), + }, TokenContractAddress); + await ApproveWithMinersAsync(approveProposalId); + await ParliamentContractStub.Release.SendAsync(approveProposalId); + + await MineAsync(new List + { TokenContractStub.Issue.GetTransaction(new IssueInput { Symbol = symbol, diff --git a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs index 143c27a168..af75ca6087 100644 --- a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs +++ b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs @@ -32,32 +32,9 @@ public ParliamentContractTest() InitializeContracts(); } - [Fact] - public async Task Get_DefaultOrganizationAddress_Test() - { - var transactionResult = - await ParliamentContractStub.GetDefaultOrganizationAddress.SendWithExceptionAsync(new Empty()); - transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - transactionResult.TransactionResult.Error.Contains("Not initialized.").ShouldBeTrue(); - - await InitializeParliamentContracts(); - var defaultParliamentAddress = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - defaultParliamentAddress.ShouldNotBeNull(); - } - - [Fact] - public async Task ParliamentContract_Initialize_Test() - { - var result = await ParliamentContractStub.Initialize.SendAsync(new InitializeInput()); - result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - [Fact] public async Task ParliamentContract_InitializeTwice_Test() { - await ParliamentContract_Initialize_Test(); - var result = await ParliamentContractStub.Initialize.SendWithExceptionAsync(new InitializeInput()); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); result.TransactionResult.Error.Contains("Already initialized.").ShouldBeTrue(); @@ -66,7 +43,7 @@ public async Task ParliamentContract_InitializeTwice_Test() [Fact] public async Task Get_Organization_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 10000 / MinersCount; var maximalAbstentionThreshold = 2000 / MinersCount; var maximalRejectionThreshold = 3000 / MinersCount; @@ -110,7 +87,7 @@ public async Task Get_OrganizationFailed_Test() [Fact] public async Task Get_Proposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -152,7 +129,7 @@ public async Task ApproveMultiProposals_Without_Authority_Test() [Fact] public async Task ApproveMultiProposals_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -185,7 +162,7 @@ public async Task Get_ProposalFailed_Test() [Fact] public async Task Create_OrganizationFailed_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -204,13 +181,7 @@ public async Task Create_OrganizationFailed_Test() }; var minerParliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); - - { - var transactionResult = - await ParliamentContractStub.CreateOrganization.SendWithExceptionAsync(createOrganizationInput); - transactionResult.TransactionResult.Error.ShouldContain("Unauthorized to create organization."); - } - + { createOrganizationInput.ProposalReleaseThreshold = proposalReleaseThreshold; createOrganizationInput.ProposalReleaseThreshold.MinimalApprovalThreshold = 10000; @@ -280,7 +251,7 @@ public async Task Create_OrganizationFailed_Test() [Fact] public async Task Create_ProposalFailed_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -374,7 +345,7 @@ public async Task Approve_Proposal_NotFoundProposal_Test() [Fact] public async Task Approve_Proposal_NotAuthorizedApproval_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -392,7 +363,7 @@ public async Task Approve_Proposal_NotAuthorizedApproval_Test() [Fact] public async Task Approve_Proposal_ExpiredTime_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -410,7 +381,7 @@ public async Task Approve_Proposal_ExpiredTime_Test() [Fact] public async Task Approve_Proposal_ApprovalAlreadyExists_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -436,7 +407,7 @@ public async Task Approve_Proposal_ApprovalAlreadyExists_Test() [Fact] public async Task Reject_Without_Authority_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -453,7 +424,7 @@ public async Task Reject_Without_Authority_Test() [Fact] public async Task Reject_With_Invalid_Proposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -482,7 +453,7 @@ public async Task Reject_With_Invalid_Proposal_Test() [Fact] public async Task Reject_Approved_Proposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -501,7 +472,7 @@ public async Task Reject_Approved_Proposal_Test() [Fact] public async Task Reject_Success_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -519,7 +490,7 @@ public async Task Reject_Success_Test() [Fact] public async Task Abstain_Without_Authority_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -536,7 +507,7 @@ public async Task Abstain_Without_Authority_Test() [Fact] public async Task Abstain_With_Invalid_Proposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -565,7 +536,7 @@ public async Task Abstain_With_Invalid_Proposal_Test() [Fact] public async Task Abstain_Approved_Proposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -584,7 +555,7 @@ public async Task Abstain_Approved_Proposal_Test() [Fact] public async Task Abstain_Success_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -602,7 +573,7 @@ public async Task Abstain_Success_Test() [Fact] public async Task Check_Proposal_ToBeReleased() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); { var minimalApprovalThreshold = 3000; @@ -676,7 +647,7 @@ public async Task Check_Proposal_ToBeReleased() [Fact] public async Task Release_NotEnoughApprove_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -706,7 +677,7 @@ public async Task Release_NotFound_Test() [Fact] public async Task Release_WrongSender_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -727,7 +698,7 @@ public async Task Release_WrongSender_Test() [Fact] public async Task Release_Expired_Proposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -744,7 +715,7 @@ public async Task Release_Expired_Proposal_Test() [Fact] public async Task Release_Proposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -776,7 +747,7 @@ public async Task Release_Proposal_Test() [Fact] public async Task Release_Proposal_AlreadyReleased_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -818,7 +789,7 @@ await ParliamentContractStub.ChangeOrganizationThreshold.SendWithExceptionAsync( [Fact] public async Task Change_OrganizationThreshold_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 3000; var maximalAbstentionThreshold = 3000; var maximalRejectionThreshold = 3000; @@ -881,7 +852,7 @@ public async Task Change_OrganizationThreshold_Test() [Fact] public async Task Check_ValidProposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6000; var maximalAbstentionThreshold = 2000; @@ -929,7 +900,7 @@ public async Task Check_ValidProposal_Test() [Fact] public async Task Clear_NotExpiredProposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var defaultParliamentAddress = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); var miner = InitialMinersKeyPairs[1]; @@ -950,7 +921,7 @@ public async Task Clear_NotExpiredProposal_Test() [Fact] public async Task Clear_ExpiredProposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; @@ -974,7 +945,7 @@ public async Task Clear_ExpiredProposal_Test() [Fact] public async Task ChangeMethodFeeController_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); var createOrganizationResult = await parliamentContractStub.CreateOrganization.SendAsync( @@ -1014,7 +985,7 @@ await parliamentContractStub.CreateOrganization.SendAsync( [Fact] public async Task ChangeMethodFeeController_WithoutAuth_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -1037,7 +1008,7 @@ public async Task ChangeMethodFeeController_WithoutAuth_Test() [Fact] public async Task ChangeMethodFeeController_With_Invalid_Authority_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); @@ -1103,7 +1074,7 @@ public async Task SetMethodFee_With_Invalid_Input_Test() [Fact] public async Task SetMethodFee_Without_Authority_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var setMethodFeeRet = await ParliamentContractStub.SetMethodFee.SendWithExceptionAsync(new MethodFees { MethodName = nameof(ParliamentContractStub.Abstain), @@ -1122,7 +1093,7 @@ public async Task SetMethodFee_Without_Authority_Test() [Fact] public async Task SetMethodFee_Success_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var parliamentContractStub = GetParliamentContractTester(InitialMinersKeyPairs[0]); var methodFeeController = await parliamentContractStub.GetMethodFeeController.CallAsync(new Empty()); var methodFeeName = nameof(parliamentContractStub.Abstain); @@ -1213,7 +1184,7 @@ await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, [Fact] public async Task ValidateOrganizationExist_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -1233,10 +1204,10 @@ public async Task ValidateOrganizationExist_Test() public async Task ValidateProposerInWhiteList_Test() { var proposer = DefaultSender; - await ParliamentContractStub.Initialize.SendAsync(new InitializeInput - { - PrivilegedProposer = proposer - }); + // await ParliamentContractStub.Initialize.SendAsync(new InitializeInput + // { + // PrivilegedProposer = proposer + // }); var isProposerInWhitelist = await ParliamentContractStub.ValidateProposerInWhiteList.CallAsync(new ValidateProposerInWhiteListInput { @@ -1287,10 +1258,10 @@ await _smartContractAddressService.SetSmartContractAddressAsync(blockIndex, [Fact] public async Task CreateProposalBySystemContract_Success_Test() { - await ParliamentContractStub.Initialize.SendAsync(new InitializeInput - { - PrivilegedProposer = DefaultSender - }); + // await ParliamentContractStub.Initialize.SendAsync(new InitializeInput + // { + // PrivilegedProposer = DefaultSender + // }); var defaultParliamentAddress = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); var chain = _blockchainService.GetChainAsync(); @@ -1338,7 +1309,7 @@ public async Task GetNotVotedProposals_With_Invalid_Proposal_Test() //fail to validate proposal, proposal expires { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -1372,7 +1343,7 @@ public async Task GetNotVotedPendingProposals_With_Invalid_Proposal_Test() } //fail to validate proposal, proposal expires { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -1395,7 +1366,7 @@ public async Task GetNotVotedPendingProposals_With_Invalid_Proposal_Test() [Fact] public async Task ApproveMultiProposals_With_Invalid_Proposal_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6667; var maximalAbstentionThreshold = 2000; var maximalRejectionThreshold = 3000; @@ -1417,7 +1388,7 @@ await ParliamentContractStub.ApproveMultiProposals.SendAsync(new ProposalIdList [Fact] public async Task Check_ValidProposal_With_Rejected_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 6000; var maximalAbstentionThreshold = 1; @@ -1461,7 +1432,7 @@ public async Task Check_ValidProposal_With_Rejected_Test() [Fact] public async Task GetReleaseThresholdReachedProposals_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 3000; var maximalAbstentionThreshold = 3000; @@ -1504,7 +1475,7 @@ public async Task GetReleaseThresholdReachedProposals_Test() [Fact] public async Task GetAvailableProposals_Test() { - await InitializeParliamentContracts(); + // await InitializeParliamentContracts(); var minimalApprovalThreshold = 3000; var maximalAbstentionThreshold = 3000; diff --git a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs index ce1efee793..72717d128d 100644 --- a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs +++ b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs @@ -37,8 +37,10 @@ public class ParliamentContractTestBase : ContractTestKit.ContractTestBase InitialMinersKeyPairs => Accounts.Take(MinersCount).Select(a => a.KeyPair).ToList(); protected Address DefaultSender => Accounts[10].Address; protected Address Tester => Accounts[MinersCount + 1].Address; + protected List InitialCoreDataCenterKeyPairs => - Accounts.Take(1).Select(a => a.KeyPair).ToList(); + Accounts.Take(3).Select(a => a.KeyPair).ToList(); + protected Address TokenContractAddress { get; set; } protected Address ConsensusContractAddress { get; set; } protected Address ParliamentContractAddress { get; set; } @@ -73,6 +75,15 @@ protected void InitializeContracts() ProposerAuthorityRequired = false, PrivilegedProposer = DefaultSender })); + + ConsensusContractAddress = AsyncHelper.RunSync(() => DeploySystemSmartContract( + KernelConstants.CodeCoverageRunnerCategory, + DPoSConsensusCode, + ConsensusSmartContractAddressNameProvider.Name, + DefaultSenderKeyPair)); + ConsensusContractStub = GetConsensusContractTester(DefaultSenderKeyPair); + AsyncHelper.RunSync(async () => await InitializeConsensusAsync()); + //deploy token contract TokenContractAddress = AsyncHelper.RunSync(() => DeploySystemSmartContract( @@ -82,14 +93,6 @@ protected void InitializeContracts() DefaultSenderKeyPair)); TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); AsyncHelper.RunSync(async () => await InitializeTokenAsync()); - - ConsensusContractAddress = AsyncHelper.RunSync(() => DeploySystemSmartContract( - KernelConstants.CodeCoverageRunnerCategory, - DPoSConsensusCode, - ConsensusSmartContractAddressNameProvider.Name, - DefaultSenderKeyPair)); - ConsensusContractStub = GetConsensusContractTester(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitializeConsensusAsync()); } @@ -119,7 +122,10 @@ private async Task InitializeTokenAsync() { const string symbol = "ELF"; const long totalSupply = 100_000_000; - await TokenContractStub.Create.SendAsync(new CreateInput + + var organizationAddress = + (await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty())); + var approveProposalId = await CreateParliamentProposalAsync(nameof(TokenContractStub.Create), organizationAddress, new CreateInput { Symbol = symbol, Decimals = 2, @@ -127,7 +133,11 @@ await TokenContractStub.Create.SendAsync(new CreateInput TokenName = "elf token", TotalSupply = totalSupply, Issuer = DefaultSender - }); + }, TokenContractAddress); + await ApproveWithMinersAsync(approveProposalId); + await ParliamentContractStub.Release.SendAsync(approveProposalId); + + await TokenContractStub.Issue.SendAsync(new IssueInput { Symbol = symbol, @@ -157,6 +167,29 @@ await ParliamentContractStub.Initialize.SendAsync(new InitializeInput PrivilegedProposer = DefaultSender }); } + + internal async Task CreateParliamentProposalAsync(string method, Address organizationAddress, + IMessage input, Address toAddress = null) + { + var proposal = (await ParliamentContractStub.CreateProposal.SendAsync(new CreateProposalInput + { + ToAddress = toAddress, + ContractMethodName = method, + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = organizationAddress, + Params = input.ToByteString() + })).Output; + return proposal; + } + + internal async Task ApproveWithMinersAsync(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) + { + var tester = GetParliamentContractTester(bp); + await tester.Approve.SendAsync(proposalId); + } + } } public class ParliamentContractPrivilegeTestBase : TestBase.ContractTestBase diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj index be41c73b32..8a46bd22dc 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests.csproj @@ -60,11 +60,6 @@ Contract PreserveNewest - - false - Contract - PreserveNewest - false Contract diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 91f70d6a0b..9ca1c138a2 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -43,6 +43,17 @@ public async Task ChargeTransactionFees_Without_Primary_Token_Test() // input With Primary Token await SetPrimaryTokenSymbolAsync(); var beforeChargeBalance = await GetBalanceAsync(address, nativeTokenSymbol); + + await TokenContractImplStub.SetMethodFee.SendAsync(new MethodFees + { + MethodName = methodName, + Fees = { new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = 1000 + } } + }); + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(new ChargeTransactionFeesInput { ContractAddress = TokenContractAddress, @@ -1119,8 +1130,7 @@ public async Task ChargeTransactionFee_DelegateNew_First( result.Delegations[NativeTokenSymbol].ShouldBe(5); } - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractStub.ConfigMethodFeeFreeAllowances), new MethodFeeFreeAllowancesConfig + await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFreeAllowancesConfig { FreeAllowances = new MethodFeeFreeAllowances { @@ -2317,8 +2327,7 @@ private async Task SetMethodOrSizeFeeAsync(string basi } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -2338,8 +2347,9 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); + return sizeFeeSymbolList; } diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index c763bd0662..136c2a8372 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -256,23 +256,23 @@ await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, }); } - // protected async Task SetMethodFeeWithProposalAsync(ByteString methodFee) - // { - // var proposal = await Tester.ExecuteContractWithMiningAsync(_parliamentAddress, - // nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), - // new CreateProposalInput - // { - // ContractMethodName = - // nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.SetMethodFee), - // ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), - // Params = methodFee, - // ToAddress = TokenContractAddress, - // OrganizationAddress = await GetParliamentDefaultOrganizationAddressAsync() - // }); - // var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); - // await ApproveWithMinersAsync(proposalId); - // await ReleaseProposalAsync(proposalId); - // } + protected async Task SetMethodFeeWithProposalAsync(ByteString methodFee) + { + var proposal = await Tester.ExecuteContractWithMiningAsync(_parliamentAddress, + nameof(ParliamentContractImplContainer.ParliamentContractImplStub.CreateProposal), + new CreateProposalInput + { + ContractMethodName = + nameof(MethodFeeProviderContractContainer.MethodFeeProviderContractStub.SetMethodFee), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + Params = methodFee, + ToAddress = TokenContractAddress, + OrganizationAddress = await GetParliamentDefaultOrganizationAddressAsync() + }); + var proposalId = Hash.Parser.ParseFrom(proposal.ReturnValue); + await ApproveWithMinersAsync(proposalId); + await ReleaseProposalAsync(proposalId); + } private async Task
GetParliamentDefaultOrganizationAddressAsync() { diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs index 3d0daac6b9..6a6ffe5a73 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeWithForkTest.cs @@ -34,19 +34,18 @@ public async Task ChargeFee_With_Fork_Test() { var amount = 100000; - var r = await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), new MethodFees + await SetMethodFeeWithProposalAsync(new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = + new MethodFee { - new MethodFee - { - Symbol = "ELF", - BasicFee = 100000 - } + Symbol = "ELF", + BasicFee = 100000 } - }); + } + }.ToByteString()); var result = await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput @@ -75,20 +74,20 @@ public async Task ChargeFee_With_Fork_Test() BlockHash = branchOneBlock.GetHash(), BlockHeight = branchOneBlock.Height }); transactionFeesMap.ShouldBeNull(); - await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), new MethodFees + + await SetMethodFeeWithProposalAsync(new MethodFees + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), + Fees = { - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), - Fees = + new MethodFee { - new MethodFee - { - Symbol = "ELF", - BasicFee = 200000 - } + Symbol = "ELF", + BasicFee = 200000 } - }); - + } + }.ToByteString()); + result = await Tester.ExecuteContractWithMiningReturnBlockAsync(TokenContractAddress, nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput { @@ -104,7 +103,7 @@ await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, BlockHash = result.Item1.GetHash(), BlockHeight = result.Item1.Height }); transactionFeesMap.First().Value.ShouldBe(fee); //300000 - targetFee.ShouldNotBe(fee); + targetFee.ShouldBe(fee); } // branch two diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj index 7b783166f8..6413e7f543 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests.csproj @@ -106,6 +106,9 @@ Protobuf\Proto\aedpos_contract.proto + + Protobuf\Proto\test_mock_parliament_contract.proto + diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs index 99519ddefa..efd21c3a47 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs @@ -4,6 +4,7 @@ using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; +using AElf.Contracts.TestContract.MockParliament; using AElf.Contracts.TokenConverter; using AElf.Contracts.Treasury; using AElf.ContractTestKit; @@ -124,7 +125,7 @@ public class ExecutionPluginForResourceFeeTestBase : ContractTestBase Accounts[0].KeyPair; @@ -201,7 +202,7 @@ await DeploySystemSmartContract(category, code, ParliamentContractAddress = await DeploySystemSmartContract(category, code, ParliamentSmartContractAddressNameProvider.Name, DefaultSenderKeyPair); ParliamentContractStub = - GetTester(ParliamentContractAddress, + GetTester(ParliamentContractAddress, DefaultSenderKeyPair); } @@ -381,7 +382,7 @@ await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync( private async Task InitializeParliament() { - await ParliamentContractStub.Initialize.SendAsync(new Contracts.Parliament.InitializeInput + await ParliamentContractStub.Initialize.SendAsync(new AElf.Contracts.TestContract.MockParliament.InitializeInput { ProposerAuthorityRequired = false, PrivilegedProposer = DefaultSender From 38c24bfc849778b61b9bc06c187b1a1989ef9f63 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 28 Jun 2023 15:53:08 +0800 Subject: [PATCH 105/139] feat: add changeVotingOption and claimProfits in VirtualAddressTestContract --- protobuf/test_virtual_address_contract.proto | 13 +++++++ ...ntracts.TestContract.VirtualAddress.csproj | 6 ++++ .../Action.cs | 34 +++++++++++++++++++ .../ReferenceState.cs | 2 ++ 4 files changed, 55 insertions(+) diff --git a/protobuf/test_virtual_address_contract.proto b/protobuf/test_virtual_address_contract.proto index b8f9a561aa..0ebaccdb8e 100644 --- a/protobuf/test_virtual_address_contract.proto +++ b/protobuf/test_virtual_address_contract.proto @@ -15,6 +15,8 @@ service VirtualAddressContract { rpc VirtualAddressVote(VirtualAddressVoteInput) returns (google.protobuf.Empty); rpc VirtualAddressWithdraw(aelf.Hash) returns (google.protobuf.Empty); + rpc VirtualAddressChangeVotingOption(VirtualAddressChangeVotingOptionInput) returns (google.protobuf.Empty); + rpc VirtualAddressClaimProfit(VirtualAddressClaimProfitInput) returns (google.protobuf.Empty); rpc GetVirtualAddress(google.protobuf.Empty) returns (aelf.Address) { option (aelf.is_view) = true; @@ -27,4 +29,15 @@ message VirtualAddressVoteInput { google.protobuf.Timestamp end_timestamp = 3; // Used to generate vote id. aelf.Hash token = 4; +} + +message VirtualAddressChangeVotingOptionInput { + bool is_reset = 1; + aelf.Hash vote_id = 2; + string pub_key = 3; +} + +message VirtualAddressClaimProfitInput { + aelf.Hash scheme_id = 1; + aelf.Address beneficiary = 2; } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.VirtualAddress/AElf.Contracts.TestContract.VirtualAddress.csproj b/test/AElf.Contracts.TestContract.VirtualAddress/AElf.Contracts.TestContract.VirtualAddress.csproj index d480fbc720..79dacdf5f2 100644 --- a/test/AElf.Contracts.TestContract.VirtualAddress/AElf.Contracts.TestContract.VirtualAddress.csproj +++ b/test/AElf.Contracts.TestContract.VirtualAddress/AElf.Contracts.TestContract.VirtualAddress.csproj @@ -24,6 +24,12 @@ Protobuf\Proto\reference\election_contract_impl.proto + + Protobuf\Proto\profit_contract.proto + + + Protobuf\Proto\profit_contract_impl.proto + diff --git a/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs b/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs index 2ce59acaed..fd0dbe2862 100644 --- a/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs +++ b/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs @@ -1,4 +1,5 @@ using AElf.Contracts.Election; +using AElf.Contracts.Profit; using AElf.Sdk.CSharp; using AElf.Types; using Google.Protobuf.WellKnownTypes; @@ -30,6 +31,33 @@ public override Empty VirtualAddressWithdraw(Hash input) return new Empty(); } + + public override Empty VirtualAddressChangeVotingOption(VirtualAddressChangeVotingOptionInput input) + { + Initialize(); + + Context.SendVirtualInline(HashHelper.ComputeFrom("test"), State.ElectionContract.Value, "ChangeVotingOption", new ChangeVotingOptionInput + { + CandidatePubkey = input.PubKey, + VoteId = input.VoteId, + IsResetVotingTime = input.IsReset + }); + + return new Empty(); + } + + public override Empty VirtualAddressClaimProfit(VirtualAddressClaimProfitInput input) + { + Initialize(); + + Context.SendVirtualInline(HashHelper.ComputeFrom("test"), State.ProfitContract.Value, "ClaimProfits", new ClaimProfitsInput + { + SchemeId = input.SchemeId, + Beneficiary = input.Beneficiary + }); + + return new Empty(); + } public override Address GetVirtualAddress(Empty input) { @@ -43,5 +71,11 @@ private void Initialize() State.ElectionContract.Value = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); } + + if (State.ProfitContract.Value == null) + { + State.ProfitContract.Value = + Context.GetContractAddressByName(SmartContractConstants.ProfitContractSystemName); + } } } \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.VirtualAddress/ReferenceState.cs b/test/AElf.Contracts.TestContract.VirtualAddress/ReferenceState.cs index 677e3c5e4c..e9d8ef4482 100644 --- a/test/AElf.Contracts.TestContract.VirtualAddress/ReferenceState.cs +++ b/test/AElf.Contracts.TestContract.VirtualAddress/ReferenceState.cs @@ -1,8 +1,10 @@ using AElf.Contracts.Election; +using AElf.Contracts.Profit; namespace AElf.Contracts.TestContract.VirtualAddress; public partial class State { internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } + internal ProfitContractContainer.ProfitContractReferenceState ProfitContract { get; set; } } \ No newline at end of file From aac99f72b83e182118181789874c8784ceef9971 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 28 Jun 2023 16:44:38 +0800 Subject: [PATCH 106/139] fix: VirtualAddress TestContract --- .../AElf.Contracts.TestContract.VirtualAddress/Action.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs b/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs index fd0dbe2862..5ead335c9c 100644 --- a/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs +++ b/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs @@ -2,6 +2,7 @@ using AElf.Contracts.Profit; using AElf.Sdk.CSharp; using AElf.Types; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; namespace AElf.Contracts.TestContract.VirtualAddress; @@ -18,7 +19,7 @@ public override Empty VirtualAddressVote(VirtualAddressVoteInput input) Amount = input.Amount, EndTimestamp = input.EndTimestamp, Token = input.Token - }); + }.ToByteString()); return new Empty(); } @@ -27,7 +28,7 @@ public override Empty VirtualAddressWithdraw(Hash input) { Initialize(); - Context.SendVirtualInline(HashHelper.ComputeFrom("test"), State.ElectionContract.Value, "Withdraw", input); + Context.SendVirtualInline(HashHelper.ComputeFrom("test"), State.ElectionContract.Value, "Withdraw", input.ToByteString()); return new Empty(); } @@ -41,7 +42,7 @@ public override Empty VirtualAddressChangeVotingOption(VirtualAddressChangeVotin CandidatePubkey = input.PubKey, VoteId = input.VoteId, IsResetVotingTime = input.IsReset - }); + }.ToByteString()); return new Empty(); } @@ -54,7 +55,7 @@ public override Empty VirtualAddressClaimProfit(VirtualAddressClaimProfitInput i { SchemeId = input.SchemeId, Beneficiary = input.Beneficiary - }); + }.ToByteString()); return new Empty(); } From 3a0943776c6872f1b8d9ad2b8d65a3f09feffd23 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Wed, 28 Jun 2023 17:08:54 +0800 Subject: [PATCH 107/139] refactor: refactor check seed symbol --- .../TokenContractConstants.cs | 6 +-- .../TokenContract_Actions.cs | 38 ++++++------- .../TokenContract_Helper.cs | 40 +++++++------- .../TokenContract_NFT_Actions.cs | 54 +++++++++++-------- .../BVT/TokenApplicationTests.cs | 2 + .../BVT/TokenManagementTests.cs | 2 +- .../MultiTokenContractTestBase.cs | 4 +- 7 files changed, 73 insertions(+), 73 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs index 4c0118d40b..68490327ea 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs @@ -19,7 +19,7 @@ public static class TokenContractConstants public const int NFTSymbolMaxLength = 30; public const string UserContractMethodFeeKey = "UserContractMethodFee"; public const string CollectionId = "0"; - public const string SeedCollectionId = "SEED-0"; - public const string SeedExternalInfoOwnerSymbol= "__seed_owned_symbol"; - public const string SeedExternalInfoExpireTime = "__seed_exp_time"; + public const string SeedCollectionSymbol = "SEED-0"; + public const string SeedOwnedSymbolExternalInfoKey= "__seed_owned_symbol"; + public const string SeedExpireTimeExternalInfoKey = "__seed_exp_time"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index be0063261d..1f116eb74e 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -45,21 +45,17 @@ public override Empty Create(CreateInput input) private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType.Token) { - AssertValidCreateInput(input); + AssertValidCreateInput(input,symbolType); if (symbolType == SymbolType.Token || symbolType == SymbolType.NftCollection) { - if (!IsAddressInCreateWhiteList(Context.Sender) && input.Symbol != TokenContractConstants.SeedCollectionId) + if (!IsAddressInCreateWhiteList(Context.Sender) && input.Symbol != TokenContractConstants.SeedCollectionSymbol) { var symbolSeed = State.SymbolSeedMap[input.Symbol]; CheckSeedNft(symbolSeed, input.Symbol); // seed nft for one-time use only long balance = State.Balances[Context.Sender][symbolSeed]; DoTransferFrom(Context.Sender, Context.Self, Context.Self, symbolSeed, balance, ""); - BurnWithAddress(new BurnInput - { - Symbol = symbolSeed, - Amount = balance - }, Context.Self); + Burn(Context.Self,symbolSeed,balance); } } @@ -109,15 +105,13 @@ private void CheckSeedNft(string symbolSeed, String symbol) var tokenInfo = State.TokenInfos[symbolSeed]; Assert(tokenInfo != null, "Seed NFT is not exist"); Assert(State.Balances[Context.Sender][symbolSeed] > 0, "owner doesn't own enough balance"); - Assert(tokenInfo.ExternalInfo != null && !tokenInfo.ExternalInfo.Equals(new ExternalInfo()), - "seed_owned_symbol is empty "); - tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoOwnerSymbol, - out var ownedSymbol); + Assert(tokenInfo.ExternalInfo != null,"seed_owned_symbol is empty ") ; + Assert( tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, + out var ownedSymbol) && !string.IsNullOrEmpty(ownedSymbol), "seed_owned_symbol is empty "); Assert(ownedSymbol == symbol, "seed_owned_symbol and input_symbol is inconsistent "); - tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoExpireTime, - out var expirationTime); - Assert(!string.IsNullOrEmpty(expirationTime) - && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime), "seed_owned_symbol is expired "); + Assert(tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, + out var expirationTime) + && !string.IsNullOrEmpty(expirationTime) && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime), "seed_owned_symbol is expired "); } @@ -270,21 +264,21 @@ public override Empty UnApprove(UnApproveInput input) public override Empty Burn(BurnInput input) { - return BurnWithAddress(input, Context.Sender); + return Burn(Context.Sender, input.Symbol, input.Amount); } - private Empty BurnWithAddress(BurnInput input, Address address) + private Empty Burn(Address address,string symbol, long amount) { - var tokenInfo = AssertValidToken(input.Symbol, input.Amount); + var tokenInfo = AssertValidToken(symbol, amount); Assert(tokenInfo.IsBurnable, "The token is not burnable."); - ModifyBalance(address, input.Symbol, -input.Amount); - tokenInfo.Supply = tokenInfo.Supply.Sub(input.Amount); + ModifyBalance(address, symbol, -amount); + tokenInfo.Supply = tokenInfo.Supply.Sub(amount); Context.Fire(new Burned { Burner = address, - Symbol = input.Symbol, - Amount = input.Amount + Symbol = symbol, + Amount = amount }); return new Empty(); } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index c5dd22bdd3..e60e474a2a 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -190,47 +190,43 @@ private int GetIssueChainId(string symbol) return tokenInfo.IssueChainId; } - private void AssertValidCreateInput(CreateInput input) + private void AssertValidCreateInput(CreateInput input, SymbolType symbolType) { Assert(input.TokenName.Length <= TokenContractConstants.TokenNameLength && input.Symbol.Length > 0 && input.Decimals >= 0 && input.Decimals <= TokenContractConstants.MaxDecimals, "Invalid input."); - - - TokenSymBolNameCheck(input.Symbol); + + SymbolLengthCheck(input.Symbol, symbolType); + SymbolPrefixDuplicatedCheck(input.Symbol, symbolType); } - private void TokenSymBolNameCheck( string symbol) + private void SymbolPrefixDuplicatedCheck(string symbol,SymbolType symbolType) { - var symbols = symbol.Split(TokenContractConstants.NFTSymbolSeparator); - var inputSymbolType = GetCreateInputSymbolType(symbol); var empty = new TokenInfo(); - if (inputSymbolType == SymbolType.Token) + var existing = State.TokenInfos[symbol]; + Assert(existing == null || existing.Equals(empty), "Token already exists."); + var symbols = symbol.Split(TokenContractConstants.NFTSymbolSeparator); + if (symbolType == SymbolType.Token) { - Assert(symbol.Length <= TokenContractConstants.SymbolMaxLength, "Invalid token symbol length"); var duplicatedNftCollection = - State.TokenInfos[ - symbols.First() + TokenContractConstants.NFTSymbolSeparator + TokenContractConstants.CollectionId]; + State.TokenInfos[symbols.First() + TokenContractConstants.NFTSymbolSeparator + TokenContractConstants.CollectionId]; Assert(duplicatedNftCollection == null || duplicatedNftCollection.Equals(empty), "Token name prefix can not be duplicated"); } - - if (inputSymbolType == SymbolType.Nft || inputSymbolType == SymbolType.NftCollection) - { - Assert(symbol.Length <= TokenContractConstants.NFTSymbolMaxLength, "Invalid NFT symbol length"); - } - - if (inputSymbolType == SymbolType.NftCollection) + if (symbolType == SymbolType.NftCollection) { var duplicatedToken = State.TokenInfos[symbols.First()]; Assert(duplicatedToken == null || duplicatedToken.Equals(empty), "Token name prefix can not be duplicated"); } + } - var existing = State.TokenInfos[symbol]; - Assert(existing == null || existing.Equals(empty), "Token already exists."); - Assert(!string.IsNullOrEmpty(symbol) && symbol.All(IsValidSymbolChar), - "Invalid symbol."); + private void SymbolLengthCheck(string symbol, SymbolType symbolType) + { + if (symbolType == SymbolType.Token) + Assert(symbol.Length <= TokenContractConstants.SymbolMaxLength, "Invalid token symbol length"); + if (symbolType == SymbolType.Nft || symbolType == SymbolType.NftCollection) + Assert(symbol.Length <= TokenContractConstants.NFTSymbolMaxLength, "Invalid NFT symbol length"); } private void CheckCrossChainTokenContractRegistrationControllerAuthority() diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 9d8b1a2d40..9b75d9d975 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -18,31 +18,38 @@ private Empty CreateNFTInfo(CreateInput input) AssertNFTCreateInput(input); var nftCollectionInfo = AssertNftCollectionExist(input.Symbol); input.IssueChainId = input.IssueChainId == 0 ? nftCollectionInfo.IssueChainId : input.IssueChainId; - Assert(input.IssueChainId == nftCollectionInfo.IssueChainId, "NFT create ChainId must be collection's issue chainId"); - Assert(Context.Sender == nftCollectionInfo.Issuer && nftCollectionInfo.Issuer == input.Issuer, "NFT issuer must be collection's issuer"); - if (nftCollectionInfo.Symbol == TokenContractConstants.SeedCollectionId) + Assert(input.IssueChainId == nftCollectionInfo.IssueChainId, + "NFT create ChainId must be collection's issue chainId"); + Assert(Context.Sender == nftCollectionInfo.Issuer && nftCollectionInfo.Issuer == input.Issuer, + "NFT issuer must be collection's issuer"); + if (nftCollectionInfo.Symbol == TokenContractConstants.SeedCollectionSymbol) { - input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoOwnerSymbol,out var ownerSymbol); - input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoExpireTime,out var expirationTime); - - Assert(!string.IsNullOrEmpty(ownerSymbol),"seed_owned_symbol is empty "); - TokenSymBolNameCheck(ownerSymbol); - Assert(!string.IsNullOrEmpty(expirationTime) - && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime),"seed_owned_symbol is expired "); - var oldSymbolSeed = State.SymbolSeedMap[ownerSymbol]; - var oldSymbolSeedExpireTime =""; - if (oldSymbolSeed !=null) - { - State.TokenInfos[oldSymbolSeed].ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExternalInfoExpireTime,out oldSymbolSeedExpireTime); - } - Assert(oldSymbolSeed == null || string.IsNullOrEmpty(oldSymbolSeedExpireTime) - || Context.CurrentBlockTime.Seconds > long.Parse(oldSymbolSeedExpireTime),"seed_owned_symbol has been created"); - State.SymbolSeedMap[ownerSymbol] = input.Symbol; + Assert( + input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, + out var ownedSymbol) && !string.IsNullOrEmpty(ownedSymbol), "seed_owned_symbol is empty"); + Assert(input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, + out var expirationTime) + && !string.IsNullOrEmpty(expirationTime) && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime), "seed_owned_symbol is expired "); + var ownedSymbolType = GetCreateInputSymbolType(ownedSymbol); + SymbolLengthCheck(ownedSymbol, ownedSymbolType); + SymbolPrefixDuplicatedCheck(ownedSymbol, ownedSymbolType); + OriginalSeedSymbolCheck(ownedSymbol); + State.SymbolSeedMap[ownedSymbol] = input.Symbol; } + return CreateToken(input, SymbolType.Nft); } - + private void OriginalSeedSymbolCheck(string ownedSymbol) + { + var oldSymbolSeed = State.SymbolSeedMap[ownedSymbol]; + Assert(oldSymbolSeed == null || !State.TokenInfos[oldSymbolSeed].ExternalInfo.Value + .TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, + out var oldSymbolSeedExpireTime) || string.IsNullOrEmpty(oldSymbolSeedExpireTime) + || Context.CurrentBlockTime.Seconds > long.Parse(oldSymbolSeedExpireTime), + "seed_owned_symbol has been created"); + } + private void DoTransferFrom(Address from, Address to, Address spender, string symbol, long amount, string memo) { @@ -53,7 +60,8 @@ private void DoTransferFrom(Address from, Address to, Address spender, string sy if (IsInWhiteList(new IsInWhiteListInput { Symbol = symbol, Address = spender }).Value) { DoTransfer(from, to, symbol, amount, memo); - DealWithExternalInfoDuringTransfer(new TransferFromInput() { From = from, To = to, Symbol = symbol, Amount = amount, Memo = memo }); + DealWithExternalInfoDuringTransfer(new TransferFromInput() + { From = from, To = to, Symbol = symbol, Amount = amount, Memo = memo }); return; } @@ -63,11 +71,11 @@ private void DoTransferFrom(Address from, Address to, Address spender, string sy } DoTransfer(from, to, symbol, amount, memo); - DealWithExternalInfoDuringTransfer(new TransferFromInput() { From = from, To = to, Symbol = symbol, Amount = amount, Memo = memo }); + DealWithExternalInfoDuringTransfer(new TransferFromInput() + { From = from, To = to, Symbol = symbol, Amount = amount, Memo = memo }); State.Allowances[from][spender][symbol] = allowance.Sub(amount); } - private string GetNftCollectionSymbol(string inputSymbol) { diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index b07ac80237..de3e681497 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -5,6 +5,7 @@ using AElf.Contracts.TestContract.BasicFunction; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; +using AElf.Kernel; using AElf.Standards.ACS10; using AElf.Types; using Google.Protobuf.WellKnownTypes; @@ -1247,6 +1248,7 @@ public async Task CrossContractCreateToken_Test() TotalSupply = TotalSupply, ExternalInfo = new TestContract.BasicFunction.ExternalInfo() }; + var result = await BasicFunctionContractStub.CreateTokenThroughMultiToken.SendAsync(createTokenInput); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var checkTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { Symbol = "TEST" }); diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs index e01690b324..49a7b58134 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs @@ -493,7 +493,7 @@ public async Task TokenCreate_Test() createTokenInfoWithInvalidDecimal.Decimals = 100; createTokenRet = await CreateMutiTokenWithExceptionAsync(TokenContractStub,createTokenInfoWithInvalidDecimal); createTokenRet.TransactionResult.Error.ShouldContain("Invalid input"); - await CreateMutiTokenAsync(TokenContractStub,createTokenInfo); + await TokenContractStub.Create.SendAsync(createTokenInfo); var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { Symbol = AliceCoinTokenInfo.Symbol diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs index 63954c5d51..c1d004cd31 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs @@ -69,10 +69,10 @@ public MultiTokenContractTestBase() nameof(TokenContractStub.Create), new CreateInput() { Symbol = "ELF", - Decimals = 0, + Decimals = 8, IsBurnable = true, TokenName = "ELF2", - TotalSupply = 1, + TotalSupply = 100_000_000_000_000_000L, Issuer = DefaultAddress, ExternalInfo = new ExternalInfo() })); From a4f8733582b277f6d149f516d96d99deb50f89c1 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Wed, 28 Jun 2023 17:11:11 +0800 Subject: [PATCH 108/139] fix: review issues --- ...PoSContract_ProcessConsensusInformation.cs | 5 +- .../Application/AEDPoSInformationProvider.cs | 8 ---- .../AEDPoSTriggerInformationProvider.cs | 8 ++-- .../Application/IAEDPoSInformationProvider.cs | 1 - .../Application/IRandomNumberProvider.cs | 47 +++++++++++++++++++ .../Application/IRandomProvider.cs | 31 ------------ .../ISmartContractBridgeContext.cs | 2 +- .../HostSmartContractBridgeContext.cs | 14 +++++- .../CSharpSmartContractContext.cs | 4 +- .../EconomicContractsTestModule.cs | 3 +- .../MockAEDPoSInformationProvider.cs | 20 -------- .../MockRandomNumberProvider.cs | 22 +++++++++ 12 files changed, 92 insertions(+), 73 deletions(-) create mode 100644 src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomNumberProvider.cs delete mode 100644 src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomProvider.cs delete mode 100644 test/AElf.Contracts.Economic.TestBase/MockAEDPoSInformationProvider.cs create mode 100644 test/AElf.Contracts.Economic.TestBase/MockRandomNumberProvider.cs diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs index af089676b8..fd1e42e738 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract_ProcessConsensusInformation.cs @@ -73,8 +73,9 @@ private void ProcessConsensusInformation(dynamic input, [CallerMemberName] strin $"Current round information:\n{currentRound.ToString(_processingBlockMinerPubkey)}"); var previousRandomHash = State.RandomHashes[Context.CurrentHeight.Sub(1)] ?? Hash.Empty; - var beta = Context.ECVrfVerify(Context.RecoverPublicKey(), previousRandomHash.ToByteArray(), - randomNumber.ToByteArray()); + Assert( + Context.ECVrfVerify(Context.RecoverPublicKey(), previousRandomHash.ToByteArray(), + randomNumber.ToByteArray(), out var beta), "Failed to verify random number."); var randomHash = Hash.LoadFromByteArray(beta); State.RandomHashes[Context.CurrentHeight] = randomHash; Context.LogDebug(() => $"New random hash generated: {randomHash} - height {Context.CurrentHeight}"); diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs index e1d82c2795..971ed6bead 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSInformationProvider.cs @@ -32,12 +32,4 @@ await _contractReaderFactory .Create(contractReaderContext).GetCurrentMinerList.CallAsync(new Empty()); return minersWithRoundNumber.Pubkeys.Select(k => k.ToHex()); } - - public async Task GetRandomHashAsync(IChainContext chainContext, long blockHeight) - { - var contractReaderContext = - await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); - return await _contractReaderFactory - .Create(contractReaderContext).GetRandomHash.CallAsync(new Int64Value { Value = blockHeight }); - } } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs index 89113766e2..b55b785c5f 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs @@ -16,15 +16,15 @@ internal class AEDPoSTriggerInformationProvider : ITriggerInformationProvider private readonly IAccountService _accountService; private readonly IInValueCache _inValueCache; private readonly ISecretSharingService _secretSharingService; - private readonly IRandomProvider _randomProvider; + private readonly IRandomNumberProvider _randomNumberProvider; public AEDPoSTriggerInformationProvider(IAccountService accountService, - ISecretSharingService secretSharingService, IInValueCache inValueCache, IRandomProvider randomProvider) + ISecretSharingService secretSharingService, IInValueCache inValueCache, IRandomNumberProvider randomNumberProvider) { _accountService = accountService; _secretSharingService = secretSharingService; _inValueCache = inValueCache; - _randomProvider = randomProvider; + _randomNumberProvider = randomNumberProvider; Logger = NullLogger.Instance; } @@ -76,7 +76,7 @@ public BytesValue GetTriggerInformationForBlockHeaderExtraData(BytesValue consen public BytesValue GetTriggerInformationForConsensusTransactions(IChainContext chainContext, BytesValue consensusCommandBytes) { - var randomProve = AsyncHelper.RunSync(async ()=> await _randomProvider.GenerateRandomProveAsync(chainContext)); + var randomProve = AsyncHelper.RunSync(async ()=> await _randomNumberProvider.GenerateRandomProofAsync(chainContext)); if (consensusCommandBytes == null) return new AElfConsensusTriggerInformation diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs index 21d817cbfb..73dcb641fe 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IAEDPoSInformationProvider.cs @@ -8,5 +8,4 @@ namespace AElf.Kernel.Consensus.AEDPoS.Application; public interface IAEDPoSInformationProvider { Task> GetCurrentMinerListAsync(ChainContext chainContext); - Task GetRandomHashAsync(IChainContext chainContext, long blockHeight); } \ No newline at end of file diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomNumberProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomNumberProvider.cs new file mode 100644 index 0000000000..cd21577534 --- /dev/null +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomNumberProvider.cs @@ -0,0 +1,47 @@ +using System.Threading.Tasks; +using AElf.Contracts.Consensus.AEDPoS; +using AElf.Kernel.Account.Application; +using AElf.Kernel.Consensus.Application; +using AElf.Kernel.SmartContract.Application; +using AElf.Types; +using Google.Protobuf.WellKnownTypes; +using Volo.Abp.DependencyInjection; + +namespace AElf.Kernel.Consensus.AEDPoS.Application; + +public interface IRandomNumberProvider +{ + Task GenerateRandomProofAsync(IChainContext chainContext); +} + +internal class RandomNumberProvider : IRandomNumberProvider, ITransientDependency +{ + private readonly IAccountService _accountService; + private readonly IConsensusReaderContextService _consensusReaderContextService; + private readonly IContractReaderFactory _contractReaderFactory; + + public RandomNumberProvider(IAccountService accountService, + IConsensusReaderContextService consensusReaderContextService, + IContractReaderFactory contractReaderFactory) + { + _accountService = accountService; + _consensusReaderContextService = consensusReaderContextService; + _contractReaderFactory = contractReaderFactory; + } + + public async Task GenerateRandomProofAsync(IChainContext chainContext) + { + var previousRandomHash = chainContext.BlockHeight == AElfConstants.GenesisBlockHeight + ? Hash.Empty + : await GetRandomHashAsync(chainContext, chainContext.BlockHeight); + return await _accountService.ECVrfProveAsync(previousRandomHash.ToByteArray()); + } + + private async Task GetRandomHashAsync(IChainContext chainContext, long blockHeight) + { + var contractReaderContext = + await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); + return await _contractReaderFactory + .Create(contractReaderContext).GetRandomHash.CallAsync(new Int64Value { Value = blockHeight }); + } +} diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomProvider.cs deleted file mode 100644 index bb891b4e20..0000000000 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/IRandomProvider.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading.Tasks; -using AElf.Kernel.Account.Application; -using AElf.Types; -using Volo.Abp.DependencyInjection; - -namespace AElf.Kernel.Consensus.AEDPoS.Application; - -public interface IRandomProvider -{ - Task GenerateRandomProveAsync(IChainContext chainContext); -} - -public class RandomProvider : IRandomProvider, ITransientDependency -{ - private readonly IAEDPoSInformationProvider _aedPoSInformationProvider; - private readonly IAccountService _accountService; - - public RandomProvider(IAEDPoSInformationProvider aedPoSInformationProvider, IAccountService accountService) - { - _aedPoSInformationProvider = aedPoSInformationProvider; - _accountService = accountService; - } - - public async Task GenerateRandomProveAsync(IChainContext chainContext) - { - var previousRandomHash = chainContext.BlockHeight == AElfConstants.GenesisBlockHeight - ? Hash.Empty - : await _aedPoSInformationProvider.GetRandomHashAsync(chainContext, chainContext.BlockHeight); - return await _accountService.ECVrfProveAsync(previousRandomHash.ToByteArray()); - } -} diff --git a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs index 1c53303b41..473ccfc932 100644 --- a/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract.Shared/ISmartContractBridgeContext.cs @@ -89,7 +89,7 @@ Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash virtualA object ValidateStateSize(object obj); - byte[] ECVrfVerify(byte[] pubKey, byte[] alpha, byte[] pi); + bool ECVrfVerify(byte[] pubKey, byte[] alpha, byte[] pi, out byte[] beta); } [Serializable] diff --git a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs index daef5aec24..53cd03ed12 100644 --- a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs @@ -350,8 +350,18 @@ public byte[] RecoverPublicKey(byte[] signature, byte[] hash) return !cabBeRecovered ? null : publicKey; } - public byte[] ECVrfVerify(byte[] pubKey, byte[] alpha, byte[] pi) + public bool ECVrfVerify(byte[] pubKey, byte[] alpha, byte[] pi, out byte[] beta) { - return CryptoHelper.ECVrfVerify(pubKey, alpha, pi); + try + { + beta = CryptoHelper.ECVrfVerify(pubKey, alpha, pi); + } + catch + { + beta = null; + return false; + } + + return true; } } \ No newline at end of file diff --git a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs index 6b90ae9a63..ae91d612d8 100644 --- a/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs +++ b/src/AElf.Sdk.CSharp/CSharpSmartContractContext.cs @@ -373,8 +373,8 @@ public Address ConvertVirtualAddressToContractAddressWithContractHashName(Hash v virtualAddress); } - public byte[] ECVrfVerify(byte[] pubKey, byte[] alpha, byte[] pi) + public bool ECVrfVerify(byte[] pubKey, byte[] alpha, byte[] pi, out byte[] beta) { - return SmartContractBridgeContextImplementation.ECVrfVerify(pubKey, alpha, pi); + return SmartContractBridgeContextImplementation.ECVrfVerify(pubKey, alpha, pi, out beta); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs index 25bd849b42..6d50eeb482 100644 --- a/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs +++ b/test/AElf.Contracts.Economic.TestBase/EconomicContractsTestModule.cs @@ -26,8 +26,7 @@ public override void ConfigureServices(ServiceConfigurationContext context) // context.Services.AddSingleton(); context.Services.AddSingleton(); context.Services.AddSingleton(); - context.Services.AddTransient(); - context.Services.AddTransient(); + context.Services.AddTransient(); context.Services.RemoveAll(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/MockAEDPoSInformationProvider.cs b/test/AElf.Contracts.Economic.TestBase/MockAEDPoSInformationProvider.cs deleted file mode 100644 index 77a4ad24ca..0000000000 --- a/test/AElf.Contracts.Economic.TestBase/MockAEDPoSInformationProvider.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using AElf.Kernel; -using AElf.Kernel.Consensus.AEDPoS.Application; -using AElf.Types; - -namespace AElf.Contracts.Economic.TestBase; - -public class MockAEDPoSInformationProvider : IAEDPoSInformationProvider -{ - public Task> GetCurrentMinerListAsync(ChainContext chainContext) - { - throw new System.NotImplementedException(); - } - - public async Task GetRandomHashAsync(IChainContext chainContext, long blockHeight) - { - return Hash.Empty; - } -} \ No newline at end of file diff --git a/test/AElf.Contracts.Economic.TestBase/MockRandomNumberProvider.cs b/test/AElf.Contracts.Economic.TestBase/MockRandomNumberProvider.cs new file mode 100644 index 0000000000..8bcd0d3d61 --- /dev/null +++ b/test/AElf.Contracts.Economic.TestBase/MockRandomNumberProvider.cs @@ -0,0 +1,22 @@ +using System.Threading.Tasks; +using AElf.Kernel; +using AElf.Kernel.Account.Application; +using AElf.Kernel.Consensus.AEDPoS.Application; +using AElf.Types; + +namespace AElf.Contracts.Economic.TestBase; + +public class MockRandomNumberProvider : IRandomNumberProvider +{ + private readonly IAccountService _accountService; + + public MockRandomNumberProvider(IAccountService accountService) + { + _accountService = accountService; + } + + public async Task GenerateRandomProofAsync(IChainContext chainContext) + { + return await _accountService.ECVrfProveAsync(Hash.Empty.ToByteArray()); + } +} \ No newline at end of file From 8c2bb254b56478800ba6274125a619da97a21e34 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Wed, 28 Jun 2023 17:15:41 +0800 Subject: [PATCH 109/139] fix: naming --- .../BlockMiningService.cs | 4 ++-- .../AEDPoSTriggerInformationProvider.cs | 8 ++++---- .../AEDPoSContractTestBase.cs | 2 +- .../BVT/ACS4ImplTest.cs | 14 +++++++------- .../BVT/MinersCountTest.cs | 8 ++++---- .../BVT/MiningProcessTest.cs | 12 ++++++------ .../BVT/ViewTests.cs | 2 +- .../OtherContractsOperation.cs | 8 ++++---- .../MultiTokenContractCrossChainTestBase.cs | 4 ++-- 9 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs index ebc9f6f87d..bf70b9a807 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs @@ -134,7 +134,7 @@ public async Task MineBlockAsync(List transactions = null, bool wit throw new InitializationFailedException("Can't find current round information."); } - var randomNumber = await GenerateRandomProveAsync(); + var randomNumber = await GenerateRandomProofAsync(); var triggerInformation = await GetConsensusTriggerInfoAsync(contractStub, pubkey, ByteString.CopyFrom(randomNumber)); var consensusTransaction = await contractStub.GenerateConsensusTransactions.CallAsync(new BytesValue { @@ -162,7 +162,7 @@ public async Task MineBlockAsync(List transactions = null, bool wit _isSkipped = false; } - private async Task GenerateRandomProveAsync() + private async Task GenerateRandomProofAsync() { var blockHeight = (await _blockchainService.GetChainAsync()).BestChainHeight; var previousRandomHash = diff --git a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs index b55b785c5f..4801f78af1 100644 --- a/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs +++ b/src/AElf.Kernel.Consensus.AEDPoS/Application/AEDPoSTriggerInformationProvider.cs @@ -76,14 +76,14 @@ public BytesValue GetTriggerInformationForBlockHeaderExtraData(BytesValue consen public BytesValue GetTriggerInformationForConsensusTransactions(IChainContext chainContext, BytesValue consensusCommandBytes) { - var randomProve = AsyncHelper.RunSync(async ()=> await _randomNumberProvider.GenerateRandomProofAsync(chainContext)); + var randomProof = AsyncHelper.RunSync(async ()=> await _randomNumberProvider.GenerateRandomProofAsync(chainContext)); if (consensusCommandBytes == null) return new AElfConsensusTriggerInformation { Pubkey = Pubkey, Behaviour = AElfConsensusBehaviour.UpdateValue, - RandomNumber = ByteString.CopyFrom(randomProve) + RandomNumber = ByteString.CopyFrom(randomProof) }.ToBytesValue(); var command = consensusCommandBytes.ToConsensusCommand(); @@ -98,7 +98,7 @@ public BytesValue GetTriggerInformationForConsensusTransactions(IChainContext ch InValue = inValue, PreviousInValue = _inValueCache.GetInValue(hint.PreviousRoundId), Behaviour = hint.Behaviour, - RandomNumber = ByteString.CopyFrom(randomProve) + RandomNumber = ByteString.CopyFrom(randomProof) }; var secretPieces = _secretSharingService.GetEncryptedPieces(hint.RoundId); @@ -120,7 +120,7 @@ public BytesValue GetTriggerInformationForConsensusTransactions(IChainContext ch { Pubkey = Pubkey, Behaviour = hint.Behaviour, - RandomNumber = ByteString.CopyFrom(randomProve) + RandomNumber = ByteString.CopyFrom(randomProof) }.ToBytesValue(); } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs index 6d023108d9..3754b0d07f 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs @@ -153,7 +153,7 @@ protected async Task BootMinerChangeRoundAsync(long nextRoundNumber = 2) .AddMilliseconds( ((long)currentRound.TotalMilliseconds(AEDPoSContractTestConstants.MiningInterval)).Mul( nextRoundNumber.Sub(1))); - var randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + var randomNumber = await GenerateRandomProofAsync(BootMinerKeyPair); currentRound.GenerateNextRoundInformation(expectedStartTime.ToTimestamp(), BlockchainStartTimestamp, ByteString.CopyFrom(randomNumber), out var nextRound); await AEDPoSContractStub.NextRound.SendAsync(nextRound); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs index 48f2f46cbe..8e1d56ce9c 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS4ImplTest.cs @@ -78,7 +78,7 @@ private async Task AEDPoSContract_GenerateConsensusTransactions TriggerInformationProvider.GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); - trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(BootMinerKeyPair)); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProofAsync(BootMinerKeyPair)); var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(trigger.ToBytesValue()); @@ -180,7 +180,7 @@ private async Task AEDPoSContract_GenerateConsensusTransactions var triggerForCommand = TriggerInformationProvider .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); - trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(usingKeyPair)); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProofAsync(usingKeyPair)); var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(trigger.ToBytesValue()); @@ -258,7 +258,7 @@ public async Task AEDPoSContract_GetInformationToUpdateConsensus_FirstRound_Extr var triggerForCommand = TriggerInformationProvider .GetTriggerInformationForBlockHeaderExtraData(consensusCommand.ToBytesValue()); var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); - trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(usingKeyPair)); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProofAsync(usingKeyPair)); var extraDataBytes = await AEDPoSContractStub.GetConsensusExtraData.CallAsync(trigger.ToBytesValue()); @@ -284,7 +284,7 @@ private async Task var triggerForCommand = TriggerInformationProvider .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); - trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(usingKeyPair)); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProofAsync(usingKeyPair)); var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(trigger.ToBytesValue()); @@ -336,7 +336,7 @@ public async Task AEDPoSContract_ConsensusTransactionValidation_Test() nextRoundInput.RoundNumber++; nextRoundInput.IsMinerListJustChanged = false; nextRoundInput.TermNumber++; - var randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + var randomNumber = await GenerateRandomProofAsync(BootMinerKeyPair); nextRoundInput.RandomNumber = ByteString.CopyFrom(randomNumber); var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); @@ -416,7 +416,7 @@ public async Task AEDPoSContract_GenerateConsensusTransaction_TinyBlock_Test() var triggerForCommand = TriggerInformationProvider .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); - trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(usingKeyPair)); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProofAsync(usingKeyPair)); var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(trigger.ToBytesValue()); @@ -449,7 +449,7 @@ public async Task AEDPoSContract_GenerateConsensusTransaction_NextTerm_Test() var triggerForCommand = TriggerInformationProvider .GetTriggerInformationForConsensusTransactions(new ChainContext(), consensusCommand.ToBytesValue()); var trigger = AElfConsensusTriggerInformation.Parser.ParseFrom(triggerForCommand.Value); - trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(usingKeyPair)); + trigger.RandomNumber = ByteString.CopyFrom(await GenerateRandomProofAsync(usingKeyPair)); var transactionList = await AEDPoSContractStub.GenerateConsensusTransactions.CallAsync(trigger.ToBytesValue()); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs index fd5304c99a..f053759f68 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MinersCountTest.cs @@ -66,7 +66,7 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() (await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggers[minerInRound.Pubkey] .ToBytesValue())).ToConsensusHeaderInformation(); - randomNumber = await GenerateRandomProveAsync(currentKeyPair); + randomNumber = await GenerateRandomProofAsync(currentKeyPair); // Update consensus information. var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey, @@ -85,7 +85,7 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() }.ToBytesValue())).ToConsensusHeaderInformation(); var nextRoundInput = NextRoundInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); - randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + randomNumber = await GenerateRandomProofAsync(BootMinerKeyPair); nextRoundInput.RandomNumber = ByteString.CopyFrom(randomNumber); await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); changeTermTime = BlockchainStartTimestamp.ToDateTime().AddMinutes(termIntervalMin).AddSeconds(10); @@ -99,7 +99,7 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() }.ToBytesValue())).ToConsensusHeaderInformation(); var nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); - randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + randomNumber = await GenerateRandomProofAsync(BootMinerKeyPair); nextTermInput.RandomNumber = ByteString.CopyFrom(randomNumber); var transactionResult = await AEDPoSContractStub.NextTerm.SendAsync(nextTermInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); @@ -128,7 +128,7 @@ public async Task AEDPoSContract_ChangeMinersCount_Test() .Pubkey) }.ToBytesValue())).ToConsensusHeaderInformation(); nextTermInput = NextTermInput.Parser.ParseFrom(nextRoundInformation.Round.ToByteArray()); - randomNumber = await GenerateRandomProveAsync(keypair); + randomNumber = await GenerateRandomProofAsync(keypair); nextTermInput.RandomNumber = ByteString.CopyFrom(randomNumber); await newMinerStub.NextTerm.SendAsync(nextTermInput); termCount++; diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs index bebe8cd7c9..43570af8f2 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/MiningProcessTest.cs @@ -59,7 +59,7 @@ await voter.Vote.SendAsync(new VoteMinerInput var headerInformation = (await AEDPoSContractStub.GetConsensusExtraData.CallAsync(triggers[minerInRound.Pubkey] .ToBytesValue())).ToConsensusHeaderInformation(); - randomNumber = await GenerateRandomProveAsync(currentKeyPair); + randomNumber = await GenerateRandomProofAsync(currentKeyPair); // Update consensus information. var toUpdate = headerInformation.Round.ExtractInformationToUpdateConsensus(minerInRound.Pubkey, ByteString.CopyFrom(randomNumber)); await tester.UpdateValue.SendAsync(toUpdate); @@ -76,7 +76,7 @@ await voter.Vote.SendAsync(new VoteMinerInput Pubkey = ByteString.CopyFrom(BootMinerKeyPair.PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); var nextTermInput = NextTermInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); - randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + randomNumber = await GenerateRandomProofAsync(BootMinerKeyPair); nextTermInput.RandomNumber = ByteString.CopyFrom(randomNumber); await AEDPoSContractStub.NextTerm.SendAsync(nextTermInput); @@ -92,7 +92,7 @@ await voter.Vote.SendAsync(new VoteMinerInput InValue = inValue, Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); - randomNumber = await GenerateRandomProveAsync(ValidationDataCenterKeyPairs[0]); + randomNumber = await GenerateRandomProofAsync(ValidationDataCenterKeyPairs[0]); var updateResult = await oneCandidate.UpdateValue.SendAsync( informationOfSecondRound.Round.ExtractInformationToUpdateConsensus(ValidationDataCenterKeyPairs[0] .PublicKey.ToHex(), ByteString.CopyFrom(randomNumber))); @@ -106,7 +106,7 @@ await voter.Vote.SendAsync(new VoteMinerInput Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation().Round; var nextRoundInput = NextRoundInput.Parser.ParseFrom(thirdRound.ToByteArray()); - randomNumber = await GenerateRandomProveAsync(ValidationDataCenterKeyPairs[0]); + randomNumber = await GenerateRandomProofAsync(ValidationDataCenterKeyPairs[0]); nextRoundInput.RandomNumber = ByteString.CopyFrom(randomNumber); await oneCandidate.NextRound.SendAsync(nextRoundInput); @@ -118,7 +118,7 @@ await voter.Vote.SendAsync(new VoteMinerInput InValue = HashHelper.ComputeFrom("InValue"), // Don't care this value in current test case. Pubkey = ByteString.CopyFrom(ValidationDataCenterKeyPairs[0].PublicKey) }.ToBytesValue())).ToConsensusHeaderInformation(); - randomNumber = await GenerateRandomProveAsync(ValidationDataCenterKeyPairs[0]); + randomNumber = await GenerateRandomProofAsync(ValidationDataCenterKeyPairs[0]); await oneCandidate.UpdateValue.SendAsync( cheatInformation.Round.ExtractInformationToUpdateConsensus(ValidationDataCenterKeyPairs[0].PublicKey .ToHex(), ByteString.CopyFrom(randomNumber))); @@ -140,7 +140,7 @@ public async Task Update_TinyBlockInformation_Test() RoundId = roundInfo.RoundId, ProducedBlocks = 4, ActualMiningTime = BlockTimeProvider.GetBlockTime(), - RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(BootMinerKeyPair)) + RandomNumber = ByteString.CopyFrom(await GenerateRandomProofAsync(BootMinerKeyPair)) }; var transactionResult = await AEDPoSContractStub.UpdateTinyBlockInformation.SendAsync(input); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs index ff97e556ec..d23ca5613a 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ViewTests.cs @@ -29,7 +29,7 @@ public async Task Query_RoundInformation_Test() }.ToBytesValue())).ToConsensusHeaderInformation(); var nextRoundInput = NextRoundInput.Parser.ParseFrom(nextTermInformation.Round.ToByteArray()); - var randomNumber = await GenerateRandomProveAsync(BootMinerKeyPair); + var randomNumber = await GenerateRandomProofAsync(BootMinerKeyPair); nextRoundInput.RandomNumber = ByteString.CopyFrom(randomNumber); var transactionResult = await AEDPoSContractStub.NextRound.SendAsync(nextRoundInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs index 8ffb5334ce..512053a26a 100644 --- a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs +++ b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs @@ -26,7 +26,7 @@ protected async Task NextTerm(ECKeyPair keyPair) victories.Value } }; - var randomNumber = await GenerateRandomProveAsync(keyPair); + var randomNumber = await GenerateRandomProofAsync(keyPair); var firstRoundOfNextTerm = miners.GenerateFirstRoundOfNewTerm(EconomicContractsTestConstants.MiningInterval, randomNumber, BlockTimeProvider.GetBlockTime(), round.RoundNumber, round.TermNumber); @@ -39,7 +39,7 @@ protected async Task NextRound(ECKeyPair keyPair) { var miner = GetConsensusContractTester(keyPair); var round = await miner.GetCurrentRoundInformation.CallAsync(new Empty()); - var randomNumber = await GenerateRandomProveAsync(keyPair); + var randomNumber = await GenerateRandomProofAsync(keyPair); round.GenerateNextRoundInformation( StartTimestamp.ToDateTime().AddMilliseconds(round.TotalMilliseconds()).ToTimestamp(), StartTimestamp, ByteString.CopyFrom(randomNumber), out var nextRound); @@ -61,7 +61,7 @@ await miner.UpdateValue.SendAsync(new UpdateValueInput ProducedBlocks = minerInRound.ProducedBlocks + 1, ActualMiningTime = minerInRound.ExpectedMiningTime, SupposedOrderOfNextRound = 1, - RandomNumber = ByteString.CopyFrom(await GenerateRandomProveAsync(keyPair)) + RandomNumber = ByteString.CopyFrom(await GenerateRandomProofAsync(keyPair)) }); } @@ -100,7 +100,7 @@ protected async Task GetVoteTokenBalance(byte[] publicKey) return balance; } - protected async Task GenerateRandomProveAsync(ECKeyPair keyPair) + protected async Task GenerateRandomProofAsync(ECKeyPair keyPair) { var consensusContractStub = GetConsensusContractTester(keyPair); var blockHeight = (await BlockchainService.GetChainAsync()).BestChainHeight; diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs index 79c3300b82..34eac22ecf 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs @@ -325,7 +325,7 @@ internal async Task BootMinerChangeRoundAsync(AEDPoSContractContainer.AEDPoSCont { if (isMainChain) { - var randomNumber = await GenerateRandomProveAsync(aedPoSContractStub, DefaultAccount.KeyPair); + var randomNumber = await GenerateRandomProofAsync(aedPoSContractStub, DefaultAccount.KeyPair); var currentRound = await aedPoSContractStub.GetCurrentRoundInformation.CallAsync(new Empty()); var expectedStartTime = TimestampHelper.GetUtcNow(); currentRound.GenerateNextRoundInformation(expectedStartTime, BlockchainStartTimestamp, @@ -362,7 +362,7 @@ internal async Task BootMinerChangeRoundAsync(AEDPoSContractContainer.AEDPoSCont } } - private async Task GenerateRandomProveAsync(AEDPoSContractContainer.AEDPoSContractStub aedPoSContractStub, + private async Task GenerateRandomProofAsync(AEDPoSContractContainer.AEDPoSContractStub aedPoSContractStub, ECKeyPair keyPair) { var blockHeight = (await BlockchainService.GetChainAsync()).BestChainHeight; From 13582b05ae8836037658c2e992f5e94698cdee57 Mon Sep 17 00:00:00 2001 From: kevin Date: Wed, 28 Jun 2023 19:32:23 +0800 Subject: [PATCH 110/139] feat: implement acs1 in VirtualAddress TestContract --- .../Action.cs | 2 +- .../Action_Fee.cs | 32 +++++++++++++++++++ .../State.cs | 3 +- 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 test/AElf.Contracts.TestContract.VirtualAddress/Action_Fee.cs diff --git a/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs b/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs index 5ead335c9c..b4db57ec2f 100644 --- a/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs +++ b/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs @@ -7,7 +7,7 @@ namespace AElf.Contracts.TestContract.VirtualAddress; -public class Action : VirtualAddressContractContainer.VirtualAddressContractBase +public partial class Action : VirtualAddressContractContainer.VirtualAddressContractBase { public override Empty VirtualAddressVote(VirtualAddressVoteInput input) { diff --git a/test/AElf.Contracts.TestContract.VirtualAddress/Action_Fee.cs b/test/AElf.Contracts.TestContract.VirtualAddress/Action_Fee.cs new file mode 100644 index 0000000000..4d117b11f7 --- /dev/null +++ b/test/AElf.Contracts.TestContract.VirtualAddress/Action_Fee.cs @@ -0,0 +1,32 @@ +using AElf.Sdk.CSharp; +using AElf.Standards.ACS1; +using Google.Protobuf.WellKnownTypes; + +namespace AElf.Contracts.TestContract.VirtualAddress; + +public partial class Action +{ + [View] + public override MethodFees GetMethodFee(StringValue input) + { + var methodFees = State.TransactionFees[input.Value]; + if (methodFees != null) + return methodFees; + + //set default tx fee + return new MethodFees + { + MethodName = input.Value, + Fees = + { + new MethodFee { Symbol = "ELF", BasicFee = 1000_0000 } + } + }; + } + + public override Empty SetMethodFee(MethodFees input) + { + State.TransactionFees[input.MethodName] = input; + return new Empty(); + } +} \ No newline at end of file diff --git a/test/AElf.Contracts.TestContract.VirtualAddress/State.cs b/test/AElf.Contracts.TestContract.VirtualAddress/State.cs index 75d9d72646..0869e1a44e 100644 --- a/test/AElf.Contracts.TestContract.VirtualAddress/State.cs +++ b/test/AElf.Contracts.TestContract.VirtualAddress/State.cs @@ -1,8 +1,9 @@ using AElf.Sdk.CSharp.State; +using AElf.Standards.ACS1; namespace AElf.Contracts.TestContract.VirtualAddress; public partial class State : ContractState { - + public MappedState TransactionFees { get; set; } } \ No newline at end of file From a3382442f6d78e498d73cc5864188f460f81a10f Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 29 Jun 2023 10:22:57 +0800 Subject: [PATCH 111/139] fix: ut --- src/AElf.ContractTestKit/ContractTestBase.cs | 36 -------------- .../AEDPoSExtensionDemoTestBase.cs | 7 +-- .../AEDPoSExtensionTests.cs | 30 ++++++++---- .../MaximumMinersCountTests.cs | 8 +++- .../ConfigurationContractTest.cs | 1 + .../ConfigurationContractTestBase.cs | 47 +++++++++++++++++++ .../AEDPoSContractTestBase.cs | 2 +- .../BVT/ACS10ImplTest.cs | 28 ++++++++--- .../BVT/ACS1ImplTest.cs | 2 +- .../ReferendumContractTest.cs | 37 +++++++++++++-- 10 files changed, 134 insertions(+), 64 deletions(-) diff --git a/src/AElf.ContractTestKit/ContractTestBase.cs b/src/AElf.ContractTestKit/ContractTestBase.cs index 5ea3f85012..170ac0a9b9 100644 --- a/src/AElf.ContractTestKit/ContractTestBase.cs +++ b/src/AElf.ContractTestKit/ContractTestBase.cs @@ -129,40 +129,4 @@ protected IReadOnlyDictionary GetPatchedCodes(string dir) // ? File.ReadAllBytes(path) // : throw new FileNotFoundException("Contract DLL cannot be found. " + path); // } - - protected async Task SubmitAndApproveProposalOfDefaultParliament(ECKeyPair senderKeyPair, Address parliamentAddress, - Address contractAddress, string methodName, IMessage message) - { - // var parliamentContractStub = - // GetTester(parliamentAddress, senderKeyPair); - // // await parliamentContractStub.Initialize.SendAsync(new AElf.Contracts.Parliament.InitializeInput - // // { - // // PrivilegedProposer = DefaultAccount.Address, - // // ProposerAuthorityRequired = false - // // }); - // var defaultParliamentAddress = - // await parliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - // - // var proposal = new CreateProposalInput - // { - // OrganizationAddress = defaultParliamentAddress, - // ContractMethodName = methodName, - // ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - // Params = message.ToByteString(), - // ToAddress = contractAddress - // }; - // var createResult = await parliamentContractStub.CreateProposal.SendAsync(proposal); - // var proposalId = createResult.Output; - // await ApproveWithMinersAsync(proposalId, parliamentAddress); - // await parliamentContractStub.Release.SendAsync(proposalId); - } - - private async Task ApproveWithMinersAsync(Hash proposalId, Address parliamentAddress) - { - // foreach (var bp in InitialCoreDataCenterKeyPairs) - // { - // var tester = GetTester(parliamentAddress, bp); - // await tester.Approve.SendAsync(proposalId); - // } - } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs index e755416f2b..a3550cb210 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionDemoTestBase.cs @@ -84,12 +84,7 @@ internal void InitialAcs3Stubs() { var parliamentStub = GetTester( ContractAddresses[ParliamentSmartContractAddressNameProvider.Name], initialKeyPair); - parliamentStub.Initialize.SendAsync(new AElf.Contracts.Parliament.InitializeInput - { - ProposerAuthorityRequired = false, - PrivilegedProposer = Address.FromPublicKey(initialKeyPair.PublicKey) - }); - + ParliamentStubs.Add(parliamentStub); } } diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs index d8c6240394..5675dfb267 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs @@ -6,8 +6,11 @@ using AElf.Contracts.MultiToken; using AElf.ContractTestKit; using AElf.ContractTestKit.AEDPoSExtension; +using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Consensus; +using AElf.Kernel.Token; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -43,15 +46,25 @@ public async Task Demo_Test() // And this will produce one block with one transaction. // This transaction will call Create method of Token Contract. - var createTokenTransaction = TokenStub.Create.GetTransaction(new CreateInput + var defaultOrganizationAddress = + await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); + await ParliamentReachAnAgreementAsync(new CreateProposalInput { - Symbol = "ELF", - Decimals = 8, - TokenName = "Test", - Issuer = Accounts[0].Address, - IsBurnable = true, - TotalSupply = 1_000_000_000_00000000 + ToAddress = ContractAddresses[TokenSmartContractAddressNameProvider.Name], + ContractMethodName = nameof(TokenStub.Create), + Params = new CreateInput + { + Symbol = "ELF", + Decimals = 8, + TokenName = "Test", + Issuer = Accounts[0].Address, + IsBurnable = true, + TotalSupply = 1_000_000_000_00000000 + }.ToByteString(), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = defaultOrganizationAddress }); + const long issueTokenAmount = 10_0000_00000000; var issueToAddress = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.First().PublicKey); var issueTokenTransaction = TokenStub.Issue.GetTransaction(new IssueInput @@ -62,12 +75,11 @@ public async Task Demo_Test() }); await BlockMiningService.MineBlockAsync(new List { - createTokenTransaction, issueTokenTransaction }); var createTokenTransactionTrace = - TransactionTraceProvider.GetTransactionTrace(createTokenTransaction.GetHash()); + TransactionTraceProvider.GetTransactionTrace(issueTokenTransaction.GetHash()); createTokenTransactionTrace.ExecutionStatus.ShouldBe(ExecutionStatus.Executed); // Check whether previous Create transaction successfully executed. diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/MaximumMinersCountTests.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/MaximumMinersCountTests.cs index 858b0d890f..69f4d0c7d9 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/MaximumMinersCountTests.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/MaximumMinersCountTests.cs @@ -3,11 +3,13 @@ using System.Threading.Tasks; using AElf.Contracts.Parliament; using AElf.ContractTestKit; +using AElf.ContractTestKit.AEDPoSExtension; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Standards.ACS3; +using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; @@ -30,7 +32,11 @@ public async Task SetMaximumMinersCountTest(int targetMinersCount) await BlockMiningService.MineBlockToNextTermAsync(); InitialAcs3Stubs(); - await ParliamentStubs.First().Initialize.SendAsync(new InitializeInput()); + await ParliamentStubs.First().Initialize.SendAsync(new InitializeInput + { + ProposerAuthorityRequired = false, + PrivilegedProposer = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.First().PublicKey) + }); var defaultOrganizationAddress = await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); await ParliamentReachAnAgreementAsync(new CreateProposalInput diff --git a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs index 2fb4b58217..f7af112853 100644 --- a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs +++ b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs @@ -345,6 +345,7 @@ public async Task SetMethodFee_Failed_Test() // token is not profitable { var tokenSymbol = "DLS"; + await CreateTokenAsync(tokenSymbol); await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, nameof(TokenContractContainer.TokenContractStub.Create), new CreateInput { diff --git a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs index aa42ed0d40..1dfc74d86b 100644 --- a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs +++ b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using AElf.Contracts.Configuration; +using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; using AElf.Contracts.TestBase; using AElf.Cryptography.ECDSA; @@ -168,4 +169,50 @@ protected async Task GetMethodFeeController(Address configuration new Empty()); return AuthorityInfo.Parser.ParseFrom(methodFeeControllerByteString); } + + protected async Task CreateTokenAsync(string symbol) + { + await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.Create), + new CreateInput + { + Symbol = "SEED-0", + Decimals = 0, + IsBurnable = true, + TokenName = "seed Collection", + TotalSupply = 1, + Issuer = Tester.GetCallOwnerAddress(), + ExternalInfo = new ExternalInfo() + }); + await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.Create), + new CreateInput + { + Symbol = "SEED-1", + Decimals = 0, + IsBurnable = true, + TokenName = "seed", + TotalSupply = 1, + Issuer = Tester.GetCallOwnerAddress(), + ExternalInfo = new ExternalInfo + { + Value = + { + { "__seed_owned_symbol", symbol }, + { "__seed_exp_time", TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString() } + } + }, + LockWhiteList = { TokenContractAddress } + }); + + await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, + nameof(TokenContractContainer.TokenContractStub.Issue), + new IssueInput + { + Symbol = "SEED-1", + Amount = 1, + To = Tester.GetCallOwnerAddress(), + Memo = "test" + }); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs index 6cc536f844..227066b234 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/AEDPoSContractTestBase.cs @@ -167,7 +167,7 @@ protected async Task CreateProposalAsync(Address contractAddress, Address ContractMethodName = methodName, ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), Params = input.ToByteString(), - ToAddress = ConsensusContractAddress + ToAddress = contractAddress }; var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs index 17d18c9803..ce36388c2e 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs @@ -2,6 +2,7 @@ using AElf.Contracts.MultiToken; using AElf.Standards.ACS10; using AElf.Types; +using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; @@ -14,14 +15,9 @@ public async Task Consensus_Donate_With_Invalid_Token_Test() { var tokenSymbol = "SEP"; + await CreateTokenAsync(tokenSymbol); + // Donate with token which is not profitable will fail - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = tokenSymbol, - TokenName = "name", - TotalSupply = 1000_000_000, - Issuer = BootMinerAddress - }); var issueAmount = 1000_000; await TokenContractStub.Issue.SendAsync(new IssueInput { @@ -48,4 +44,22 @@ await TokenContractStub.Issue.SendAsync(new IssueInput }); balanceAfterDonate.Balance.ShouldBe(issueAmount); } + + private async Task CreateTokenAsync(string symbol) + { + var defaultOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + + const string proposalCreationMethodName = nameof(TokenContractStub.Create); + var proposalId = await CreateProposalAsync(TokenContractAddress, defaultOrganization, + proposalCreationMethodName, new CreateInput + { + Symbol = symbol, + TokenName = "name", + TotalSupply = 1000_000_000, + Issuer = BootMinerAddress + }); + await ApproveWithMinersAsync(proposalId); + var result = await ParliamentContractStub.Release.SendAsync(proposalId); + var t = "t"; + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS1ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS1ImplTest.cs index 058f3afcd9..489f4d80ad 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS1ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS1ImplTest.cs @@ -31,7 +31,7 @@ await ParliamentContractStub.CreateOrganization.SendAsync( const string proposalCreationMethodName = nameof(AEDPoSContractImplContainer.AEDPoSContractImplStub.ChangeMethodFeeController); - var proposalId = await CreateProposalAsync(methodFeeController.ContractAddress, + var proposalId = await CreateProposalAsync(ConsensusContractAddress, methodFeeController.OwnerAddress, proposalCreationMethodName, new AuthorityInfo { OwnerAddress = organizationAddress, diff --git a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs index ba8ca9b78f..ec34758530 100644 --- a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs +++ b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Threading.Tasks; using AElf.Contracts.MultiToken; +using AElf.Contracts.Parliament; using AElf.Cryptography.ECDSA; using AElf.CSharp.Core.Extension; using AElf.Kernel; @@ -1292,10 +1293,11 @@ private async Task CreateProposalAsync(ECKeyPair proposalKeyPair, Address { var defaultParliamentAddress = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, TokenContractAddress, nameof(TokenContractStub.Create), new CreateInput { - Symbol = "SEED-" + "0", + Symbol = "SEED-0", Decimals = 0, IsBurnable = true, TokenName = "seed Collection", @@ -1306,7 +1308,7 @@ await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, Parliame await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, TokenContractAddress, nameof(TokenContractStub.Create), new CreateInput { - Symbol = "SEED-" + "1", + Symbol = "SEED-1", Decimals = 0, IsBurnable = true, TokenName = "seed token" + 1, @@ -1331,7 +1333,7 @@ await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, Parliame Memo = "ddd", To = organizationAddress }); - + var createInput = new CreateInput { Symbol = "NEW", @@ -1539,4 +1541,33 @@ private MethodFees GetValidMethodFees() } }; } + + private async Task SubmitAndApproveProposalOfDefaultParliament(ECKeyPair senderKeyPair, Address parliamentAddress, + Address contractAddress, string methodName, IMessage message) + { + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + + var proposal = new CreateProposalInput + { + OrganizationAddress = defaultParliamentAddress, + ContractMethodName = methodName, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = message.ToByteString(), + ToAddress = contractAddress + }; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalId = createResult.Output; + await ApproveWithMinersAsync(proposalId, parliamentAddress); + await ParliamentContractStub.Release.SendAsync(proposalId); + } + + private async Task ApproveWithMinersAsync(Hash proposalId, Address parliamentAddress) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) + { + var tester = GetTester(parliamentAddress, bp); + await tester.Approve.SendAsync(proposalId); + } + } } \ No newline at end of file From 392525d1ef155385ea8f144ecd4e8bd36b66a0e4 Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 29 Jun 2023 10:38:48 +0800 Subject: [PATCH 112/139] fix: cr --- .../ElectionContract_Elector.cs | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs index d524390f92..1cb2b933a7 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs @@ -524,22 +524,17 @@ private ElectorVote GetElectorVote(byte[] recoveredPublicKey) var voterVotes = State.ElectorVotes[Context.Sender.ToBase58()]; if (voterVotes != null) return voterVotes; - if (recoveredPublicKey != null) - { - var publicKey = recoveredPublicKey.ToHex(); + if (recoveredPublicKey == null) return null; - voterVotes = State.ElectorVotes[publicKey]?.Clone(); + var publicKey = recoveredPublicKey.ToHex(); - if (voterVotes != null) - { - voterVotes.Address ??= Context.Sender; - - State.ElectorVotes.Remove(publicKey); - return voterVotes; - } - } + voterVotes = State.ElectorVotes[publicKey]?.Clone(); + + if (voterVotes == null) return null; + voterVotes.Address ??= Context.Sender; - return null; + State.ElectorVotes.Remove(publicKey); + return voterVotes; } /// @@ -646,10 +641,10 @@ public override Empty Withdraw(Hash input) Assert(voterVotes != null, $"Voter {Context.Sender.ToBase58()} never votes before"); - voterVotes!.ActiveVotingRecordIds.Remove(input); + voterVotes.ActiveVotingRecordIds.Remove(input); voterVotes.WithdrawnVotingRecordIds.Add(input); voterVotes.ActiveVotedVotesAmount = voterVotes.ActiveVotedVotesAmount.Sub(votingRecord.Amount); - + State.ElectorVotes[Context.Sender.ToBase58()] = voterVotes; // Update Candidate's Votes information. @@ -658,7 +653,7 @@ public override Empty Withdraw(Hash input) Assert(candidateVotes != null, $"Newest pubkey {newestPubkey} is invalid. Old pubkey is {votingRecord.Option}"); - candidateVotes!.ObtainedActiveVotingRecordIds.Remove(input); + candidateVotes.ObtainedActiveVotingRecordIds.Remove(input); candidateVotes.ObtainedWithdrawnVotingRecordIds.Add(input); candidateVotes.ObtainedActiveVotedVotesAmount = candidateVotes.ObtainedActiveVotedVotesAmount.Sub(votingRecord.Amount); From 2e8f2afe605dde4e0901d7bc08105fdcdabe763b Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Thu, 29 Jun 2023 11:57:04 +0800 Subject: [PATCH 113/139] feat: add ut --- .../TokenContract_Helper.cs | 1 + .../BVT/TokenApplicationTests.cs | 24 +++++++- .../MultiTokenContractCrossChainTest.cs | 45 ++++++++------- .../MultiTokenContractCrossChainTestBase.cs | 55 +++++++++++++++++++ .../MultiTokenContractReferenceFeeTest.cs | 35 ++++++++---- 5 files changed, 129 insertions(+), 31 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index e60e474a2a..dd74bc3d11 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -199,6 +199,7 @@ private void AssertValidCreateInput(CreateInput input, SymbolType symbolType) SymbolLengthCheck(input.Symbol, symbolType); SymbolPrefixDuplicatedCheck(input.Symbol, symbolType); + OriginalSeedSymbolCheck(input.Symbol); } private void SymbolPrefixDuplicatedCheck(string symbol,SymbolType symbolType) diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index de3e681497..8889d9e5ce 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -1248,7 +1248,29 @@ public async Task CrossContractCreateToken_Test() TotalSupply = TotalSupply, ExternalInfo = new TestContract.BasicFunction.ExternalInfo() }; - + var input = new CreateInput + { + Symbol = SeedNFTSymbolPre + 100, + Decimals = 0, + IsBurnable = true, + TokenName = "seed token" + 100, + TotalSupply = 1, + Issuer = DefaultAddress, + ExternalInfo = new ExternalInfo(), + LockWhiteList = { TokenContractAddress } + }; + input.ExternalInfo.Value["__seed_owned_symbol"] = createTokenInput.Symbol; + input.ExternalInfo.Value["__seed_exp_time"] = TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString(); + await TokenContractStub.Create.SendAsync(input); + await TokenContractStub.Issue.SendAsync(new IssueInput + { + Symbol = input.Symbol, + Amount = 1, + Memo = "ddd", + To = BasicFunctionContractAddress + + }); + var result = await BasicFunctionContractStub.CreateTokenThroughMultiToken.SendAsync(createTokenInput); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var checkTokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { Symbol = "TEST" }); diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs index c40cc6ed98..56dd025f9c 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs @@ -195,8 +195,8 @@ public async Task MainChain_CrossChainCreateToken_Test() // Side chain create token var createTransaction = - CreateTransactionForTokenCreation(SideChainTokenContractStub, SideChainTestKit.DefaultAccount.Address, - SymbolForTesting); + await CreateTransactionForTokenCreation(SideChainTokenContractStub, SideChainTestKit.DefaultAccount.Address, + SymbolForTesting,SideTokenContractAddress); var executedSet = await SideChainTestKit.MineAsync(new List { createTransaction }); var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); @@ -236,8 +236,8 @@ public async Task SideChain_CrossChainCreateToken_Test() // Main chain create token await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting); + var createTransaction = await CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting,TokenContractAddress); var blockExecutedSet = await MineAsync(new List { createTransaction }); var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); @@ -328,14 +328,14 @@ public async Task SideChain_CrossChainCreateToken_WithAlreadyCreated_Test() await RegisterSideChainContractAddressOnMainChainAsync(); await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting); + var createTransaction =await CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting,TokenContractAddress); var blockExecutedSet = await MineAsync(new List { createTransaction }); var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); - var sideCreateTransaction = CreateTransactionForTokenCreation(SideChainTokenContractStub, - SideChainTestKit.DefaultAccount.Address, SymbolForTesting); + var sideCreateTransaction =await CreateTransactionForTokenCreation(SideChainTokenContractStub, + SideChainTestKit.DefaultAccount.Address, SymbolForTesting,SideTokenContractAddress); blockExecutedSet = await SideChainTestKit.MineAsync(new List { sideCreateTransaction }); var sideCreateResult = blockExecutedSet.TransactionResultMap[sideCreateTransaction.GetHash()]; Assert.True(sideCreateResult.Status == TransactionResultStatus.Mined, sideCreateResult.Error); @@ -437,8 +437,8 @@ public async Task MainChain_CrossChainTransfer_NativeToken_Test() [Fact] public async Task MainChain_CrossChainTransfer_Without_Burnable_Token_Test() { - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting, false); + var createTransaction = await CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting, TokenContractAddress, false); var blockExecutedSet = await MineAsync(new List { createTransaction }); var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); @@ -471,8 +471,8 @@ public async Task MainChain_CrossChainTransfer_Test() // Main chain create token await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting); + var createTransaction = await CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting,TokenContractAddress); var executedSet = await MineAsync(new List { createTransaction }); var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); @@ -723,8 +723,8 @@ public async Task SideChain_CrossChainReceived_InvalidToken_Test() await RegisterMainChainTokenContractAddressOnSideChainAsync(sideChainId); var transferAmount = 1000; - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting); + var createTransaction = await CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting,TokenContractAddress); var executedSet = await MineAsync(new List { createTransaction }); var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; createResult.Status.ShouldBe(TransactionResultStatus.Mined, createResult.Error); @@ -809,8 +809,8 @@ public async Task SideChain_CrossChainReceived_DifferentReceiver_Test() public async Task CrossChainCreateToken_WithoutRegister_Test() { await GenerateSideChainAsync(false); - var createTransaction = CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting); + var createTransaction =await CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting,TokenContractAddress); var blockExecutedSet = await MineAsync(new List { createTransaction }); var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); @@ -871,12 +871,13 @@ private Transaction ValidateTransaction(Address tokenContractAddress, Hash name, } - private Transaction CreateTransactionForTokenCreation( + private async Task CreateTransactionForTokenCreation( TokenContractImplContainer.TokenContractImplStub tokenContractImplStub, - Address issuer, string symbol, bool isBurnable = true) + Address issuer, string symbol, Address lockWhiteAddress, bool isBurnable = true) { + await CreateSeedNftCollection(tokenContractImplStub,issuer ); var tokenInfo = GetTokenInfo(symbol, issuer, isBurnable); - return tokenContractImplStub.Create.GetTransaction(new CreateInput + var input = new CreateInput { Symbol = tokenInfo.Symbol, Decimals = tokenInfo.Decimals, @@ -884,8 +885,12 @@ private Transaction CreateTransactionForTokenCreation( IsBurnable = tokenInfo.IsBurnable, TokenName = tokenInfo.TokenName, TotalSupply = tokenInfo.TotalSupply - }); + }; + await CreateSeedNftAsync(tokenContractImplStub,input,lockWhiteAddress); + return tokenContractImplStub.Create.GetTransaction(input); } + + private Transaction CreateTokenInfoValidationTransaction(TokenInfo createdTokenInfo, TokenContractImplContainer.TokenContractImplStub tokenContractImplStub) diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs index ca4e882201..2aafdf8911 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.CrossChain; @@ -73,6 +74,9 @@ public class MultiTokenContractCrossChainTestBase : ContractTestBase CreateSeedNftAsync(TokenContractImplContainer.TokenContractImplStub stub, + CreateInput createInput,Address lockWhiteAddress) + { + var input = BuildSeedCreateInput(createInput,lockWhiteAddress); + await stub.Create.SendAsync(input); + await stub.Issue.SendAsync(new IssueInput + { + Symbol = input.Symbol, + Amount = 1, + Memo = "ddd", + To = input.Issuer + }); + return input; + } + + internal CreateInput BuildSeedCreateInput(CreateInput createInput,Address lockWhiteAddress) + { + Interlocked.Increment(ref SeedNum); + var input = new CreateInput + { + Symbol = SeedNFTSymbolPre + SeedNum, + Decimals = 0, + IsBurnable = true, + TokenName = "seed token" + SeedNum, + TotalSupply = 1, + Issuer = createInput.Issuer, + ExternalInfo = new ExternalInfo(), + LockWhiteList = { lockWhiteAddress } + }; + input.ExternalInfo.Value["__seed_owned_symbol"] = createInput.Symbol; + input.ExternalInfo.Value["__seed_exp_time"] = TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString(); + return input; + } + } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs index 4db7135097..fbb14ced18 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs @@ -496,14 +496,17 @@ public async Task SetSymbolsToPayTxSizeFee_With_Invalid_Weight_Test() var theDefaultController = await GetDefaultParliamentAddressAsync(); var primaryTokenSymbol = await GetThePrimaryTokenAsync(); var feeToken = "FEETOKEN"; - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateSeedNftCollection(TokenContractStub,TokenContractAddress); + var input = new CreateInput { Symbol = feeToken, TokenName = "name", Issuer = TokenContractAddress, TotalSupply = 100_000, IsBurnable = true - }); + }; + await CreateSeedNftAsync(TokenContractStub,input,TokenContractAddress); + await TokenContractStub.Create.SendAsync(input); var newSymbolList = new SymbolListToPayTxSizeFee(); newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee { @@ -531,13 +534,16 @@ public async Task SetSymbolsToPayTxSizeFee_With_Repeat_Token_Test() var theDefaultController = await GetDefaultParliamentAddressAsync(); var primaryTokenSymbol = await GetThePrimaryTokenAsync(); var feeToken = "FEETOKEN"; - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateSeedNftCollection(TokenContractStub,TokenContractAddress); + var input = new CreateInput { Symbol = feeToken, TokenName = "name", Issuer = TokenContractAddress, TotalSupply = 100_000 - }); + }; + await CreateSeedNftAsync(TokenContractStub,input,TokenContractAddress); + await TokenContractStub.Create.SendAsync(input); var newSymbolList = new SymbolListToPayTxSizeFee { SymbolsToPayTxSizeFee = @@ -572,13 +578,16 @@ public async Task SetSymbolsToPayTxSizeFee_Without_PrimaryToken_Test() { var theDefaultController = await GetDefaultParliamentAddressAsync(); var feeToken = "FEETOKEN"; - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateSeedNftCollection(TokenContractStub,TokenContractAddress); + var input = new CreateInput { Symbol = feeToken, TokenName = "name", Issuer = TokenContractAddress, TotalSupply = 100_000 - }); + }; + await CreateSeedNftAsync(TokenContractStub,input,TokenContractAddress); + await TokenContractStub.Create.SendAsync(input); var newSymbolList = new SymbolListToPayTxSizeFee(); newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee { @@ -596,13 +605,16 @@ public async Task SetSymbolsToPayTxSizeFee_Without_Profitable_Token_Test() var theDefaultController = await GetDefaultParliamentAddressAsync(); var primaryTokenSymbol = await GetThePrimaryTokenAsync(); const string feeToken = "FEETOKEN"; - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateSeedNftCollection(TokenContractStub,TokenContractAddress); + var input = new CreateInput { Symbol = feeToken, TokenName = "name", Issuer = TokenContractAddress, TotalSupply = 100_000 - }); + }; + await CreateSeedNftAsync(TokenContractStub,input,TokenContractAddress); + await TokenContractStub.Create.SendAsync(input); var newSymbolList = new SymbolListToPayTxSizeFee { SymbolsToPayTxSizeFee = @@ -695,14 +707,17 @@ public async Task SetSymbolsToPayTxSizeFee_Success_Test() var theDefaultController = await GetDefaultParliamentAddressAsync(); var primaryTokenSymbol = await GetThePrimaryTokenAsync(); const string feeToken = "FEETOKEN"; - await TokenContractStub.Create.SendAsync(new CreateInput + await CreateSeedNftCollection(TokenContractStub,TokenContractAddress); + var input = new CreateInput { Symbol = feeToken, TokenName = "name", Issuer = TokenContractAddress, TotalSupply = 100_000, IsBurnable = true - }); + }; + await CreateSeedNftAsync(TokenContractStub,input,TokenContractAddress); + await TokenContractStub.Create.SendAsync(input); var newSymbolList = new SymbolListToPayTxSizeFee { SymbolsToPayTxSizeFee = From 89bc0a8023ca022054ad46bd82a59402332da06b Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 29 Jun 2023 14:16:18 +0800 Subject: [PATCH 114/139] fix: ut --- .../AEDPoSExtensionTests.cs | 6 ++ .../SideChainConsensusInformationTest.cs | 36 +++++-- .../SideChainRentFeeTestBase.cs | 23 +--- .../SideChainSideChainRentFeeTest.cs | 32 +++--- .../ReferendumContractTest.cs | 89 ++++++++++------ .../TokenConvertConnectorTest.cs | 100 +++--------------- .../TokenConverterContractTests.cs | 8 +- .../TokenConverterTestBase.cs | 82 ++++++++++++-- test/AElf.OS.TestBase/OSTestHelper.cs | 24 +++++ .../AElf.Parallel.Tests/ParallelTestHelper.cs | 27 ++--- test/AElf.Parallel.Tests/ParallelTests.cs | 2 +- 11 files changed, 226 insertions(+), 203 deletions(-) diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs index 5675dfb267..5d535f3ab1 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; +using AElf.Contracts.Parliament; using AElf.ContractTestKit; using AElf.ContractTestKit.AEDPoSExtension; using AElf.CSharp.Core.Extension; @@ -46,6 +47,11 @@ public async Task Demo_Test() // And this will produce one block with one transaction. // This transaction will call Create method of Token Contract. + await ParliamentStubs.First().Initialize.SendAsync(new InitializeInput + { + ProposerAuthorityRequired = false, + PrivilegedProposer = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.First().PublicKey) + }); var defaultOrganizationAddress = await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); await ParliamentReachAnAgreementAsync(new CreateProposalInput diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs index 793ac1ac41..504758a980 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs @@ -3,10 +3,15 @@ using System.Threading.Tasks; using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; +using AElf.Contracts.Parliament; using AElf.ContractTestKit; using AElf.ContractTestKit.AEDPoSExtension; +using AElf.CSharp.Core.Extension; +using AElf.Kernel; using AElf.Kernel.Consensus; +using AElf.Kernel.Token; using AElf.Standards.ACS10; +using AElf.Standards.ACS3; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -52,6 +57,11 @@ public async Task UpdateInformationFromCrossChainTest() } }; + await ParliamentStubs.First().Initialize.SendAsync(new InitializeInput + { + ProposerAuthorityRequired = false, + PrivilegedProposer = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.First().PublicKey) + }); await CreateAndIssueToken("ELF"); await CreateAndIssueToken("READ"); await TokenStub.Transfer.SendAsync(new TransferInput @@ -79,15 +89,25 @@ await mockedCrossChainStub.UpdateInformationFromCrossChain.SendAsync(new BytesVa private async Task CreateAndIssueToken(string symbol) { - var createTokenTransaction = TokenStub.Create.GetTransaction(new CreateInput + var defaultOrganizationAddress = + await ParliamentStubs.First().GetDefaultOrganizationAddress.CallAsync(new Empty()); + await ParliamentReachAnAgreementAsync(new CreateProposalInput { - Symbol = symbol, - Decimals = 8, - TokenName = "Test", - Issuer = Accounts[0].Address, - IsBurnable = true, - TotalSupply = 1_000_000_000_00000000 + ToAddress = ContractAddresses[TokenSmartContractAddressNameProvider.Name], + ContractMethodName = nameof(TokenStub.Create), + Params = new CreateInput + { + Symbol = symbol, + Decimals = 8, + TokenName = "Test", + Issuer = Accounts[0].Address, + IsBurnable = true, + TotalSupply = 1_000_000_000_00000000 + }.ToByteString(), + ExpiredTime = TimestampHelper.GetUtcNow().AddDays(1), + OrganizationAddress = defaultOrganizationAddress }); + const long issueTokenAmount = 10_0000_00000000; var issueToAddress = Address.FromPublicKey(MissionedECKeyPairs.InitialKeyPairs.First().PublicKey); var issueTokenTransaction = TokenStub.Issue.GetTransaction(new IssueInput @@ -98,7 +118,7 @@ private async Task CreateAndIssueToken(string symbol) }); await BlockMiningService.MineBlockAsync(new List { - createTokenTransaction, + // createTokenTransaction, issueTokenTransaction }); } diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeTestBase.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeTestBase.cs index 9d505d89d1..096c82d929 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeTestBase.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainRentFeeTestBase.cs @@ -76,7 +76,7 @@ protected void DeployContracts() TokenSmartContractAddressNameProvider.Name, DefaultSenderKeyPair)); TokenContractStub = GetTokenContractTester(DefaultSenderKeyPair); - AsyncHelper.RunSync(async () => await InitializeTokenAsync()); + // AsyncHelper.RunSync(async () => await InitializeTokenAsync()); ParliamentContractAddress = AsyncHelper.RunSync(() => DeploySystemSmartContract( @@ -141,27 +141,6 @@ internal AEDPoSContractImplContainer.AEDPoSContractImplStub GetConsensusContract return GetTester(ConsensusContractAddress, keyPair); } - private async Task InitializeTokenAsync() - { - const long totalSupply = 100_000_000; - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = NativeTokenSymbol, - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = totalSupply, - Issuer = DefaultSender - }); - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = NativeTokenSymbol, - Amount = totalSupply - 20 * 100_000L, - To = DefaultSender, - Memo = "Issue token to default user." - }); - } - private async Task InitializeParliamentContract() { var initializeResult = await ParliamentContractStub.Initialize.SendAsync(new InitializeInput diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs index e9b625eb32..7fb41a95ab 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs @@ -293,12 +293,13 @@ await TokenContractStub.GetBalance.SendAsync(new GetBalanceInput // each tx set private async Task InitialTokenContractAsync(bool issueToken = true) { - await CreateTokenAsync("CPU", ResourceSupply, issueToken); - await CreateTokenAsync("RAM", ResourceSupply, issueToken); - await CreateTokenAsync("DISK", ResourceSupply, issueToken); - await CreateTokenAsync("NET", ResourceSupply, issueToken); var defaultParliamentOrganization = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + await CreateTokenAsync("ELF", ResourceSupply, issueToken, defaultParliamentOrganization); + await CreateTokenAsync("CPU", ResourceSupply, issueToken, defaultParliamentOrganization); + await CreateTokenAsync("RAM", ResourceSupply, issueToken, defaultParliamentOrganization); + await CreateTokenAsync("DISK", ResourceSupply, issueToken, defaultParliamentOrganization); + await CreateTokenAsync("NET", ResourceSupply, issueToken, defaultParliamentOrganization); var setSideChainCreatorProposalInput = new InitializeFromParentChainInput { ResourceAmount = @@ -331,18 +332,19 @@ await UpdateSideChainRentalDefaultProposalAsync( nameof(TokenContractImplContainer.TokenContractImplStub.UpdateRental), updateRentalInput); } - private async Task CreateTokenAsync(string symbol, long supply, bool issueToken) + private async Task CreateTokenAsync(string symbol, long supply, bool issueToken, Address organizationAddress) { - await TokenContractStub.Create.SendAsync(new CreateInput - { - Decimals = 8, - Issuer = Creator, - Symbol = symbol, - TotalSupply = supply, - IsBurnable = true, - TokenName = $"{symbol} token." - }); - + await ParliamentReachAnAgreementAsync(TokenContractAddress, organizationAddress, + nameof(TokenContractStub.Create), new CreateInput + { + Decimals = 8, + Issuer = Creator, + Symbol = symbol, + TotalSupply = supply, + IsBurnable = true, + TokenName = $"{symbol} token." + }); + if (!issueToken) return; await TokenContractStub.Issue.SendAsync(new IssueInput diff --git a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs index ec34758530..7b81a08d8c 100644 --- a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs +++ b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs @@ -532,6 +532,17 @@ public async Task Check_Proposal_ToBeRelease() result = await ReferendumContractStub.GetProposal.CallAsync(proposalId); result.ToBeReleased.ShouldBeFalse(); } + } + + [Fact] + public async Task Check_Proposal_ToBeRelease_Rejection() + { + var minimalApproveThreshold = 1000; + var minimalVoteThreshold = 1000; + var maximalRejectionThreshold = 1000; + var maximalAbstentionThreshold = 1000; + var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, + maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); //Rejection probability > maximalRejectionThreshold { var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); @@ -610,7 +621,7 @@ public async Task Release_Proposal_Test() var maximalAbstentionThreshold = 10000; var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); - + await ApproveAndTransferCreateTokenFee(DefaultSenderKeyPair, minimalApproveThreshold, organizationAddress); var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); await ApproveAllowanceAsync(Accounts[3].KeyPair, minimalApproveThreshold, proposalId); @@ -635,7 +646,7 @@ public async Task Release_Proposal_AlreadyReleased_Test() var maximalAbstentionThreshold = 10000; var organizationAddress = await CreateOrganizationAsync(minimalApproveThreshold, minimalVoteThreshold, maximalAbstentionThreshold, maximalRejectionThreshold, new[] { DefaultSender }); - + await ApproveAndTransferCreateTokenFee(DefaultSenderKeyPair, minimalApproveThreshold, organizationAddress); var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); @@ -1290,11 +1301,41 @@ private CreateProposalInput GetValidCreateProposalInput(Address organizationAddr private async Task CreateProposalAsync(ECKeyPair proposalKeyPair, Address organizationAddress, Timestamp timestamp = null) + { + await PrepareCreateToken(organizationAddress); + var createInput = new CreateInput + { + Symbol = "NEW", + Decimals = 2, + TotalSupply = 10_0000, + TokenName = "new token", + Issuer = organizationAddress, + IsBurnable = true + }; + var createProposalInput = new CreateProposalInput + { + ContractMethodName = nameof(TokenContract.Create), + ToAddress = TokenContractAddress, + Params = createInput.ToByteString(), + ExpiredTime = timestamp ?? BlockTimeProvider.GetBlockTime().AddSeconds(1000), + OrganizationAddress = organizationAddress + }; + ReferendumContractStub = GetReferendumContractTester(proposalKeyPair); + var proposal = await ReferendumContractStub.CreateProposal.SendAsync(createProposalInput); + proposal.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + return proposal.Output; + } + + private async Task PrepareCreateToken(Address organizationAddress) { var defaultParliamentAddress = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - - await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, TokenContractAddress, + var seedCollectionInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput + { + Symbol = "SEED-0" + }); + await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, + TokenContractAddress, nameof(TokenContractStub.Create), new CreateInput { Symbol = "SEED-0", @@ -1305,7 +1346,9 @@ await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, Parliame Issuer = defaultParliamentAddress, ExternalInfo = new ExternalInfo() }); - await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, TokenContractAddress, + + await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, + TokenContractAddress, nameof(TokenContractStub.Create), new CreateInput { Symbol = "SEED-1", @@ -1318,14 +1361,15 @@ await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, Parliame { Value = { - {"__seed_owned_symbol", "NEW"}, - {"__seed_exp_time", TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString()} + { "__seed_owned_symbol", "NEW" }, + { "__seed_exp_time", TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString() } } }, LockWhiteList = { TokenContractAddress } }); - - await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, TokenContractAddress, + + await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, + TokenContractAddress, nameof(TokenContractStub.Issue), new IssueInput { Symbol = "SEED-1", @@ -1333,28 +1377,6 @@ await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, Parliame Memo = "ddd", To = organizationAddress }); - - var createInput = new CreateInput - { - Symbol = "NEW", - Decimals = 2, - TotalSupply = 10_0000, - TokenName = "new token", - Issuer = organizationAddress, - IsBurnable = true - }; - var createProposalInput = new CreateProposalInput - { - ContractMethodName = nameof(TokenContract.Create), - ToAddress = TokenContractAddress, - Params = createInput.ToByteString(), - ExpiredTime = timestamp ?? BlockTimeProvider.GetBlockTime().AddSeconds(1000), - OrganizationAddress = organizationAddress - }; - ReferendumContractStub = GetReferendumContractTester(proposalKeyPair); - var proposal = await ReferendumContractStub.CreateProposal.SendAsync(createProposalInput); - proposal.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - return proposal.Output; } private async Task CreateReferendumProposalAsync(ECKeyPair proposalKeyPair, IMessage input, @@ -1498,6 +1520,7 @@ private async Task ApproveWithMinersAsync(Hash proposalId) approveResult.TransactionResult.Error.ShouldBeNullOrEmpty(); } } + private async Task ApproveAndTransferCreateTokenFee(ECKeyPair proposalKeyPair, long minimalApproveThreshold, Address organizationAddress) { @@ -1541,13 +1564,13 @@ private MethodFees GetValidMethodFees() } }; } - + private async Task SubmitAndApproveProposalOfDefaultParliament(ECKeyPair senderKeyPair, Address parliamentAddress, Address contractAddress, string methodName, IMessage message) { var defaultParliamentAddress = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - + var proposal = new CreateProposalInput { OrganizationAddress = defaultParliamentAddress, diff --git a/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs b/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs index fdefbd921a..f45a95bf3f 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs @@ -15,11 +15,6 @@ namespace AElf.Contracts.TokenConverter; public partial class TokenConverterContractTests { - public TokenConverterContractTests() - { - AsyncHelper.RunSync(InitializeParliamentContractAsync); - } - [Fact] public async Task DefaultController_Test() { @@ -295,15 +290,7 @@ public async Task Set_Connector_Test() var tokenSymbol = "TRA"; //with authority user { - var createTokenRet = (await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = tokenSymbol, - TokenName = "NET name", - TotalSupply = 100_0000_0000, - Issuer = DefaultSender, - IsBurnable = true - })).TransactionResult; - createTokenRet.Status.ShouldBe(TransactionResultStatus.Mined); + await CreateTokenAsync(tokenSymbol); var pairConnector = new PairConnectorParam { ResourceConnectorSymbol = tokenSymbol, @@ -328,16 +315,7 @@ await ExecuteProposalForParliamentTransaction(TokenConverterContractAddress, public async Task Update_Connector_Success_Test() { var token = "NETT"; - var createTokenRet = (await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = token, - TokenName = "NETT name", - TotalSupply = 100_0000_0000, - Issuer = DefaultSender, - IsBurnable = true, - LockWhiteList = { TokenConverterContractAddress } - })).TransactionResult; - createTokenRet.Status.ShouldBe(TransactionResultStatus.Mined); + await CreateTokenAsync(token); var pairConnector = new PairConnectorParam { ResourceConnectorSymbol = token, @@ -526,15 +504,16 @@ private PairConnectorParam GetLegalPairConnectorParam(string tokenSymbol, long n private async Task CreateTokenAsync(string symbol, long totalSupply = 100_0000_0000) { - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = symbol, - TokenName = symbol + " name", - TotalSupply = totalSupply, - Issuer = DefaultSender, - IsBurnable = true, - LockWhiteList = { TokenConverterContractAddress } - }); + await ExecuteProposalForParliamentTransaction(TokenContractAddress, nameof(TokenContractStub.Create), + new CreateInput + { + Symbol = symbol, + TokenName = symbol + " name", + TotalSupply = totalSupply, + Issuer = DefaultSender, + IsBurnable = true, + LockWhiteList = { TokenContractAddress, TokenConverterContractAddress } + }); } private async Task AddPairConnectorAsync(string tokenSymbol) @@ -545,59 +524,4 @@ await ExecuteProposalForParliamentTransaction( nameof(TokenConverterContractImplContainer.TokenConverterContractImplStub.AddPairConnector), pairConnector); } - - private async Task ApproveByParliamentMembers(Hash proposalId) - { - foreach (var bp in InitialCoreDataCenterKeyPairs) - { - var tester = GetParliamentContractTester(bp); - await tester.Approve.SendAsync(proposalId); - } - } - - private async Task CreateAndApproveProposalForParliament(Address contract, - string method, IMessage input, Address parliamentOrganization = null) - { - if (parliamentOrganization == null) - parliamentOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = new CreateProposalInput - { - OrganizationAddress = parliamentOrganization, - ContractMethodName = method, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), - Params = input.ToByteString(), - ToAddress = contract - }; - var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - var proposalHash = createResult.Output; - await ApproveByParliamentMembers(proposalHash); - return proposalHash; - } - - private async Task ExecuteProposalForParliamentTransactionWithException( - Address contract, - string method, IMessage input, Address parliamentOrganization = null) - { - if (parliamentOrganization == null) - parliamentOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalHash = - await CreateAndApproveProposalForParliament(contract, method, input, - parliamentOrganization); - var releaseResult = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalHash); - return releaseResult.TransactionResult; - } - - private async Task ExecuteProposalForParliamentTransaction(Address contract, - string method, IMessage input, Address parliamentOrganization = null) - { - if (parliamentOrganization == null) - parliamentOrganization = - await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalHash = - await CreateAndApproveProposalForParliament(contract, method, input, - parliamentOrganization); - await ParliamentContractStub.Release.SendAsync(proposalHash); - } } \ No newline at end of file diff --git a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs index 8d8bd44935..d9e0cec8b9 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs @@ -363,7 +363,7 @@ private InitializeInput GetLegalInitializeInput() private async Task CreateRamToken() { - var createResult = (await TokenContractStub.Create.SendAsync( + await ExecuteProposalForParliamentTransaction(TokenContractAddress, nameof(TokenContractStub.Create), new CreateInput { Symbol = WriteConnector.Symbol, @@ -371,9 +371,9 @@ private async Task CreateRamToken() IsBurnable = true, Issuer = DefaultSender, TokenName = "Write Resource", - TotalSupply = 100_0000L - })).TransactionResult; - createResult.Status.ShouldBe(TransactionResultStatus.Mined); + TotalSupply = 100_0000L, + LockWhiteList = { TokenContractAddress, TokenConverterContractAddress } + }); var issueResult = (await TokenContractStub.Issue.SendAsync( new IssueInput diff --git a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs index e453e1b0fd..9a10c8f384 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs @@ -7,11 +7,15 @@ using AElf.Contracts.Treasury; using AElf.ContractTestKit.AEDPoSExtension; using AElf.Cryptography.ECDSA; +using AElf.CSharp.Core.Extension; using AElf.EconomicSystem; +using AElf.Kernel; using AElf.Kernel.Consensus; using AElf.Kernel.Proposal; using AElf.Kernel.Token; +using AElf.Standards.ACS3; using AElf.Types; +using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Volo.Abp.Threading; @@ -30,7 +34,7 @@ public TokenConverterTestBase() ParliamentSmartContractAddressNameProvider.Name, ConsensusSmartContractAddressNameProvider.Name })); - + AsyncHelper.RunSync(InitializeParliamentContractAsync); AsyncHelper.RunSync(InitializeTokenAsync); } @@ -47,16 +51,17 @@ protected async Task GetBalanceAsync(string symbol, Address owner) private async Task InitializeTokenAsync() { - await TokenContractStub.Create.SendAsync(new CreateInput - { - Symbol = "ELF", - Decimals = 2, - IsBurnable = true, - TokenName = "elf token", - TotalSupply = 1000_0000_0000L, - Issuer = DefaultSender, - LockWhiteList = { TokenConverterContractAddress } - }); + await ExecuteProposalForParliamentTransaction(TokenContractAddress, nameof(TokenContractStub.Create), + new CreateInput + { + Symbol = "ELF", + Decimals = 2, + IsBurnable = true, + TokenName = "elf token", + TotalSupply = 1000_0000_0000L, + Issuer = DefaultSender, + LockWhiteList = { TokenContractAddress, TokenConverterContractAddress } + }); await TokenContractStub.Issue.SendAsync(new IssueInput { Symbol = "ELF", @@ -94,6 +99,61 @@ private void CheckResult(TransactionResult result) if (!string.IsNullOrEmpty(result.Error)) throw new Exception(result.Error); } + protected async Task ExecuteProposalForParliamentTransaction(Address contract, + string method, IMessage input, Address parliamentOrganization = null) + { + if (parliamentOrganization == null) + parliamentOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalHash = + await CreateAndApproveProposalForParliament(contract, method, input, + parliamentOrganization); + await ParliamentContractStub.Release.SendAsync(proposalHash); + } + + private async Task CreateAndApproveProposalForParliament(Address contract, + string method, IMessage input, Address parliamentOrganization = null) + { + if (parliamentOrganization == null) + parliamentOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposal = new CreateProposalInput + { + OrganizationAddress = parliamentOrganization, + ContractMethodName = method, + ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1), + Params = input.ToByteString(), + ToAddress = contract + }; + var createResult = await ParliamentContractStub.CreateProposal.SendAsync(proposal); + var proposalHash = createResult.Output; + await ApproveByParliamentMembers(proposalHash); + return proposalHash; + } + + protected async Task ExecuteProposalForParliamentTransactionWithException( + Address contract, + string method, IMessage input, Address parliamentOrganization = null) + { + if (parliamentOrganization == null) + parliamentOrganization = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalHash = + await CreateAndApproveProposalForParliament(contract, method, input, + parliamentOrganization); + var releaseResult = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalHash); + return releaseResult.TransactionResult; + } + + private async Task ApproveByParliamentMembers(Hash proposalId) + { + foreach (var bp in InitialCoreDataCenterKeyPairs) + { + var tester = GetParliamentContractTester(bp); + await tester.Approve.SendAsync(proposalId); + } + } + #region Contract Address protected Address TokenContractAddress => diff --git a/test/AElf.OS.TestBase/OSTestHelper.cs b/test/AElf.OS.TestBase/OSTestHelper.cs index a2f430808f..c8675db0d1 100644 --- a/test/AElf.OS.TestBase/OSTestHelper.cs +++ b/test/AElf.OS.TestBase/OSTestHelper.cs @@ -435,6 +435,20 @@ private async Task StartNodeAsync() IsBurnable = true }.ToByteString() }); + + tokenContractDto + .AddGenesisTransactionMethodCall(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Create), Params = new CreateInput + { + Symbol = "TELF", + TokenName = "ELF_Token", + TotalSupply = TokenTotalSupply, + Decimals = 2, + Issuer = ownAddress, + IsBurnable = true + }.ToByteString() + }); tokenContractDto.AddGenesisTransactionMethodCall(new ContractInitializationMethodCall { @@ -452,6 +466,16 @@ private async Task StartNodeAsync() Memo = "Issue" }.ToByteString() }); + tokenContractDto.AddGenesisTransactionMethodCall(new ContractInitializationMethodCall + { + MethodName = nameof(TokenContractContainer.TokenContractStub.Issue), Params = new IssueInput + { + Symbol = "TELF", + Amount = TokenTotalSupply, + To = ownAddress, + Memo = "Issue" + }.ToByteString() + }); tokenContractDto.AddGenesisTransactionMethodCall(new ContractInitializationMethodCall { diff --git a/test/AElf.Parallel.Tests/ParallelTestHelper.cs b/test/AElf.Parallel.Tests/ParallelTestHelper.cs index e2b523791f..94934e37d8 100644 --- a/test/AElf.Parallel.Tests/ParallelTestHelper.cs +++ b/test/AElf.Parallel.Tests/ParallelTestHelper.cs @@ -173,37 +173,22 @@ await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainC return GetBalanceOutput.Parser.ParseFrom(returnValue).Balance; } - public async Task CreateAndIssueTokenAsync(string symbol, Address issueAddress) + public async Task TransferTokenAsync(string symbol, Address issueAddress) { var ownAddress = await _accountService.GetAccountAsync(); var tokenContractAddress = await _smartContractAddressService.GetAddressByContractNameAsync(await GetChainContextAsync(), TokenSmartContractAddressNameProvider.StringName); - var createTokenTransaction = GenerateTransaction(ownAddress, tokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.Create), - new CreateInput - { - Symbol = symbol, - TokenName = $"{symbol}_Token", - TotalSupply = TokenTotalSupply, - Decimals = 2, - Issuer = ownAddress, - IsBurnable = true - }); - var signature = await _accountService.SignAsync(createTokenTransaction.GetHash().ToByteArray()); - createTokenTransaction.Signature = ByteString.CopyFrom(signature); - await BroadcastTransactions(new List { createTokenTransaction }); - await MinedOneBlock(); - + var issueTokenTransaction = GenerateTransaction(ownAddress, tokenContractAddress, - nameof(TokenContractContainer.TokenContractStub.Issue), new IssueInput + nameof(TokenContractContainer.TokenContractStub.Transfer), new TransferInput { Symbol = symbol, - Amount = TokenTotalSupply, + Amount = 100_000000, To = issueAddress, - Memo = "Issue" + Memo = "Transfer" }); - signature = await _accountService.SignAsync(issueTokenTransaction.GetHash().ToByteArray()); + var signature = await _accountService.SignAsync(issueTokenTransaction.GetHash().ToByteArray()); issueTokenTransaction.Signature = ByteString.CopyFrom(signature); await BroadcastTransactions(new List { issueTokenTransaction }); await MinedOneBlock(); diff --git a/test/AElf.Parallel.Tests/ParallelTests.cs b/test/AElf.Parallel.Tests/ParallelTests.cs index b0dbbd5e5a..19b8452e24 100644 --- a/test/AElf.Parallel.Tests/ParallelTests.cs +++ b/test/AElf.Parallel.Tests/ParallelTests.cs @@ -224,7 +224,7 @@ public async Task TransferTwoSymbolParallelTest() var symbol = "TELF"; var keyPair = CryptoHelper.GenerateKeyPair(); var address = Address.FromPublicKey(keyPair.PublicKey); - await _parallelTestHelper.CreateAndIssueTokenAsync(symbol, address); + await _parallelTestHelper.TransferTokenAsync(symbol, address); var transactionList = new List(); var accountAddress = await _accountService.GetAccountAsync(); From 6b4b18409179ee59de1c2a5fb190f7575a406c49 Mon Sep 17 00:00:00 2001 From: YueZh127 Date: Thu, 29 Jun 2023 14:30:16 +0800 Subject: [PATCH 115/139] Add vrf benchmark test --- bench/AElf.Benchmark/VRFTests.cs | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 bench/AElf.Benchmark/VRFTests.cs diff --git a/bench/AElf.Benchmark/VRFTests.cs b/bench/AElf.Benchmark/VRFTests.cs new file mode 100644 index 0000000000..9dae76aafd --- /dev/null +++ b/bench/AElf.Benchmark/VRFTests.cs @@ -0,0 +1,45 @@ +using System; +using AElf.Cryptography; +using AElf.Cryptography.ECDSA; +using BenchmarkDotNet.Attributes; + +namespace AElf.Benchmark; + +[MarkdownExporterAttribute.GitHub] +public class VrfTests : BenchmarkTestBase +{ + private ECKeyPair _key; + private byte[] _alphaBytes; + private byte[] _piBytes; + + [Params(1,10,100,1000)] public int VectorCount; + + [GlobalSetup] + public void GlobalSetup() + { + _key = CryptoHelper.FromPrivateKey( + ByteArrayHelper.HexStringToByteArray("2eaeb403475a9962ad59302ab53fa2b668d2d24bf5a2a917707e5b2f4ded392b")); + var alpha = "fb779e58991c424eaaf10b3d364c3b3e756c7b435109a985e547c058964d7bd5"; + _alphaBytes = Convert.FromHexString(alpha); + var pi = "03ea6c4bdb4a9e1ae0a17c427ec074f68cdac7a57e4f3fded1b07d20dd5385baf05a9d1e4064cd1c2c5e8608e96b7e3e2058500f178b414b8e910178f17a7a77af7e88befeabceb77cae3e9fd2e1a6c051"; + _piBytes = Convert.FromHexString(pi); + } + + [Benchmark] + public void VrfProveTest() + { + for (var i = 0; i < VectorCount; i++) + { + CryptoHelper.ECVrfProve(_key, _alphaBytes); + } + } + + [Benchmark] + public void VrfVerifyTest() + { + for (var i = 0; i < VectorCount; i++) + { + CryptoHelper.ECVrfVerify(_key.PublicKey, _alphaBytes, _piBytes); + } + } +} \ No newline at end of file From 375fb3313fb98b24fed2d6e02d80dc08e4398f28 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Thu, 29 Jun 2023 15:57:04 +0800 Subject: [PATCH 116/139] refactor: code method rename --- .../TokenContractConstants.cs | 2 +- .../TokenContract_Actions.cs | 28 +++++++------- .../TokenContract_Helper.cs | 37 ++++++++----------- .../TokenContract_NFT_Actions.cs | 18 +++++---- .../BVT/NftApplicationTests.cs | 26 ++++++------- .../BVT/TokenApplicationTests.cs | 10 ++--- .../BVT/TokenManagementTests.cs | 22 +++++------ .../MultiTokenContractCrossChainTest.cs | 1 - 8 files changed, 70 insertions(+), 74 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs index 68490327ea..a4641e2188 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs @@ -18,7 +18,7 @@ public static class TokenContractConstants public const char NFTSymbolSeparator = '-'; public const int NFTSymbolMaxLength = 30; public const string UserContractMethodFeeKey = "UserContractMethodFee"; - public const string CollectionId = "0"; + public const string CollectionSymbolSuffix = "0"; public const string SeedCollectionSymbol = "SEED-0"; public const string SeedOwnedSymbolExternalInfoKey= "__seed_owned_symbol"; public const string SeedExpireTimeExternalInfoKey = "__seed_exp_time"; diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 1f116eb74e..49b9ee6c33 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -45,17 +45,18 @@ public override Empty Create(CreateInput input) private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType.Token) { - AssertValidCreateInput(input,symbolType); + AssertValidCreateInput(input, symbolType); if (symbolType == SymbolType.Token || symbolType == SymbolType.NftCollection) { - if (!IsAddressInCreateWhiteList(Context.Sender) && input.Symbol != TokenContractConstants.SeedCollectionSymbol) + if (!IsAddressInCreateWhiteList(Context.Sender) && + input.Symbol != TokenContractConstants.SeedCollectionSymbol) { var symbolSeed = State.SymbolSeedMap[input.Symbol]; - CheckSeedNft(symbolSeed, input.Symbol); + CheckSeedNFT(symbolSeed, input.Symbol); // seed nft for one-time use only long balance = State.Balances[Context.Sender][symbolSeed]; DoTransferFrom(Context.Sender, Context.Self, Context.Self, symbolSeed, balance, ""); - Burn(Context.Self,symbolSeed,balance); + Burn(Context.Self, symbolSeed, balance); } } @@ -99,19 +100,20 @@ private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType. return new Empty(); } - private void CheckSeedNft(string symbolSeed, String symbol) + private void CheckSeedNFT(string symbolSeed, String symbol) { - Assert(!string.IsNullOrEmpty(symbolSeed), "Seed NFT is not exist"); + Assert(!string.IsNullOrEmpty(symbolSeed), "seed NFT is not exist"); var tokenInfo = State.TokenInfos[symbolSeed]; - Assert(tokenInfo != null, "Seed NFT is not exist"); + Assert(tokenInfo != null, "seed NFT is not exist"); Assert(State.Balances[Context.Sender][symbolSeed] > 0, "owner doesn't own enough balance"); - Assert(tokenInfo.ExternalInfo != null,"seed_owned_symbol is empty ") ; - Assert( tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, - out var ownedSymbol) && !string.IsNullOrEmpty(ownedSymbol), "seed_owned_symbol is empty "); - Assert(ownedSymbol == symbol, "seed_owned_symbol and input_symbol is inconsistent "); + Assert(tokenInfo.ExternalInfo != null, "seed_owned_symbol is not exists"); + Assert(tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, + out var ownedSymbol), "seed_owned_symbol is not exists"); + Assert(ownedSymbol == symbol, "seed_owned_symbol and input_symbol is inconsistent"); Assert(tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, out var expirationTime) - && !string.IsNullOrEmpty(expirationTime) && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime), "seed_owned_symbol is expired "); + && long.TryParse(expirationTime, out var expirationTimeLong) && + Context.CurrentBlockTime.Seconds <= expirationTimeLong, "seed_owned_symbol is expired"); } @@ -267,7 +269,7 @@ public override Empty Burn(BurnInput input) return Burn(Context.Sender, input.Symbol, input.Amount); } - private Empty Burn(Address address,string symbol, long amount) + private Empty Burn(Address address, string symbol, long amount) { var tokenInfo = AssertValidToken(symbol, amount); Assert(tokenInfo.IsBurnable, "The token is not burnable."); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index dd74bc3d11..6f04a14520 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -143,9 +143,7 @@ private void AssertCrossChainTransaction(Transaction originalTransaction, Addres private void RegisterTokenInfo(TokenInfo tokenInfo) { - var empty = new TokenInfo(); - var existing = State.TokenInfos[tokenInfo.Symbol]; - Assert(existing == null || existing.Equals(empty), "Token already exists."); + CheckTokenExists(tokenInfo.Symbol); Assert(!string.IsNullOrEmpty(tokenInfo.Symbol) && tokenInfo.Symbol.All(IsValidSymbolChar), "Invalid symbol."); Assert(!string.IsNullOrEmpty(tokenInfo.TokenName), "Token name can neither be null nor empty."); @@ -197,32 +195,29 @@ private void AssertValidCreateInput(CreateInput input, SymbolType symbolType) && input.Decimals >= 0 && input.Decimals <= TokenContractConstants.MaxDecimals, "Invalid input."); - SymbolLengthCheck(input.Symbol, symbolType); - SymbolPrefixDuplicatedCheck(input.Symbol, symbolType); - OriginalSeedSymbolCheck(input.Symbol); + CheckSymbolLength(input.Symbol, symbolType); + if (symbolType == SymbolType.Nft) return; + CheckTokenAndCollectionExists(input.Symbol); + if(IsAddressInCreateWhiteList(Context.Sender))CheckSymbolSeed(input.Symbol); + } + + private void CheckTokenAndCollectionExists(string symbol) + { + var symbols = symbol.Split(TokenContractConstants.NFTSymbolSeparator); + var tokenSymbol = symbols.First(); + CheckTokenExists(tokenSymbol); + var collectionSymbol = symbols.First() + TokenContractConstants.NFTSymbolSeparator + TokenContractConstants.CollectionSymbolSuffix; + CheckTokenExists(collectionSymbol); } - private void SymbolPrefixDuplicatedCheck(string symbol,SymbolType symbolType) + private void CheckTokenExists(string symbol) { var empty = new TokenInfo(); var existing = State.TokenInfos[symbol]; Assert(existing == null || existing.Equals(empty), "Token already exists."); - var symbols = symbol.Split(TokenContractConstants.NFTSymbolSeparator); - if (symbolType == SymbolType.Token) - { - var duplicatedNftCollection = - State.TokenInfos[symbols.First() + TokenContractConstants.NFTSymbolSeparator + TokenContractConstants.CollectionId]; - Assert(duplicatedNftCollection == null || duplicatedNftCollection.Equals(empty), - "Token name prefix can not be duplicated"); - } - if (symbolType == SymbolType.NftCollection) - { - var duplicatedToken = State.TokenInfos[symbols.First()]; - Assert(duplicatedToken == null || duplicatedToken.Equals(empty), "Token name prefix can not be duplicated"); - } } - private void SymbolLengthCheck(string symbol, SymbolType symbolType) + private void CheckSymbolLength(string symbol, SymbolType symbolType) { if (symbolType == SymbolType.Token) Assert(symbol.Length <= TokenContractConstants.SymbolMaxLength, "Invalid token symbol length"); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 9b75d9d975..8dd7408666 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -26,27 +26,29 @@ private Empty CreateNFTInfo(CreateInput input) { Assert( input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, - out var ownedSymbol) && !string.IsNullOrEmpty(ownedSymbol), "seed_owned_symbol is empty"); + out var ownedSymbol) , "seed_owned_symbol is not exists"); Assert(input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, out var expirationTime) - && !string.IsNullOrEmpty(expirationTime) && Context.CurrentBlockTime.Seconds <= long.Parse(expirationTime), "seed_owned_symbol is expired "); + && long.TryParse(expirationTime, out var expirationTimeLong ) && Context.CurrentBlockTime.Seconds <= expirationTimeLong, "seed_owned_symbol is expired "); var ownedSymbolType = GetCreateInputSymbolType(ownedSymbol); - SymbolLengthCheck(ownedSymbol, ownedSymbolType); - SymbolPrefixDuplicatedCheck(ownedSymbol, ownedSymbolType); - OriginalSeedSymbolCheck(ownedSymbol); + Assert(ownedSymbolType != SymbolType.Nft,"seed_owned_symbol can not be NFT"); + CheckSymbolLength(ownedSymbol, ownedSymbolType); + CheckTokenAndCollectionExists(ownedSymbol); + CheckSymbolSeed(ownedSymbol); State.SymbolSeedMap[ownedSymbol] = input.Symbol; } return CreateToken(input, SymbolType.Nft); } - private void OriginalSeedSymbolCheck(string ownedSymbol) + private void CheckSymbolSeed(string ownedSymbol) { var oldSymbolSeed = State.SymbolSeedMap[ownedSymbol]; + Assert(oldSymbolSeed == null || !State.TokenInfos[oldSymbolSeed].ExternalInfo.Value .TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, - out var oldSymbolSeedExpireTime) || string.IsNullOrEmpty(oldSymbolSeedExpireTime) - || Context.CurrentBlockTime.Seconds > long.Parse(oldSymbolSeedExpireTime), + out var oldSymbolSeedExpireTime) || !long.TryParse(oldSymbolSeedExpireTime,out var symbolSeedExpireTime) + || Context.CurrentBlockTime.Seconds > symbolSeedExpireTime, "seed_owned_symbol has been created"); } diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs index ac9924bc95..59fc06cae5 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs @@ -357,7 +357,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() result.TransactionResult.Error.ShouldContain("NFT issuer must be collection's issuer"); } { - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput + var result = await TokenContractStub.Create.SendWithExceptionAsync( new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -376,7 +376,7 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() public async Task MultiTokenContract_Create_NFT_Collection_NotExist() { var input = Nft721Info; - var result = await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput + var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -395,7 +395,7 @@ public async Task MultiTokenContract_Create_NFT_Already_Exist() { await CreateNftCollectionAndNft(false); var input = Nft721Info; - var result = await CreateSeedNftWithExceptionAsync(TokenContractStub, new CreateInput + var result = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput { Symbol = $"{NftCollection721Info.Symbol}{input.Symbol}", TokenName = input.TokenName, @@ -741,7 +741,7 @@ public async Task CreateTokenTest() Symbol = "XYZ-0" }); failCollection.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - failCollection.TransactionResult.Error.ShouldContain("Token name prefix can not be duplicated"); + failCollection.TransactionResult.Error.ShouldContain("Token already exists."); var successCollection = await CreateMutiTokenAsync(TokenContractStub, new CreateInput { @@ -764,7 +764,7 @@ public async Task CreateTokenTest() Symbol = "GHJ" }); fTokenAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - fTokenAsync.TransactionResult.Error.ShouldContain("Token name prefix can not be duplicated"); + fTokenAsync.TransactionResult.Error.ShouldContain("Token already exists."); var createInput = BuildSeedCreateInput(new CreateInput() @@ -773,7 +773,7 @@ public async Task CreateTokenTest() }); createInput.ExternalInfo.Value["__seed_owned_symbol"] = ""; var ownError = await TokenContractStub.Create.SendWithExceptionAsync(createInput); - ownError.TransactionResult.Error.ShouldContain("seed_owned_symbol is empty"); + ownError.TransactionResult.Error.ShouldContain("Invalid Symbol input"); var createInputExpire = BuildSeedCreateInput(new CreateInput() { Symbol = "GHT" @@ -801,7 +801,7 @@ public async Task FeedNftCreateTest() var createInput = await CreateSeedNftAsync(TokenContractStub, new CreateInput { Issuer = DefaultAddress, - Symbol = "XYZ" + Symbol = "XYZ-0" }); createInput.ExternalInfo.Value["__seed_exp_time"] = "1234"; @@ -814,7 +814,7 @@ await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() var input = BuildSeedCreateInput(new CreateInput { Issuer = DefaultAddress, - Symbol = "XYZ" + Symbol = "XYZ-0" }); var seedRes = await TokenContractStub.Create.SendAsync(input); seedRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); @@ -831,7 +831,7 @@ await TokenContractStub.Issue.SendAsync(new IssueInput Memo = "ddd", To = DefaultAddress }); - input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; + input.ExternalInfo.Value["__seed_owned_symbol"] = "XY-0"; await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() { @@ -843,7 +843,7 @@ await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() inconsistentExceptionAsync.TransactionResult.Error.ShouldContain( "seed_owned_symbol and input_symbol is inconsistent"); - input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ"; + input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; input.ExternalInfo.Value["__seed_exp_time"] = ""; await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() { @@ -855,7 +855,7 @@ await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() expireExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); expireExceptionAsync.TransactionResult.Error.ShouldContain("seed_owned_symbol is expired"); - input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ"; + input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; input.ExternalInfo.Value["__seed_exp_time"] = "1234"; await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() { @@ -873,7 +873,7 @@ await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() }); var emptyExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); emptyExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - emptyExceptionAsync.TransactionResult.Error.ShouldContain("seed_owned_symbol is empty"); + emptyExceptionAsync.TransactionResult.Error.ShouldContain("seed_owned_symbol is not exists"); } private CreateInput GetCreateInput() @@ -885,7 +885,7 @@ private CreateInput GetCreateInput() Decimals = 0, Issuer = DefaultAddress, IssueChainId = _chainId, - Symbol = "XYZ" + Symbol = "XYZ-0" }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index 8889d9e5ce..724b2b45c1 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -813,7 +813,7 @@ public async Task MultiTokenContract_Burn_Invalid_Token_Test() { await CreateAndIssueMultiTokensAsync(); var unburnedTokenSymbol = "UNBURNED"; - await CreateMutiTokenAsync(TokenContractStub,new CreateInput + await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = unburnedTokenSymbol, TokenName = "Name", @@ -946,7 +946,7 @@ await BasicFunctionContractStub.TransferTokenToContract.SendAsync( public async Task ChangeTokenIssuer_Test() { const string tokenSymbol = "PO"; - await CreateMutiTokenAsync(TokenContractStub,new CreateInput + await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = tokenSymbol, TokenName = "Name", @@ -985,7 +985,7 @@ await tokenIssuerStub.ChangeTokenIssuer.SendAsync(new ChangeTokenIssuerInput public async Task ChangeTokenIssuer_Without_Authorization_Test() { const string tokenSymbol = "PO"; - await CreateMutiTokenAsync(TokenContractStub,new CreateInput + await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = tokenSymbol, TokenName = "Name", @@ -1187,7 +1187,7 @@ await TokenContractStub.Issue.SendAsync(new IssueInput [Fact] public async Task ValidateTokenInfoExists_ExternalInfo_Test() { - await CreateMutiTokenAsync(TokenContractStub,new CreateInput + await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = AliceCoinTokenInfo.Symbol, TokenName = AliceCoinTokenInfo.TokenName, @@ -1236,7 +1236,6 @@ await CreateMutiTokenAsync(TokenContractStub,new CreateInput [Fact] public async Task CrossContractCreateToken_Test() { - var fee = await TokenContractStub.GetMethodFee.CallAsync(new StringValue { Value = "Create" }); var createTokenInput = new CreateTokenThroughMultiTokenInput { @@ -1268,7 +1267,6 @@ await TokenContractStub.Issue.SendAsync(new IssueInput Amount = 1, Memo = "ddd", To = BasicFunctionContractAddress - }); var result = await BasicFunctionContractStub.CreateTokenThroughMultiToken.SendAsync(createTokenInput); diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs index 49a7b58134..4cb13a561c 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs @@ -111,7 +111,7 @@ public MultiTokenContractTests() private async Task CreateNativeTokenAsync() { - await CreateMutiTokenAsync(TokenContractStub,new CreateInput + await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = NativeTokenInfo.Symbol, TokenName = NativeTokenInfo.TokenName, @@ -130,8 +130,7 @@ await CreateMutiTokenAsync(TokenContractStub,new CreateInput private async Task CreatePrimaryTokenAsync() { - - await CreateMutiTokenAsync(TokenContractStub,new CreateInput + await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Decimals = PrimaryTokenInfo.Decimals, IsBurnable = PrimaryTokenInfo.IsBurnable, @@ -160,7 +159,7 @@ private async Task CreateNormalTokenAsync() tokenInfo.ShouldBe(new TokenInfo()); } - await CreateMutiTokenAsync(TokenContractStub,new CreateInput + await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = AliceCoinTokenInfo.Symbol, TokenName = AliceCoinTokenInfo.TokenName, @@ -227,7 +226,7 @@ public async Task MultiTokenContract_Create_NotSame_Test() { await CreateAndIssueMultiTokensAsync(); - await CreateMutiTokenAsync(TokenContractStub,new CreateInput + await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = BobCoinTokenInfo.Symbol, TokenName = BobCoinTokenInfo.TokenName, @@ -250,7 +249,7 @@ await CreateMutiTokenAsync(TokenContractStub,new CreateInput [Fact(DisplayName = "[MultiToken] Create Token use custom address")] public async Task MultiTokenContract_Create_UseCustomAddress_Test() { - var transactionResult = (await CreateMutiTokenWithExceptionAsync(TokenContractStub,new CreateInput + var transactionResult = (await CreateMutiTokenWithExceptionAsync(TokenContractStub, new CreateInput { Symbol = BobCoinTokenInfo.Symbol, Decimals = 2, @@ -390,7 +389,7 @@ public async Task IssueToken_With_Invalid_Input() //invalid chain id { var chainTokenSymbol = "CHAIN"; - await CreateMutiTokenAsync(TokenContractStub ,new CreateInput + await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = chainTokenSymbol, TokenName = "chain token", @@ -414,7 +413,7 @@ await CreateMutiTokenAsync(TokenContractStub ,new CreateInput public async Task IssueToken_Test() { var newTokenSymbol = "AIN"; - await CreateMutiTokenAsync(TokenContractStub,new CreateInput + await CreateMutiTokenAsync(TokenContractStub, new CreateInput { Symbol = newTokenSymbol, TokenName = "ain token", @@ -486,14 +485,15 @@ public async Task TokenCreate_Test() var createTokenInfoWithInvalidTokenName = new CreateInput(); createTokenInfoWithInvalidTokenName.MergeFrom(createTokenInfo); createTokenInfoWithInvalidTokenName.Symbol = "ITISAVERYLONGSYMBOLNAME"; - var createTokenRet = await CreateSeedNftWithExceptionAsync(TokenContractStub,createTokenInfoWithInvalidTokenName); + var createTokenRet = + await CreateSeedNftWithExceptionAsync(TokenContractStub, createTokenInfoWithInvalidTokenName); createTokenRet.TransactionResult.Error.ShouldContain("Invalid token symbol length"); var createTokenInfoWithInvalidDecimal = new CreateInput(); createTokenInfoWithInvalidDecimal.MergeFrom(createTokenInfo); createTokenInfoWithInvalidDecimal.Decimals = 100; - createTokenRet = await CreateMutiTokenWithExceptionAsync(TokenContractStub,createTokenInfoWithInvalidDecimal); + createTokenRet = await CreateMutiTokenWithExceptionAsync(TokenContractStub, createTokenInfoWithInvalidDecimal); createTokenRet.TransactionResult.Error.ShouldContain("Invalid input"); - await TokenContractStub.Create.SendAsync(createTokenInfo); + await TokenContractStub.Create.SendAsync(createTokenInfo); var tokenInfo = await TokenContractStub.GetTokenInfo.CallAsync(new GetTokenInfoInput { Symbol = AliceCoinTokenInfo.Symbol diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs index 56dd025f9c..10d1faa0a2 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs @@ -333,7 +333,6 @@ public async Task SideChain_CrossChainCreateToken_WithAlreadyCreated_Test() var blockExecutedSet = await MineAsync(new List { createTransaction }); var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); - var sideCreateTransaction =await CreateTransactionForTokenCreation(SideChainTokenContractStub, SideChainTestKit.DefaultAccount.Address, SymbolForTesting,SideTokenContractAddress); blockExecutedSet = await SideChainTestKit.MineAsync(new List { sideCreateTransaction }); From 9703326b558fe342e52ee43bdab72b1e4f7b9d98 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Thu, 29 Jun 2023 16:25:50 +0800 Subject: [PATCH 117/139] format: code format --- .../TokenContractConstants.cs | 2 +- .../TokenContract_Helper.cs | 10 ++++++---- .../TokenContract_NFT_Actions.cs | 16 +++++++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs index a4641e2188..6bc260520e 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs @@ -20,6 +20,6 @@ public static class TokenContractConstants public const string UserContractMethodFeeKey = "UserContractMethodFee"; public const string CollectionSymbolSuffix = "0"; public const string SeedCollectionSymbol = "SEED-0"; - public const string SeedOwnedSymbolExternalInfoKey= "__seed_owned_symbol"; + public const string SeedOwnedSymbolExternalInfoKey = "__seed_owned_symbol"; public const string SeedExpireTimeExternalInfoKey = "__seed_exp_time"; } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 6f04a14520..602b61123c 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -15,7 +15,8 @@ public partial class TokenContract { private static bool IsValidSymbolChar(char character) { - return (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9') || character == TokenContractConstants.NFTSymbolSeparator; + return (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9') || + character == TokenContractConstants.NFTSymbolSeparator; } private bool IsValidItemIdChar(char character) @@ -194,11 +195,11 @@ private void AssertValidCreateInput(CreateInput input, SymbolType symbolType) && input.Symbol.Length > 0 && input.Decimals >= 0 && input.Decimals <= TokenContractConstants.MaxDecimals, "Invalid input."); - + CheckSymbolLength(input.Symbol, symbolType); if (symbolType == SymbolType.Nft) return; CheckTokenAndCollectionExists(input.Symbol); - if(IsAddressInCreateWhiteList(Context.Sender))CheckSymbolSeed(input.Symbol); + if (IsAddressInCreateWhiteList(Context.Sender)) CheckSymbolSeed(input.Symbol); } private void CheckTokenAndCollectionExists(string symbol) @@ -206,7 +207,8 @@ private void CheckTokenAndCollectionExists(string symbol) var symbols = symbol.Split(TokenContractConstants.NFTSymbolSeparator); var tokenSymbol = symbols.First(); CheckTokenExists(tokenSymbol); - var collectionSymbol = symbols.First() + TokenContractConstants.NFTSymbolSeparator + TokenContractConstants.CollectionSymbolSuffix; + var collectionSymbol = symbols.First() + TokenContractConstants.NFTSymbolSeparator + + TokenContractConstants.CollectionSymbolSuffix; CheckTokenExists(collectionSymbol); } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 8dd7408666..743e29a09d 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -26,12 +26,13 @@ private Empty CreateNFTInfo(CreateInput input) { Assert( input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, - out var ownedSymbol) , "seed_owned_symbol is not exists"); + out var ownedSymbol), "seed_owned_symbol is not exists"); Assert(input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, out var expirationTime) - && long.TryParse(expirationTime, out var expirationTimeLong ) && Context.CurrentBlockTime.Seconds <= expirationTimeLong, "seed_owned_symbol is expired "); + && long.TryParse(expirationTime, out var expirationTimeLong) && + Context.CurrentBlockTime.Seconds <= expirationTimeLong, "seed_owned_symbol is expired "); var ownedSymbolType = GetCreateInputSymbolType(ownedSymbol); - Assert(ownedSymbolType != SymbolType.Nft,"seed_owned_symbol can not be NFT"); + Assert(ownedSymbolType != SymbolType.Nft, "seed_owned_symbol can not be NFT"); CheckSymbolLength(ownedSymbol, ownedSymbolType); CheckTokenAndCollectionExists(ownedSymbol); CheckSymbolSeed(ownedSymbol); @@ -44,11 +45,12 @@ private Empty CreateNFTInfo(CreateInput input) private void CheckSymbolSeed(string ownedSymbol) { var oldSymbolSeed = State.SymbolSeedMap[ownedSymbol]; - + Assert(oldSymbolSeed == null || !State.TokenInfos[oldSymbolSeed].ExternalInfo.Value - .TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, - out var oldSymbolSeedExpireTime) || !long.TryParse(oldSymbolSeedExpireTime,out var symbolSeedExpireTime) - || Context.CurrentBlockTime.Seconds > symbolSeedExpireTime, + .TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, + out var oldSymbolSeedExpireTime) || + !long.TryParse(oldSymbolSeedExpireTime, out var symbolSeedExpireTime) + || Context.CurrentBlockTime.Seconds > symbolSeedExpireTime, "seed_owned_symbol has been created"); } From 17a36e6eac0adf11e1320eb5335f047199935cec Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Thu, 29 Jun 2023 17:05:03 +0800 Subject: [PATCH 118/139] feat: add ut --- .../MultiTokenContractCrossChainTest.cs | 38 +++++++++---------- .../MultiTokenContractCrossChainTestBase.cs | 2 +- .../MultiTokenContractReferenceFeeTest.cs | 30 +++++++-------- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs index 10d1faa0a2..aa4f5d8fbf 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs @@ -195,8 +195,8 @@ public async Task MainChain_CrossChainCreateToken_Test() // Side chain create token var createTransaction = - await CreateTransactionForTokenCreation(SideChainTokenContractStub, SideChainTestKit.DefaultAccount.Address, - SymbolForTesting,SideTokenContractAddress); + await CreateTransactionForTokenCreation(SideChainTokenContractStub, SideChainTestKit.DefaultAccount.Address, + SymbolForTesting, SideTokenContractAddress); var executedSet = await SideChainTestKit.MineAsync(new List { createTransaction }); var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); @@ -236,8 +236,8 @@ public async Task SideChain_CrossChainCreateToken_Test() // Main chain create token await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var createTransaction = await CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting,TokenContractAddress); + var createTransaction = await CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting, TokenContractAddress); var blockExecutedSet = await MineAsync(new List { createTransaction }); var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); @@ -328,13 +328,13 @@ public async Task SideChain_CrossChainCreateToken_WithAlreadyCreated_Test() await RegisterSideChainContractAddressOnMainChainAsync(); await BootMinerChangeRoundAsync(AEDPoSContractStub, true); - var createTransaction =await CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting,TokenContractAddress); + var createTransaction = await CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting, TokenContractAddress); var blockExecutedSet = await MineAsync(new List { createTransaction }); var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); - var sideCreateTransaction =await CreateTransactionForTokenCreation(SideChainTokenContractStub, - SideChainTestKit.DefaultAccount.Address, SymbolForTesting,SideTokenContractAddress); + var sideCreateTransaction = await CreateTransactionForTokenCreation(SideChainTokenContractStub, + SideChainTestKit.DefaultAccount.Address, SymbolForTesting, SideTokenContractAddress); blockExecutedSet = await SideChainTestKit.MineAsync(new List { sideCreateTransaction }); var sideCreateResult = blockExecutedSet.TransactionResultMap[sideCreateTransaction.GetHash()]; Assert.True(sideCreateResult.Status == TransactionResultStatus.Mined, sideCreateResult.Error); @@ -471,7 +471,7 @@ public async Task MainChain_CrossChainTransfer_Test() // Main chain create token await BootMinerChangeRoundAsync(AEDPoSContractStub, true); var createTransaction = await CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting,TokenContractAddress); + DefaultAccount.Address, SymbolForTesting, TokenContractAddress); var executedSet = await MineAsync(new List { createTransaction }); var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); @@ -647,10 +647,11 @@ public async Task SideChain_CrossChainReceived_NativeToken_Test() TransferTransactionBytes = crossChainTransferTransaction.ToByteString(), MerklePath = transferMerKlePath }; - var receiveResult = await SideChainTokenContractStub.CrossChainReceiveToken.SendAsync(crossChainReceiveTokenInput); - + var receiveResult = + await SideChainTokenContractStub.CrossChainReceiveToken.SendAsync(crossChainReceiveTokenInput); + var logEvent = receiveResult.TransactionResult.Logs.First(l => l.Name == nameof(CrossChainReceived)); - var receivedEvent =new CrossChainReceived(); + var receivedEvent = new CrossChainReceived(); receivedEvent.MergeFrom(logEvent.NonIndexed); receivedEvent.From.ShouldBe(SideChainTestKit.DefaultAccount.Address); receivedEvent.To.ShouldBe(SideChainTestKit.DefaultAccount.Address); @@ -723,7 +724,7 @@ public async Task SideChain_CrossChainReceived_InvalidToken_Test() var transferAmount = 1000; var createTransaction = await CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting,TokenContractAddress); + DefaultAccount.Address, SymbolForTesting, TokenContractAddress); var executedSet = await MineAsync(new List { createTransaction }); var createResult = executedSet.TransactionResultMap[createTransaction.GetHash()]; createResult.Status.ShouldBe(TransactionResultStatus.Mined, createResult.Error); @@ -808,8 +809,8 @@ public async Task SideChain_CrossChainReceived_DifferentReceiver_Test() public async Task CrossChainCreateToken_WithoutRegister_Test() { await GenerateSideChainAsync(false); - var createTransaction =await CreateTransactionForTokenCreation(TokenContractStub, - DefaultAccount.Address, SymbolForTesting,TokenContractAddress); + var createTransaction = await CreateTransactionForTokenCreation(TokenContractStub, + DefaultAccount.Address, SymbolForTesting, TokenContractAddress); var blockExecutedSet = await MineAsync(new List { createTransaction }); var createResult = blockExecutedSet.TransactionResultMap[createTransaction.GetHash()]; Assert.True(createResult.Status == TransactionResultStatus.Mined, createResult.Error); @@ -874,7 +875,7 @@ private async Task CreateTransactionForTokenCreation( TokenContractImplContainer.TokenContractImplStub tokenContractImplStub, Address issuer, string symbol, Address lockWhiteAddress, bool isBurnable = true) { - await CreateSeedNftCollection(tokenContractImplStub,issuer ); + await CreateSeedNftCollection(tokenContractImplStub, issuer); var tokenInfo = GetTokenInfo(symbol, issuer, isBurnable); var input = new CreateInput { @@ -885,11 +886,10 @@ private async Task CreateTransactionForTokenCreation( TokenName = tokenInfo.TokenName, TotalSupply = tokenInfo.TotalSupply }; - await CreateSeedNftAsync(tokenContractImplStub,input,lockWhiteAddress); + await CreateSeedNftAsync(tokenContractImplStub, input, lockWhiteAddress); return tokenContractImplStub.Create.GetTransaction(input); } - - + private Transaction CreateTokenInfoValidationTransaction(TokenInfo createdTokenInfo, TokenContractImplContainer.TokenContractImplStub tokenContractImplStub) diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs index 2aafdf8911..a0d08696bd 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs @@ -381,7 +381,7 @@ internal async Task CreateSeedNftCollection(TokenContractImplContainer.TokenCont { var input = new CreateInput { - Symbol = SeedNFTSymbolPre + SeedNum, + Symbol = SeedNFTSymbolPre + 0, Decimals = 0, IsBurnable = true, TokenName = "seed Collection", diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs index fbb14ced18..8a3d594ead 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs @@ -496,16 +496,16 @@ public async Task SetSymbolsToPayTxSizeFee_With_Invalid_Weight_Test() var theDefaultController = await GetDefaultParliamentAddressAsync(); var primaryTokenSymbol = await GetThePrimaryTokenAsync(); var feeToken = "FEETOKEN"; - await CreateSeedNftCollection(TokenContractStub,TokenContractAddress); + await CreateSeedNftCollection(TokenContractStub, DefaultAccount.Address); var input = new CreateInput { Symbol = feeToken, TokenName = "name", - Issuer = TokenContractAddress, + Issuer = DefaultAccount.Address, TotalSupply = 100_000, IsBurnable = true }; - await CreateSeedNftAsync(TokenContractStub,input,TokenContractAddress); + await CreateSeedNftAsync(TokenContractStub, input, TokenContractAddress); await TokenContractStub.Create.SendAsync(input); var newSymbolList = new SymbolListToPayTxSizeFee(); newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee @@ -534,15 +534,15 @@ public async Task SetSymbolsToPayTxSizeFee_With_Repeat_Token_Test() var theDefaultController = await GetDefaultParliamentAddressAsync(); var primaryTokenSymbol = await GetThePrimaryTokenAsync(); var feeToken = "FEETOKEN"; - await CreateSeedNftCollection(TokenContractStub,TokenContractAddress); + await CreateSeedNftCollection(TokenContractStub, DefaultAccount.Address); var input = new CreateInput { Symbol = feeToken, TokenName = "name", - Issuer = TokenContractAddress, + Issuer = DefaultAccount.Address, TotalSupply = 100_000 }; - await CreateSeedNftAsync(TokenContractStub,input,TokenContractAddress); + await CreateSeedNftAsync(TokenContractStub, input, TokenContractAddress); await TokenContractStub.Create.SendAsync(input); var newSymbolList = new SymbolListToPayTxSizeFee { @@ -578,15 +578,15 @@ public async Task SetSymbolsToPayTxSizeFee_Without_PrimaryToken_Test() { var theDefaultController = await GetDefaultParliamentAddressAsync(); var feeToken = "FEETOKEN"; - await CreateSeedNftCollection(TokenContractStub,TokenContractAddress); + await CreateSeedNftCollection(TokenContractStub, DefaultAccount.Address); var input = new CreateInput { Symbol = feeToken, TokenName = "name", - Issuer = TokenContractAddress, + Issuer = DefaultAccount.Address, TotalSupply = 100_000 }; - await CreateSeedNftAsync(TokenContractStub,input,TokenContractAddress); + await CreateSeedNftAsync(TokenContractStub, input, TokenContractAddress); await TokenContractStub.Create.SendAsync(input); var newSymbolList = new SymbolListToPayTxSizeFee(); newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee @@ -605,15 +605,15 @@ public async Task SetSymbolsToPayTxSizeFee_Without_Profitable_Token_Test() var theDefaultController = await GetDefaultParliamentAddressAsync(); var primaryTokenSymbol = await GetThePrimaryTokenAsync(); const string feeToken = "FEETOKEN"; - await CreateSeedNftCollection(TokenContractStub,TokenContractAddress); + await CreateSeedNftCollection(TokenContractStub, DefaultAccount.Address); var input = new CreateInput { Symbol = feeToken, TokenName = "name", - Issuer = TokenContractAddress, + Issuer = DefaultAccount.Address, TotalSupply = 100_000 }; - await CreateSeedNftAsync(TokenContractStub,input,TokenContractAddress); + await CreateSeedNftAsync(TokenContractStub, input, TokenContractAddress); await TokenContractStub.Create.SendAsync(input); var newSymbolList = new SymbolListToPayTxSizeFee { @@ -707,16 +707,16 @@ public async Task SetSymbolsToPayTxSizeFee_Success_Test() var theDefaultController = await GetDefaultParliamentAddressAsync(); var primaryTokenSymbol = await GetThePrimaryTokenAsync(); const string feeToken = "FEETOKEN"; - await CreateSeedNftCollection(TokenContractStub,TokenContractAddress); + await CreateSeedNftCollection(TokenContractStub, DefaultAccount.Address); var input = new CreateInput { Symbol = feeToken, TokenName = "name", - Issuer = TokenContractAddress, + Issuer = DefaultAccount.Address, TotalSupply = 100_000, IsBurnable = true }; - await CreateSeedNftAsync(TokenContractStub,input,TokenContractAddress); + await CreateSeedNftAsync(TokenContractStub, input, TokenContractAddress); await TokenContractStub.Create.SendAsync(input); var newSymbolList = new SymbolListToPayTxSizeFee { From 1c5c773f4da388285ce53544ad8028d2bf7990c4 Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 29 Jun 2023 17:36:22 +0800 Subject: [PATCH 119/139] fix: adjust comment of ElectorVotes --- contract/AElf.Contracts.Election/ElectionContractState.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contract/AElf.Contracts.Election/ElectionContractState.cs b/contract/AElf.Contracts.Election/ElectionContractState.cs index 7e3a85731f..f9bfd7125e 100644 --- a/contract/AElf.Contracts.Election/ElectionContractState.cs +++ b/contract/AElf.Contracts.Election/ElectionContractState.cs @@ -15,7 +15,7 @@ public partial class ElectionContractState : ContractState public SingletonState FlexibleHash { get; set; } public SingletonState WelcomeHash { get; set; } - // Pubkey -> ElectorVote + // Old:Pubkey/New:Address -> ElectorVote public MappedState ElectorVotes { get; set; } public MappedState CandidateVotes { get; set; } From 628d67f24bbe1664bd94966b2a0e3f8849cba2d3 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Thu, 29 Jun 2023 19:13:31 +0800 Subject: [PATCH 120/139] feat: revert get random hash --- .../AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs | 2 +- .../BlockMiningService.cs | 8 +++++--- .../OtherContractsOperation.cs | 8 +++++--- .../MultiTokenContractCrossChainTestBase.cs | 6 ++++-- .../ParliamentContractTest.cs | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs index c4043e3d49..e129ea9236 100644 --- a/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs +++ b/contract/AElf.Contracts.Consensus.AEDPoS/AEDPoSContract.cs @@ -116,7 +116,7 @@ public override Empty UpdateTinyBlockInformation(TinyBlockInput input) // Keep this for compatibility. public override Hash GetRandomHash(Int64Value input) { - Assert(input.Value > 0, "Invalid block height."); + Assert(input.Value > 1, "Invalid block height."); Assert(Context.CurrentHeight >= input.Value, "Block height not reached."); return State.RandomHashes[input.Value] ?? Hash.Empty; } diff --git a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs index bf70b9a807..85e43156e9 100644 --- a/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs +++ b/src/AElf.ContractTestKit.AEDPoSExtension/BlockMiningService.cs @@ -161,13 +161,15 @@ public async Task MineBlockAsync(List transactions = null, bool wit _isSkipped = false; } - + private async Task GenerateRandomProofAsync() { var blockHeight = (await _blockchainService.GetChainAsync()).BestChainHeight; var previousRandomHash = - await _contractStubs.First().GetRandomHash.CallAsync(new Int64Value - { Value = blockHeight == 0 ? 1 : blockHeight }); + blockHeight <= 1 + ? Hash.Empty + : await _contractStubs.First().GetRandomHash.CallAsync(new Int64Value + { Value = blockHeight }); return CryptoHelper.ECVrfProve((ECKeyPair)_testDataProvider.GetKeyPair(), previousRandomHash.ToByteArray()); } diff --git a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs index 512053a26a..d89e73bd70 100644 --- a/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs +++ b/test/AElf.Contracts.Economic.TestBase/OtherContractsOperation.cs @@ -99,14 +99,16 @@ protected async Task GetVoteTokenBalance(byte[] publicKey) return balance; } - + protected async Task GenerateRandomProofAsync(ECKeyPair keyPair) { var consensusContractStub = GetConsensusContractTester(keyPair); var blockHeight = (await BlockchainService.GetChainAsync()).BestChainHeight; var previousRandomHash = - await consensusContractStub.GetRandomHash.CallAsync(new Int64Value - { Value = blockHeight == 0 ? 1 : blockHeight }); + blockHeight <= 1 + ? Hash.Empty + : await consensusContractStub.GetRandomHash.CallAsync(new Int64Value + { Value = blockHeight }); return CryptoHelper.ECVrfProve(keyPair, previousRandomHash.ToByteArray()); } diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs index 34eac22ecf..889f5d79ad 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs @@ -367,8 +367,10 @@ private async Task GenerateRandomProofAsync(AEDPoSContractContainer.AEDP { var blockHeight = (await BlockchainService.GetChainAsync()).BestChainHeight; var previousRandomHash = - await aedPoSContractStub.GetRandomHash.CallAsync(new Int64Value - { Value = blockHeight == 0 ? 1 : blockHeight }); + blockHeight <= 1 + ? Hash.Empty + : await aedPoSContractStub.GetRandomHash.CallAsync(new Int64Value + { Value = blockHeight }); return CryptoHelper.ECVrfProve(keyPair, previousRandomHash.ToByteArray()); } diff --git a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs index 143c27a168..6836b299e4 100644 --- a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs +++ b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTest.cs @@ -325,7 +325,7 @@ public async Task Create_ProposalFailed_Test() } //"Expired proposal." { - createProposalInput.ExpiredTime = TimestampHelper.GetUtcNow().AddSeconds(-1); + createProposalInput.ExpiredTime = TimestampHelper.GetUtcNow().AddMinutes(-10); var transactionResult = await ParliamentContractStub.CreateProposal.SendWithExceptionAsync(createProposalInput); transactionResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); From 627157542aa04d4d5f5d074fc6b687803e359997 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Thu, 29 Jun 2023 20:13:44 +0800 Subject: [PATCH 121/139] feat: update Assert description --- .../TokenContract_Actions.cs | 15 ++++---- .../TokenContract_NFTHelper.cs | 2 +- .../TokenContract_NFT_Actions.cs | 8 ++-- .../BVT/NftApplicationTests.cs | 37 +++++++++++++++---- .../BVT/TokenFeeTest.cs | 16 +++++++- 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 49b9ee6c33..f8ac986a91 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -102,18 +102,17 @@ private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType. private void CheckSeedNFT(string symbolSeed, String symbol) { - Assert(!string.IsNullOrEmpty(symbolSeed), "seed NFT is not exist"); + Assert(!string.IsNullOrEmpty(symbolSeed), "Seed NFT does not exist."); var tokenInfo = State.TokenInfos[symbolSeed]; - Assert(tokenInfo != null, "seed NFT is not exist"); - Assert(State.Balances[Context.Sender][symbolSeed] > 0, "owner doesn't own enough balance"); - Assert(tokenInfo.ExternalInfo != null, "seed_owned_symbol is not exists"); - Assert(tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, - out var ownedSymbol), "seed_owned_symbol is not exists"); - Assert(ownedSymbol == symbol, "seed_owned_symbol and input_symbol is inconsistent"); + Assert(tokenInfo != null, "Seed NFT does not exist."); + Assert(State.Balances[Context.Sender][symbolSeed] > 0, "Seed NFT balance is not enough."); + Assert(tokenInfo.ExternalInfo != null && tokenInfo.ExternalInfo.Value.TryGetValue( + TokenContractConstants.SeedOwnedSymbolExternalInfoKey, out var ownedSymbol) && ownedSymbol == symbol, + "Invalid OwnedSymbol."); Assert(tokenInfo.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, out var expirationTime) && long.TryParse(expirationTime, out var expirationTimeLong) && - Context.CurrentBlockTime.Seconds <= expirationTimeLong, "seed_owned_symbol is expired"); + Context.CurrentBlockTime.Seconds <= expirationTimeLong, "OwnedSymbol is expired."); } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFTHelper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFTHelper.cs index 3652a25f91..bddfb444bf 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFTHelper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFTHelper.cs @@ -10,7 +10,7 @@ private SymbolType GetCreateInputSymbolType(string symbol) Assert(words[0].Length > 0 && words[0].All(IsValidCreateSymbolChar), "Invalid Symbol input"); if (words.Length == 1) return SymbolType.Token; Assert(words.Length == 2 && words[1].Length > 0 && words[1].All(IsValidItemIdChar), "Invalid NFT Symbol input"); - return words[1] == "0" ? SymbolType.NftCollection : SymbolType.Nft; + return words[1] == TokenContractConstants.CollectionSymbolSuffix ? SymbolType.NftCollection : SymbolType.Nft; } private void AssertNFTCreateInput(CreateInput input) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 743e29a09d..984d3fd0d5 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -26,13 +26,13 @@ private Empty CreateNFTInfo(CreateInput input) { Assert( input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, - out var ownedSymbol), "seed_owned_symbol is not exists"); + out var ownedSymbol), "OwnedSymbol does not exists."); Assert(input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, out var expirationTime) && long.TryParse(expirationTime, out var expirationTimeLong) && - Context.CurrentBlockTime.Seconds <= expirationTimeLong, "seed_owned_symbol is expired "); + Context.CurrentBlockTime.Seconds <= expirationTimeLong, "Invalid ownedSymbol."); var ownedSymbolType = GetCreateInputSymbolType(ownedSymbol); - Assert(ownedSymbolType != SymbolType.Nft, "seed_owned_symbol can not be NFT"); + Assert(ownedSymbolType != SymbolType.Nft, "Invalid OwnedSymbol."); CheckSymbolLength(ownedSymbol, ownedSymbolType); CheckTokenAndCollectionExists(ownedSymbol); CheckSymbolSeed(ownedSymbol); @@ -51,7 +51,7 @@ private void CheckSymbolSeed(string ownedSymbol) out var oldSymbolSeedExpireTime) || !long.TryParse(oldSymbolSeedExpireTime, out var symbolSeedExpireTime) || Context.CurrentBlockTime.Seconds > symbolSeedExpireTime, - "seed_owned_symbol has been created"); + "OwnedSymbol has been created"); } diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs index 59fc06cae5..3f4e0f6ece 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs @@ -780,7 +780,7 @@ public async Task CreateTokenTest() }); createInputExpire.ExternalInfo.Value["__seed_exp_time"] = "1234"; var expireError = await TokenContractStub.Create.SendWithExceptionAsync(createInputExpire); - expireError.TransactionResult.Error.ShouldContain("seed_owned_symbol is expired"); + expireError.TransactionResult.Error.ShouldContain("Invalid ownedSymbol."); // create nft var nftSuccessAsync = await TokenContractStub.Create.SendAsync(new CreateInput { @@ -822,7 +822,7 @@ await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() // owner doesn't own enough balance var nftAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); nftAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - nftAsync.TransactionResult.Error.ShouldContain("owner doesn't own enough balance"); + nftAsync.TransactionResult.Error.ShouldContain("Seed NFT balance is not enough"); // ExternalInfo check await TokenContractStub.Issue.SendAsync(new IssueInput { @@ -841,7 +841,7 @@ await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() var inconsistentExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); inconsistentExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); inconsistentExceptionAsync.TransactionResult.Error.ShouldContain( - "seed_owned_symbol and input_symbol is inconsistent"); + "Invalid OwnedSymbol"); input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; input.ExternalInfo.Value["__seed_exp_time"] = ""; @@ -853,7 +853,7 @@ await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() var expireExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync( GetCreateInput()); expireExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - expireExceptionAsync.TransactionResult.Error.ShouldContain("seed_owned_symbol is expired"); + expireExceptionAsync.TransactionResult.Error.ShouldContain("OwnedSymbol is expired"); input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; input.ExternalInfo.Value["__seed_exp_time"] = "1234"; @@ -864,16 +864,37 @@ await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() }); var expireExceptionAsync1 = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); expireExceptionAsync1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - expireExceptionAsync1.TransactionResult.Error.ShouldContain("seed_owned_symbol is expired"); - - var s = await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + expireExceptionAsync1.TransactionResult.Error.ShouldContain("OwnedSymbol is expired"); + await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput { Symbol = input.Symbol, ExternalInfo = new ExternalInfo() }); var emptyExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); emptyExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - emptyExceptionAsync.TransactionResult.Error.ShouldContain("seed_owned_symbol is not exists"); + emptyExceptionAsync.TransactionResult.Error.ShouldContain("Invalid OwnedSymbol"); + input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; + input.ExternalInfo.Value["__seed_exp_time"] = TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString(); + await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput + { + Symbol = input.Symbol, + ExternalInfo = input.ExternalInfo + }); + var re = await SubmitAndApproveProposalOfDefaultParliamentWithException(TokenContractAddress, + nameof(TokenContractStub.Create), new CreateInput + { + Symbol = "XYZ-0", + Decimals = 0, + IsBurnable = true, + TokenName = "ELF2", + TotalSupply = 100_000_000_000_000_000L, + Issuer = DefaultAddress, + ExternalInfo = new ExternalInfo() + }); + re.TransactionResult.Error.ShouldContain("OwnedSymbol has been created"); + re.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + + } private CreateInput GetCreateInput() diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs index 46d940c1d3..645615d320 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs @@ -1,5 +1,6 @@ using System.Linq; using System.Threading.Tasks; +using AElf.CSharp.Core; using AElf.Types; using Google.Protobuf; using Google.Protobuf.WellKnownTypes; @@ -221,7 +222,7 @@ private async Task SubmitAndApproveProposalOfDefaultParliament(Address contractA { var defaultParliamentAddress = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposalId = await CreateProposalAsync(TokenContractAddress, + var proposalId = await CreateProposalAsync(contractAddress, defaultParliamentAddress, methodName, message); await ApproveWithMinersAsync(proposalId); var releaseResult = await ParliamentContractStub.Release.SendAsync(proposalId); @@ -229,6 +230,19 @@ private async Task SubmitAndApproveProposalOfDefaultParliament(Address contractA releaseResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } + private async Task> SubmitAndApproveProposalOfDefaultParliamentWithException( + Address contractAddress, + string methodName, + IMessage message) + { + var defaultParliamentAddress = + await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalId = await CreateProposalAsync(contractAddress, + defaultParliamentAddress, methodName, message); + await ApproveWithMinersAsync(proposalId); + return await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + } + private Transaction GenerateTokenTransaction(Address from, string method, IMessage input) { return new Transaction From 5fd7b8998e695b7aea83ffd4a7d0700a4bddab20 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Thu, 29 Jun 2023 20:43:52 +0800 Subject: [PATCH 122/139] feat: update assert desc --- contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 984d3fd0d5..677674e10b 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -26,7 +26,7 @@ private Empty CreateNFTInfo(CreateInput input) { Assert( input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, - out var ownedSymbol), "OwnedSymbol does not exists."); + out var ownedSymbol), "OwnedSymbol does not exist."); Assert(input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, out var expirationTime) && long.TryParse(expirationTime, out var expirationTimeLong) && From 8008b60b51997f723c8b969f29f833f938f2696c Mon Sep 17 00:00:00 2001 From: kevin Date: Fri, 30 Jun 2023 12:06:47 +0800 Subject: [PATCH 123/139] fix: ut --- .../BVT/ACS2_TokenResourceTests.cs | 1 - .../ExecutePluginTransactionDirectlyTest.cs | 163 ++++++------ ...inTransactionDirectlyTest_FreeAllowance.cs | 251 ++++++++---------- .../ExecutionPluginForMethodFeeTestBase.cs | 5 +- 4 files changed, 209 insertions(+), 211 deletions(-) diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs index ca83cfb813..35f84f7154 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS2_TokenResourceTests.cs @@ -133,7 +133,6 @@ public async Task ACS2_GetResourceInfo_Transfer_MultiToken_Test() [Fact] public async Task ACS2_GetResourceInfo_TransferFrom_WithDelegate_Test() { - await CreateNativeTokenAsync(); var delegations1 = new Dictionary { [NativeToken] = 1000, diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index 9febee0f69..ff26b36007 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -45,13 +45,16 @@ public async Task ChargeTransactionFees_Without_Primary_Token_Test() await TokenContractImplStub.SetMethodFee.SendAsync(new MethodFees { MethodName = methodName, - Fees = { new MethodFee + Fees = { - Symbol = NativeTokenSymbol, - BasicFee = 1000 - } } + new MethodFee + { + Symbol = NativeTokenSymbol, + BasicFee = 1000 + } + } }); - + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(new ChargeTransactionFeesInput { ContractAddress = TokenContractAddress, @@ -162,7 +165,7 @@ public async Task ChargeTransactionFees_With_Different_Transaction_Size_Fee_Toke BaseTokenWeight = baseWeight[i] }); } - + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var beforeBalanceList = await GetDefaultBalancesAsync(orderedSymbolList); @@ -229,7 +232,7 @@ await TokenContractStub.InitializeFromParentChain.SendAsync(new InitializeFromPa var result = await TokenContractStub.DonateResourceToken.SendAsync(feeMap); var transactionFeeClaimedDic = result.TransactionResult.Logs.Where(o => o.Name == nameof(ResourceTokenClaimed)) .Select(o => ResourceTokenClaimed.Parser.ParseFrom(o.NonIndexed)).ToDictionary(o => o.Symbol, o => o); - + for (var i = 0; i < symbolList.Length; i++) { var balance = await GetBalanceAsync(DefaultSender, symbolList[i]); @@ -263,13 +266,13 @@ public async Task ClaimTransactionFee_Balance_WithOut_Receiver_Test() } }; var result = await TokenContractStub.ClaimTransactionFees.SendAsync(claimFeeInput); - + var transactionFeeClaimed = TransactionFeeClaimed.Parser.ParseFrom(result.TransactionResult.Logs .First(l => l.Name.Contains(nameof(TransactionFeeClaimed))).NonIndexed); transactionFeeClaimed.Symbol.ShouldBe(tokenSymbol); transactionFeeClaimed.Amount.ShouldBe(feeAmount); transactionFeeClaimed.Receiver.ShouldBe(TokenContractAddress); - + var afterBurned = await GetTokenSupplyAmount(tokenSymbol); (beforeBurned - afterBurned).ShouldBe(feeAmount); } @@ -297,13 +300,13 @@ public async Task ClaimTransactionFee_Balance_With_Receiver_Test() } }; var result = await TokenContractStub.ClaimTransactionFees.SendAsync(claimFeeInput); - + var transactionFeeClaimed = TransactionFeeClaimed.Parser.ParseFrom(result.TransactionResult.Logs .First(l => l.Name.Contains(nameof(TransactionFeeClaimed))).NonIndexed); transactionFeeClaimed.Symbol.ShouldBe(tokenSymbol); transactionFeeClaimed.Amount.ShouldBe(feeAmount); transactionFeeClaimed.Receiver.ShouldBe(TokenContractAddress); - + var afterBurned = await GetTokenSupplyAmount(tokenSymbol); var afterBalance = await GetBalanceAsync(receiver, tokenSymbol); var shouldBurned = feeAmount.Div(10); @@ -325,7 +328,8 @@ public async Task FreeAllowancesTest(long threshold, long initialBalance, long f await SetPrimaryTokenSymbolAsync(); await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFreeAllowancesConfig + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -450,7 +454,8 @@ public async Task FreeAllowances_MultToken_Test( await IssueTokenToDefaultSenderAsync(sizeFeeSymbol, sizeFeeBalance); } - await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFreeAllowancesConfig + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -633,28 +638,36 @@ public async Task ChargeTransactionFee_Delegate( await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeUserBalance, userAddress); } - await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFreeAllowancesConfig - { - FreeAllowances = new MethodFeeFreeAllowances + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { - new MethodFeeFreeAllowance - { - Symbol = basicFeeSymbol, - Amount = baseFeeFreeAmount - }, - new MethodFeeFreeAllowance + new ConfigTransactionFeeFreeAllowance { - Symbol = sizeFeeSymbol, - Amount = sizeFeeFreeAmount + TransactionFeeFreeAllowances = new TransactionFeeFreeAllowances + { + Value = + { + new TransactionFeeFreeAllowance + { + Symbol = basicFeeSymbol, + Amount = baseFeeFreeAmount + }, + new TransactionFeeFreeAllowance + { + Symbol = sizeFeeSymbol, + Amount = sizeFeeFreeAmount + } + } + }, + Symbol = NativeTokenSymbol, + RefreshSeconds = 100, + Threshold = threshold } } - }, - RefreshSeconds = 100, - Threshold = threshold - }); - + }); + { var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(userAddress); if (threshold <= initialBalance) @@ -685,7 +698,7 @@ await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFre } } }; - + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee @@ -708,7 +721,7 @@ await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFre }; await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); - + var chargeTransactionFeesInput = new ChargeTransactionFeesInput { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), @@ -832,8 +845,9 @@ await TokenContractStub2.SetTransactionFeeDelegations.SendAsync(new SetTransacti await IssueTokenToUserAsync(basicFeeSymbol, baseFeeDelegateBalance, DelegateeAddress); await IssueTokenToUserAsync(sizeFeeSymbol, sizeFeeDelegateBalance, DelegateeAddress); } - - await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFreeAllowancesConfig + + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -874,7 +888,7 @@ await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFre } } }; - await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -1166,7 +1180,8 @@ public async Task ChargeTransactionFee_DelegateNew_First( result.Delegations[NativeTokenSymbol].ShouldBe(5); } - await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFreeAllowancesConfig + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -1208,8 +1223,8 @@ await TokenContractStub.ConfigMethodFeeFreeAllowances.SendAsync(new MethodFeeFre freeAllowances.Map.ShouldBeEmpty(); } } - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); - + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol, sizeFeeSymbol, 80); + var chargeTransactionFeesInput = new ChargeTransactionFeesInput { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), @@ -1389,7 +1404,7 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( DelegateInfoList = { delegateInfo2 } }); - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol, sizeFeeSymbol, 80); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -1547,7 +1562,7 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( DelegateInfoList = { delegateInfo2 } }); - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol, sizeFeeSymbol, 80); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -1688,7 +1703,7 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( DelegateInfoList = { delegateInfo2 } }); - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,80); + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol, sizeFeeSymbol, 80); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -1700,37 +1715,37 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( var chargeFeeRetDefault = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRetDefault.Output.Success.ShouldBe(false); - //no change - var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DefaultSender - }); - afterBalance.Balance.ShouldBe(0); + //no change + var afterBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = DefaultSender + }); + afterBalance.Balance.ShouldBe(0); - //no change - var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput - { - Symbol = basicFeeSymbol, - Owner = DelegateeAddress - }); - afterDelegateeBalance.Balance.ShouldBe(20); + //no change + var afterDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = DelegateeAddress + }); + afterDelegateeBalance.Balance.ShouldBe(20); - var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + var afterSecondaryDelegateeBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = basicFeeSymbol, + Owner = Delegatee2Address + }); + afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); + var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( + new GetTransactionFeeDelegateInfoInput { - Symbol = basicFeeSymbol, - Owner = Delegatee2Address + DelegateeAddress = Delegatee2Address, + DelegatorAddress = DelegateeAddress, + ContractAddress = TokenContractAddress, + MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) }); - afterSecondaryDelegateeBalance.Balance.ShouldBe(afterBalanceDelegatee); - var delegation = await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( - new GetTransactionFeeDelegateInfoInput - { - DelegateeAddress = Delegatee2Address, - DelegatorAddress = DelegateeAddress, - ContractAddress = TokenContractAddress, - MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer) - }); - delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); + delegation.Delegations[basicFeeSymbol].ShouldBe(afterDelegateeAmount); } [Theory] @@ -1801,7 +1816,7 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( DelegateInfoList = { delegateInfo2 } }); - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,basicFee); + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol, sizeFeeSymbol, basicFee); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -1847,7 +1862,7 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( } [Theory] - [InlineData( 10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] + [InlineData(10, 20, 100, 1000, 1000, 1000, 10, 10, 20, 20, 100, 100, 80, 80, 20, 920)] public async Task ChargeTransactionFee_DelegationOldFirst_NewSecond_Success( long initialBalance, long initialDelegateeBalance, long initialDelegatee2Balance, long delegateeAmountNativeToken, long delegateeAmountBasic, long delegateeAmountSize, @@ -1907,8 +1922,8 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( DelegateInfoList = { delegateInfo2 } }); - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,basicFee); - + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol, sizeFeeSymbol, basicFee); + var chargeTransactionFeesInput = new ChargeTransactionFeesInput { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), @@ -2046,7 +2061,7 @@ await TokenContractStubDelegate2.SetTransactionFeeDelegateInfos.SendAsync( DelegateInfoList = { delegateInfo2 } }); - var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol,sizeFeeSymbol,basicFee); + var sizeFeeSymbolList = await SetMethodOrSizeFeeAsync(basicFeeSymbol, sizeFeeSymbol, basicFee); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -2323,7 +2338,7 @@ private async Task IssueTokenListToUserAsync(List symbols, long amount, await IssueTokenToUserAsync(symbol, amount, address); } } - + private async Task GetSetDelegationResultAsync(List<(Address, Address)> delegateAddressList, long refBlockHeight) { @@ -2392,7 +2407,7 @@ private async Task SetMethodOrSizeFeeAsync(string basi }; await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); - + return sizeFeeSymbolList; } diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs index 4300646d96..0cdb3ab91e 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest_FreeAllowance.cs @@ -18,8 +18,8 @@ public async Task ConfigTransactionFeeFreeAllowances_Test() { await SetPrimaryTokenSymbolAsync(); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -61,8 +61,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 2_00000000); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -108,7 +108,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, public async Task ConfigTransactionFeeFreeAllowances_Unauthorized_Test() { var result = - await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendWithExceptionAsync( + await TokenContractImplStub2.ConfigTransactionFeeFreeAllowances.SendWithExceptionAsync( new ConfigTransactionFeeFreeAllowancesInput()); result.TransactionResult.Error.ShouldContain("Unauthorized behavior."); } @@ -119,8 +119,8 @@ public async Task ConfigTransactionFeeFreeAllowances_MultipleTokens_OneByOne_Tes await SetPrimaryTokenSymbolAsync(); await CreateTokenAndIssueAsync(); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -165,8 +165,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, userCFreeAllowances.Result.Map.ShouldBe(userAFreeAllowances.Result.Map); } - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -231,8 +231,8 @@ public async Task ConfigTransactionFeeFreeAllowances_MultipleTokens_AtOnce_Test( await SetPrimaryTokenSymbolAsync(); await CreateTokenAndIssueAsync(); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -312,8 +312,8 @@ public async Task ConfigTransactionFeeFreeAllowances_MultipleTokens_Modify_Test( await ConfigTransactionFeeFreeAllowances_MultipleTokens_AtOnce_Test(); await CreateTokenAsync(DefaultSender, "ABC"); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -376,18 +376,18 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, [Fact] public async Task ConfigTransactionFeeFreeAllowances_InvalidInput_Test() { - var message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + var message = await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendWithExceptionAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { new ConfigTransactionFeeFreeAllowance() } }); - message.ShouldContain("Invalid input symbol"); + message.TransactionResult.Error.ShouldContain("Invalid input symbol"); - message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + message = await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendWithExceptionAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -397,10 +397,10 @@ public async Task ConfigTransactionFeeFreeAllowances_InvalidInput_Test() } } }); - message.ShouldContain("Symbol TEST not exist"); + message.TransactionResult.Error.ShouldContain("Symbol TEST not exist"); - message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + message = await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendWithExceptionAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -410,10 +410,10 @@ public async Task ConfigTransactionFeeFreeAllowances_InvalidInput_Test() } } }); - message.ShouldContain("Invalid input allowances"); + message.TransactionResult.Error.ShouldContain("Invalid input allowances"); - message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + message = await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendWithExceptionAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -435,10 +435,10 @@ public async Task ConfigTransactionFeeFreeAllowances_InvalidInput_Test() } } }); - message.ShouldContain("Invalid input threshold"); + message.TransactionResult.Error.ShouldContain("Invalid input threshold"); - message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + message = await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendWithExceptionAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -461,15 +461,14 @@ public async Task ConfigTransactionFeeFreeAllowances_InvalidInput_Test() } } }); - message.ShouldContain("Invalid input refresh seconds"); + message.TransactionResult.Error.ShouldContain("Invalid input refresh seconds"); } [Fact] public async Task RemoveTransactionFeeFreeAllowancesConfig_Unauthorized_Test() { - var result = - await TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig.SendWithExceptionAsync( - new RemoveTransactionFeeFreeAllowancesConfigInput()); + var result = await TokenContractImplStub2.RemoveTransactionFeeFreeAllowancesConfig.SendWithExceptionAsync( + new RemoveTransactionFeeFreeAllowancesConfigInput()); result.TransactionResult.Error.ShouldContain("Unauthorized behavior."); } @@ -484,8 +483,7 @@ public async Task RemoveTransactionFeeFreeAllowancesConfig_Test() var config = TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Result.Value.Count.ShouldBe(2); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + await TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig.SendAsync( new RemoveTransactionFeeFreeAllowancesConfigInput { Symbols = { USDT } @@ -498,8 +496,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); // symbol not exist - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + await TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig.SendAsync( new RemoveTransactionFeeFreeAllowancesConfigInput { Symbols = { USDT } @@ -512,8 +509,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, userAFreeAllowances.Result.Map.Keys.First().ShouldBe(NativeTokenSymbol); // Duplicate symbols - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + await TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig.SendAsync( new RemoveTransactionFeeFreeAllowancesConfigInput { Symbols = { NativeTokenSymbol, NativeTokenSymbol } @@ -535,8 +531,7 @@ public async Task RemoveTransactionFeeFreeAllowancesConfig_MultipleTokens_AtOnce var config = TokenContractImplStub.GetTransactionFeeFreeAllowancesConfig.CallAsync(new Empty()); config.Result.Value.Count.ShouldBe(2); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + await TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig.SendAsync( new RemoveTransactionFeeFreeAllowancesConfigInput { Symbols = { NativeTokenSymbol, USDT } @@ -548,19 +543,17 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, [Fact] public async Task RemoveTransactionFeeFreeAllowancesConfig_InvalidInput_Test() { - var message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + var message = await TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig.SendWithExceptionAsync( new RemoveTransactionFeeFreeAllowancesConfigInput { Symbols = { USDT } }); - message.ShouldContain("Method fee free allowances config not set"); + message.TransactionResult.Error.ShouldContain("Method fee free allowances config not set"); await ConfigTransactionFeeFreeAllowances_MultipleTokens_AtOnce_Test(); - message = await SubmitProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig), + message = await TokenContractImplStub.RemoveTransactionFeeFreeAllowancesConfig.SendWithExceptionAsync( new RemoveTransactionFeeFreeAllowancesConfigInput()); - message.ShouldContain("Invalid input"); + message.TransactionResult.Error.ShouldContain("Invalid input"); } [Theory] @@ -578,8 +571,8 @@ public async Task ChargeTransactionFee_Test(long initialELFBalance, long initial await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialELFBalance); await IssueTokenToDefaultSenderAsync(USDT, initialUSDTBalance); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -632,8 +625,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -691,8 +683,8 @@ public async Task ChargeTransactionFee_MultipleTokens_Test(long initialELFBalanc await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -745,8 +737,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -766,8 +757,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); if (initialELFBalance >= thresholdELF) @@ -842,8 +832,7 @@ public async Task ChargeTransactionFee_NoFreeAllowance_Test(long initialBalance, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -857,8 +846,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var chargeTransactionFeesInput = new ChargeTransactionFeesInput { @@ -890,8 +878,8 @@ public async Task ChargeTransactionFee_SingleThreshold_Test(long initialBalance, await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -932,8 +920,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -953,8 +940,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); @@ -1012,8 +998,8 @@ public async Task ChargeTransactionFee_NotEnough_Test(long initialELFBalance, lo await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -1066,8 +1052,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -1087,8 +1072,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -1133,8 +1117,8 @@ public async Task ChargeTransactionFee_ClearFreeAllowance_Test(long initialBalan await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -1170,8 +1154,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -1185,8 +1168,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -1257,8 +1239,8 @@ public async Task ChargeTransactionFee_RefreshTime_Test() await IssueTokenToDefaultSenderAsync(Token1, 10000); await IssueTokenToDefaultSenderAsync(Token2, 10000); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -1311,8 +1293,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -1332,8 +1313,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -1427,8 +1407,8 @@ public async Task ChargeTransactionFee_FreeAllowanceFirst_Test(long initialBalan await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, initialBalance); await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -1469,8 +1449,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -1490,8 +1469,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); freeAllowances.Map.Keys.First().ShouldBe(NativeTokenSymbol); @@ -1522,20 +1500,29 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, [Theory] // case 24 - [InlineData(1000, 1000, 1000, 1000, Token1, 1000, Token1, 1000, 600, 10, Token2, 1000, Token2, 1000, 300, 10, 1000, 1000, 1000, 1000, 0, 0, 1000, 1000, 5000, 1, 1, USDT, 3000, Token2, 3000, false)] + [InlineData(1000, 1000, 1000, 1000, Token1, 1000, Token1, 1000, 600, 10, Token2, 1000, Token2, 1000, 300, 10, 1000, + 1000, 1000, 1000, 0, 0, 1000, 1000, 5000, 1, 1, USDT, 3000, Token2, 3000, false)] // case 28 - [InlineData(10000, 10000, 1000, 0, Token1, 2000, NativeTokenSymbol, 2000, 600, 10000, Token1, 1000, USDT, 200, 300, 10000, 2000, 0, 0, 200, 10000, 10000, 1000, 0, 2000, 1, 2, Token1, 1000, USDT, 200, true)] + [InlineData(10000, 10000, 1000, 0, Token1, 2000, NativeTokenSymbol, 2000, 600, 10000, Token1, 1000, USDT, 200, 300, + 10000, 2000, 0, 0, 200, 10000, 10000, 1000, 0, 2000, 1, 2, Token1, 1000, USDT, 200, true)] // case 29 - [InlineData(10000, 10000, 1000, 0, Token1, 2000, NativeTokenSymbol, 1000, 600, 10000, Token1, 1000, USDT, 100, 300, 10000, 1000, 1000, 0, 100, 10000, 10000, 1000, 0, 2000, 1, 2, Token1, 1000, USDT, 200, true)] + [InlineData(10000, 10000, 1000, 0, Token1, 2000, NativeTokenSymbol, 1000, 600, 10000, Token1, 1000, USDT, 100, 300, + 10000, 1000, 1000, 0, 100, 10000, 10000, 1000, 0, 2000, 1, 2, Token1, 1000, USDT, 200, true)] // case 30 - [InlineData(10000, 10000, 1000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, USDT, 100, 300, 100, 500, 0, 0, 100, 9000, 10000, 1000, 0, 2000, 1, 1, Token1, 1500, USDT, 200, true)] + [InlineData(10000, 10000, 1000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, USDT, 100, 300, + 100, 500, 0, 0, 100, 9000, 10000, 1000, 0, 2000, 1, 1, Token1, 1500, USDT, 200, true)] // case 31 - [InlineData(10000, 10000, 10000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, NativeTokenSymbol, 1000, 300, 100, 0, 0, 0, 0, 9000, 10000, 7000, 0, 3000, 5, 3, NativeTokenSymbol, 3000, Token1, 3000, true)] + [InlineData(10000, 10000, 10000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, + NativeTokenSymbol, 1000, 300, 100, 0, 0, 0, 0, 9000, 10000, 7000, 0, 3000, 5, 3, NativeTokenSymbol, 3000, + Token1, 3000, true)] // case 32 - [InlineData(10000, 10000, 1000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, NativeTokenSymbol, 1000, 300, 100, 0, 0, 0, 0, 0, 10000, 0, 0, 3000, 5, 3, NativeTokenSymbol, 15000, USDT, 20000, false)] + [InlineData(10000, 10000, 1000, 0, Token1, 1000, NativeTokenSymbol, 1000, 600, 100, Token1, 1000, NativeTokenSymbol, + 1000, 300, 100, 0, 0, 0, 0, 0, 10000, 0, 0, 3000, 5, 3, NativeTokenSymbol, 15000, USDT, 20000, false)] // case 33 - [InlineData(5000, 10000, 0, 0, Token1, 1000, Token1, 1000, 600, 100, Token2, 1000, Token2, 1000, 300, 100, 0, 0, 1000, 1000, 0, 8000, 0, 0, 10000, 1, 5, USDT, 2000, NativeTokenSymbol, 0, false)] - [InlineData(2000, 0, 0, 0, Token1, 0, NativeTokenSymbol, 0, 0, 10000, Token2, 0, Token2, 0, 0, 10000, 0, 0, 0, 0, 500, 0, 0, 0, 0, 1, 1, NativeTokenSymbol, 1500, USDT, 100, true)] + [InlineData(5000, 10000, 0, 0, Token1, 1000, Token1, 1000, 600, 100, Token2, 1000, Token2, 1000, 300, 100, 0, 0, + 1000, 1000, 0, 8000, 0, 0, 10000, 1, 5, USDT, 2000, NativeTokenSymbol, 0, false)] + [InlineData(2000, 0, 0, 0, Token1, 0, NativeTokenSymbol, 0, 0, 10000, Token2, 0, Token2, 0, 0, 10000, 0, 0, 0, 0, + 500, 0, 0, 0, 0, 1, 1, NativeTokenSymbol, 1500, USDT, 100, true)] public async Task ChargeTransactionFee_MultipleTxFeeTokens_Test(long initialELFBalance, long initialUSDTBalance, long initialToken1Balance, long initialToken2Balance, string firstFreeSymbolELF, long firstFreeAmountELF, string secondFreeSymbolELF, long secondFreeAmountELF, long refreshSecondsELF, long thresholdELF, @@ -1557,8 +1544,7 @@ public async Task ChargeTransactionFee_MultipleTxFeeTokens_Test(long initialELFB await IssueTokenToDefaultSenderAsync(Token1, initialToken1Balance); await IssueTokenToDefaultSenderAsync(Token2, initialToken2Balance); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( new ConfigTransactionFeeFreeAllowancesInput { Value = @@ -1632,8 +1618,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, }); } - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -1653,8 +1638,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DefaultSender); if (initialELFBalance >= thresholdELF) @@ -1725,7 +1709,8 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, [Theory] [InlineData(100, 100, 100)] - public async Task ChargeTransactionFee_DelegateMultipleFeeTokens_PriorityAllowance_Success_Test(long initialELFBalance, long initialUSDTBalance, + public async Task ChargeTransactionFee_DelegateMultipleFeeTokens_PriorityAllowance_Success_Test( + long initialELFBalance, long initialUSDTBalance, long initialToken1Balance) { await SetPrimaryTokenSymbolAsync(); @@ -1734,15 +1719,15 @@ public async Task ChargeTransactionFee_DelegateMultipleFeeTokens_PriorityAllowan await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 5); await IssueTokenToDefaultSenderAsync(USDT, 5); - await IssueTokenToDefaultSenderAsync(Token1,5); + await IssueTokenToDefaultSenderAsync(Token1, 5); await IssueTokenToUserAsync(NativeTokenSymbol, initialELFBalance, DelegateeAddress); await IssueTokenToUserAsync(USDT, initialUSDTBalance, DelegateeAddress); await IssueTokenToUserAsync(Token1, initialToken1Balance, DelegateeAddress); await SetDelegateeAsync(); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -1793,8 +1778,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -1814,8 +1798,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var freeAllowances = await TokenContractImplStub.GetTransactionFeeFreeAllowances.CallAsync(DelegateeAddress); if (initialELFBalance >= 100) @@ -1824,15 +1807,16 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(NativeTokenSymbol); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(5); - + freeAllowances.Map.Values.First().Map.Keys.ElementAt(1).ShouldBe(USDT); freeAllowances.Map.Values.First().Map.Values.ElementAt(1).Symbol.ShouldBe(USDT); freeAllowances.Map.Values.First().Map.Values.ElementAt(1).Amount.ShouldBe(30); - + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(10); } + var chargeTransactionFeesInput = new ChargeTransactionFeesInput { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), @@ -1840,7 +1824,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, TransactionSizeFee = 7, }; chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); @@ -1860,17 +1844,17 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Keys.ElementAt(1).ShouldBe(USDT); freeAllowances.Map.Values.First().Map.Values.ElementAt(1).Symbol.ShouldBe(USDT); freeAllowances.Map.Values.First().Map.Values.ElementAt(1).Amount.ShouldBe(9); - + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(3); } - await CheckUserTokenAsync(DelegateeAddress,Token1, 100); - await CheckUserTokenAsync(DelegateeAddress,NativeTokenSymbol, 100); - await CheckUserTokenAsync(DelegateeAddress,USDT, 100); + await CheckUserTokenAsync(DelegateeAddress, Token1, 100); + await CheckUserTokenAsync(DelegateeAddress, NativeTokenSymbol, 100); + await CheckUserTokenAsync(DelegateeAddress, USDT, 100); } - + [Fact] public async Task ChargeTransactionFee_DelegateMultipleFeeTokens_PriorityAllowanceGreaterThan0_Success_Test() { @@ -1880,15 +1864,15 @@ public async Task ChargeTransactionFee_DelegateMultipleFeeTokens_PriorityAllowan await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 5); await IssueTokenToDefaultSenderAsync(USDT, 5); - await IssueTokenToDefaultSenderAsync(Token1,5); + await IssueTokenToDefaultSenderAsync(Token1, 5); await IssueTokenToUserAsync(NativeTokenSymbol, 100, DelegateeAddress); await IssueTokenToUserAsync(USDT, 100, DelegateeAddress); await IssueTokenToUserAsync(Token1, 100, DelegateeAddress); await SetDelegateeAsync(); - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplStub.ConfigTransactionFeeFreeAllowances), new ConfigTransactionFeeFreeAllowancesInput + await TokenContractImplStub.ConfigTransactionFeeFreeAllowances.SendAsync( + new ConfigTransactionFeeFreeAllowancesInput { Value = { @@ -1934,8 +1918,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetMethodFee), methodFee); + await TokenContractImplStub.SetMethodFee.SendAsync(methodFee); var sizeFeeSymbolList = new SymbolListToPayTxSizeFee { @@ -1955,8 +1938,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, } } }; - await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, - nameof(TokenContractImplContainer.TokenContractImplStub.SetSymbolsToPayTxSizeFee), sizeFeeSymbolList); + await TokenContractImplStub.SetSymbolsToPayTxSizeFee.SendAsync(sizeFeeSymbolList); var initialELFBalance = (await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { Owner = DelegateeAddress, @@ -1970,11 +1952,12 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(USDT); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(USDT); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(10); - + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(10); } + var chargeTransactionFeesInput = new ChargeTransactionFeesInput { MethodName = nameof(TokenContractContainer.TokenContractStub.Transfer), @@ -1982,7 +1965,7 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, TransactionSizeFee = 7, }; chargeTransactionFeesInput.SymbolsToPayTxSizeFee.AddRange(sizeFeeSymbolList.SymbolsToPayTxSizeFee); - + var chargeFeeRet = await TokenContractStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput); chargeFeeRet.Output.Success.ShouldBe(true); @@ -1997,15 +1980,15 @@ await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress, freeAllowances.Map.Values.First().Map.Keys.First().ShouldBe(USDT); freeAllowances.Map.Values.First().Map.Values.First().Symbol.ShouldBe(USDT); freeAllowances.Map.Values.First().Map.Values.First().Amount.ShouldBe(0); - + freeAllowances.Map.Values.First().Map.Keys.Last().ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.Last().Symbol.ShouldBe(Token1); freeAllowances.Map.Values.First().Map.Values.Last().Amount.ShouldBe(0); } - await CheckUserTokenAsync(DelegateeAddress,Token1, 80); - await CheckUserTokenAsync(DelegateeAddress,NativeTokenSymbol, 100); - await CheckUserTokenAsync(DelegateeAddress,USDT, 89); + await CheckUserTokenAsync(DelegateeAddress, Token1, 80); + await CheckUserTokenAsync(DelegateeAddress, NativeTokenSymbol, 100); + await CheckUserTokenAsync(DelegateeAddress, USDT, 89); } private async Task SetDelegateeAsync() @@ -2041,8 +2024,8 @@ private async Task CheckDefaultSenderTokenAsync(string symbol, long amount) balance.Balance.ShouldBe(amount); } - - private async Task CheckUserTokenAsync(Address user,string symbol, long amount) + + private async Task CheckUserTokenAsync(Address user, string symbol, long amount) { var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput { diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index 0416f4b583..934bce2f3a 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -341,6 +341,7 @@ protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() internal Address ConsensusContractAddress { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } internal TokenContractImplContainer.TokenContractImplStub TokenContractImplStub { get; set; } + internal TokenContractImplContainer.TokenContractImplStub TokenContractImplStub2 { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub2 { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub3 { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStubDelegator { get; set; } @@ -356,8 +357,6 @@ protected ExecutePluginTransactionDirectlyForMethodFeeTestBase() internal TokenContractImplContainer.TokenContractImplStub TokenContractStubSecondaryDelegate5 { get; set; } internal TokenContractImplContainer.TokenContractImplStub TokenContractStubSecondaryDelegate6 { get; set; } - - internal TokenContractImplContainer.TokenContractImplStub TokenContractImplStub { get; set; } internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } internal AEDPoSContractContainer.AEDPoSContractStub AEDPoSContractStub { get; set; } internal ECKeyPair DefaultSenderKeyPair => Accounts[0].KeyPair; @@ -468,6 +467,8 @@ private async Task DeployContractsAsync() TokenContractImplStub = GetTester(TokenContractAddress, DefaultSenderKeyPair); + TokenContractImplStub2 = + GetTester(TokenContractAddress, UserKeyPair); } // Parliament From 94b491f225d41edf4ba1f5e1228bf4a4f1b441ec Mon Sep 17 00:00:00 2001 From: gldeng Date: Fri, 30 Jun 2023 13:44:22 +0800 Subject: [PATCH 124/139] fix: Use factory to create hasher --- src/AElf.Cryptography/ECVRF/Vrf.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index de01110ae3..bbebe61a93 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -179,7 +179,7 @@ private byte[] GammaToHash(IECPoint gamma) } var gammaCofBytes = curve.SerializePoint(gammaCof, true); - using var hasher = SHA256.Create(); + using var hasher = _hasherFactory.Create(); using var stream = new MemoryStream(); stream.WriteByte(_config.SuiteString); stream.WriteByte(0x03); From e7ac420b9d02f6332ea3df9d4867d188014ca852 Mon Sep 17 00:00:00 2001 From: gldeng Date: Fri, 30 Jun 2023 13:44:22 +0800 Subject: [PATCH 125/139] fix: Use factory to create hasher --- src/AElf.Cryptography/ECVRF/Vrf.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AElf.Cryptography/ECVRF/Vrf.cs b/src/AElf.Cryptography/ECVRF/Vrf.cs index de01110ae3..bbebe61a93 100644 --- a/src/AElf.Cryptography/ECVRF/Vrf.cs +++ b/src/AElf.Cryptography/ECVRF/Vrf.cs @@ -179,7 +179,7 @@ private byte[] GammaToHash(IECPoint gamma) } var gammaCofBytes = curve.SerializePoint(gammaCof, true); - using var hasher = SHA256.Create(); + using var hasher = _hasherFactory.Create(); using var stream = new MemoryStream(); stream.WriteByte(_config.SuiteString); stream.WriteByte(0x03); From cffdb5b7c7acfc5db3c6c880afd51b8b9de4c82c Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 4 Jul 2023 19:54:00 +0800 Subject: [PATCH 126/139] feat: validate input and add ut --- .../TokenContract_Actions.cs | 17 +- .../TokenContract_Delegation.cs | 1 + ...TokenContract_Fee_Calculate_Coefficient.cs | 2 + .../TokenContract_Helper.cs | 8 + .../TokenContract_NFT_Actions.cs | 3 + .../BVT/TokenFeeTest.cs | 8 +- .../ExecutePluginTransactionDirectlyTest.cs | 181 +++++++++++++----- 7 files changed, 174 insertions(+), 46 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 660af1d57b..1d51f41935 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -124,7 +124,7 @@ private void CheckSeedNFT(string symbolSeed, String symbol) public override Empty SetPrimaryTokenSymbol(SetPrimaryTokenSymbolInput input) { Assert(State.ChainPrimaryTokenSymbol.Value == null, "Failed to set primary token symbol."); - Assert(State.TokenInfos[input.Symbol] != null, "Invalid input."); + Assert(!string.IsNullOrWhiteSpace(input.Symbol) && State.TokenInfos[input.Symbol] != null, "Invalid input symbol."); State.ChainPrimaryTokenSymbol.Value = input.Symbol; Context.Fire(new ChainPrimaryTokenSymbolSet { TokenSymbol = input.Symbol }); @@ -179,6 +179,8 @@ public override Empty Transfer(TransferInput input) public override Empty Lock(LockInput input) { + Assert(!string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol."); + AssertValidInputAddress(input.Address); AssertSystemContractOrLockWhiteListAddress(input.Symbol); // For Election Contract @@ -208,6 +210,8 @@ public override Empty Lock(LockInput input) public override Empty Unlock(UnlockInput input) { + Assert(!string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol."); + AssertValidInputAddress(input.Address); AssertSystemContractOrLockWhiteListAddress(input.Symbol); // For Election Contract @@ -245,6 +249,7 @@ public override Empty TransferFrom(TransferFromInput input) public override Empty Approve(ApproveInput input) { + AssertValidInputAddress(input.Spender); AssertValidToken(input.Symbol, input.Amount); State.Allowances[Context.Sender][input.Spender][input.Symbol] = input.Amount; Context.Fire(new Approved @@ -259,6 +264,7 @@ public override Empty Approve(ApproveInput input) public override Empty UnApprove(UnApproveInput input) { + AssertValidInputAddress(input.Spender); AssertValidToken(input.Symbol, input.Amount); var oldAllowance = State.Allowances[Context.Sender][input.Spender][input.Symbol]; var amountOrAll = Math.Min(input.Amount, oldAllowance); @@ -296,6 +302,7 @@ private Empty Burn(Address address, string symbol, long amount) public override Empty CheckThreshold(CheckThresholdInput input) { + AssertValidInputAddress(input.Sender); var meetThreshold = false; var meetBalanceSymbolList = new List(); foreach (var symbolToThreshold in input.SymbolToThreshold) @@ -367,6 +374,7 @@ public override Empty TransferToContract(TransferToContractInput input) public override Empty AdvanceResourceToken(AdvanceResourceTokenInput input) { + AssertValidInputAddress(input.ContractAddress); Assert( Context.Variables.GetStringArray(TokenContractConstants.PayTxFeeSymbolListName) .Contains(input.ResourceTokenSymbol), @@ -380,6 +388,8 @@ public override Empty AdvanceResourceToken(AdvanceResourceTokenInput input) public override Empty TakeResourceTokenBack(TakeResourceTokenBackInput input) { + Assert(!string.IsNullOrWhiteSpace(input.ResourceTokenSymbol), "Invalid input resource token symbol."); + AssertValidInputAddress(input.ContractAddress); var advancedAmount = State.AdvancedResourceToken[input.ContractAddress][Context.Sender][input.ResourceTokenSymbol]; Assert(advancedAmount >= input.Amount, "Can't take back that more."); @@ -391,6 +401,7 @@ public override Empty TakeResourceTokenBack(TakeResourceTokenBackInput input) public override Empty ValidateTokenInfoExists(ValidateTokenInfoExistsInput input) { + Assert(!string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol."); var tokenInfo = State.TokenInfos[input.Symbol]; if (tokenInfo == null) throw new AssertionException("Token validation failed."); @@ -414,6 +425,9 @@ public override Empty ValidateTokenInfoExists(ValidateTokenInfoExistsInput input public override Empty ChangeTokenIssuer(ChangeTokenIssuerInput input) { + Assert(!string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol."); + AssertValidInputAddress(input.NewTokenIssuer); + var tokenInfo = State.TokenInfos[input.Symbol]; Assert(tokenInfo != null, $"invalid token symbol: {input.Symbol}"); // ReSharper disable once PossibleNullReferenceException @@ -426,6 +440,7 @@ public override Empty ChangeTokenIssuer(ChangeTokenIssuerInput input) public override Empty ResetExternalInfo(ResetExternalInfoInput input) { + Assert(!string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol."); var tokenInfo = State.TokenInfos[input.Symbol]; Assert(tokenInfo.Issuer == Context.Sender, "No permission to reset external info."); tokenInfo.ExternalInfo = input.ExternalInfo; diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs index 8ccb15e3e3..1ac302ccef 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Delegation.cs @@ -12,6 +12,7 @@ public partial class TokenContract public override SetTransactionFeeDelegationsOutput SetTransactionFeeDelegations( SetTransactionFeeDelegationsInput input) { + AssertValidInputAddress(input.DelegatorAddress); Assert(input.Delegations != null, "Delegations cannot be null!"); // get all delegatees, init it if null. diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fee_Calculate_Coefficient.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fee_Calculate_Coefficient.cs index 8efefd5df0..09e4ebb328 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fee_Calculate_Coefficient.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fee_Calculate_Coefficient.cs @@ -15,6 +15,7 @@ public partial class TokenContract /// public override Empty UpdateCoefficientsForContract(UpdateCoefficientsInput input) { + Assert(input.Coefficients != null, "Invalid input coefficients."); Assert(input.Coefficients.FeeTokenType != (int)FeeTypeEnum.Tx, "Invalid fee type."); AssertDeveloperFeeController(); UpdateCoefficients(input); @@ -23,6 +24,7 @@ public override Empty UpdateCoefficientsForContract(UpdateCoefficientsInput inpu public override Empty UpdateCoefficientsForSender(UpdateCoefficientsInput input) { + Assert(input.Coefficients != null, "Invalid input coefficients."); AssertUserFeeController(); input.Coefficients.FeeTokenType = (int)FeeTypeEnum.Tx; // The only possible for now. UpdateCoefficients(input); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 9996eff984..10d3bd5160 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -51,6 +51,11 @@ private void AssertValidMemo(string memo) "Invalid memo size."); } + private void AssertValidInputAddress(Address input) + { + Assert(input != null && !input.Value.IsNullOrEmpty(), "Invalid input address."); + } + private void DoTransfer(Address from, Address to, string symbol, long amount, string memo = null) { Assert(from != to, "Can't do transfer to sender itself."); @@ -120,6 +125,9 @@ private List GetSymbolListSortedByExpirationTime(TransactionFeeFreeAllow private long GetBalance(Address address, string symbol) { + AssertValidInputAddress(address); + Assert(!string.IsNullOrWhiteSpace(symbol), "Invalid symbol."); + return State.Balances[address][symbol]; } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 677674e10b..12cd89468f 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -57,6 +57,9 @@ private void CheckSymbolSeed(string ownedSymbol) private void DoTransferFrom(Address from, Address to, Address spender, string symbol, long amount, string memo) { + AssertValidInputAddress(from); + AssertValidInputAddress(to); + // First check allowance. var allowance = State.Allowances[from][spender][symbol]; if (allowance < amount) diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs index 2e9831a030..c4ae34ae8f 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenFeeTest.cs @@ -134,7 +134,13 @@ public async Task UpdateCoefficientForSender_Without_Authorization_Test() initializeControllerRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); var updateRet = await TokenContractStub.UpdateCoefficientsForSender.SendWithExceptionAsync( - new UpdateCoefficientsInput()); + new UpdateCoefficientsInput + { + Coefficients = new CalculateFeeCoefficients + { + FeeTokenType = 0 + } + }); updateRet.TransactionResult.Error.ShouldContain("no permission"); } diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index ff26b36007..c3d5d824c5 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -3,11 +3,8 @@ using System.Threading.Tasks; using AElf.Contracts.MultiToken; using AElf.CSharp.Core; -using AElf.CSharp.Core.Extension; using AElf.Standards.ACS1; -using AElf.Standards.ACS3; using AElf.Types; -using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; @@ -2331,6 +2328,143 @@ await TokenContractStubDelegate1.GetTransactionFeeDelegateInfo.CallAsync( } } + [Fact] + public async Task SetPrimaryTokenSymbol_InvalidInput_Test() + { + { + var result = + await TokenContractStub.SetPrimaryTokenSymbol.SendWithExceptionAsync(new SetPrimaryTokenSymbolInput()); + result.TransactionResult.Error.ShouldContain("Invalid input symbol."); + } + { + await IssueTokenToDefaultSenderAsync(NativeTokenSymbol, 1000000); + var result = await TokenContractStub.Transfer.SendWithExceptionAsync(new TransferInput + { + Symbol = NativeTokenSymbol, + Amount = 100 + }); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = await TokenContractStub.Lock.SendWithExceptionAsync(new LockInput()); + result.TransactionResult.Error.ShouldContain("Invalid input symbol."); + } + { + var result = await TokenContractStub.Lock.SendWithExceptionAsync(new LockInput + { + Symbol = NativeTokenSymbol + }); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = await TokenContractStub.Unlock.SendWithExceptionAsync(new UnlockInput()); + result.TransactionResult.Error.ShouldContain("Invalid input symbol."); + } + { + var result = await TokenContractStub.Unlock.SendWithExceptionAsync(new UnlockInput + { + Symbol = NativeTokenSymbol + }); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = await TokenContractStub.TransferFrom.SendWithExceptionAsync(new TransferFromInput + { + Symbol = NativeTokenSymbol, + Amount = 100 + }); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = await TokenContractStub.TransferFrom.SendWithExceptionAsync(new TransferFromInput + { + Symbol = NativeTokenSymbol, + Amount = 100, + From = DefaultSender + }); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = await TokenContractStub.Approve.SendWithExceptionAsync(new ApproveInput()); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = await TokenContractStub.UnApprove.SendWithExceptionAsync(new UnApproveInput()); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = await TokenContractStub.CheckThreshold.SendWithExceptionAsync(new CheckThresholdInput()); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = + await TokenContractImplStub.AdvanceResourceToken + .SendWithExceptionAsync(new AdvanceResourceTokenInput()); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = + await TokenContractImplStub.TakeResourceTokenBack.SendWithExceptionAsync( + new TakeResourceTokenBackInput()); + result.TransactionResult.Error.ShouldContain("Invalid input resource token symbol."); + } + { + var result = await TokenContractImplStub.TakeResourceTokenBack.SendWithExceptionAsync( + new TakeResourceTokenBackInput + { + ResourceTokenSymbol = NativeTokenSymbol + }); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = + await TokenContractImplStub.ValidateTokenInfoExists.SendWithExceptionAsync( + new ValidateTokenInfoExistsInput()); + result.TransactionResult.Error.ShouldContain("Invalid input symbol."); + } + { + var result = + await TokenContractImplStub.ChangeTokenIssuer.SendWithExceptionAsync(new ChangeTokenIssuerInput()); + result.TransactionResult.Error.ShouldContain("Invalid input symbol."); + } + { + var result = await TokenContractImplStub.ChangeTokenIssuer.SendWithExceptionAsync(new ChangeTokenIssuerInput + { + Symbol = NativeTokenSymbol + }); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = + await TokenContractImplStub.ResetExternalInfo.SendWithExceptionAsync(new ResetExternalInfoInput()); + result.TransactionResult.Error.ShouldContain("Invalid input symbol."); + } + { + var result = + await TokenContractImplStub.SetTransactionFeeDelegations.SendWithExceptionAsync( + new SetTransactionFeeDelegationsInput()); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = + await TokenContractImplStub.SetTransactionFeeDelegations.SendWithExceptionAsync( + new SetTransactionFeeDelegationsInput()); + result.TransactionResult.Error.ShouldContain("Invalid input address."); + } + { + var result = + await TokenContractImplStub.UpdateCoefficientsForContract.SendWithExceptionAsync( + new UpdateCoefficientsInput()); + result.TransactionResult.Error.ShouldContain("Invalid input coefficients."); + } + { + var result = + await TokenContractImplStub.UpdateCoefficientsForSender.SendWithExceptionAsync( + new UpdateCoefficientsInput()); + result.TransactionResult.Error.ShouldContain("Invalid input coefficients."); + } + } + private async Task IssueTokenListToUserAsync(List symbols, long amount, Address address) { foreach (var symbol in symbols) @@ -2464,47 +2598,6 @@ private async Task IssueTokenToUserAsync(string tokenSymbol, long amount, Addres issueResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } -// single node - private async Task SubmitAndPassProposalOfDefaultParliamentAsync(Address contractAddress, string methodName, - IMessage input) - { - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = new CreateProposalInput - { - OrganizationAddress = defaultParliament, - ToAddress = contractAddress, - Params = input.ToByteString(), - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var createProposalRet = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - createProposalRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = createProposalRet.Output; - await ParliamentContractStub.Approve.SendAsync(proposalId); - var releaseRet = await ParliamentContractStub.Release.SendAsync(proposalId); - releaseRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - } - - private async Task SubmitProposalOfDefaultParliamentAsync(Address contractAddress, string methodName, - IMessage input) - { - var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); - var proposal = new CreateProposalInput - { - OrganizationAddress = defaultParliament, - ToAddress = contractAddress, - Params = input.ToByteString(), - ContractMethodName = methodName, - ExpiredTime = TimestampHelper.GetUtcNow().AddHours(1) - }; - var createProposalRet = await ParliamentContractStub.CreateProposal.SendAsync(proposal); - createProposalRet.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - var proposalId = createProposalRet.Output; - await ParliamentContractStub.Approve.SendAsync(proposalId); - var releaseRet = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); - return releaseRet.TransactionResult.Error; - } - private async Task GetBalanceAsync(Address address, string tokenSymbol) { var balance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput From fed69938a6586b4e9631436445dacc77c9f80698 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Wed, 5 Jul 2023 09:50:39 +0800 Subject: [PATCH 127/139] feat: handle format exception --- .../Services/TransactionResultAppService.cs | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs b/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs index f8bb29f461..08552f42e5 100644 --- a/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs +++ b/src/AElf.WebApp.Application.Chain/Services/TransactionResultAppService.cs @@ -309,28 +309,11 @@ private async Task FormatTransactionParamsAsync(TransactionDto transaction, Byte try { var parameters = methodDescriptor.InputType.Parser.ParseFrom(@params); - if (!TryFormatToJsonString(parameters, out var paramsJson)) - throw new UserFriendlyException(Error.Message[Error.InvalidParams], Error.InvalidParams.ToString()); - transaction.Params = paramsJson; + transaction.Params = JsonFormatter.ToDiagnosticString(parameters);; } - catch (Exception exception) when (exception is not UserFriendlyException) + catch (Exception exception) { Logger.LogError(exception, "Failed to parse transaction params: {params}", transaction.Params); } } - - private bool TryFormatToJsonString(IMessage message, out string json) - { - try - { - json = JsonFormatter.ToDiagnosticString(message); - } - catch - { - json = string.Empty; - return false; - } - - return true; - } } \ No newline at end of file From a6b02eb9b5196e165854f5849f6c0b5f42aa5b49 Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 6 Jul 2023 10:03:44 +0800 Subject: [PATCH 128/139] fix: remove redundant --- contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs index 238abd7712..25f853ec11 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Fees.cs @@ -287,12 +287,6 @@ private bool ChargeTransactionFeesToBill(ChargeTransactionFeesInput input, Addre return false; } - //For delegation, if the base fee fails to be charged, the size fee will not be charged - if (delegations != null && !successToChargeBaseFee) - { - return false; - } - var successToChargeSizeFee = true; if (!isSizeFeeFree) { From e5f32a66e2a40c648b87137c47a3837678a99c53 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 10 Jul 2023 18:12:35 +0800 Subject: [PATCH 129/139] feat: add Owner and fix ut --- .../CrossChainContract_Helper.cs | 3 +- .../EconomicContract.cs | 9 +- .../ElectionContract_Elector.cs | 2 +- .../TokenContract_Actions.cs | 44 +-- .../TokenContract_Helper.cs | 1 + .../TokenContract_NFT_Actions.cs | 16 +- protobuf/token_contract.proto | 19 +- protobuf/token_contract_impl.proto | 4 +- .../TokenContractInitializationProvider.cs | 3 +- .../SideChainSideChainRentFeeTest.cs | 3 +- .../AssociationContractTests.cs | 3 +- .../ConfigurationContractTest.cs | 3 +- .../ConfigurationContractTestBase.cs | 6 +- .../BVT/ACS10ImplTest.cs | 3 +- .../CrossChainContractTestBase.cs | 3 +- .../ContractsPreparation.cs | 3 +- .../BVT/TreasuryBasicTests.cs | 6 +- .../BVT/NftApplicationTests.cs | 263 ++++++++---------- .../BVT/TokenApplicationTests.cs | 67 +---- .../BVT/TokenDelegationTest.cs | 1 + .../BVT/TokenEconomicTests.cs | 6 +- .../BVT/TokenManagementTests.cs | 9 +- .../MultiTokenContractTestBase.cs | 3 +- .../MultiTokenContractReferenceFeeTest.cs | 18 +- .../ParliamentContractTestBase.cs | 3 +- .../ReferendumContractTest.cs | 6 +- .../TestContractTestBase.cs | 6 +- .../ExecutePluginTransactionDirectlyTest.cs | 18 +- ...TestTokenContractInitializationProvider.cs | 3 +- test/AElf.OS.TestBase/OSTestHelper.cs | 6 +- 30 files changed, 231 insertions(+), 309 deletions(-) diff --git a/contract/AElf.Contracts.CrossChain/CrossChainContract_Helper.cs b/contract/AElf.Contracts.CrossChain/CrossChainContract_Helper.cs index 9ae9dac72b..5f01430998 100644 --- a/contract/AElf.Contracts.CrossChain/CrossChainContract_Helper.cs +++ b/contract/AElf.Contracts.CrossChain/CrossChainContract_Helper.cs @@ -189,7 +189,8 @@ private void CreateSideChainToken(SideChainCreationRequest sideChainCreationRequ Issuer = creator, IssueChainId = chainId, Symbol = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenSymbol, - TotalSupply = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenTotalSupply + TotalSupply = sideChainCreationRequest.SideChainTokenCreationRequest.SideChainTokenTotalSupply, + Owner = creator }); } diff --git a/contract/AElf.Contracts.Economic/EconomicContract.cs b/contract/AElf.Contracts.Economic/EconomicContract.cs index f9c0fbe353..e971433777 100644 --- a/contract/AElf.Contracts.Economic/EconomicContract.cs +++ b/contract/AElf.Contracts.Economic/EconomicContract.cs @@ -59,7 +59,8 @@ private void CreateNativeToken(InitialEconomicSystemInput input) Decimals = input.NativeTokenDecimals, IsBurnable = input.IsNativeTokenBurnable, Issuer = Context.Self, - LockWhiteList = { lockWhiteList } + LockWhiteList = { lockWhiteList }, + Owner = Context.Self }); State.TokenContract.SetPrimaryTokenSymbol.Send(new SetPrimaryTokenSymbolInput @@ -88,7 +89,8 @@ private void CreateResourceTokens() Decimals = EconomicContractConstants.ResourceTokenDecimals, Issuer = Context.Self, LockWhiteList = { lockWhiteList }, - IsBurnable = true + IsBurnable = true, + Owner = Context.Self }); State.TokenContract.Issue.Send(new IssueInput @@ -120,7 +122,8 @@ private void CreateElectionTokens() Decimals = EconomicContractConstants.ElectionTokenDecimals, Issuer = Context.Self, IsBurnable = true, - LockWhiteList = { lockWhiteList } + LockWhiteList = { lockWhiteList }, + Owner = Context.Self }); State.TokenContract.Issue.Send(new IssueInput { diff --git a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs index 1cb2b933a7..eaf28224fe 100644 --- a/contract/AElf.Contracts.Election/ElectionContract_Elector.cs +++ b/contract/AElf.Contracts.Election/ElectionContract_Elector.cs @@ -324,7 +324,7 @@ private void AssertValidLockSeconds(long lockSeconds) Assert(lockSeconds <= State.MaximumLockTime.Value, $"Invalid lock time. At most {State.MaximumLockTime.Value.Div(60).Div(60).Div(24)} days"); } - + private void LockTokensOfVoter(long amount, Hash voteId) { State.TokenContract.Lock.Send(new LockInput diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 1d51f41935..49ee4de9d3 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -69,7 +69,8 @@ private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType. Issuer = input.Issuer, IsBurnable = input.IsBurnable, IssueChainId = input.IssueChainId == 0 ? Context.ChainId : input.IssueChainId, - ExternalInfo = input.ExternalInfo ?? new ExternalInfo() + ExternalInfo = input.ExternalInfo ?? new ExternalInfo(), + Owner = input.Owner }; RegisterTokenInfo(tokenInfo); if (string.IsNullOrEmpty(State.NativeTokenSymbol.Value)) @@ -94,7 +95,8 @@ private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType. Issuer = tokenInfo.Issuer, IsBurnable = tokenInfo.IsBurnable, IssueChainId = tokenInfo.IssueChainId, - ExternalInfo = tokenInfo.ExternalInfo + ExternalInfo = tokenInfo.ExternalInfo, + Owner = tokenInfo.Owner }); return new Empty(); @@ -408,7 +410,7 @@ public override Empty ValidateTokenInfoExists(ValidateTokenInfoExistsInput input var validationResult = tokenInfo.TokenName == input.TokenName && tokenInfo.IsBurnable == input.IsBurnable && tokenInfo.Decimals == input.Decimals && tokenInfo.Issuer == input.Issuer && tokenInfo.TotalSupply == input.TotalSupply && - tokenInfo.IssueChainId == input.IssueChainId; + tokenInfo.IssueChainId == input.IssueChainId && tokenInfo.Owner == input.Owner; if (tokenInfo.ExternalInfo != null && tokenInfo.ExternalInfo.Value.Count > 0 || input.ExternalInfo != null && input.ExternalInfo.Count > 0) @@ -423,36 +425,6 @@ public override Empty ValidateTokenInfoExists(ValidateTokenInfoExistsInput input return new Empty(); } - public override Empty ChangeTokenIssuer(ChangeTokenIssuerInput input) - { - Assert(!string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol."); - AssertValidInputAddress(input.NewTokenIssuer); - - var tokenInfo = State.TokenInfos[input.Symbol]; - Assert(tokenInfo != null, $"invalid token symbol: {input.Symbol}"); - // ReSharper disable once PossibleNullReferenceException - Assert(tokenInfo.Issuer == Context.Sender && tokenInfo.IssueChainId == Context.ChainId, - "Permission denied"); - tokenInfo.Issuer = input.NewTokenIssuer; - State.TokenInfos[input.Symbol] = tokenInfo; - return new Empty(); - } - - public override Empty ResetExternalInfo(ResetExternalInfoInput input) - { - Assert(!string.IsNullOrWhiteSpace(input.Symbol), "Invalid input symbol."); - var tokenInfo = State.TokenInfos[input.Symbol]; - Assert(tokenInfo.Issuer == Context.Sender, "No permission to reset external info."); - tokenInfo.ExternalInfo = input.ExternalInfo; - State.TokenInfos[input.Symbol] = tokenInfo; - Context.Fire(new ExternalInfoChanged - { - Symbol = input.Symbol, - ExternalInfo = input.ExternalInfo - }); - return new Empty(); - } - public override Empty AddAddressToCreateTokenWhiteList(Address input) { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); @@ -492,7 +464,8 @@ public override Empty CrossChainCreateToken(CrossChainCreateTokenInput input) Issuer = validateTokenInfoExistsInput.Issuer, IsBurnable = validateTokenInfoExistsInput.IsBurnable, IssueChainId = validateTokenInfoExistsInput.IssueChainId, - ExternalInfo = new ExternalInfo { Value = { validateTokenInfoExistsInput.ExternalInfo } } + ExternalInfo = new ExternalInfo { Value = { validateTokenInfoExistsInput.ExternalInfo } }, + Owner = validateTokenInfoExistsInput.Owner }; RegisterTokenInfo(tokenInfo); @@ -505,7 +478,8 @@ public override Empty CrossChainCreateToken(CrossChainCreateTokenInput input) Issuer = validateTokenInfoExistsInput.Issuer, IsBurnable = validateTokenInfoExistsInput.IsBurnable, IssueChainId = validateTokenInfoExistsInput.IssueChainId, - ExternalInfo = new ExternalInfo { Value = { validateTokenInfoExistsInput.ExternalInfo } } + ExternalInfo = new ExternalInfo { Value = { validateTokenInfoExistsInput.ExternalInfo } }, + Owner = validateTokenInfoExistsInput.Owner }); return new Empty(); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 10d3bd5160..e8bbf1f8fc 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -189,6 +189,7 @@ private void RegisterTokenInfo(TokenInfo tokenInfo) Assert(!string.IsNullOrEmpty(tokenInfo.TokenName), "Token name can neither be null nor empty."); Assert(tokenInfo.TotalSupply > 0, "Invalid total supply."); Assert(tokenInfo.Issuer != null, "Invalid issuer address."); + Assert(tokenInfo.Owner != null, "Invalid owner address."); State.TokenInfos[tokenInfo.Symbol] = tokenInfo; } diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 12cd89468f..2b004d0c9b 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -20,12 +20,20 @@ private Empty CreateNFTInfo(CreateInput input) input.IssueChainId = input.IssueChainId == 0 ? nftCollectionInfo.IssueChainId : input.IssueChainId; Assert(input.IssueChainId == nftCollectionInfo.IssueChainId, "NFT create ChainId must be collection's issue chainId"); - Assert(Context.Sender == nftCollectionInfo.Issuer && nftCollectionInfo.Issuer == input.Issuer, - "NFT issuer must be collection's issuer"); + if (nftCollectionInfo.Owner == null) + { + Assert(Context.Sender == nftCollectionInfo.Issuer && nftCollectionInfo.Issuer == input.Issuer, + "NFT issuer must be collection's issuer"); + } + else + { + Assert(Context.Sender == nftCollectionInfo.Owner && nftCollectionInfo.Owner == input.Owner, + "NFT owner must be collection's owner"); + } + if (nftCollectionInfo.Symbol == TokenContractConstants.SeedCollectionSymbol) { - Assert( - input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, + Assert(input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, out var ownedSymbol), "OwnedSymbol does not exist."); Assert(input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, out var expirationTime) diff --git a/protobuf/token_contract.proto b/protobuf/token_contract.proto index aad7866615..5082990a99 100644 --- a/protobuf/token_contract.proto +++ b/protobuf/token_contract.proto @@ -57,10 +57,6 @@ service TokenContract { rpc Burn (BurnInput) returns (google.protobuf.Empty) { } - // Change the issuer of the specified token. Only the original issuer can change it. - rpc ChangeTokenIssuer (ChangeTokenIssuerInput) returns (google.protobuf.Empty) { - } - // Set the primary token of side chain. rpc SetPrimaryTokenSymbol (SetPrimaryTokenSymbolInput) returns (google.protobuf.Empty) { } @@ -131,9 +127,6 @@ service TokenContract { rpc InitializeAuthorizedController (google.protobuf.Empty) returns (google.protobuf.Empty){ } - rpc ResetExternalInfo (ResetExternalInfoInput) returns (google.protobuf.Empty){ - } - rpc AddAddressToCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) { } rpc RemoveAddressFromCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) { @@ -246,7 +239,7 @@ message TokenInfo { int64 total_supply = 4; // The precision of the token. int32 decimals = 5; - // The address that created the token. + // The address that has permission to issue the token. aelf.Address issuer = 6; // A flag indicating if this token is burnable. bool is_burnable = 7; @@ -256,6 +249,8 @@ message TokenInfo { int64 issued = 9; // The external information of the token. ExternalInfo external_info = 10; + // The address that owns the token. + aelf.Address owner = 11; } message ExternalInfo { @@ -271,7 +266,7 @@ message CreateInput { int64 total_supply = 3; // The precision of the token int32 decimals = 4; - // The address that created the token. + // The address that has permission to issue the token. aelf.Address issuer = 5; // A flag indicating if this token is burnable. bool is_burnable = 6; @@ -281,6 +276,8 @@ message CreateInput { int32 issue_chain_id = 8; // The external information of the token. ExternalInfo external_info = 9; + // The address that owns the token. + aelf.Address owner = 10; } message SetPrimaryTokenSymbolInput { @@ -792,7 +789,7 @@ message TokenCreated { int64 total_supply = 3; // The precision of the token. int32 decimals = 4; - // The address that created the token. + // The address that has permission to issue the token. aelf.Address issuer = 5; // A flag indicating if this token is burnable. bool is_burnable = 6; @@ -800,6 +797,8 @@ message TokenCreated { int32 issue_chain_id = 7; // The external information of the token. ExternalInfo external_info = 8; + // The address that owns the token. + aelf.Address owner = 9; } message Issued { diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index e2a6bd1fb8..97acd5b439 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -205,7 +205,7 @@ message ValidateTokenInfoExistsInput{ int64 total_supply = 3; // The precision of the token. int32 decimals = 4; - // The address that created the token. + // The address that has permission to issue the token. aelf.Address issuer = 5; // A flag indicating if this token is burnable. bool is_burnable = 6; @@ -213,6 +213,8 @@ message ValidateTokenInfoExistsInput{ int32 issue_chain_id = 7; // The external information of the token. map external_info = 8; + // The address that owns the token. + aelf.Address owner = 9; } message UpdateRentalInput { diff --git a/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs b/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs index 7fa7bd32b6..86cb6cf208 100644 --- a/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs +++ b/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs @@ -138,7 +138,8 @@ private CreateInput GenerateTokenCreateInput(TokenInfo tokenInfo, Address issuer IsBurnable = tokenInfo.IsBurnable, Symbol = tokenInfo.Symbol, TokenName = tokenInfo.TokenName, - TotalSupply = tokenInfo.TotalSupply + TotalSupply = tokenInfo.TotalSupply, + Owner = issuer ?? tokenInfo.Issuer }; } } \ No newline at end of file diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs index 7fb41a95ab..ef56dc42c5 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainSideChainRentFeeTest.cs @@ -342,7 +342,8 @@ await ParliamentReachAnAgreementAsync(TokenContractAddress, organizationAddress, Symbol = symbol, TotalSupply = supply, IsBurnable = true, - TokenName = $"{symbol} token." + TokenName = $"{symbol} token.", + Owner = Creator }); if (!issueToken) return; diff --git a/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs b/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs index f8c1c4079b..ff344d4e20 100644 --- a/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs +++ b/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs @@ -952,7 +952,8 @@ public async Task SetMethodFee_Fail_Test() Symbol = tokenSymbol, TokenName = "name", Issuer = DefaultSender, - TotalSupply = 1000_000 + TotalSupply = 1000_000, + Owner = DefaultSender }); await ApproveWithMinersAsync(proposalId); diff --git a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs index f7af112853..f0876ac70f 100644 --- a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs +++ b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTest.cs @@ -352,7 +352,8 @@ await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, Symbol = tokenSymbol, TokenName = "name", Issuer = TokenContractAddress, - TotalSupply = 1000_000 + TotalSupply = 1000_000, + Owner = TokenContractAddress }); var result = await Tester.ExecuteContractWithMiningAsync(ConfigurationContractAddress, diff --git a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs index 1dfc74d86b..e15bd44ad2 100644 --- a/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs +++ b/test/AElf.Contracts.Configuration.Tests/ConfigurationContractTestBase.cs @@ -182,7 +182,8 @@ await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, TokenName = "seed Collection", TotalSupply = 1, Issuer = Tester.GetCallOwnerAddress(), - ExternalInfo = new ExternalInfo() + ExternalInfo = new ExternalInfo(), + Owner = Tester.GetCallOwnerAddress() }); await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, nameof(TokenContractContainer.TokenContractStub.Create), @@ -202,7 +203,8 @@ await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, { "__seed_exp_time", TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString() } } }, - LockWhiteList = { TokenContractAddress } + LockWhiteList = { TokenContractAddress }, + Owner = Tester.GetCallOwnerAddress() }); await Tester.ExecuteContractWithMiningAsync(TokenContractAddress, diff --git a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs index ce36388c2e..80a823f031 100644 --- a/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs +++ b/test/AElf.Contracts.Consensus.AEDPoS.Tests/BVT/ACS10ImplTest.cs @@ -56,7 +56,8 @@ private async Task CreateTokenAsync(string symbol) Symbol = symbol, TokenName = "name", TotalSupply = 1000_000_000, - Issuer = BootMinerAddress + Issuer = BootMinerAddress, + Owner = BootMinerAddress }); await ApproveWithMinersAsync(proposalId); var result = await ParliamentContractStub.Release.SendAsync(proposalId); diff --git a/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs b/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs index a47840028c..dd09f11b48 100644 --- a/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs +++ b/test/AElf.Contracts.CrossChain.Tests/CrossChainContractTestBase.cs @@ -171,7 +171,8 @@ private async Task InitializeTokenAsync() IsBurnable = true, TokenName = "elf token", TotalSupply = totalSupply, - Issuer = DefaultSender + Issuer = DefaultSender, + Owner = DefaultSender }, TokenContractAddress); await ApproveWithMinersAsync(approveProposalId); await ParliamentContractStub.Release.SendAsync(approveProposalId); diff --git a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs index 6c2f5a9152..cde20e76c9 100644 --- a/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs +++ b/test/AElf.Contracts.Economic.TestBase/ContractsPreparation.cs @@ -535,7 +535,8 @@ await ExecuteProposalForParliamentTransaction(TokenContractAddress, { TokenConverterContractAddress, TreasuryContractAddress - } + }, + Owner = BootMinerAddress }); await TokenContractStub.Issue.SendAsync(new IssueInput { diff --git a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs index 57d3d0b778..24fc9e63d0 100644 --- a/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs +++ b/test/AElf.Contracts.EconomicSystem.Tests/BVT/TreasuryBasicTests.cs @@ -281,7 +281,8 @@ public async Task Treasury_SetSymbolList_With_Invalid_Token_Test() TokenName = "TEST name", TotalSupply = 1_0000_0000, Issuer = BootMinerAddress, - IsBurnable = true + IsBurnable = true, + Owner = BootMinerAddress }; await ExecuteProposalForParliamentTransactionWithException(Tester, TokenContractAddress, nameof(TokenContractStub.Create), tokenCreateInput); @@ -328,7 +329,8 @@ public async Task Treasury_SetSymbolList_Success_Test() TokenName = "CWJ name", TotalSupply = 1_0000_0000, Issuer = BootMinerAddress, - IsBurnable = true + IsBurnable = true, + Owner = BootMinerAddress }; await ExecuteProposalForParliamentTransaction(TokenContractAddress, nameof(TokenContractStub.Create), tokenCreateInput); diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs index 3f4e0f6ece..460ed2f108 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs @@ -46,7 +46,8 @@ public partial class MultiTokenContractTests "https://i.seadn.io/gcs/files/0f5cdfaaf687de2ebb5834b129a5bef3.png?auto=format&w=3840" } } - } + }, + Owner = Accounts[0].Address }; private TokenInfo NftCollection1155Info => new() @@ -138,7 +139,8 @@ private async Task> CreateNftAsync(string colllectionSym Issuer = nftInfo.Issuer, IsBurnable = nftInfo.IsBurnable, IssueChainId = nftInfo.IssueChainId, - ExternalInfo = nftInfo.ExternalInfo + ExternalInfo = nftInfo.ExternalInfo, + Owner = nftInfo.Issuer }); } @@ -220,7 +222,8 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() Decimals = 8, Issuer = input.Issuer, IssueChainId = input.IssueChainId, - ExternalInfo = input.ExternalInfo + ExternalInfo = input.ExternalInfo, + Owner = input.Owner }); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); result.TransactionResult.Error.ShouldContain("NFT's decimals must be 0"); @@ -235,7 +238,8 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() Decimals = input.Decimals, Issuer = input.Issuer, IssueChainId = input.IssueChainId, - ExternalInfo = input.ExternalInfo + ExternalInfo = input.ExternalInfo, + Owner = input.Owner }); var result = await TokenContractStub.Create.SendWithExceptionAsync(seedInput);; @@ -252,7 +256,8 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() Decimals = input.Decimals, Issuer = input.Issuer, IssueChainId = input.IssueChainId, - ExternalInfo = input.ExternalInfo + ExternalInfo = input.ExternalInfo, + Owner = input.Owner }); var result = await TokenContractStub.Create.SendWithExceptionAsync(seedInput);; result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); @@ -351,7 +356,8 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() Decimals = input.Decimals, Issuer = Accounts.Last().Address, IssueChainId = input.IssueChainId, - ExternalInfo = input.ExternalInfo + ExternalInfo = input.ExternalInfo, + Owner = input.Owner }); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); result.TransactionResult.Error.ShouldContain("NFT issuer must be collection's issuer"); @@ -365,7 +371,8 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() Decimals = input.Decimals, Issuer = input.Issuer, IssueChainId = ChainHelper.ConvertBase58ToChainId("tDVV"), - ExternalInfo = input.ExternalInfo + ExternalInfo = input.ExternalInfo, + Owner = input.Owner }); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); result.TransactionResult.Error.ShouldContain("NFT create ChainId must be collection's issue chainId"); @@ -384,7 +391,8 @@ public async Task MultiTokenContract_Create_NFT_Collection_NotExist() Decimals = input.Decimals, Issuer = input.Issuer, IssueChainId = input.IssueChainId, - ExternalInfo = input.ExternalInfo + ExternalInfo = input.ExternalInfo, + Owner = input.Owner }); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); result.TransactionResult.Error.ShouldContain("NFT collection not exist"); @@ -403,7 +411,8 @@ public async Task MultiTokenContract_Create_NFT_Already_Exist() Decimals = input.Decimals, Issuer = input.Issuer, IssueChainId = input.IssueChainId, - ExternalInfo = input.ExternalInfo + ExternalInfo = input.ExternalInfo, + Owner = input.Owner }); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); result.TransactionResult.Error.ShouldContain("Token already exists."); @@ -673,38 +682,6 @@ public async Task NftIssue_Approve_TransferFrom() ownerBalanceOutput.Balance.ShouldBe(90); } - [Fact(DisplayName = "[seed-nft] ResetExternalInfo Test")] - public async Task ResetExternalInfoInputTest() - { - var createInput = await CreateSeedNftAsync(TokenContractStub, new CreateInput - { - Issuer = DefaultAddress, - Symbol = "XYZ" - }); - - var symbol = createInput.Symbol; - createInput.ExternalInfo.Value["__seed_exp_time"] = "1234"; - // permission check - var exceptionRes = await TokenContractStubUser.ResetExternalInfo.SendWithExceptionAsync( - new ResetExternalInfoInput - { - Symbol = createInput.Symbol, - ExternalInfo = createInput.ExternalInfo - }); - exceptionRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - exceptionRes.TransactionResult.Error.ShouldContain("No permission to reset external info"); - var result = await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() - { - Symbol = createInput.Symbol, - ExternalInfo = createInput.ExternalInfo - }); - var tokenInfoRs = await TokenContractStub.GetTokenInfo.SendAsync(new GetTokenInfoInput - { - Symbol = symbol, - }); - tokenInfoRs.Output.ExternalInfo.Value["__seed_exp_time"].ShouldBe("1234"); - } - [Fact(DisplayName = "[token] create Test")] public async Task CreateTokenTest() { @@ -794,108 +771,108 @@ public async Task CreateTokenTest() nftSuccessAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } - [Fact(DisplayName = "[feed nft] create Test")] - public async Task FeedNftCreateTest() - { - // symbol expire reCreate success - var createInput = await CreateSeedNftAsync(TokenContractStub, new CreateInput - { - Issuer = DefaultAddress, - Symbol = "XYZ-0" - }); - - createInput.ExternalInfo.Value["__seed_exp_time"] = "1234"; - await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() - { - Symbol = createInput.Symbol, - ExternalInfo = createInput.ExternalInfo - }); - - var input = BuildSeedCreateInput(new CreateInput - { - Issuer = DefaultAddress, - Symbol = "XYZ-0" - }); - var seedRes = await TokenContractStub.Create.SendAsync(input); - seedRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); - - // owner doesn't own enough balance - var nftAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); - nftAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - nftAsync.TransactionResult.Error.ShouldContain("Seed NFT balance is not enough"); - // ExternalInfo check - await TokenContractStub.Issue.SendAsync(new IssueInput - { - Symbol = input.Symbol, - Amount = 1, - Memo = "ddd", - To = DefaultAddress - }); - input.ExternalInfo.Value["__seed_owned_symbol"] = "XY-0"; - - await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() - { - Symbol = input.Symbol, - ExternalInfo = input.ExternalInfo - }); - var inconsistentExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); - inconsistentExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - inconsistentExceptionAsync.TransactionResult.Error.ShouldContain( - "Invalid OwnedSymbol"); - - input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; - input.ExternalInfo.Value["__seed_exp_time"] = ""; - await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() - { - Symbol = input.Symbol, - ExternalInfo = input.ExternalInfo - }); - var expireExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync( - GetCreateInput()); - expireExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - expireExceptionAsync.TransactionResult.Error.ShouldContain("OwnedSymbol is expired"); - - input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; - input.ExternalInfo.Value["__seed_exp_time"] = "1234"; - await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() - { - Symbol = input.Symbol, - ExternalInfo = input.ExternalInfo - }); - var expireExceptionAsync1 = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); - expireExceptionAsync1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - expireExceptionAsync1.TransactionResult.Error.ShouldContain("OwnedSymbol is expired"); - await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput - { - Symbol = input.Symbol, - ExternalInfo = new ExternalInfo() - }); - var emptyExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); - emptyExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - emptyExceptionAsync.TransactionResult.Error.ShouldContain("Invalid OwnedSymbol"); - input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; - input.ExternalInfo.Value["__seed_exp_time"] = TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString(); - await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput - { - Symbol = input.Symbol, - ExternalInfo = input.ExternalInfo - }); - var re = await SubmitAndApproveProposalOfDefaultParliamentWithException(TokenContractAddress, - nameof(TokenContractStub.Create), new CreateInput - { - Symbol = "XYZ-0", - Decimals = 0, - IsBurnable = true, - TokenName = "ELF2", - TotalSupply = 100_000_000_000_000_000L, - Issuer = DefaultAddress, - ExternalInfo = new ExternalInfo() - }); - re.TransactionResult.Error.ShouldContain("OwnedSymbol has been created"); - re.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - - - } + // [Fact(DisplayName = "[feed nft] create Test")] + // public async Task FeedNftCreateTest() + // { + // // symbol expire reCreate success + // var createInput = await CreateSeedNftAsync(TokenContractStub, new CreateInput + // { + // Issuer = DefaultAddress, + // Symbol = "XYZ-0" + // }); + // + // createInput.ExternalInfo.Value["__seed_exp_time"] = "1234"; + // await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + // { + // Symbol = createInput.Symbol, + // ExternalInfo = createInput.ExternalInfo + // }); + // + // var input = BuildSeedCreateInput(new CreateInput + // { + // Issuer = DefaultAddress, + // Symbol = "XYZ-0" + // }); + // var seedRes = await TokenContractStub.Create.SendAsync(input); + // seedRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + // + // // owner doesn't own enough balance + // var nftAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); + // nftAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + // nftAsync.TransactionResult.Error.ShouldContain("Seed NFT balance is not enough"); + // // ExternalInfo check + // await TokenContractStub.Issue.SendAsync(new IssueInput + // { + // Symbol = input.Symbol, + // Amount = 1, + // Memo = "ddd", + // To = DefaultAddress + // }); + // input.ExternalInfo.Value["__seed_owned_symbol"] = "XY-0"; + // + // await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + // { + // Symbol = input.Symbol, + // ExternalInfo = input.ExternalInfo + // }); + // var inconsistentExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); + // inconsistentExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + // inconsistentExceptionAsync.TransactionResult.Error.ShouldContain( + // "Invalid OwnedSymbol"); + // + // input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; + // input.ExternalInfo.Value["__seed_exp_time"] = ""; + // await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + // { + // Symbol = input.Symbol, + // ExternalInfo = input.ExternalInfo + // }); + // var expireExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync( + // GetCreateInput()); + // expireExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + // expireExceptionAsync.TransactionResult.Error.ShouldContain("OwnedSymbol is expired"); + // + // input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; + // input.ExternalInfo.Value["__seed_exp_time"] = "1234"; + // await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput() + // { + // Symbol = input.Symbol, + // ExternalInfo = input.ExternalInfo + // }); + // var expireExceptionAsync1 = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); + // expireExceptionAsync1.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + // expireExceptionAsync1.TransactionResult.Error.ShouldContain("OwnedSymbol is expired"); + // await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput + // { + // Symbol = input.Symbol, + // ExternalInfo = new ExternalInfo() + // }); + // var emptyExceptionAsync = await TokenContractStub.Create.SendWithExceptionAsync(GetCreateInput()); + // emptyExceptionAsync.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + // emptyExceptionAsync.TransactionResult.Error.ShouldContain("Invalid OwnedSymbol"); + // input.ExternalInfo.Value["__seed_owned_symbol"] = "XYZ-0"; + // input.ExternalInfo.Value["__seed_exp_time"] = TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString(); + // await TokenContractStub.ResetExternalInfo.SendAsync(new ResetExternalInfoInput + // { + // Symbol = input.Symbol, + // ExternalInfo = input.ExternalInfo + // }); + // var re = await SubmitAndApproveProposalOfDefaultParliamentWithException(TokenContractAddress, + // nameof(TokenContractStub.Create), new CreateInput + // { + // Symbol = "XYZ-0", + // Decimals = 0, + // IsBurnable = true, + // TokenName = "ELF2", + // TotalSupply = 100_000_000_000_000_000L, + // Issuer = DefaultAddress, + // ExternalInfo = new ExternalInfo() + // }); + // re.TransactionResult.Error.ShouldContain("OwnedSymbol has been created"); + // re.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + // + // + // } private CreateInput GetCreateInput() { diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index 724b2b45c1..4292cededb 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -942,67 +942,6 @@ await BasicFunctionContractStub.TransferTokenToContract.SendAsync( afterBalance.Balance.ShouldBe(beforeBalance.Balance.Add(transferAmount)); } - [Fact(DisplayName = "[MultiToken] ChangeTokenIssuer test")] - public async Task ChangeTokenIssuer_Test() - { - const string tokenSymbol = "PO"; - await CreateMutiTokenAsync(TokenContractStub, new CreateInput - { - Symbol = tokenSymbol, - TokenName = "Name", - TotalSupply = 100_000_000_000L, - Decimals = 10, - IsBurnable = true, - Issuer = Accounts[1].Address - }); - var tokenIssuerStub = - GetTester(TokenContractAddress, Accounts[1].KeyPair); - - { - var issueNotExistTokenRet = await tokenIssuerStub.ChangeTokenIssuer.SendWithExceptionAsync( - new ChangeTokenIssuerInput - { - Symbol = "NOTEXIST", - NewTokenIssuer = Accounts[2].Address - }); - issueNotExistTokenRet.TransactionResult.Error.ShouldContain("invalid token symbol"); - } - { - await tokenIssuerStub.ChangeTokenIssuer.SendAsync(new ChangeTokenIssuerInput - { - Symbol = tokenSymbol, - NewTokenIssuer = Accounts[2].Address - }); - var tokenInfo = await tokenIssuerStub.GetTokenInfo.CallAsync(new GetTokenInfoInput - { - Symbol = tokenSymbol - }); - tokenInfo.Issuer.ShouldBe(Accounts[2].Address); - } - } - - [Fact(DisplayName = "[MultiToken] sender is not the token issuer")] - public async Task ChangeTokenIssuer_Without_Authorization_Test() - { - const string tokenSymbol = "PO"; - await CreateMutiTokenAsync(TokenContractStub, new CreateInput - { - Symbol = tokenSymbol, - TokenName = "Name", - TotalSupply = 100_000_000_000L, - Decimals = 10, - IsBurnable = true, - Issuer = Accounts[1].Address - }); - var changeIssuerRet = await TokenContractStub.ChangeTokenIssuer.SendWithExceptionAsync( - new ChangeTokenIssuerInput - { - Symbol = tokenSymbol, - NewTokenIssuer = Accounts[2].Address - }); - changeIssuerRet.TransactionResult.Error.ShouldContain("permission denied"); - } - [Fact(DisplayName = "[MultiToken] Token initialize from parent chain test")] public async Task InitializeFromParent_Test() { @@ -1064,7 +1003,8 @@ public async Task Side_Chain_Creat_Token_Test() TokenName = "Ali", Decimals = 4, TotalSupply = 100_000, - Issuer = DefaultAddress + Issuer = DefaultAddress, + Owner = DefaultAddress }); createTokenRet.TransactionResult.Error.ShouldContain( "Failed to create token if side chain creator already set."); @@ -1256,7 +1196,8 @@ public async Task CrossContractCreateToken_Test() TotalSupply = 1, Issuer = DefaultAddress, ExternalInfo = new ExternalInfo(), - LockWhiteList = { TokenContractAddress } + LockWhiteList = { TokenContractAddress }, + Owner = DefaultAddress }; input.ExternalInfo.Value["__seed_owned_symbol"] = createTokenInput.Symbol; input.ExternalInfo.Value["__seed_exp_time"] = TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString(); diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs index f57f3e560f..8b690c7afd 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs @@ -275,6 +275,7 @@ await TokenContractStub.Create.SendAsync(new CreateInput Decimals = NativeTokenInfo.Decimals, Issuer = NativeTokenInfo.Issuer, IsBurnable = NativeTokenInfo.IsBurnable, + Owner = NativeTokenInfo.Owner }); } diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenEconomicTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenEconomicTests.cs index d35af8163a..89ab1cce32 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenEconomicTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenEconomicTests.cs @@ -18,7 +18,8 @@ await TokenContractStub.Create.SendAsync(new CreateInput TokenName = "elf token", TotalSupply = totalSupply, Issuer = DefaultAddress, - LockWhiteList = { TreasuryContractAddress } + LockWhiteList = { TreasuryContractAddress }, + Owner = DefaultAddress }); await TokenContractStub.Issue.SendAsync(new IssueInput { @@ -51,7 +52,8 @@ await TreasuryContractStub.InitialMiningRewardProfitItem.SendAsync( { ParliamentContractAddress, TreasuryContractAddress - } + }, + Owner = DefaultAddress })).TransactionResult; } diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs index 4cb13a561c..ac014867e4 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs @@ -50,7 +50,8 @@ public MultiTokenContractTests() IsBurnable = true, Issuer = Accounts[0].Address, Supply = 0, - IssueChainId = _chainId + IssueChainId = _chainId, + Owner = Accounts[0].Address }; private TokenInfo PrimaryTokenInfo => new() @@ -78,7 +79,8 @@ public MultiTokenContractTests() Issuer = Accounts[0].Address, Supply = 0, IssueChainId = _chainId, - ExternalInfo = new ExternalInfo() + ExternalInfo = new ExternalInfo(), + Owner = Accounts[0].Address }; /// @@ -480,7 +482,8 @@ public async Task TokenCreate_Test() OtherBasicFunctionContractAddress, TokenConverterContractAddress, TreasuryContractAddress - } + }, + Owner = AliceCoinTokenInfo.Owner }; var createTokenInfoWithInvalidTokenName = new CreateInput(); createTokenInfoWithInvalidTokenName.MergeFrom(createTokenInfo); diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs index b127745e8c..260812af73 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs @@ -82,7 +82,8 @@ public MultiTokenContractTestBase() TokenName = "ELF2", TotalSupply = 100_000_000_000_000_000L, Issuer = DefaultAddress, - ExternalInfo = new ExternalInfo() + ExternalInfo = new ExternalInfo(), + Owner = DefaultAddress })); AsyncHelper.RunSync(() => CreateSeedNftCollection(TokenContractStub)); diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs index 8a3d594ead..f32c400c35 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractReferenceFeeTest.cs @@ -503,7 +503,8 @@ public async Task SetSymbolsToPayTxSizeFee_With_Invalid_Weight_Test() TokenName = "name", Issuer = DefaultAccount.Address, TotalSupply = 100_000, - IsBurnable = true + IsBurnable = true, + Owner = DefaultAccount.Address }; await CreateSeedNftAsync(TokenContractStub, input, TokenContractAddress); await TokenContractStub.Create.SendAsync(input); @@ -540,7 +541,8 @@ public async Task SetSymbolsToPayTxSizeFee_With_Repeat_Token_Test() Symbol = feeToken, TokenName = "name", Issuer = DefaultAccount.Address, - TotalSupply = 100_000 + TotalSupply = 100_000, + Owner = DefaultAccount.Address }; await CreateSeedNftAsync(TokenContractStub, input, TokenContractAddress); await TokenContractStub.Create.SendAsync(input); @@ -584,7 +586,8 @@ public async Task SetSymbolsToPayTxSizeFee_Without_PrimaryToken_Test() Symbol = feeToken, TokenName = "name", Issuer = DefaultAccount.Address, - TotalSupply = 100_000 + TotalSupply = 100_000, + Owner = DefaultAccount.Address }; await CreateSeedNftAsync(TokenContractStub, input, TokenContractAddress); await TokenContractStub.Create.SendAsync(input); @@ -611,7 +614,8 @@ public async Task SetSymbolsToPayTxSizeFee_Without_Profitable_Token_Test() Symbol = feeToken, TokenName = "name", Issuer = DefaultAccount.Address, - TotalSupply = 100_000 + TotalSupply = 100_000, + Owner = DefaultAccount.Address }; await CreateSeedNftAsync(TokenContractStub, input, TokenContractAddress); await TokenContractStub.Create.SendAsync(input); @@ -660,7 +664,8 @@ await TokenContractStub.Create.SendAsync(new CreateInput TokenName = "name", Issuer = TokenContractAddress, TotalSupply = newTokenTotalSupply, - IsBurnable = true + IsBurnable = true, + Owner = TokenContractAddress }); var invalidBaseTokenWeight = (int)long.MaxValue.Div(newTokenTotalSupply).Add(1); newSymbolList.SymbolsToPayTxSizeFee.Add(new SymbolToPayTxSizeFee @@ -714,7 +719,8 @@ public async Task SetSymbolsToPayTxSizeFee_Success_Test() TokenName = "name", Issuer = DefaultAccount.Address, TotalSupply = 100_000, - IsBurnable = true + IsBurnable = true, + Owner = DefaultAccount.Address }; await CreateSeedNftAsync(TokenContractStub, input, TokenContractAddress); await TokenContractStub.Create.SendAsync(input); diff --git a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs index 72717d128d..d70eac58c3 100644 --- a/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs +++ b/test/AElf.Contracts.Parliament.Tests/ParliamentContractTestBase.cs @@ -132,7 +132,8 @@ private async Task InitializeTokenAsync() IsBurnable = true, TokenName = "elf token", TotalSupply = totalSupply, - Issuer = DefaultSender + Issuer = DefaultSender, + Owner = DefaultSender }, TokenContractAddress); await ApproveWithMinersAsync(approveProposalId); await ParliamentContractStub.Release.SendAsync(approveProposalId); diff --git a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs index 7b81a08d8c..8b72ae506a 100644 --- a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs +++ b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs @@ -1344,7 +1344,8 @@ await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, Parliame TokenName = "seed Collection", TotalSupply = 1, Issuer = defaultParliamentAddress, - ExternalInfo = new ExternalInfo() + ExternalInfo = new ExternalInfo(), + Owner = defaultParliamentAddress }); await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, @@ -1365,7 +1366,8 @@ await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, Parliame { "__seed_exp_time", TimestampHelper.GetUtcNow().AddDays(1).Seconds.ToString() } } }, - LockWhiteList = { TokenContractAddress } + LockWhiteList = { TokenContractAddress }, + Owner = defaultParliamentAddress }); await SubmitAndApproveProposalOfDefaultParliament(DefaultSenderKeyPair, ParliamentContractAddress, diff --git a/test/AElf.Contracts.TestContract.Tests/TestContractTestBase.cs b/test/AElf.Contracts.TestContract.Tests/TestContractTestBase.cs index 8ebd7a63e2..861a23a300 100644 --- a/test/AElf.Contracts.TestContract.Tests/TestContractTestBase.cs +++ b/test/AElf.Contracts.TestContract.Tests/TestContractTestBase.cs @@ -329,7 +329,8 @@ protected async Task InitializeTestContracts() { TokenConverterContractAddress, TreasuryContractAddress - } + }, + Owner = DefaultSender }); CheckResult(createResult.TransactionResult); @@ -356,7 +357,8 @@ protected async Task InitializeTestContracts() { TokenConverterContractAddress, TreasuryContractAddress - } + }, + Owner = DefaultSender }); CheckResult(createResult.TransactionResult); issueResult = await TokenContractStub.Issue.SendAsync(new IssueInput diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs index c3d5d824c5..49e50a0205 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutePluginTransactionDirectlyTest.cs @@ -2422,23 +2422,6 @@ await TokenContractImplStub.ValidateTokenInfoExists.SendWithExceptionAsync( new ValidateTokenInfoExistsInput()); result.TransactionResult.Error.ShouldContain("Invalid input symbol."); } - { - var result = - await TokenContractImplStub.ChangeTokenIssuer.SendWithExceptionAsync(new ChangeTokenIssuerInput()); - result.TransactionResult.Error.ShouldContain("Invalid input symbol."); - } - { - var result = await TokenContractImplStub.ChangeTokenIssuer.SendWithExceptionAsync(new ChangeTokenIssuerInput - { - Symbol = NativeTokenSymbol - }); - result.TransactionResult.Error.ShouldContain("Invalid input address."); - } - { - var result = - await TokenContractImplStub.ResetExternalInfo.SendWithExceptionAsync(new ResetExternalInfoInput()); - result.TransactionResult.Error.ShouldContain("Invalid input symbol."); - } { var result = await TokenContractImplStub.SetTransactionFeeDelegations.SendWithExceptionAsync( @@ -2572,6 +2555,7 @@ await TokenContractStub.Create.SendAsync(new CreateInput TotalSupply = 1000_00000000, IsBurnable = isBurned, Issuer = creator, + Owner = creator }); } diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestTokenContractInitializationProvider.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestTokenContractInitializationProvider.cs index 38cc9592d0..585a902412 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestTokenContractInitializationProvider.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/MethodFeeTestTokenContractInitializationProvider.cs @@ -28,7 +28,8 @@ public MethodFeeTestTokenContractInitializationProvider() : base(null) IsBurnable = true, TokenName = "elf token", TotalSupply = 1_000_000_00000000L, - Issuer = SampleAccount.Accounts[0].Address + Issuer = SampleAccount.Accounts[0].Address, + Owner = SampleAccount.Accounts[0].Address }.ToByteString() }); diff --git a/test/AElf.OS.TestBase/OSTestHelper.cs b/test/AElf.OS.TestBase/OSTestHelper.cs index c8675db0d1..cbef7de0eb 100644 --- a/test/AElf.OS.TestBase/OSTestHelper.cs +++ b/test/AElf.OS.TestBase/OSTestHelper.cs @@ -432,7 +432,8 @@ private async Task StartNodeAsync() TotalSupply = TokenTotalSupply, Decimals = 2, Issuer = ownAddress, - IsBurnable = true + IsBurnable = true, + Owner = ownAddress }.ToByteString() }); @@ -446,7 +447,8 @@ private async Task StartNodeAsync() TotalSupply = TokenTotalSupply, Decimals = 2, Issuer = ownAddress, - IsBurnable = true + IsBurnable = true, + Owner = ownAddress }.ToByteString() }); From 924432532a42f62269b5b8a47252a38d71e590a2 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Mon, 10 Jul 2023 21:25:40 +0800 Subject: [PATCH 130/139] feat: add ut --- .../AEDPoSExtensionTests.cs | 1 + .../SideChainConsensusInformationTest.cs | 1 + .../AssociationContractTests.cs | 2 +- .../BVT/ACS1_ImplementTest.cs | 1 + .../BVT/NftApplicationTests.cs | 4 ++++ .../BVT/TokenApplicationTests.cs | 8 +++++++- .../BVT/TokenDelegationTest.cs | 1 + .../BVT/TokenManagementTests.cs | 6 ++++++ .../MultiTokenContractTestBase.cs | 2 ++ .../MultiTokenContractCrossChainTestBase.cs | 2 ++ .../AElf.Contracts.Profit.Tests/ProfitContractTestBase.cs | 1 + .../ReferendumContractTest.cs | 1 + .../ReferendumContractTestBase.cs | 3 ++- test/AElf.Contracts.TestBase/ContractTester.cs | 4 ++++ test/AElf.Contracts.TestContract.DApp/DAppContract.cs | 1 + .../TokenConvertConnectorTest.cs | 1 + .../TokenConverterContractTests.cs | 1 + .../TokenConverterTestBase.cs | 1 + .../TokenHolderContractTestBase.cs | 7 ++++++- test/AElf.Contracts.TokenHolder.Tests/TokenHolderTests.cs | 1 + test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs | 1 + .../ExecutionPluginForCallThresholdTestBase.cs | 3 ++- .../ExecutionPluginForMethodFeeTest.cs | 3 ++- .../ExecutionPluginForMethodFeeTestBase.cs | 3 ++- .../ExecutionPluginForUserContractMethodFeeTest.cs | 3 ++- .../ExecutionPluginForResourceFeeTestBase.cs | 5 +++++ 26 files changed, 59 insertions(+), 8 deletions(-) diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs index 5d535f3ab1..5f7d8d1c5f 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/AEDPoSExtensionTests.cs @@ -64,6 +64,7 @@ await ParliamentReachAnAgreementAsync(new CreateProposalInput Decimals = 8, TokenName = "Test", Issuer = Accounts[0].Address, + Owner = Accounts[0].Address, IsBurnable = true, TotalSupply = 1_000_000_000_00000000 }.ToByteString(), diff --git a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs index 504758a980..8686d6fbd0 100644 --- a/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs +++ b/test/AElf.Contracts.AEDPoSExtension.Demo.Tests/SideChainConsensusInformationTest.cs @@ -101,6 +101,7 @@ await ParliamentReachAnAgreementAsync(new CreateProposalInput Decimals = 8, TokenName = "Test", Issuer = Accounts[0].Address, + Owner = Accounts[0].Address, IsBurnable = true, TotalSupply = 1_000_000_000_00000000 }.ToByteString(), diff --git a/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs b/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs index ff344d4e20..0da11d0fa3 100644 --- a/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs +++ b/test/AElf.Contracts.Association.Tests/AssociationContractTests.cs @@ -953,7 +953,7 @@ public async Task SetMethodFee_Fail_Test() TokenName = "name", Issuer = DefaultSender, TotalSupply = 1000_000, - Owner = DefaultSender + Owner = DefaultSender, }); await ApproveWithMinersAsync(proposalId); diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs index b5e4e25d46..ec111cbc73 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/ACS1_ImplementTest.cs @@ -215,6 +215,7 @@ await CreateMutiTokenAsync(TokenContractStub,new CreateInput Symbol = tokenNotProfitable, TokenName = "name", Issuer = DefaultAddress, + Owner = DefaultAddress, TotalSupply = 1000_000 }); var methodFees = new MethodFees diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs index 460ed2f108..2f9a616d98 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs @@ -78,6 +78,7 @@ public partial class MultiTokenContractTests TotalSupply = 1, Decimals = 0, Issuer = Accounts[0].Address, + Owner = Accounts[0].Address, IssueChainId = _chainId, IsBurnable = true, ExternalInfo = new ExternalInfo() @@ -123,6 +124,7 @@ private async Task> CreateNftCollectionAsync(TokenInfo c TotalSupply = collectionInfo.TotalSupply, Decimals = collectionInfo.Decimals, Issuer = collectionInfo.Issuer, + Owner = collectionInfo.Issuer, IssueChainId = collectionInfo.IssueChainId, ExternalInfo = collectionInfo.ExternalInfo }); @@ -272,6 +274,7 @@ public async Task MultiTokenContract_Create_NFTCollection_Input_Check_Test() TotalSupply = input.TotalSupply, Decimals = input.Decimals, Issuer = NftCollection721Info.Issuer, + Owner = NftCollection721Info.Issuer, IssueChainId = ChainHelper.ConvertBase58ToChainId("tDVV"), ExternalInfo = input.ExternalInfo }); @@ -692,6 +695,7 @@ public async Task CreateTokenTest() TotalSupply = TotalSupply, Decimals = 0, Issuer = DefaultAddress, + Owner = DefaultAddress, IssueChainId = _chainId, }); res.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index 4292cededb..b4aa6e54d7 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -380,6 +380,7 @@ await CreateMutiTokenAsync(TokenContractStub,new CreateInput Decimals = 2, IsBurnable = true, Issuer = DefaultAddress, + Owner = DefaultAddress, TokenName = "elf test token", TotalSupply = DPoSContractConsts.LockTokenForElection * 1000000, LockWhiteList = @@ -820,7 +821,8 @@ public async Task MultiTokenContract_Burn_Invalid_Token_Test() TotalSupply = 100_000_000_000L, Decimals = 10, IsBurnable = false, - Issuer = DefaultAddress + Issuer = DefaultAddress, + Owner = DefaultAddress, }); var burnRet = await TokenContractStub.Burn.SendWithExceptionAsync(new BurnInput { @@ -1112,6 +1114,7 @@ await CreateMutiTokenAsync(TokenContractStub,new CreateInput { Symbol = symbol, Issuer = creator, + Owner = creator, TokenName = symbol + "name", TotalSupply = totalSupply, Decimals = 4 @@ -1134,6 +1137,7 @@ public async Task ValidateTokenInfoExists_ExternalInfo_Test() TotalSupply = AliceCoinTokenInfo.TotalSupply, Decimals = AliceCoinTokenInfo.Decimals, Issuer = AliceCoinTokenInfo.Issuer, + Owner = AliceCoinTokenInfo.Issuer, IsBurnable = AliceCoinTokenInfo.IsBurnable, LockWhiteList = { @@ -1152,6 +1156,7 @@ public async Task ValidateTokenInfoExists_ExternalInfo_Test() TotalSupply = AliceCoinTokenInfo.TotalSupply, Decimals = AliceCoinTokenInfo.Decimals, Issuer = AliceCoinTokenInfo.Issuer, + Owner = AliceCoinTokenInfo.Issuer, IsBurnable = AliceCoinTokenInfo.IsBurnable, IssueChainId = _chainId }); @@ -1166,6 +1171,7 @@ public async Task ValidateTokenInfoExists_ExternalInfo_Test() TotalSupply = AliceCoinTokenInfo.TotalSupply, Decimals = AliceCoinTokenInfo.Decimals, Issuer = AliceCoinTokenInfo.Issuer, + Owner = AliceCoinTokenInfo.Issuer, IsBurnable = AliceCoinTokenInfo.IsBurnable, ExternalInfo = { { "key", "value" } } }); diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs index 8b690c7afd..47acb0a625 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenDelegationTest.cs @@ -171,6 +171,7 @@ await CreateMutiTokenAsync(TokenContractStub,new CreateInput TotalSupply = 1000_00000000, IsBurnable = isBurned, Issuer = creator, + Owner = creator, }); } diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs index ac014867e4..ae7e336a98 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenManagementTests.cs @@ -137,6 +137,7 @@ private async Task CreatePrimaryTokenAsync() Decimals = PrimaryTokenInfo.Decimals, IsBurnable = PrimaryTokenInfo.IsBurnable, Issuer = PrimaryTokenInfo.Issuer, + Owner = PrimaryTokenInfo.Issuer, TotalSupply = PrimaryTokenInfo.TotalSupply, Symbol = PrimaryTokenInfo.Symbol, TokenName = PrimaryTokenInfo.TokenName, @@ -168,6 +169,7 @@ private async Task CreateNormalTokenAsync() TotalSupply = AliceCoinTokenInfo.TotalSupply, Decimals = AliceCoinTokenInfo.Decimals, Issuer = AliceCoinTokenInfo.Issuer, + Owner = AliceCoinTokenInfo.Issuer, IsBurnable = AliceCoinTokenInfo.IsBurnable, LockWhiteList = { @@ -235,6 +237,7 @@ public async Task MultiTokenContract_Create_NotSame_Test() TotalSupply = BobCoinTokenInfo.TotalSupply, Decimals = BobCoinTokenInfo.Decimals, Issuer = BobCoinTokenInfo.Issuer, + Owner = BobCoinTokenInfo.Issuer, IsBurnable = BobCoinTokenInfo.IsBurnable }); @@ -257,6 +260,7 @@ public async Task MultiTokenContract_Create_UseCustomAddress_Test() Decimals = 2, IsBurnable = true, Issuer = DefaultAddress, + Owner = DefaultAddress, TokenName = BobCoinTokenInfo.TokenName, TotalSupply = AliceCoinTotalAmount, LockWhiteList = @@ -396,6 +400,7 @@ public async Task IssueToken_With_Invalid_Input() Symbol = chainTokenSymbol, TokenName = "chain token", Issuer = DefaultAddress, + Owner = DefaultAddress, IssueChainId = 10, TotalSupply = 1000_000, Decimals = 8 @@ -420,6 +425,7 @@ public async Task IssueToken_Test() Symbol = newTokenSymbol, TokenName = "ain token", Issuer = DefaultAddress, + Owner = DefaultAddress, TotalSupply = 1000_000, Decimals = 8 }); diff --git a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs index 260812af73..232a5f5b8b 100644 --- a/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs +++ b/test/AElf.Contracts.MultiToken.Tests/MultiTokenContractTestBase.cs @@ -174,6 +174,7 @@ internal async Task CreateSeedNftCollection(TokenContractImplContainer.TokenCont TokenName = "seed Collection", TotalSupply = 1, Issuer = DefaultAddress, + Owner = DefaultAddress, ExternalInfo = new ExternalInfo() }; await stub.Create.SendAsync(input); @@ -216,6 +217,7 @@ internal CreateInput BuildSeedCreateInput(CreateInput createInput) TokenName = "seed token" + SeedNum, TotalSupply = 1, Issuer = DefaultAddress, + Owner = DefaultAddress, ExternalInfo = new ExternalInfo(), LockWhiteList = { TokenContractAddress } }; diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs index 1f123f668f..a84a9d9d98 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTestBase.cs @@ -408,6 +408,7 @@ internal async Task CreateSeedNftCollection(TokenContractImplContainer.TokenCont TokenName = "seed Collection", TotalSupply = 1, Issuer = address, + Owner = address, ExternalInfo = new ExternalInfo() }; var re= await stub.Create.SendAsync(input); @@ -440,6 +441,7 @@ internal CreateInput BuildSeedCreateInput(CreateInput createInput,Address lockWh TokenName = "seed token" + SeedNum, TotalSupply = 1, Issuer = createInput.Issuer, + Owner = createInput.Issuer, ExternalInfo = new ExternalInfo(), LockWhiteList = { lockWhiteAddress } }; diff --git a/test/AElf.Contracts.Profit.Tests/ProfitContractTestBase.cs b/test/AElf.Contracts.Profit.Tests/ProfitContractTestBase.cs index 0b857f0e49..82dbf5f5ed 100644 --- a/test/AElf.Contracts.Profit.Tests/ProfitContractTestBase.cs +++ b/test/AElf.Contracts.Profit.Tests/ProfitContractTestBase.cs @@ -158,6 +158,7 @@ private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList TokenName = "elf token", TotalSupply = ProfitContractTestConstants.NativeTokenTotalSupply, Issuer = Starter, + Owner = Starter, LockWhiteList = { ProfitContractAddress diff --git a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs index 8b72ae506a..50561f4857 100644 --- a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs +++ b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs @@ -1310,6 +1310,7 @@ private async Task CreateProposalAsync(ECKeyPair proposalKeyPair, Address TotalSupply = 10_0000, TokenName = "new token", Issuer = organizationAddress, + Owner = organizationAddress, IsBurnable = true }; var createProposalInput = new CreateProposalInput diff --git a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestBase.cs b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestBase.cs index add7e3d3fb..58d057d846 100644 --- a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestBase.cs +++ b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTestBase.cs @@ -141,7 +141,8 @@ private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList IsBurnable = true, TokenName = "elf token", TotalSupply = totalSupply, - Issuer = DefaultSender + Issuer = DefaultSender, + Owner = DefaultSender, }); //issue default user diff --git a/test/AElf.Contracts.TestBase/ContractTester.cs b/test/AElf.Contracts.TestBase/ContractTester.cs index 2ac2ea3092..06520a17d2 100644 --- a/test/AElf.Contracts.TestBase/ContractTester.cs +++ b/test/AElf.Contracts.TestBase/ContractTester.cs @@ -710,6 +710,7 @@ public Action> GetDefaultContractTypes(Address iss TotalSupply = totalSupply, Decimals = 8, Issuer = issuer, + Owner = issuer, IsBurnable = true }); tokenContractCallList.Add(nameof(TokenContract.SetPrimaryTokenSymbol), @@ -767,6 +768,7 @@ public Action> GetSideChainSystemContract(Address Symbol = "ELF", Decimals = 2, Issuer = issuer, + Owner = issuer, IsBurnable = true, TokenName = "elf token", TotalSupply = TokenTotalSupply, @@ -781,6 +783,7 @@ public Action> GetSideChainSystemContract(Address Decimals = nativeTokenInfo.Decimals, IssueChainId = nativeTokenInfo.IssueChainId, Issuer = nativeTokenInfo.Issuer, + Owner = nativeTokenInfo.Issuer, IsBurnable = nativeTokenInfo.IsBurnable, Symbol = nativeTokenInfo.Symbol, TokenName = nativeTokenInfo.TokenName, @@ -796,6 +799,7 @@ public Action> GetSideChainSystemContract(Address Decimals = 2, IsBurnable = true, Issuer = Address.FromPublicKey(KeyPair.PublicKey), + Owner = Address.FromPublicKey(KeyPair.PublicKey), TotalSupply = 1_000_000_000, Symbol = symbol, TokenName = "TEST", diff --git a/test/AElf.Contracts.TestContract.DApp/DAppContract.cs b/test/AElf.Contracts.TestContract.DApp/DAppContract.cs index 9e5d90337f..ec205bd134 100644 --- a/test/AElf.Contracts.TestContract.DApp/DAppContract.cs +++ b/test/AElf.Contracts.TestContract.DApp/DAppContract.cs @@ -197,6 +197,7 @@ private void CreateToken(Address profitReceiver, bool isLockWhiteListIncludingSe TokenName = "DApp Token", Decimals = DAppConstants.Decimal, Issuer = Context.Self, + Owner = Context.Self, IsBurnable = true, TotalSupply = DAppConstants.TotalSupply, LockWhiteList = diff --git a/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs b/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs index f45a95bf3f..6c462e1d96 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/TokenConvertConnectorTest.cs @@ -511,6 +511,7 @@ await ExecuteProposalForParliamentTransaction(TokenContractAddress, nameof(Token TokenName = symbol + " name", TotalSupply = totalSupply, Issuer = DefaultSender, + Owner = DefaultSender, IsBurnable = true, LockWhiteList = { TokenContractAddress, TokenConverterContractAddress } }); diff --git a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs index d9e0cec8b9..2f598d96e1 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterContractTests.cs @@ -370,6 +370,7 @@ await ExecuteProposalForParliamentTransaction(TokenContractAddress, nameof(Token Decimals = 2, IsBurnable = true, Issuer = DefaultSender, + Owner = DefaultSender, TokenName = "Write Resource", TotalSupply = 100_0000L, LockWhiteList = { TokenContractAddress, TokenConverterContractAddress } diff --git a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs index 9a10c8f384..3167d6a9e5 100644 --- a/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs +++ b/test/AElf.Contracts.TokenConverter.Tests/TokenConverterTestBase.cs @@ -60,6 +60,7 @@ await ExecuteProposalForParliamentTransaction(TokenContractAddress, nameof(Token TokenName = "elf token", TotalSupply = 1000_0000_0000L, Issuer = DefaultSender, + Owner = DefaultSender, LockWhiteList = { TokenContractAddress, TokenConverterContractAddress } }); await TokenContractStub.Issue.SendAsync(new IssueInput diff --git a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs index 440b952d63..e127c3a78b 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderContractTestBase.cs @@ -134,6 +134,7 @@ protected void InitializeContracts() TokenName = "collection", TotalSupply = 1, Issuer = Starter, + Owner = Starter, LockWhiteList = { TokenContractAddress @@ -156,6 +157,7 @@ protected void InitializeContracts() TokenName = "collection", TotalSupply = 1, Issuer = Starter, + Owner = Starter, LockWhiteList = { TokenContractAddress @@ -178,6 +180,7 @@ protected void InitializeContracts() TokenName = "collection", TotalSupply = 1, Issuer = Starter, + Owner = Starter, LockWhiteList = { TokenContractAddress @@ -289,6 +292,7 @@ private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList TokenName = "elf token", TotalSupply = TokenHolderContractTestConstants.NativeTokenTotalSupply, Issuer = Starter, + Owner = Starter, LockWhiteList = { ProfitContractAddress, @@ -321,7 +325,8 @@ private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList IsBurnable = true, TokenName = "collection", TotalSupply = 1, - Issuer = Starter + Issuer = Starter, + Owner = Starter, }); return tokenContractCallList; diff --git a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderTests.cs b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderTests.cs index 959bc2cb56..68698e8177 100644 --- a/test/AElf.Contracts.TokenHolder.Tests/TokenHolderTests.cs +++ b/test/AElf.Contracts.TokenHolder.Tests/TokenHolderTests.cs @@ -504,6 +504,7 @@ await TokenContractStub.Create.SendAsync(new CreateInput TokenName = symbol + " name", TotalSupply = totalSupply, Issuer = Starter, + Owner = Starter, LockWhiteList = { ProfitContractAddress } }); await TokenContractStub.Issue.SendAsync(new IssueInput diff --git a/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs b/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs index 779aaa37b1..b8bc955652 100644 --- a/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs +++ b/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs @@ -134,6 +134,7 @@ private SystemContractDeploymentInput.Types.SystemTransactionMethodCallList Gene TokenName = "elf token for testing", TotalSupply = totalSupply, Issuer = DefaultSender, + Owner = DefaultSender, LockWhiteList = { VoteContractAddress diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs index 196ef5f109..fa3bcb5de1 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs @@ -122,7 +122,8 @@ private async Task InitializeTokenAsync() IsBurnable = true, TokenName = "elf token", TotalSupply = 1000_00000000L, - Issuer = DefaultSender + Issuer = DefaultSender, + Owner = DefaultSender }); createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs index 0c1237863d..b265f1cca9 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTest.cs @@ -61,7 +61,8 @@ await tokenStub.Create.SendAsync(new CreateInput IsBurnable = true, TokenName = "test token", TotalSupply = 1_000_000_00000000L, - Issuer = DefaultSender + Issuer = DefaultSender, + Owner = DefaultSender }); if (issueAmount != 0) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs index 934bce2f3a..62376dcaec 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForMethodFeeTestBase.cs @@ -510,7 +510,8 @@ private async Task CreateNativeTokenAsync() IsBurnable = true, TokenName = "elf token", TotalSupply = totalSupply, - Issuer = DefaultSender + Issuer = DefaultSender, + Owner = DefaultSender }); createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); } diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs index a43198b8a6..25e8daa5f4 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForMethodFee.Tests/ExecutionPluginForUserContractMethodFeeTest.cs @@ -314,7 +314,8 @@ await TokenContractStub.Create.SendAsync(new CreateInput IsBurnable = true, TokenName = "test token", TotalSupply = 1_000_000_00000000L, - Issuer = DefaultAddress + Issuer = DefaultAddress, + Owner = DefaultAddress, }); if (issueAmount != 0) diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs index efd21c3a47..7f641bdb82 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForResourceFee.Tests/ExecutionPluginForResourceFeeTestBase.cs @@ -232,6 +232,7 @@ await TokenContractStub.Create.SendAsync(new CreateInput TokenName = "elf token", TotalSupply = totalSupply, Issuer = DefaultSender, + Owner = DefaultSender, LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } }); @@ -266,6 +267,7 @@ await TokenContractStub.Create.SendAsync(new CreateInput TokenName = "read token", TotalSupply = totalSupply, Issuer = DefaultSender, + Owner = DefaultSender, LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } }); @@ -289,6 +291,7 @@ await TokenContractStub.Create.SendAsync(new CreateInput TokenName = "sto token", TotalSupply = totalSupply, Issuer = DefaultSender, + Owner = DefaultSender, LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } }); @@ -312,6 +315,7 @@ await TokenContractStub.Create.SendAsync(new CreateInput TokenName = "net token", TotalSupply = totalSupply, Issuer = DefaultSender, + Owner = DefaultSender, LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } }); @@ -334,6 +338,7 @@ await TokenContractStub.Create.SendAsync(new CreateInput TokenName = "WRITE token", TotalSupply = totalSupply, Issuer = DefaultSender, + Owner = DefaultSender, LockWhiteList = { TreasuryContractAddress, TokenConverterAddress } }); From 535b033496d1c7523d4010f6112674c628e9403a Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 10 Jul 2023 21:41:22 +0800 Subject: [PATCH 131/139] fix: cr --- .../TokenContract_NFT_Actions.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index 2b004d0c9b..1926727e68 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -20,17 +20,10 @@ private Empty CreateNFTInfo(CreateInput input) input.IssueChainId = input.IssueChainId == 0 ? nftCollectionInfo.IssueChainId : input.IssueChainId; Assert(input.IssueChainId == nftCollectionInfo.IssueChainId, "NFT create ChainId must be collection's issue chainId"); - if (nftCollectionInfo.Owner == null) - { - Assert(Context.Sender == nftCollectionInfo.Issuer && nftCollectionInfo.Issuer == input.Issuer, - "NFT issuer must be collection's issuer"); - } - else - { - Assert(Context.Sender == nftCollectionInfo.Owner && nftCollectionInfo.Owner == input.Owner, - "NFT owner must be collection's owner"); - } - + + var owner = nftCollectionInfo.Owner ?? nftCollectionInfo.Issuer; + Assert(Context.Sender == owner && owner == input.Owner, "NFT owner must be collection's owner"); + if (nftCollectionInfo.Symbol == TokenContractConstants.SeedCollectionSymbol) { Assert(input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, From eaec904dc85fe3c7454ccfe34c7805cdb6b0d931 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 10 Jul 2023 22:18:08 +0800 Subject: [PATCH 132/139] test: log --- src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs index 53cd03ed12..e039fa314d 100644 --- a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs @@ -121,7 +121,7 @@ public void LogDebug(Func func) { #if DEBUG _smartContractBridgeService.LogDebug(() => - $"TX = {Transaction?.GetHash().ToHex()}, Method = {Transaction?.MethodName}, {func()}"); + $"TX = {Transaction?.GetHash().ToHex()}, Method = {Transaction?.MethodName}, {func()}, Hello World"); #endif } From 481fc8d8f6f3df7a43d5631c471717602c236fc2 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 11 Jul 2023 10:51:39 +0800 Subject: [PATCH 133/139] fix: TokenContractInitializationProvider.cs --- contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs | 4 ++++ .../HostSmartContractBridgeContext.cs | 2 +- src/AElf.Kernel.Token/TokenContractInitializationProvider.cs | 3 +-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 49ee4de9d3..41b08cc496 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -35,6 +35,10 @@ public override Empty Create(CreateInput input) // can not call create on side chain Assert(State.SideChainCreator.Value == null, "Failed to create token if side chain creator already set."); var inputSymbolType = GetCreateInputSymbolType(input.Symbol); + if (input.Owner == null) + { + input.Owner = input.Issuer; + } return inputSymbolType switch { SymbolType.NftCollection => CreateNFTCollection(input), diff --git a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs index e039fa314d..53cd03ed12 100644 --- a/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs +++ b/src/AElf.Kernel.SmartContract/HostSmartContractBridgeContext.cs @@ -121,7 +121,7 @@ public void LogDebug(Func func) { #if DEBUG _smartContractBridgeService.LogDebug(() => - $"TX = {Transaction?.GetHash().ToHex()}, Method = {Transaction?.MethodName}, {func()}, Hello World"); + $"TX = {Transaction?.GetHash().ToHex()}, Method = {Transaction?.MethodName}, {func()}"); #endif } diff --git a/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs b/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs index 86cb6cf208..7fa7bd32b6 100644 --- a/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs +++ b/src/AElf.Kernel.Token/TokenContractInitializationProvider.cs @@ -138,8 +138,7 @@ private CreateInput GenerateTokenCreateInput(TokenInfo tokenInfo, Address issuer IsBurnable = tokenInfo.IsBurnable, Symbol = tokenInfo.Symbol, TokenName = tokenInfo.TokenName, - TotalSupply = tokenInfo.TotalSupply, - Owner = issuer ?? tokenInfo.Issuer + TotalSupply = tokenInfo.TotalSupply }; } } \ No newline at end of file From 4d3e2a247b91fa28eeceae1cc51218a0885303b2 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Tue, 11 Jul 2023 11:04:43 +0800 Subject: [PATCH 134/139] feat: add ut --- .../UnitTestTokenContractInitializationProvider.cs | 1 + .../BVT/NftApplicationTests.cs | 6 ++++-- .../MultiTokenContractCrossChainTest.cs | 3 +++ .../SideChainUnitTestTokenContractInitializationProvider.cs | 1 + .../UnitTestTokenContractInitializationProvider.cs | 1 + .../BasicContract_Action.cs | 1 + .../ExecutionPluginForCallThresholdTestBase.cs | 3 ++- 7 files changed, 13 insertions(+), 3 deletions(-) diff --git a/test/AElf.Contracts.Association.Tests/UnitTestTokenContractInitializationProvider.cs b/test/AElf.Contracts.Association.Tests/UnitTestTokenContractInitializationProvider.cs index aa110100ca..99cd591ce1 100644 --- a/test/AElf.Contracts.Association.Tests/UnitTestTokenContractInitializationProvider.cs +++ b/test/AElf.Contracts.Association.Tests/UnitTestTokenContractInitializationProvider.cs @@ -38,6 +38,7 @@ public override List GetInitializeMethodList(b { Decimals = _economicOptions.Decimals, Issuer = address, + Owner = address, IsBurnable = _economicOptions.IsBurnable, Symbol = _economicOptions.Symbol, TokenName = _economicOptions.TokenName, diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs index 2f9a616d98..24055b432b 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs @@ -360,10 +360,10 @@ public async Task MultiTokenContract_Create_NFT_Input_Check_Test() Issuer = Accounts.Last().Address, IssueChainId = input.IssueChainId, ExternalInfo = input.ExternalInfo, - Owner = input.Owner + Owner = Accounts.Last().Address }); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); - result.TransactionResult.Error.ShouldContain("NFT issuer must be collection's issuer"); + result.TransactionResult.Error.ShouldContain("NFT owner must be collection's owner"); } { var result = await TokenContractStub.Create.SendWithExceptionAsync( new CreateInput @@ -730,6 +730,7 @@ public async Task CreateTokenTest() TotalSupply = TotalSupply, Decimals = 0, Issuer = DefaultAddress, + Owner = DefaultAddress, IssueChainId = _chainId, Symbol = "GHJ-0" }); @@ -769,6 +770,7 @@ public async Task CreateTokenTest() TotalSupply = TotalSupply, Decimals = 0, Issuer = DefaultAddress, + Owner = DefaultAddress, IssueChainId = _chainId, Symbol = "GHJ-1" }); diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs index aa4f5d8fbf..4c76a04b09 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/MultiTokenContractCrossChainTest.cs @@ -487,6 +487,7 @@ public async Task MainChain_CrossChainTransfer_Test() Symbol = createdTokenInfo.Symbol, Decimals = createdTokenInfo.Decimals, Issuer = createdTokenInfo.Issuer, + Owner = createdTokenInfo.Issuer, IsBurnable = createdTokenInfo.IsBurnable, TotalSupply = createdTokenInfo.TotalSupply, IssueChainId = createdTokenInfo.IssueChainId @@ -882,6 +883,7 @@ private async Task CreateTransactionForTokenCreation( Symbol = tokenInfo.Symbol, Decimals = tokenInfo.Decimals, Issuer = tokenInfo.Issuer, + Owner = tokenInfo.Issuer, IsBurnable = tokenInfo.IsBurnable, TokenName = tokenInfo.TokenName, TotalSupply = tokenInfo.TotalSupply @@ -900,6 +902,7 @@ private Transaction CreateTokenInfoValidationTransaction(TokenInfo createdTokenI Symbol = createdTokenInfo.Symbol, Decimals = createdTokenInfo.Decimals, Issuer = createdTokenInfo.Issuer, + Owner = createdTokenInfo.Issuer, IsBurnable = createdTokenInfo.IsBurnable, TotalSupply = createdTokenInfo.TotalSupply, IssueChainId = createdTokenInfo.IssueChainId diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainUnitTestTokenContractInitializationProvider.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainUnitTestTokenContractInitializationProvider.cs index e6f9791681..aeb8d3148a 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainUnitTestTokenContractInitializationProvider.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/SideChainUnitTestTokenContractInitializationProvider.cs @@ -127,6 +127,7 @@ private CreateInput GenerateTokenCreateInput(TokenInfo tokenInfo) Decimals = tokenInfo.Decimals, IssueChainId = tokenInfo.IssueChainId, Issuer = tokenInfo.Issuer, + Owner = tokenInfo.Issuer, IsBurnable = tokenInfo.IsBurnable, Symbol = tokenInfo.Symbol, TokenName = tokenInfo.TokenName, diff --git a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/UnitTestTokenContractInitializationProvider.cs b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/UnitTestTokenContractInitializationProvider.cs index b9df291357..cc84673ccf 100644 --- a/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/UnitTestTokenContractInitializationProvider.cs +++ b/test/AElf.Contracts.MultiTokenCrossChainTransfer.Tests/UnitTestTokenContractInitializationProvider.cs @@ -38,6 +38,7 @@ public override List GetInitializeMethodList(b { Decimals = _economicOptions.Decimals, Issuer = address, + Owner = address, IsBurnable = _economicOptions.IsBurnable, Symbol = _economicOptions.Symbol, TokenName = _economicOptions.TokenName, diff --git a/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_Action.cs b/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_Action.cs index b2b539bb91..b5596c26d7 100644 --- a/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_Action.cs +++ b/test/AElf.Contracts.TestContract.BasicFunction/BasicContract_Action.cs @@ -185,6 +185,7 @@ public override Empty CreateTokenThroughMultiToken(CreateTokenThroughMultiTokenI Symbol = input.Symbol, Decimals = input.Decimals, Issuer = input.Issuer, + Owner = input.Issuer, IsBurnable = input.IsBurnable, IssueChainId = input.IssueChainId, TokenName = input.TokenName, diff --git a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs index fa3bcb5de1..5dce8cc994 100644 --- a/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs +++ b/test/AElf.Kernel.SmartContract.ExecutionPluginForCallThreshold.Tests/ExecutionPluginForCallThresholdTestBase.cs @@ -147,7 +147,8 @@ private async Task InitializeTokenAsync() IsBurnable = true, TokenName = "WRITE token", TotalSupply = 1000_0000L, - Issuer = DefaultSender + Issuer = DefaultSender, + Owner = DefaultSender }); createResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); From 65a3697e813304a90b1fe5bfd7e25fd765fbf845 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Tue, 11 Jul 2023 11:43:18 +0800 Subject: [PATCH 135/139] feat:fix ut --- test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs index 50561f4857..d22a250401 100644 --- a/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs +++ b/test/AElf.Contracts.Referendum.Tests/ReferendumContractTest.cs @@ -98,6 +98,7 @@ public async Task Get_Proposal_Test() TotalSupply = 10_0000, TokenName = "new token", Issuer = organizationAddress, + Owner = organizationAddress, IsBurnable = true }; var proposalId = await CreateProposalAsync(DefaultSenderKeyPair, organizationAddress); From 9e5894bcd8552164b43a1cff364e25d764dd7b7d Mon Sep 17 00:00:00 2001 From: zhxymh Date: Wed, 12 Jul 2023 17:51:33 +0800 Subject: [PATCH 136/139] feat: support virtual address --- .../AElf.Contracts.MultiToken.csproj | 3 -- .../TokenContractReferenceState.cs | 2 - .../TokenContractState.cs | 3 ++ .../TokenContract_Actions.cs | 12 ++--- .../TokenContract_Helper.cs | 22 ++++++-- .../TreasuryContract.cs | 2 +- protobuf/test_virtual_address_contract.proto | 8 +++ .../Full/BackupSubsidyTests.cs | 35 ++++++++++++ .../Action.cs | 6 +++ .../AElf.Contracts.Vote.Tests.csproj | 8 +++ .../BVT/BasicTests.cs | 54 +++++++++++++++++++ .../VoteContractTestBase.cs | 11 ++++ 12 files changed, 149 insertions(+), 17 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj b/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj index 6bf48ead5a..44d6ef3422 100644 --- a/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj +++ b/contract/AElf.Contracts.MultiToken/AElf.Contracts.MultiToken.csproj @@ -55,9 +55,6 @@ Protobuf\Proto\acs12.proto - - Protobuf\Proto\reference\election_contract.proto - diff --git a/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs b/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs index 77d86f98f2..05021eabd2 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractReferenceState.cs @@ -1,7 +1,6 @@ using AElf.Contracts.Association; using AElf.Contracts.Configuration; using AElf.Contracts.Consensus.AEDPoS; -using AElf.Contracts.Election; using AElf.Contracts.Parliament; using AElf.Contracts.Referendum; using AElf.Standards.ACS10; @@ -17,5 +16,4 @@ public partial class TokenContractState internal DividendPoolContractContainer.DividendPoolContractReferenceState DividendPoolContract { get; set; } internal ConfigurationContainer.ConfigurationReferenceState ConfigurationContract { get; set; } - internal ElectionContractContainer.ElectionContractReferenceState ElectionContract { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState.cs b/contract/AElf.Contracts.MultiToken/TokenContractState.cs index c01f53a1c7..92da423908 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState.cs @@ -60,4 +60,7 @@ public partial class TokenContractState : ContractState /// delegator address -> contract address -> method name -> delegatee info /// public MappedState TransactionFeeDelegateInfoMap { get; set; } + + public SingletonState
ElectionContractAddress { get; set; } + public SingletonState
VoteContractAddress { get; set; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 660af1d57b..f7e4cbdefc 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -180,10 +180,8 @@ public override Empty Transfer(TransferInput input) public override Empty Lock(LockInput input) { AssertSystemContractOrLockWhiteListAddress(input.Symbol); - - // For Election Contract - var electionContractAddress = GetElectionContractAddress(); - Assert(Context.Sender == electionContractAddress || Context.Origin == input.Address, + + Assert(IsInLockWhiteList(Context.Sender) || Context.Origin == input.Address, "Lock behaviour should be initialed by origin address."); var allowance = State.Allowances[input.Address][Context.Sender][input.Symbol]; @@ -209,10 +207,8 @@ public override Empty Lock(LockInput input) public override Empty Unlock(UnlockInput input) { AssertSystemContractOrLockWhiteListAddress(input.Symbol); - - // For Election Contract - var electionContractAddress = GetElectionContractAddress(); - Assert(Context.Sender == electionContractAddress || Context.Origin == input.Address, + + Assert(IsInLockWhiteList(Context.Sender) || Context.Origin == input.Address, "Unlock behaviour should be initialed by origin address."); AssertValidToken(input.Symbol, input.Amount); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs index 9996eff984..75f6aeb713 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Helper.cs @@ -322,15 +322,31 @@ private void FireExternalLogEvent(TokenInfo tokenInfo, TransferFromInput input) NonIndexed = input.ToByteString() }); } + + private bool IsInLockWhiteList(Address address) + { + return address == GetElectionContractAddress() || address == GetVoteContractAddress(); + } private Address GetElectionContractAddress() { - if (State.ElectionContract.Value == null) + if (State.ElectionContractAddress.Value == null) { - State.ElectionContract.Value = + State.ElectionContractAddress.Value = Context.GetContractAddressByName(SmartContractConstants.ElectionContractSystemName); } - return State.ElectionContract.Value; + return State.ElectionContractAddress.Value; + } + + private Address GetVoteContractAddress() + { + if (State.VoteContractAddress.Value == null) + { + State.VoteContractAddress.Value = + Context.GetContractAddressByName(SmartContractConstants.VoteContractSystemName); + } + + return State.VoteContractAddress.Value; } } \ No newline at end of file diff --git a/contract/AElf.Contracts.Treasury/TreasuryContract.cs b/contract/AElf.Contracts.Treasury/TreasuryContract.cs index 7f0c1c3ecc..6a75b5f448 100644 --- a/contract/AElf.Contracts.Treasury/TreasuryContract.cs +++ b/contract/AElf.Contracts.Treasury/TreasuryContract.cs @@ -606,7 +606,7 @@ public override Empty SetProfitsReceiver(SetProfitsReceiverInput input) var pubkey = ByteString.CopyFrom(ByteArrayHelper.HexStringToByteArray(input.Pubkey)); var admin = State.ElectionContract.GetCandidateAdmin.Call(new StringValue {Value = input.Pubkey}); - Assert(Context.Origin == admin , "No permission."); + Assert(Context.Sender == admin , "No permission."); var candidateList = State.ElectionContract.GetCandidates.Call(new Empty()); Assert(candidateList.Value.Contains(pubkey),"Pubkey is not a candidate."); diff --git a/protobuf/test_virtual_address_contract.proto b/protobuf/test_virtual_address_contract.proto index 0ebaccdb8e..cdfb14fa05 100644 --- a/protobuf/test_virtual_address_contract.proto +++ b/protobuf/test_virtual_address_contract.proto @@ -17,6 +17,7 @@ service VirtualAddressContract { rpc VirtualAddressWithdraw(aelf.Hash) returns (google.protobuf.Empty); rpc VirtualAddressChangeVotingOption(VirtualAddressChangeVotingOptionInput) returns (google.protobuf.Empty); rpc VirtualAddressClaimProfit(VirtualAddressClaimProfitInput) returns (google.protobuf.Empty); + rpc ForwardCall(ForwardCallInput) returns (google.protobuf.Empty); rpc GetVirtualAddress(google.protobuf.Empty) returns (aelf.Address) { option (aelf.is_view) = true; @@ -40,4 +41,11 @@ message VirtualAddressChangeVotingOptionInput { message VirtualAddressClaimProfitInput { aelf.Hash scheme_id = 1; aelf.Address beneficiary = 2; +} + +message ForwardCallInput { + aelf.Hash virtual_address = 1; + aelf.Address contract_address = 2; + string method_name = 3; + bytes args = 4; } \ No newline at end of file diff --git a/test/AElf.Contracts.Election.Tests/Full/BackupSubsidyTests.cs b/test/AElf.Contracts.Election.Tests/Full/BackupSubsidyTests.cs index 48a1f5a9b2..c4d466b08f 100644 --- a/test/AElf.Contracts.Election.Tests/Full/BackupSubsidyTests.cs +++ b/test/AElf.Contracts.Election.Tests/Full/BackupSubsidyTests.cs @@ -618,6 +618,41 @@ await candidateAdminStub.SetProfitsReceiver.SendAsync( } } + [Fact] + public async Task SetProfitsReceiver_Wrong_Admin_Test() + { + var announceElectionKeyPair = ValidationDataCenterKeyPairs.First(); + var candidateAdmin = ValidationDataCenterKeyPairs.Last(); + var profitReceiver = candidateAdmin; + var candidateAdminAddress = Address.FromPublicKey(candidateAdmin.PublicKey); + await AnnounceElectionAsync(announceElectionKeyPair, candidateAdminAddress); + + var candidateAdminStub = + GetTester(TreasuryContractAddress, + candidateAdmin); + await candidateAdminStub.SetProfitsReceiver.SendAsync( + new Treasury.SetProfitsReceiverInput + { + Pubkey = announceElectionKeyPair.PublicKey.ToHex(), + ProfitsReceiverAddress = Address.FromPublicKey(profitReceiver.PublicKey) + }); + var getProfitReceiver = await GetProfitReceiver(announceElectionKeyPair.PublicKey.ToHex()); + getProfitReceiver.ShouldBe(Address.FromPublicKey(profitReceiver.PublicKey)); + + var wrongAdminStub = + GetTester(TreasuryContractAddress, + announceElectionKeyPair); + var setResult = await wrongAdminStub.SetProfitsReceiver.SendWithExceptionAsync( + new Treasury.SetProfitsReceiverInput(new Treasury.SetProfitsReceiverInput + { + Pubkey = announceElectionKeyPair.PublicKey.ToHex(), + ProfitsReceiverAddress = Address.FromPublicKey(profitReceiver.PublicKey) + })); + + setResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + setResult.TransactionResult.Error.ShouldContain("No permission."); + } + private async Task GetBackupSubsidyProfitDetails(Address address) { return await ProfitContractStub.GetProfitDetails.CallAsync(new GetProfitDetailsInput diff --git a/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs b/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs index b4db57ec2f..295830ea1c 100644 --- a/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs +++ b/test/AElf.Contracts.TestContract.VirtualAddress/Action.cs @@ -59,6 +59,12 @@ public override Empty VirtualAddressClaimProfit(VirtualAddressClaimProfitInput i return new Empty(); } + + public override Empty ForwardCall(ForwardCallInput input) + { + Context.SendVirtualInline(input.VirtualAddress, input.ContractAddress, input.MethodName, input.Args); + return new Empty(); + } public override Address GetVirtualAddress(Empty input) { diff --git a/test/AElf.Contracts.Vote.Tests/AElf.Contracts.Vote.Tests.csproj b/test/AElf.Contracts.Vote.Tests/AElf.Contracts.Vote.Tests.csproj index 896f50b0ab..5ad16fa9b5 100644 --- a/test/AElf.Contracts.Vote.Tests/AElf.Contracts.Vote.Tests.csproj +++ b/test/AElf.Contracts.Vote.Tests/AElf.Contracts.Vote.Tests.csproj @@ -34,6 +34,11 @@ + + false + Contract + PreserveNewest + @@ -81,5 +86,8 @@ Protobuf\Proto\aedpos_contract_impl.proto + + Protobuf\Proto\test_virtual_address_contract.proto + diff --git a/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs b/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs index a4b112bf30..05ef4e05a2 100644 --- a/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs +++ b/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs @@ -2,10 +2,13 @@ using System.Text; using System.Threading.Tasks; using AElf.Contracts.MultiToken; +using AElf.Contracts.TestContract.VirtualAddress; using AElf.CSharp.Core; using AElf.CSharp.Core.Extension; using AElf.Kernel; using AElf.Types; +using Google.Protobuf; +using Google.Protobuf.WellKnownTypes; using Shouldly; using Xunit; @@ -661,4 +664,55 @@ public async Task VoteContract_GetVotingIds_Test() }); voteIds.ActiveVotes.Count.ShouldBe(1); } + + [Fact] + public async Task Vote_VirtualAddress_Success() + { + var registerItem = await RegisterVotingItemAsync(100, 3, true, DefaultSender, 1); + var voteItemId = registerItem.VotingItemId; + var voter = await VirtualAddressContractStub.GetVirtualAddress.CallAsync(new Empty()); + var voteAmount = 100; + await TokenContractStub.Transfer.SendAsync(new TransferInput + { + Symbol = TestTokenSymbol, + Amount = 1000, + To = voter, + Memo = "transfer token to voter" + }); + var beforeVoteBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = TestTokenSymbol, + Owner = voter + }); + var sendResult = await VirtualAddressContractStub.ForwardCall.SendAsync(new ForwardCallInput + { + ContractAddress = VoteContractAddress, + MethodName = "Vote", + VirtualAddress = HashHelper.ComputeFrom("test"), + Args = (new VoteInput + { + VotingItemId = voteItemId, + Option = registerItem.Options[1], + Amount = voteAmount + }).ToByteString() + }); + + sendResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + var voteResult = await VoteContractStub.GetVotingResult.CallAsync(new GetVotingResultInput + { + SnapshotNumber = 1, + VotingItemId = voteItemId + }); + voteResult.Results[registerItem.Options[1]].ShouldBe(voteAmount); + voteResult.VotesAmount.ShouldBe(voteAmount); + voteResult.VotersCount.ShouldBe(1); + var afterVoteBalance = await TokenContractStub.GetBalance.CallAsync(new GetBalanceInput + { + Symbol = TestTokenSymbol, + Owner = voter + }); + beforeVoteBalance.Balance.Sub(afterVoteBalance.Balance).ShouldBe(voteAmount); + var voteItems = await VoteContractStub.GetVotedItems.CallAsync(voter); + voteItems.VotedItemVoteIds.Count.ShouldBe(1); + } } \ No newline at end of file diff --git a/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs b/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs index 779aaa37b1..5161f8ac08 100644 --- a/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs +++ b/test/AElf.Contracts.Vote.Tests/VoteContractTestBase.cs @@ -4,6 +4,7 @@ using AElf.Contracts.Consensus.AEDPoS; using AElf.Contracts.MultiToken; using AElf.Contracts.Parliament; +using AElf.Contracts.TestContract.VirtualAddress; using AElf.ContractTestKit; using AElf.Cryptography.ECDSA; using AElf.GovernmentSystem; @@ -32,11 +33,13 @@ public class VoteContractTestBase : ContractTestBase protected Address ParliamentContractAddress { get; set; } protected new Address ContractZeroAddress => ContractAddressService.GetZeroSmartContractAddress(); protected Address ConsensusContractAddress { get; set; } + protected Address VirtualAddressContractAddress { get; set; } internal ACS0Container.ACS0Stub BasicContractZeroStub { get; set; } internal TokenContractContainer.TokenContractStub TokenContractStub { get; set; } internal VoteContractImplContainer.VoteContractImplStub VoteContractStub { get; set; } internal ParliamentContractImplContainer.ParliamentContractImplStub ParliamentContractStub { get; set; } internal AEDPoSContractImplContainer.AEDPoSContractImplStub AEDPoSContractStub { get; set; } + internal VirtualAddressContractContainer.VirtualAddressContractStub VirtualAddressContractStub { get; set; } protected void InitializeContracts() { @@ -88,6 +91,14 @@ protected void InitializeContracts() TransactionMethodCallList = GenerateConsensusInitializationCallList() })).Output; AEDPoSContractStub = GetConsensusContractTester(DefaultSenderKeyPair); + + VirtualAddressContractAddress = AsyncHelper.RunSync(async () => + await DeployContractAsync( + KernelConstants.CodeCoverageRunnerCategory, + Codes.Single(kv => kv.Key.EndsWith("VirtualAddress")).Value, + HashHelper.ComputeFrom("AElf.Contracts.TestContract.VirtualAddress"), + DefaultSenderKeyPair)); + VirtualAddressContractStub = GetTester(VirtualAddressContractAddress, DefaultSenderKeyPair); } internal ACS0Container.ACS0Stub GetContractZeroTester(ECKeyPair keyPair) From 16b09fe34f78e3601c78623f06c498b97c72613c Mon Sep 17 00:00:00 2001 From: zhxymh Date: Wed, 12 Jul 2023 18:17:22 +0800 Subject: [PATCH 137/139] test: add withdraw test --- .../BVT/BasicTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs b/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs index 05ef4e05a2..c7ca327187 100644 --- a/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs +++ b/test/AElf.Contracts.Vote.Tests/BVT/BasicTests.cs @@ -714,5 +714,27 @@ await TokenContractStub.Transfer.SendAsync(new TransferInput beforeVoteBalance.Balance.Sub(afterVoteBalance.Balance).ShouldBe(voteAmount); var voteItems = await VoteContractStub.GetVotedItems.CallAsync(voter); voteItems.VotedItemVoteIds.Count.ShouldBe(1); + + var votingIds = await VoteContractStub.GetVotingIds.CallAsync(new GetVotingIdsInput + { + Voter = voter, + VotingItemId = voteItemId + }); + var currentVoteId = votingIds.ActiveVotes.First(); + + sendResult = await VirtualAddressContractStub.ForwardCall.SendAsync(new ForwardCallInput + { + ContractAddress = VoteContractAddress, + MethodName = "Withdraw", + VirtualAddress = HashHelper.ComputeFrom("test"), + Args = (new WithdrawInput + { + VoteId = currentVoteId + }).ToByteString() + }); + sendResult.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var afterWithdrawBalance = GetUserBalance(voter); + afterWithdrawBalance.ShouldBe(beforeVoteBalance.Balance); } } \ No newline at end of file From 4784a280567bf21382f365533a334d17f05d07d6 Mon Sep 17 00:00:00 2001 From: zhxymh Date: Thu, 13 Jul 2023 18:13:27 +0800 Subject: [PATCH 138/139] feat: check inline deploy or update contracts --- contract/AElf.Contracts.Genesis/BasicContractZero.cs | 3 +++ .../AElf.Contracts.Genesis/BasicContractZero_Helper.cs | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/contract/AElf.Contracts.Genesis/BasicContractZero.cs b/contract/AElf.Contracts.Genesis/BasicContractZero.cs index ff29b81689..9f47577bed 100644 --- a/contract/AElf.Contracts.Genesis/BasicContractZero.cs +++ b/contract/AElf.Contracts.Genesis/BasicContractZero.cs @@ -365,6 +365,7 @@ public override Empty SetContractProposalExpirationTimePeriod(SetContractProposa public override DeployUserSmartContractOutput DeployUserSmartContract(ContractDeploymentInput input) { + AssertInlineDeployOrUpdateUserContract(); AssertUserDeployContract(); var codeHash = HashHelper.ComputeFrom(input.Code.ToByteArray()); @@ -395,6 +396,8 @@ public override DeployUserSmartContractOutput DeployUserSmartContract(ContractDe public override Empty UpdateUserSmartContract(ContractUpdateInput input) { + AssertInlineDeployOrUpdateUserContract(); + var info = State.ContractInfos[input.Address]; Assert(info != null, "Contract not found."); Assert(Context.Sender == info.Author, "No permission."); diff --git a/contract/AElf.Contracts.Genesis/BasicContractZero_Helper.cs b/contract/AElf.Contracts.Genesis/BasicContractZero_Helper.cs index 04aa2da726..40678c4203 100644 --- a/contract/AElf.Contracts.Genesis/BasicContractZero_Helper.cs +++ b/contract/AElf.Contracts.Genesis/BasicContractZero_Helper.cs @@ -359,6 +359,16 @@ private void AssertContractExists(Hash codeHash) { Assert(State.SmartContractRegistrations[codeHash] == null, "contract code has already been deployed before."); } + + private void AssertInlineDeployOrUpdateUserContract() + { + Assert(Context.Origin == Context.Sender || !IsMainChain(), "Deploy or update contracts using inline transactions is not allowed."); + } + + private bool IsMainChain() + { + return Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName) != null; + } } public static class AddressHelper From 88d2a8533cc73c42d610ec744b6b3d8757e74050 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 17 Jul 2023 15:19:56 +0800 Subject: [PATCH 139/139] fix: CrossChainCreateToken --- contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index d599dd2c85..483f073b54 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -465,7 +465,7 @@ public override Empty CrossChainCreateToken(CrossChainCreateTokenInput input) IsBurnable = validateTokenInfoExistsInput.IsBurnable, IssueChainId = validateTokenInfoExistsInput.IssueChainId, ExternalInfo = new ExternalInfo { Value = { validateTokenInfoExistsInput.ExternalInfo } }, - Owner = validateTokenInfoExistsInput.Owner + Owner = validateTokenInfoExistsInput.Owner ?? validateTokenInfoExistsInput.Issuer }; RegisterTokenInfo(tokenInfo); @@ -479,7 +479,7 @@ public override Empty CrossChainCreateToken(CrossChainCreateTokenInput input) IsBurnable = validateTokenInfoExistsInput.IsBurnable, IssueChainId = validateTokenInfoExistsInput.IssueChainId, ExternalInfo = new ExternalInfo { Value = { validateTokenInfoExistsInput.ExternalInfo } }, - Owner = validateTokenInfoExistsInput.Owner + Owner = tokenInfo.Owner }); return new Empty();