From 41bd58278e4b670e3edd0bffb396f7e05b526208 Mon Sep 17 00:00:00 2001 From: Hwee-Boon Yar Date: Tue, 3 Jan 2023 14:02:32 +0800 Subject: [PATCH] [Tests] Add test case to protect ERC1155 token ID detection --- AlphaWallet.xcodeproj/project.pbxproj | 12 ++++++++++ .../RPC/CallSmartContractFunctionTests.swift | 24 +++++++++++++++++++ .../RPC/CallSmartContractFunction.swift | 7 +++++- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 AlphaWalletTests/modules/AlphaWalletFoundation/RPC/CallSmartContractFunctionTests.swift diff --git a/AlphaWallet.xcodeproj/project.pbxproj b/AlphaWallet.xcodeproj/project.pbxproj index d4fbad57b..209c00c58 100644 --- a/AlphaWallet.xcodeproj/project.pbxproj +++ b/AlphaWallet.xcodeproj/project.pbxproj @@ -343,6 +343,7 @@ 5E7C7BFE9C8CAA3E204B1FAA /* TokenRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7F89E3480D3680750EA9 /* TokenRowView.swift */; }; 5E7C7C0D3181CD31A581AEBE /* EditBookmarkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7F55495A6095B3E86248 /* EditBookmarkViewController.swift */; }; 5E7C7C0FAC500A6651E663FD /* TransferTokensCardQuantitySelectionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C703BA1D0E9ACB7399155 /* TransferTokensCardQuantitySelectionViewModel.swift */; }; + 5E7C7C53FC6F46DF501E8AD1 /* CallSmartContractFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C78E17FA9C8C892EEA355 /* CallSmartContractFunctionTests.swift */; }; 5E7C7C60BAF11B0BD135FC1E /* GroupActivityViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7E58DD0CF4E2B35B6ED2 /* GroupActivityViewCell.swift */; }; 5E7C7C869A09FD09DCE77EE6 /* ActivityCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C760CC5A9E144BDB5451D /* ActivityCellViewModel.swift */; }; 5E7C7C8C689E972389F4A564 /* CrashReporterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C76A087FB8690364F8552 /* CrashReporterViewController.swift */; }; @@ -1158,6 +1159,7 @@ 5E7C78CDFEB86A8356EA5818 /* TokenCardRowViewProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenCardRowViewProtocol.swift; sourceTree = ""; }; 5E7C78CF45AA54EF8647C44B /* SeedPhraseBackupIntroductionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeedPhraseBackupIntroductionViewController.swift; sourceTree = ""; }; 5E7C78DB6F47344EBBC2567F /* ChainIdTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChainIdTests.swift; sourceTree = ""; }; + 5E7C78E17FA9C8C892EEA355 /* CallSmartContractFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallSmartContractFunctionTests.swift; sourceTree = ""; }; 5E7C78E5C8FAEA752B32626D /* UIActivityViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIActivityViewController.swift; sourceTree = ""; }; 5E7C78EFAF641C41F06C46BF /* ServersCoordinatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServersCoordinatorTests.swift; sourceTree = ""; }; 5E7C7900C580D38703DEB396 /* FakeDomainResolutionService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FakeDomainResolutionService.swift; sourceTree = ""; }; @@ -3017,6 +3019,14 @@ path = Models; sourceTree = ""; }; + 5E7C77D279AE7B89A9C8D2E0 /* RPC */ = { + isa = PBXGroup; + children = ( + 5E7C78E17FA9C8C892EEA355 /* CallSmartContractFunctionTests.swift */, + ); + path = RPC; + sourceTree = ""; + }; 5E7C78095E4361EDA4CC72B1 /* Types */ = { isa = PBXGroup; children = ( @@ -3081,6 +3091,7 @@ 8722324528D8607F001A9BCC /* Oneinch */, 5E7C733DEBED923B8D281682 /* Tokens */, 5E7C7D5C0666C0010B6343C8 /* Browser */, + 5E7C77D279AE7B89A9C8D2E0 /* RPC */, ); path = AlphaWalletFoundation; sourceTree = ""; @@ -5729,6 +5740,7 @@ 5E7C74B9BD63DEFE074BB80D /* ErrorTests.swift in Sources */, 5E7C7A0D678C2CE065CC8BB1 /* Erc1155TokenIdsFetcherTests.swift in Sources */, 5E7C7D7F197980329CFB502D /* DappCommandTests.swift in Sources */, + 5E7C7C53FC6F46DF501E8AD1 /* CallSmartContractFunctionTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/AlphaWalletTests/modules/AlphaWalletFoundation/RPC/CallSmartContractFunctionTests.swift b/AlphaWalletTests/modules/AlphaWalletFoundation/RPC/CallSmartContractFunctionTests.swift new file mode 100644 index 000000000..19fad5591 --- /dev/null +++ b/AlphaWalletTests/modules/AlphaWalletFoundation/RPC/CallSmartContractFunctionTests.swift @@ -0,0 +1,24 @@ +// Copyright © 2023 Stormbird PTE. LTD. + +import XCTest +import AlphaWalletWeb3 +@testable import AlphaWalletFoundation + +class CallSmartContractFunctionTests: XCTestCase { + //This is important to assert that the caching key is different event whe the event is the same, because we use the same ERC1155 transfer event for both checking send and receive events + func testEventLogCachingKey() { + let contractAddress = AlphaWallet.Address(string: "0xbbce83173d5c1D122AE64856b4Af0D5AE07Fa362")! + let server = RPCServer.main + let eventName = "TransferSingle" + let abiString = AlphaWallet.Ethereum.ABI.erc1155String + let nullFilter: [EventFilterable]? = nil + let recipientAddress = EthereumAddress(AlphaWallet.Address(string: "0x3EA245FC5909A55e426a2C044Aa4b48a143F9819")!.eip55String)! + let sendParameterFilters: [[EventFilterable]?] = [nullFilter, [recipientAddress], nullFilter] + let receiveParameterFilters: [[EventFilterable]?] = [nullFilter, nullFilter, [recipientAddress]] + let sendFilter = EventFilter(fromBlock: .blockNumber(0), toBlock: .blockNumber(100), addresses: nil, parameterFilters: sendParameterFilters) + let receiveFilter = EventFilter(fromBlock: .blockNumber(0), toBlock: .blockNumber(100), addresses: nil, parameterFilters: receiveParameterFilters) + let sendCachingKey = GetEventLogs.generateEventLogCachingKey(contractAddress: contractAddress, server: server, eventName: eventName, abiString: abiString, filter: sendFilter) + let receiveCachingKey = GetEventLogs.generateEventLogCachingKey(contractAddress: contractAddress, server: server, eventName: eventName, abiString: abiString, filter: receiveFilter) + XCTAssertNotEqual(sendCachingKey, receiveCachingKey) + } +} diff --git a/modules/AlphaWalletFoundation/AlphaWalletFoundation/RPC/CallSmartContractFunction.swift b/modules/AlphaWalletFoundation/AlphaWalletFoundation/RPC/CallSmartContractFunction.swift index 85444e0db..74b2abafb 100644 --- a/modules/AlphaWalletFoundation/AlphaWalletFoundation/RPC/CallSmartContractFunction.swift +++ b/modules/AlphaWalletFoundation/AlphaWalletFoundation/RPC/CallSmartContractFunction.swift @@ -140,7 +140,7 @@ final class GetEventLogs { .value(contractAddress) }.then(on: queue, { [weak self, queue] contractAddress -> Promise<[EventParserResultProtocol]> in //It is fine to use the default String representation of `EventFilter` in the cache key. But it is crucial to include it, because the actual variables of the event log fetching are in there. For example ERC1155's `TransferSingle` event is used for fetching both send and receive single token ID events. We can ony tell based on the arguments in `EventFilter` whether it is a send or receive - let key = "\(contractAddress.eip55String)-\(server.chainID)-\(eventName)-\(abiString)-\(filter)" + let key = Self.generateEventLogCachingKey(contractAddress: contractAddress, server: server, eventName: eventName, abiString: abiString, filter: filter) if let promise = self?.inFlightPromises[key] { return promise @@ -161,4 +161,9 @@ final class GetEventLogs { throw error }) } + + //Exposed for testing + static func generateEventLogCachingKey(contractAddress: AlphaWallet.Address, server: RPCServer, eventName: String, abiString: String, filter: EventFilter) -> String { + "\(contractAddress.eip55String)-\(server.chainID)-\(eventName)-\(abiString)-\(filter)" + } }