From ab522bbf346745409ba7d6c78ece10d750e578ce Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Thu, 29 Feb 2024 15:43:03 +0800 Subject: [PATCH 1/7] feat: add batch approve --- .../TokenContractConstants.cs | 1 + .../TokenContractState.cs | 2 + .../TokenContract_Actions.cs | 48 +++++++-- protobuf/token_contract.proto | 8 +- protobuf/token_contract_impl.proto | 9 ++ .../BVT/TokenApplicationTests.cs | 97 +++++++++++++++++++ 6 files changed, 158 insertions(+), 7 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs index a14a4e9496..db4923fd4e 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs @@ -22,4 +22,5 @@ public static class TokenContractConstants public const string SeedCollectionSymbol = "SEED-0"; public const string SeedOwnedSymbolExternalInfoKey = "__seed_owned_symbol"; public const string SeedExpireTimeExternalInfoKey = "__seed_exp_time"; + public const int DefaultMaximumBatchApproveCount = 10; } \ No newline at end of file diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState.cs b/contract/AElf.Contracts.MultiToken/TokenContractState.cs index c32b0ea62f..dc386b311b 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState.cs @@ -65,4 +65,6 @@ public partial class TokenContractState : ContractState public SingletonState
VoteContractAddress { get; set; } public SingletonState TokenIssuerAndOwnerModificationDisabled { get; set; } + + public SingletonState MaximumBatchApproveCount { 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 249afc33ea..ca328a6260 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -251,16 +251,28 @@ 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; + Approve(input.Spender, input.Symbol, input.Amount); + return new Empty(); + } + + private void Approve(Address spender, string symbol, long amount) + { + AssertValidInputAddress(spender); + AssertValidToken(symbol, amount); + State.Allowances[Context.Sender][spender][symbol] = amount; Context.Fire(new Approved { Owner = Context.Sender, - Spender = input.Spender, - Symbol = input.Symbol, - Amount = input.Amount + Spender = spender, + Symbol = symbol, + Amount = amount }); + } + + public override Empty BatchApprove(BatchApproveInput input) + { + Assert(input.Value.Count <= GetMaximumBatchApproveCount(), "Exceeds the maximum batch approve count."); + foreach (var approve in input.Value) Approve(approve.Spender, approve.Symbol, approve.Amount); return new Empty(); } @@ -626,4 +638,28 @@ public override BoolValue GetTokenIssuerAndOwnerModificationEnabled(Empty input) Value = !State.TokenIssuerAndOwnerModificationDisabled.Value }; } + + public override Empty SetMaximumBatchApproveCount(Int32Value input) + { + AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); + Assert(input.Value != 0, "Invalid input."); + State.MaximumBatchApproveCount.Value = input.Value; + return new Empty(); + } + + public override Int32Value GetMaximumBatchApproveCount(Empty input) + { + return new Int32Value + { + Value = GetMaximumBatchApproveCount() + }; + } + + private int GetMaximumBatchApproveCount() + { + var maximumBatchApproveCount = State.MaximumBatchApproveCount.Value == 0 + ? TokenContractConstants.DefaultMaximumBatchApproveCount + : State.MaximumBatchApproveCount.Value; + return maximumBatchApproveCount; + } } \ No newline at end of file diff --git a/protobuf/token_contract.proto b/protobuf/token_contract.proto index d858bf5f1d..e1174b8b45 100644 --- a/protobuf/token_contract.proto +++ b/protobuf/token_contract.proto @@ -40,7 +40,10 @@ service TokenContract { // enabling the Spender to call TransferFrom. rpc Approve (ApproveInput) returns (google.protobuf.Empty) { } - + + rpc BatchApprove (BatchApproveInput) returns (google.protobuf.Empty) { + } + // This is the reverse operation for Approve, it will decrease the allowance. rpc UnApprove (UnApproveInput) returns (google.protobuf.Empty) { } @@ -354,6 +357,9 @@ message ApproveInput { // The amount of token to approve. int64 amount = 3; } +message BatchApproveInput { + repeated ApproveInput value = 1; +} message UnApproveInput { // The address that allowance will be decreased. diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index 9a7779ec45..ece30da14c 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -83,6 +83,11 @@ service TokenContractImpl { rpc RemoveTransactionFeeFreeAllowancesConfig (RemoveTransactionFeeFreeAllowancesConfigInput) returns (google.protobuf.Empty) { } + rpc SetMaximumBatchApproveCount (google.protobuf.Int32Value) 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){ } @@ -173,6 +178,10 @@ service TokenContractImpl { rpc GetTokenIssuerAndOwnerModificationEnabled(google.protobuf.Empty) returns (google.protobuf.BoolValue) { option (aelf.is_view) = true; } + + rpc GetMaximumBatchApproveCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) { + + } } message AdvanceResourceTokenInput { diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index dba96e1023..07b737dfd0 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -171,6 +171,103 @@ public async Task MultiTokenContract_Approve_ContractAddress_Test() basicAllowanceOutput.Allowance.ShouldBe(2000L); } + [Fact(DisplayName = "[MultiToken] BatchApprove token to Contract")] + public async Task MultiTokenContract_BatchApprove_ContractAddress_Test() + { + await CreateTokenAndIssue(); + var approveBasisResult = (await TokenContractStub.BatchApprove.SendAsync(new BatchApproveInput + { + Value = + { + new ApproveInput + { + Symbol = SymbolForTest, + Amount = 2000L, + Spender = BasicFunctionContractAddress + }, + new ApproveInput + { + Symbol = SymbolForTest, + Amount = 1000L, + Spender = OtherBasicFunctionContractAddress + }, + new ApproveInput + { + Symbol = SymbolForTest, + Amount = 5000L, + Spender = TreasuryContractAddress + } + } + })).TransactionResult; + approveBasisResult.Status.ShouldBe(TransactionResultStatus.Mined); + + var basicAllowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Owner = DefaultAddress, + Spender = BasicFunctionContractAddress, + Symbol = SymbolForTest + }); + basicAllowanceOutput.Allowance.ShouldBe(2000L); + var otherBasicAllowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Owner = DefaultAddress, + Spender = OtherBasicFunctionContractAddress, + Symbol = SymbolForTest + }); + otherBasicAllowanceOutput.Allowance.ShouldBe(1000L); + var treasuryAllowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Owner = DefaultAddress, + Spender = TreasuryContractAddress, + Symbol = SymbolForTest + }); + treasuryAllowanceOutput.Allowance.ShouldBe(5000L); + } + + [Fact] + public async Task MultiTokenContract_SetMaximumBatchApproveCount_Test() + { + var result = await TokenContractStub.SetMaximumBatchApproveCount.SendWithExceptionAsync(new Int32Value + { + Value = 1 + }); + result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + result.TransactionResult.Error.ShouldContain("Unauthorized behavior"); + var maximumBatchApproveCountOutput = await TokenContractStub.GetMaximumBatchApproveCount.CallAsync(new Empty()); + maximumBatchApproveCountOutput.Value.ShouldBe(10); + var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); + var proposalId = await CreateProposalAsync(TokenContractAddress, + defaultParliament, nameof(TokenContractStub.SetMaximumBatchApproveCount), + new Int32Value + { + Value = 1 + }); + await ApproveWithMinersAsync(proposalId); + await ParliamentContractStub.Release.SendAsync(proposalId); + maximumBatchApproveCountOutput = await TokenContractStub.GetMaximumBatchApproveCount.CallAsync(new Empty()); + maximumBatchApproveCountOutput.Value.ShouldBe(1); + var approveBasisResult = (await TokenContractStub.BatchApprove.SendWithExceptionAsync(new BatchApproveInput + { + Value = + { + new ApproveInput + { + Symbol = SymbolForTest, + Amount = 2000L, + Spender = BasicFunctionContractAddress + }, + new ApproveInput + { + Symbol = SymbolForTest, + Amount = 1000L, + Spender = OtherBasicFunctionContractAddress + } + } + })).TransactionResult; + approveBasisResult.Status.ShouldBe(TransactionResultStatus.Failed); + approveBasisResult.Error.ShouldContain("Exceeds the maximum batch approve count"); + } + [Fact(DisplayName = "[MultiToken] Approve token out of owner's balance")] public async Task MultiTokenContract_Approve_OutOfAmount_Test() { From 7d84b6b68d907ede1c373439f576f19d72e8f8a0 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Fri, 1 Mar 2024 09:59:48 +0800 Subject: [PATCH 2/7] feat: update MaximumBatchApproveCount check --- contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index ca328a6260..ad7605faaa 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -642,7 +642,7 @@ public override BoolValue GetTokenIssuerAndOwnerModificationEnabled(Empty input) public override Empty SetMaximumBatchApproveCount(Int32Value input) { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); - Assert(input.Value != 0, "Invalid input."); + Assert(input.Value > 0, "Invalid input."); State.MaximumBatchApproveCount.Value = input.Value; return new Empty(); } From eb4ceaad5304e1fc9100e0faf805445a1d4e9c76 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Fri, 1 Mar 2024 11:53:47 +0800 Subject: [PATCH 3/7] feat: ApproveInputList distinct --- .../TokenContract_Actions.cs | 18 ++++++-- .../BVT/TokenApplicationTests.cs | 42 +++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index ad7605faaa..49f0556bb1 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -251,14 +251,14 @@ public override Empty TransferFrom(TransferFromInput input) public override Empty Approve(ApproveInput input) { + AssertValidInputAddress(input.Spender); + AssertValidToken(input.Symbol, input.Amount); Approve(input.Spender, input.Symbol, input.Amount); return new Empty(); } private void Approve(Address spender, string symbol, long amount) { - AssertValidInputAddress(spender); - AssertValidToken(symbol, amount); State.Allowances[Context.Sender][spender][symbol] = amount; Context.Fire(new Approved { @@ -271,8 +271,18 @@ private void Approve(Address spender, string symbol, long amount) public override Empty BatchApprove(BatchApproveInput input) { - Assert(input.Value.Count <= GetMaximumBatchApproveCount(), "Exceeds the maximum batch approve count."); - foreach (var approve in input.Value) Approve(approve.Spender, approve.Symbol, approve.Amount); + Assert(input != null && input.Value != null, "Invalid input ."); + foreach (var approve in input.Value) + { + AssertValidInputAddress(approve.Spender); + AssertValidToken(approve.Symbol, approve.Amount); + } + + var approveInputList = input.Value.GroupBy(approve => approve.Symbol + approve.Spender, approve => approve) + .Select(approve => approve.Last()).ToList(); + Assert(approveInputList.Count <= GetMaximumBatchApproveCount(), "Exceeds the maximum batch approve count."); + foreach (var approve in approveInputList) + Approve(approve.Spender, approve.Symbol, approve.Amount); return new Empty(); } diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index 07b737dfd0..fe80b7710f 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -222,6 +222,47 @@ public async Task MultiTokenContract_BatchApprove_ContractAddress_Test() Symbol = SymbolForTest }); treasuryAllowanceOutput.Allowance.ShouldBe(5000L); + + approveBasisResult = (await TokenContractStub.BatchApprove.SendAsync(new BatchApproveInput + { + Value = + { + new ApproveInput + { + Symbol = SymbolForTest, + Amount = 1000L, + Spender = BasicFunctionContractAddress + }, + new ApproveInput + { + Symbol = SymbolForTest, + Amount = 3000L, + Spender = BasicFunctionContractAddress + }, + new ApproveInput + { + Symbol = SymbolForTest, + Amount = 3000L, + Spender = TreasuryContractAddress + } + } + })).TransactionResult; + approveBasisResult.Status.ShouldBe(TransactionResultStatus.Mined); + basicAllowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Owner = DefaultAddress, + Spender = BasicFunctionContractAddress, + Symbol = SymbolForTest + }); + basicAllowanceOutput.Allowance.ShouldBe(3000L); + + treasuryAllowanceOutput = await TokenContractStub.GetAllowance.CallAsync(new GetAllowanceInput + { + Owner = DefaultAddress, + Spender = TreasuryContractAddress, + Symbol = SymbolForTest + }); + treasuryAllowanceOutput.Allowance.ShouldBe(3000L); } [Fact] @@ -246,6 +287,7 @@ public async Task MultiTokenContract_SetMaximumBatchApproveCount_Test() await ParliamentContractStub.Release.SendAsync(proposalId); maximumBatchApproveCountOutput = await TokenContractStub.GetMaximumBatchApproveCount.CallAsync(new Empty()); maximumBatchApproveCountOutput.Value.ShouldBe(1); + await CreateTokenAndIssue(); var approveBasisResult = (await TokenContractStub.BatchApprove.SendWithExceptionAsync(new BatchApproveInput { Value = From cc028e2f551de6fc9ebbbfcae38a0b6edb5b722e Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Fri, 1 Mar 2024 14:00:41 +0800 Subject: [PATCH 4/7] feat: method rename --- .../TokenContractConstants.cs | 2 +- .../TokenContract_Actions.cs | 12 ++++++------ protobuf/token_contract_impl.proto | 4 ++-- .../BVT/TokenApplicationTests.cs | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs index db4923fd4e..59eae99a8c 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractConstants.cs @@ -22,5 +22,5 @@ public static class TokenContractConstants public const string SeedCollectionSymbol = "SEED-0"; public const string SeedOwnedSymbolExternalInfoKey = "__seed_owned_symbol"; public const string SeedExpireTimeExternalInfoKey = "__seed_exp_time"; - public const int DefaultMaximumBatchApproveCount = 10; + public const int DefaultMaxBatchApproveCount = 100; } \ 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 49f0556bb1..8ccceb13d9 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -280,7 +280,7 @@ public override Empty BatchApprove(BatchApproveInput input) var approveInputList = input.Value.GroupBy(approve => approve.Symbol + approve.Spender, approve => approve) .Select(approve => approve.Last()).ToList(); - Assert(approveInputList.Count <= GetMaximumBatchApproveCount(), "Exceeds the maximum batch approve count."); + Assert(approveInputList.Count <= GetMaxBatchApproveCount(), "Exceeds the maximum batch approve count."); foreach (var approve in approveInputList) Approve(approve.Spender, approve.Symbol, approve.Amount); return new Empty(); @@ -649,7 +649,7 @@ public override BoolValue GetTokenIssuerAndOwnerModificationEnabled(Empty input) }; } - public override Empty SetMaximumBatchApproveCount(Int32Value input) + public override Empty SetMaxBatchApproveCount(Int32Value input) { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); Assert(input.Value > 0, "Invalid input."); @@ -657,18 +657,18 @@ public override Empty SetMaximumBatchApproveCount(Int32Value input) return new Empty(); } - public override Int32Value GetMaximumBatchApproveCount(Empty input) + public override Int32Value GetMaxBatchApproveCount(Empty input) { return new Int32Value { - Value = GetMaximumBatchApproveCount() + Value = GetMaxBatchApproveCount() }; } - private int GetMaximumBatchApproveCount() + private int GetMaxBatchApproveCount() { var maximumBatchApproveCount = State.MaximumBatchApproveCount.Value == 0 - ? TokenContractConstants.DefaultMaximumBatchApproveCount + ? TokenContractConstants.DefaultMaxBatchApproveCount : State.MaximumBatchApproveCount.Value; return maximumBatchApproveCount; } diff --git a/protobuf/token_contract_impl.proto b/protobuf/token_contract_impl.proto index ece30da14c..5885914e80 100644 --- a/protobuf/token_contract_impl.proto +++ b/protobuf/token_contract_impl.proto @@ -83,7 +83,7 @@ service TokenContractImpl { rpc RemoveTransactionFeeFreeAllowancesConfig (RemoveTransactionFeeFreeAllowancesConfigInput) returns (google.protobuf.Empty) { } - rpc SetMaximumBatchApproveCount (google.protobuf.Int32Value) returns (google.protobuf.Empty) { + rpc SetMaxBatchApproveCount (google.protobuf.Int32Value) returns (google.protobuf.Empty) { } @@ -179,7 +179,7 @@ service TokenContractImpl { option (aelf.is_view) = true; } - rpc GetMaximumBatchApproveCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) { + rpc GetMaxBatchApproveCount (google.protobuf.Empty) returns (google.protobuf.Int32Value) { } } diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index fe80b7710f..fec97b0026 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -268,24 +268,24 @@ public async Task MultiTokenContract_BatchApprove_ContractAddress_Test() [Fact] public async Task MultiTokenContract_SetMaximumBatchApproveCount_Test() { - var result = await TokenContractStub.SetMaximumBatchApproveCount.SendWithExceptionAsync(new Int32Value + var result = await TokenContractStub.SetMaxBatchApproveCount.SendWithExceptionAsync(new Int32Value { Value = 1 }); result.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); result.TransactionResult.Error.ShouldContain("Unauthorized behavior"); - var maximumBatchApproveCountOutput = await TokenContractStub.GetMaximumBatchApproveCount.CallAsync(new Empty()); - maximumBatchApproveCountOutput.Value.ShouldBe(10); + var maximumBatchApproveCountOutput = await TokenContractStub.GetMaxBatchApproveCount.CallAsync(new Empty()); + maximumBatchApproveCountOutput.Value.ShouldBe(100); var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty()); var proposalId = await CreateProposalAsync(TokenContractAddress, - defaultParliament, nameof(TokenContractStub.SetMaximumBatchApproveCount), + defaultParliament, nameof(TokenContractStub.SetMaxBatchApproveCount), new Int32Value { Value = 1 }); await ApproveWithMinersAsync(proposalId); await ParliamentContractStub.Release.SendAsync(proposalId); - maximumBatchApproveCountOutput = await TokenContractStub.GetMaximumBatchApproveCount.CallAsync(new Empty()); + maximumBatchApproveCountOutput = await TokenContractStub.GetMaxBatchApproveCount.CallAsync(new Empty()); maximumBatchApproveCountOutput.Value.ShouldBe(1); await CreateTokenAndIssue(); var approveBasisResult = (await TokenContractStub.BatchApprove.SendWithExceptionAsync(new BatchApproveInput From b4263e3d2c5ce5930c08e842afb5b70e501794ec Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Fri, 1 Mar 2024 16:25:25 +0800 Subject: [PATCH 5/7] feat: update BatchApproveInputCount check --- contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 8ccceb13d9..5ba46b9623 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -272,15 +272,14 @@ private void Approve(Address spender, string symbol, long amount) public override Empty BatchApprove(BatchApproveInput input) { Assert(input != null && input.Value != null, "Invalid input ."); + Assert(input.Value.Count <= GetMaxBatchApproveCount(), "Exceeds the maximum batch approve count."); foreach (var approve in input.Value) { AssertValidInputAddress(approve.Spender); AssertValidToken(approve.Symbol, approve.Amount); } - var approveInputList = input.Value.GroupBy(approve => approve.Symbol + approve.Spender, approve => approve) .Select(approve => approve.Last()).ToList(); - Assert(approveInputList.Count <= GetMaxBatchApproveCount(), "Exceeds the maximum batch approve count."); foreach (var approve in approveInputList) Approve(approve.Spender, approve.Symbol, approve.Amount); return new Empty(); From aa1b5b30bf204472105826df62327a9c12bcd764 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Sun, 3 Mar 2024 14:35:05 +0800 Subject: [PATCH 6/7] feat:rename MaxBatchApproveCount --- .../AElf.Contracts.MultiToken/TokenContractState.cs | 2 +- .../AElf.Contracts.MultiToken/TokenContract_Actions.cs | 10 +++++----- .../BVT/TokenApplicationTests.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContractState.cs b/contract/AElf.Contracts.MultiToken/TokenContractState.cs index dc386b311b..b687cf1598 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContractState.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContractState.cs @@ -66,5 +66,5 @@ public partial class TokenContractState : ContractState public SingletonState TokenIssuerAndOwnerModificationDisabled { get; set; } - public SingletonState MaximumBatchApproveCount { get; set; } + public SingletonState MaxBatchApproveCount { 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 5ba46b9623..08ff42a689 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -272,7 +272,7 @@ private void Approve(Address spender, string symbol, long amount) public override Empty BatchApprove(BatchApproveInput input) { Assert(input != null && input.Value != null, "Invalid input ."); - Assert(input.Value.Count <= GetMaxBatchApproveCount(), "Exceeds the maximum batch approve count."); + Assert(input.Value.Count <= GetMaxBatchApproveCount(), "Exceeds the max batch approve count."); foreach (var approve in input.Value) { AssertValidInputAddress(approve.Spender); @@ -652,7 +652,7 @@ public override Empty SetMaxBatchApproveCount(Int32Value input) { AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); Assert(input.Value > 0, "Invalid input."); - State.MaximumBatchApproveCount.Value = input.Value; + State.MaxBatchApproveCount.Value = input.Value; return new Empty(); } @@ -666,9 +666,9 @@ public override Int32Value GetMaxBatchApproveCount(Empty input) private int GetMaxBatchApproveCount() { - var maximumBatchApproveCount = State.MaximumBatchApproveCount.Value == 0 + var maxBatchApproveCount = State.MaxBatchApproveCount.Value == 0 ? TokenContractConstants.DefaultMaxBatchApproveCount - : State.MaximumBatchApproveCount.Value; - return maximumBatchApproveCount; + : State.MaxBatchApproveCount.Value; + return maxBatchApproveCount; } } \ 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 fec97b0026..a63eba113c 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -307,7 +307,7 @@ public async Task MultiTokenContract_SetMaximumBatchApproveCount_Test() } })).TransactionResult; approveBasisResult.Status.ShouldBe(TransactionResultStatus.Failed); - approveBasisResult.Error.ShouldContain("Exceeds the maximum batch approve count"); + approveBasisResult.Error.ShouldContain("Exceeds the max batch approve count"); } [Fact(DisplayName = "[MultiToken] Approve token out of owner's balance")] From 4f7f5639c31e6518620935f5a5af413555d67408 Mon Sep 17 00:00:00 2001 From: "louis.li" Date: Sun, 3 Mar 2024 17:11:41 +0800 Subject: [PATCH 7/7] feat:update BatchApprove check --- .../AElf.Contracts.MultiToken/TokenContract_Actions.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 162ba78c01..2a477cafe7 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -272,7 +272,7 @@ private void Approve(Address spender, string symbol, long amount) public override Empty BatchApprove(BatchApproveInput input) { - Assert(input != null && input.Value != null, "Invalid input ."); + Assert(input != null && input.Value != null && input.Value.Count > 0, "Invalid input ."); Assert(input.Value.Count <= GetMaxBatchApproveCount(), "Exceeds the max batch approve count."); foreach (var approve in input.Value) { @@ -651,8 +651,8 @@ public override BoolValue GetTokenIssuerAndOwnerModificationEnabled(Empty input) public override Empty SetMaxBatchApproveCount(Int32Value input) { - AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); Assert(input.Value > 0, "Invalid input."); + AssertSenderAddressWith(GetDefaultParliamentController().OwnerAddress); State.MaxBatchApproveCount.Value = input.Value; return new Empty(); } @@ -667,9 +667,8 @@ public override Int32Value GetMaxBatchApproveCount(Empty input) private int GetMaxBatchApproveCount() { - var maxBatchApproveCount = State.MaxBatchApproveCount.Value == 0 + return State.MaxBatchApproveCount.Value == 0 ? TokenContractConstants.DefaultMaxBatchApproveCount : State.MaxBatchApproveCount.Value; - return maxBatchApproveCount; } } \ No newline at end of file