From a61889e1c75b04f7ddf8323a298e1342ec45f155 Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Sat, 28 Mar 2026 17:11:24 +0000 Subject: [PATCH 1/7] Initial plan From 6a1df03f3e7cc36da2147bc3dc8beddea7a8a4f9 Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Sat, 28 Mar 2026 17:15:34 +0000 Subject: [PATCH 2/7] Add chain ID to distributed lock cache key for better multi-chain isolation Agent-Logs-Url: https://github.com/Tricksfor-Organization/DistributedNonce/sessions/9fd81540-7755-4bd3-a2ff-466d28379204 Co-authored-by: Phelecks <47243363+Phelecks@users.noreply.github.com> --- .../Services/DistributedNonceService.cs | 27 ++++++- .../DistributedNonceIntegrationTests.cs | 78 ++++++++++++++++++- 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/DistributedNonce/Services/DistributedNonceService.cs b/src/DistributedNonce/Services/DistributedNonceService.cs index 6a669eb..d49d520 100644 --- a/src/DistributedNonce/Services/DistributedNonceService.cs +++ b/src/DistributedNonce/Services/DistributedNonceService.cs @@ -2,6 +2,7 @@ using DistributedLockManager.Interfaces; using Nethereum.Hex.HexTypes; using Nethereum.JsonRpc.Client; +using Nethereum.RPC.Eth; using Nethereum.RPC.Eth.DTOs; using Nethereum.RPC.Eth.Transactions; using Nethereum.RPC.NonceServices; @@ -22,16 +23,33 @@ private sealed class CreateDistributedNonceServiceInstance(string accountAddress { private readonly IDistributedLockService _distributedLockService = distributedLockService; private readonly string _address = accountAddress; + private BigInteger? _chainId = null; public IClient Client { get; set; } = client; public BigInteger CurrentNonce { get; set; } = -1; public bool UseLatestTransactionsOnly { get; set; } = useLatestTransactionsOnly; + private async Task GetChainIdAsync() + { + if (_chainId.HasValue) + { + return _chainId.Value; + } + + var ethChainId = new EthChainId(Client); + var chainIdHex = await ethChainId.SendRequestAsync().ConfigureAwait(continueOnCapturedContext: false); + _chainId = chainIdHex.Value; + return _chainId.Value; + } + public async Task GetNextNonceAsync() { HexBigInteger nextNonce = new(BigInteger.Zero); EthGetTransactionCount ethGetTransactionCount = new(Client); + // Get chain ID to include in the lock key for better isolation + var chainId = await GetChainIdAsync(); + await _distributedLockService.RunWithLockAsync(func: async () => { try @@ -42,7 +60,7 @@ await _distributedLockService.RunWithLockAsync(func: async () => block = BlockParameter.CreateLatest(); } - HexBigInteger hexBigInteger = + HexBigInteger hexBigInteger = await ethGetTransactionCount.SendRequestAsync(_address, block). ConfigureAwait(continueOnCapturedContext: false); if (hexBigInteger.Value <= CurrentNonce) @@ -61,13 +79,16 @@ await ethGetTransactionCount.SendRequestAsync(_address, block). { throw new InvalidOperationException($"An error occurred during get next nonce for account: {_address}, {exception.Message}"); } - }, $"{LockKeyPrefix}{_address}", CancellationToken.None); + }, $"{LockKeyPrefix}{chainId}_{_address}", CancellationToken.None); return nextNonce; } public async Task ResetNonceAsync() { + // Get chain ID to include in the lock key for better isolation + var chainId = await GetChainIdAsync(); + await _distributedLockService.RunWithLockAsync(func: async () => { try @@ -79,7 +100,7 @@ await _distributedLockService.RunWithLockAsync(func: async () => { throw new InvalidOperationException($"An error occurred during reset nonce for account: {_address}."); } - }, $"{LockKeyPrefix}{_address}", CancellationToken.None); + }, $"{LockKeyPrefix}{chainId}_{_address}", CancellationToken.None); } } } \ No newline at end of file diff --git a/tests/DistributedNonce.Tests/DistributedNonceIntegrationTests.cs b/tests/DistributedNonce.Tests/DistributedNonceIntegrationTests.cs index 77996fe..65f2681 100644 --- a/tests/DistributedNonce.Tests/DistributedNonceIntegrationTests.cs +++ b/tests/DistributedNonce.Tests/DistributedNonceIntegrationTests.cs @@ -59,12 +59,32 @@ public async Task OneTimeSetUp() _clientReturns5 = Substitute.For(); _clientReturns5 .SendRequestAsync(Arg.Any()) - .Returns(Task.FromResult(new HexBigInteger(new BigInteger(5)))); + .Returns(callInfo => + { + var request = callInfo.Arg(); + // Mock eth_chainId to return chain ID 1 (Ethereum mainnet) + if (request.Method == "eth_chainId") + { + return Task.FromResult(new HexBigInteger(new BigInteger(1))); + } + // Mock eth_getTransactionCount to return 5 + return Task.FromResult(new HexBigInteger(new BigInteger(5))); + }); _clientReturns7 = Substitute.For(); _clientReturns7 .SendRequestAsync(Arg.Any()) - .Returns(Task.FromResult(new HexBigInteger(new BigInteger(7)))); + .Returns(callInfo => + { + var request = callInfo.Arg(); + // Mock eth_chainId to return chain ID 1 (Ethereum mainnet) + if (request.Method == "eth_chainId") + { + return Task.FromResult(new HexBigInteger(new BigInteger(1))); + } + // Mock eth_getTransactionCount to return 7 + return Task.FromResult(new HexBigInteger(new BigInteger(7))); + }); } [OneTimeTearDown] @@ -170,4 +190,58 @@ public async Task GetNextNonceAsync_Concurrent_Calls_Produce_Unique_Sequential_V var expected = Enumerable.Range(7, count).Select(i => new BigInteger(i)); values.ShouldBe(expected, ignoreOrder: true); } + + [Test, Order(6)] + public async Task GetNextNonceAsync_DifferentChainIds_UsesDifferentLockKeys() + { + if (scope is null) Assert.Fail("Service scope not initialized"); + var sp = scope!.ServiceProvider; + var service = sp.GetRequiredService(); + + // Create a client that returns chain ID 1 (Ethereum mainnet) + var clientChain1 = Substitute.For(); + clientChain1 + .SendRequestAsync(Arg.Any()) + .Returns(callInfo => + { + var request = callInfo.Arg(); + if (request.Method == "eth_chainId") + { + return Task.FromResult(new HexBigInteger(new BigInteger(1))); + } + return Task.FromResult(new HexBigInteger(new BigInteger(10))); + }); + + // Create a client that returns chain ID 137 (Polygon mainnet) + var clientChain137 = Substitute.For(); + clientChain137 + .SendRequestAsync(Arg.Any()) + .Returns(callInfo => + { + var request = callInfo.Arg(); + if (request.Method == "eth_chainId") + { + return Task.FromResult(new HexBigInteger(new BigInteger(137))); + } + return Task.FromResult(new HexBigInteger(new BigInteger(20))); + }); + + var address = "0x0000000000000000000000000000000000000004"; + + // Get nonce services for the same address but different chains + var nonceServiceChain1 = service.GetInstance(address, clientChain1); + var nonceServiceChain137 = service.GetInstance(address, clientChain137); + + // Get nonces from both chains + var nonceChain1 = await nonceServiceChain1.GetNextNonceAsync(); + var nonceChain137 = await nonceServiceChain137.GetNextNonceAsync(); + + // They should return different nonces because they use different lock keys + // Chain 1 returns 10, Chain 137 returns 20 + Assert.Multiple(() => + { + Assert.That(nonceChain1.Value, Is.EqualTo(new BigInteger(10)), "Chain 1 should return nonce 10"); + Assert.That(nonceChain137.Value, Is.EqualTo(new BigInteger(20)), "Chain 137 should return nonce 20"); + }); + } } From a19820d6c13bc646dafd09ed1f743700ead582f8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 17:29:51 +0000 Subject: [PATCH 3/7] Wrap GetChainIdAsync in try/catch with consistent error handling in both methods Agent-Logs-Url: https://github.com/Tricksfor-Organization/DistributedNonce/sessions/d9924183-4db0-4706-a9b3-9f7cc8733f6f Co-authored-by: Phelecks <47243363+Phelecks@users.noreply.github.com> --- .../Services/DistributedNonceService.cs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/DistributedNonce/Services/DistributedNonceService.cs b/src/DistributedNonce/Services/DistributedNonceService.cs index d49d520..b30568e 100644 --- a/src/DistributedNonce/Services/DistributedNonceService.cs +++ b/src/DistributedNonce/Services/DistributedNonceService.cs @@ -47,8 +47,15 @@ public async Task GetNextNonceAsync() EthGetTransactionCount ethGetTransactionCount = new(Client); - // Get chain ID to include in the lock key for better isolation - var chainId = await GetChainIdAsync(); + BigInteger chainId; + try + { + chainId = await GetChainIdAsync().ConfigureAwait(continueOnCapturedContext: false); + } + catch (Exception exception) + { + throw new InvalidOperationException($"An error occurred during get next nonce for account: {_address}", exception); + } await _distributedLockService.RunWithLockAsync(func: async () => { @@ -86,8 +93,15 @@ await ethGetTransactionCount.SendRequestAsync(_address, block). public async Task ResetNonceAsync() { - // Get chain ID to include in the lock key for better isolation - var chainId = await GetChainIdAsync(); + BigInteger chainId; + try + { + chainId = await GetChainIdAsync().ConfigureAwait(continueOnCapturedContext: false); + } + catch (Exception exception) + { + throw new InvalidOperationException($"An error occurred during reset nonce for account: {_address}", exception); + } await _distributedLockService.RunWithLockAsync(func: async () => { From dbe70218bb088869ebdead7df286b3f7faab8315 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 17:36:45 +0000 Subject: [PATCH 4/7] Make GetChainIdAsync concurrency-safe with SemaphoreSlim and fix Client setter Agent-Logs-Url: https://github.com/Tricksfor-Organization/DistributedNonce/sessions/9dc86feb-2962-4e16-99b1-ad4a766e45d9 Co-authored-by: Phelecks <47243363+Phelecks@users.noreply.github.com> --- .../Services/DistributedNonceService.cs | 60 +++++++++++++++++-- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/src/DistributedNonce/Services/DistributedNonceService.cs b/src/DistributedNonce/Services/DistributedNonceService.cs index b30568e..2b34371 100644 --- a/src/DistributedNonce/Services/DistributedNonceService.cs +++ b/src/DistributedNonce/Services/DistributedNonceService.cs @@ -19,12 +19,39 @@ public INonceService GetInstance(string address, IClient client, bool useLatestT return new CreateDistributedNonceServiceInstance(address, client, _distributedLockService, useLatestTransactionsOnly); } - private sealed class CreateDistributedNonceServiceInstance(string accountAddress, IClient client, IDistributedLockService distributedLockService, bool useLatestTransactionsOnly = false) : INonceService + private sealed class CreateDistributedNonceServiceInstance(string accountAddress, IClient client, IDistributedLockService distributedLockService, bool useLatestTransactionsOnly = false) : INonceService, IDisposable { private readonly IDistributedLockService _distributedLockService = distributedLockService; private readonly string _address = accountAddress; + private readonly SemaphoreSlim _chainIdSemaphore = new(1, 1); + private IClient _client = client; private BigInteger? _chainId = null; - public IClient Client { get; set; } = client; + private int _disposed = 0; + public IClient Client + { + get => _client; + set + { + if (value is null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (!ReferenceEquals(_client, value)) + { + _chainIdSemaphore.Wait(); + try + { + _client = value; + _chainId = null; + } + finally + { + _chainIdSemaphore.Release(); + } + } + } + } public BigInteger CurrentNonce { get; set; } = -1; public bool UseLatestTransactionsOnly { get; set; } = useLatestTransactionsOnly; @@ -35,10 +62,23 @@ private async Task GetChainIdAsync() return _chainId.Value; } - var ethChainId = new EthChainId(Client); - var chainIdHex = await ethChainId.SendRequestAsync().ConfigureAwait(continueOnCapturedContext: false); - _chainId = chainIdHex.Value; - return _chainId.Value; + await _chainIdSemaphore.WaitAsync().ConfigureAwait(continueOnCapturedContext: false); + try + { + if (_chainId.HasValue) + { + return _chainId.Value; + } + + var ethChainId = new EthChainId(Client); + var chainIdHex = await ethChainId.SendRequestAsync().ConfigureAwait(continueOnCapturedContext: false); + _chainId = chainIdHex.Value; + return _chainId.Value; + } + finally + { + _chainIdSemaphore.Release(); + } } public async Task GetNextNonceAsync() @@ -116,5 +156,13 @@ await _distributedLockService.RunWithLockAsync(func: async () => } }, $"{LockKeyPrefix}{chainId}_{_address}", CancellationToken.None); } + + public void Dispose() + { + if (Interlocked.CompareExchange(ref _disposed, 1, 0) == 0) + { + _chainIdSemaphore.Dispose(); + } + } } } \ No newline at end of file From 256e5e5ec1e91388bd8b0c35746bebeed5ca45d1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 17:48:13 +0000 Subject: [PATCH 5/7] Replace SemaphoreSlim with distributed lock for chain ID initialization Agent-Logs-Url: https://github.com/Tricksfor-Organization/DistributedNonce/sessions/3ec7ab5c-f50a-4115-8404-cd7419391e90 Co-authored-by: Phelecks <47243363+Phelecks@users.noreply.github.com> --- .../Services/DistributedNonceService.cs | 62 +++++++------------ 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/src/DistributedNonce/Services/DistributedNonceService.cs b/src/DistributedNonce/Services/DistributedNonceService.cs index 2b34371..7797ddc 100644 --- a/src/DistributedNonce/Services/DistributedNonceService.cs +++ b/src/DistributedNonce/Services/DistributedNonceService.cs @@ -19,14 +19,12 @@ public INonceService GetInstance(string address, IClient client, bool useLatestT return new CreateDistributedNonceServiceInstance(address, client, _distributedLockService, useLatestTransactionsOnly); } - private sealed class CreateDistributedNonceServiceInstance(string accountAddress, IClient client, IDistributedLockService distributedLockService, bool useLatestTransactionsOnly = false) : INonceService, IDisposable + private sealed class CreateDistributedNonceServiceInstance(string accountAddress, IClient client, IDistributedLockService distributedLockService, bool useLatestTransactionsOnly = false) : INonceService { private readonly IDistributedLockService _distributedLockService = distributedLockService; private readonly string _address = accountAddress; - private readonly SemaphoreSlim _chainIdSemaphore = new(1, 1); private IClient _client = client; private BigInteger? _chainId = null; - private int _disposed = 0; public IClient Client { get => _client; @@ -39,46 +37,30 @@ public IClient Client if (!ReferenceEquals(_client, value)) { - _chainIdSemaphore.Wait(); - try - { - _client = value; - _chainId = null; - } - finally - { - _chainIdSemaphore.Release(); - } + _client = value; + _chainId = null; } } } public BigInteger CurrentNonce { get; set; } = -1; public bool UseLatestTransactionsOnly { get; set; } = useLatestTransactionsOnly; - private async Task GetChainIdAsync() + private async Task EnsureChainIdAsync() { if (_chainId.HasValue) { - return _chainId.Value; + return; } - await _chainIdSemaphore.WaitAsync().ConfigureAwait(continueOnCapturedContext: false); - try + await _distributedLockService.RunWithLockAsync(func: async () => { - if (_chainId.HasValue) + if (!_chainId.HasValue) { - return _chainId.Value; + var ethChainId = new EthChainId(Client); + var chainIdHex = await ethChainId.SendRequestAsync().ConfigureAwait(continueOnCapturedContext: false); + _chainId = chainIdHex.Value; } - - var ethChainId = new EthChainId(Client); - var chainIdHex = await ethChainId.SendRequestAsync().ConfigureAwait(continueOnCapturedContext: false); - _chainId = chainIdHex.Value; - return _chainId.Value; - } - finally - { - _chainIdSemaphore.Release(); - } + }, $"{LockKeyPrefix}chainId_{_address}", CancellationToken.None); } public async Task GetNextNonceAsync() @@ -90,7 +72,12 @@ public async Task GetNextNonceAsync() BigInteger chainId; try { - chainId = await GetChainIdAsync().ConfigureAwait(continueOnCapturedContext: false); + await EnsureChainIdAsync().ConfigureAwait(continueOnCapturedContext: false); + chainId = _chainId ?? throw new InvalidOperationException($"Chain ID could not be determined for account: {_address}"); + } + catch (InvalidOperationException) + { + throw; } catch (Exception exception) { @@ -136,7 +123,12 @@ public async Task ResetNonceAsync() BigInteger chainId; try { - chainId = await GetChainIdAsync().ConfigureAwait(continueOnCapturedContext: false); + await EnsureChainIdAsync().ConfigureAwait(continueOnCapturedContext: false); + chainId = _chainId ?? throw new InvalidOperationException($"Chain ID could not be determined for account: {_address}"); + } + catch (InvalidOperationException) + { + throw; } catch (Exception exception) { @@ -156,13 +148,5 @@ await _distributedLockService.RunWithLockAsync(func: async () => } }, $"{LockKeyPrefix}{chainId}_{_address}", CancellationToken.None); } - - public void Dispose() - { - if (Interlocked.CompareExchange(ref _disposed, 1, 0) == 0) - { - _chainIdSemaphore.Dispose(); - } - } } } \ No newline at end of file From 0eb4c8455960ded72e963805e0a7047255605158 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 18:02:32 +0000 Subject: [PATCH 6/7] Consolidate everything into a single distributed lock per operation Agent-Logs-Url: https://github.com/Tricksfor-Organization/DistributedNonce/sessions/58932dcb-4ab5-432c-9e86-2902fa5631f2 Co-authored-by: Phelecks <47243363+Phelecks@users.noreply.github.com> --- .../Services/DistributedNonceService.cs | 63 ++++--------------- .../DistributedNonceIntegrationTests.cs | 6 +- 2 files changed, 14 insertions(+), 55 deletions(-) diff --git a/src/DistributedNonce/Services/DistributedNonceService.cs b/src/DistributedNonce/Services/DistributedNonceService.cs index 7797ddc..089a99c 100644 --- a/src/DistributedNonce/Services/DistributedNonceService.cs +++ b/src/DistributedNonce/Services/DistributedNonceService.cs @@ -45,49 +45,23 @@ public IClient Client public BigInteger CurrentNonce { get; set; } = -1; public bool UseLatestTransactionsOnly { get; set; } = useLatestTransactionsOnly; - private async Task EnsureChainIdAsync() - { - if (_chainId.HasValue) - { - return; - } - - await _distributedLockService.RunWithLockAsync(func: async () => - { - if (!_chainId.HasValue) - { - var ethChainId = new EthChainId(Client); - var chainIdHex = await ethChainId.SendRequestAsync().ConfigureAwait(continueOnCapturedContext: false); - _chainId = chainIdHex.Value; - } - }, $"{LockKeyPrefix}chainId_{_address}", CancellationToken.None); - } - public async Task GetNextNonceAsync() { HexBigInteger nextNonce = new(BigInteger.Zero); - EthGetTransactionCount ethGetTransactionCount = new(Client); - - BigInteger chainId; - try - { - await EnsureChainIdAsync().ConfigureAwait(continueOnCapturedContext: false); - chainId = _chainId ?? throw new InvalidOperationException($"Chain ID could not be determined for account: {_address}"); - } - catch (InvalidOperationException) - { - throw; - } - catch (Exception exception) - { - throw new InvalidOperationException($"An error occurred during get next nonce for account: {_address}", exception); - } - await _distributedLockService.RunWithLockAsync(func: async () => { try { + if (!_chainId.HasValue) + { + var ethChainId = new EthChainId(Client); + var chainIdHex = await ethChainId.SendRequestAsync().ConfigureAwait(continueOnCapturedContext: false); + _chainId = chainIdHex.Value; + } + + EthGetTransactionCount ethGetTransactionCount = new(Client); + BlockParameter block = BlockParameter.CreatePending(); if (UseLatestTransactionsOnly) { @@ -113,28 +87,13 @@ await ethGetTransactionCount.SendRequestAsync(_address, block). { throw new InvalidOperationException($"An error occurred during get next nonce for account: {_address}, {exception.Message}"); } - }, $"{LockKeyPrefix}{chainId}_{_address}", CancellationToken.None); + }, $"{LockKeyPrefix}{_address}", CancellationToken.None); return nextNonce; } public async Task ResetNonceAsync() { - BigInteger chainId; - try - { - await EnsureChainIdAsync().ConfigureAwait(continueOnCapturedContext: false); - chainId = _chainId ?? throw new InvalidOperationException($"Chain ID could not be determined for account: {_address}"); - } - catch (InvalidOperationException) - { - throw; - } - catch (Exception exception) - { - throw new InvalidOperationException($"An error occurred during reset nonce for account: {_address}", exception); - } - await _distributedLockService.RunWithLockAsync(func: async () => { try @@ -146,7 +105,7 @@ await _distributedLockService.RunWithLockAsync(func: async () => { throw new InvalidOperationException($"An error occurred during reset nonce for account: {_address}."); } - }, $"{LockKeyPrefix}{chainId}_{_address}", CancellationToken.None); + }, $"{LockKeyPrefix}{_address}", CancellationToken.None); } } } \ No newline at end of file diff --git a/tests/DistributedNonce.Tests/DistributedNonceIntegrationTests.cs b/tests/DistributedNonce.Tests/DistributedNonceIntegrationTests.cs index 65f2681..a03da29 100644 --- a/tests/DistributedNonce.Tests/DistributedNonceIntegrationTests.cs +++ b/tests/DistributedNonce.Tests/DistributedNonceIntegrationTests.cs @@ -192,7 +192,7 @@ public async Task GetNextNonceAsync_Concurrent_Calls_Produce_Unique_Sequential_V } [Test, Order(6)] - public async Task GetNextNonceAsync_DifferentChainIds_UsesDifferentLockKeys() + public async Task GetNextNonceAsync_DifferentChains_ProduceIndependentNonces() { if (scope is null) Assert.Fail("Service scope not initialized"); var sp = scope!.ServiceProvider; @@ -228,7 +228,7 @@ public async Task GetNextNonceAsync_DifferentChainIds_UsesDifferentLockKeys() var address = "0x0000000000000000000000000000000000000004"; - // Get nonce services for the same address but different chains + // Each chain uses a separate service instance, so nonce counters are independent var nonceServiceChain1 = service.GetInstance(address, clientChain1); var nonceServiceChain137 = service.GetInstance(address, clientChain137); @@ -236,7 +236,7 @@ public async Task GetNextNonceAsync_DifferentChainIds_UsesDifferentLockKeys() var nonceChain1 = await nonceServiceChain1.GetNextNonceAsync(); var nonceChain137 = await nonceServiceChain137.GetNextNonceAsync(); - // They should return different nonces because they use different lock keys + // They should return different nonces because they have independent nonce counters // Chain 1 returns 10, Chain 137 returns 20 Assert.Multiple(() => { From f2d1cfb5cbb87c7b3f015864410183198751e41e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 18:32:45 +0000 Subject: [PATCH 7/7] Use ArgumentNullException.ThrowIfNull in Client property setter Agent-Logs-Url: https://github.com/Tricksfor-Organization/DistributedNonce/sessions/8ed1eb1f-ba24-4521-af20-ecede7081a1f Co-authored-by: Phelecks <47243363+Phelecks@users.noreply.github.com> --- src/DistributedNonce/Services/DistributedNonceService.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/DistributedNonce/Services/DistributedNonceService.cs b/src/DistributedNonce/Services/DistributedNonceService.cs index 089a99c..d846eb3 100644 --- a/src/DistributedNonce/Services/DistributedNonceService.cs +++ b/src/DistributedNonce/Services/DistributedNonceService.cs @@ -30,10 +30,7 @@ public IClient Client get => _client; set { - if (value is null) - { - throw new ArgumentNullException(nameof(value)); - } + ArgumentNullException.ThrowIfNull(value); if (!ReferenceEquals(_client, value)) {