public async void GetRedeemedEventTest() { var api = new EtherScanApi(Common.EthTestNet); var eventSignatureHash = EventSignatureExtractor.GetSignatureHash <RedeemedEventDTO>(); var eventsAsyncResult = await api.GetContractEventsAsync( address : "0x527d1049837edf5f99c287a41a87702686082bf8", fromBlock : Common.EthTestNet.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : eventSignatureHash, topic1 : "0x7ca4344b5d8e624917b6b0cee015bab65397349062ec2fcdbaebc25d5e1cbb4d") .ConfigureAwait(false); Assert.False(eventsAsyncResult.HasError); var events = eventsAsyncResult.Value?.ToList(); Assert.NotNull(events); Assert.Single(events); Assert.True(events.First().IsRedeemedEvent()); var redeemedEvent = events.First().ParseRedeemedEvent(); Assert.NotNull(redeemedEvent); Assert.Equal("7ca4344b5d8e624917b6b0cee015bab65397349062ec2fcdbaebc25d5e1cbb4d", redeemedEvent.HashedSecret.ToHexString()); Assert.Equal("f53c77f812c16243d3cdffc48fc4fd5a1f36541db9409b112a0e56436fc7fa35", redeemedEvent.Secret.ToHexString()); }
public static ERC20InitiatedEventDTO ParseERC20InitiatedEvent( this EtherScanApi.ContractEvent contractEvent) { var eventSignatureHash = EventSignatureExtractor.GetSignatureHash <ERC20InitiatedEventDTO>(); if (contractEvent.Topics == null || contractEvent.Topics.Count != 4 || contractEvent.EventSignatureHash() != eventSignatureHash) { throw new Exception("Invalid contract event"); } var initiatorHex = contractEvent.HexData.Substring(PrefixOffset, TopicSizeInHex); var refundTimeHex = contractEvent.HexData.Substring(PrefixOffset + TopicSizeInHex, TopicSizeInHex); var countdownHex = contractEvent.HexData.Substring(PrefixOffset + 2 * TopicSizeInHex, TopicSizeInHex); var valueHex = contractEvent.HexData.Substring(PrefixOffset + 3 * TopicSizeInHex, TopicSizeInHex); var redeemFeeHex = contractEvent.HexData.Substring(PrefixOffset + 4 * TopicSizeInHex, TopicSizeInHex); var active = contractEvent.HexData.Substring(PrefixOffset + 5 * TopicSizeInHex, TopicSizeInHex); return(new ERC20InitiatedEventDTO { HashedSecret = Hex.FromString(contractEvent.Topics[1], true), ERC20Contract = $"0x{contractEvent.Topics[2].Substring(contractEvent.Topics[2].Length - AddressLengthInHex)}", Participant = $"0x{contractEvent.Topics[3].Substring(contractEvent.Topics[3].Length - AddressLengthInHex)}", Initiator = $"0x{initiatorHex.Substring(initiatorHex.Length - AddressLengthInHex)}", RefundTimestamp = new HexBigInteger(refundTimeHex).Value, Countdown = new HexBigInteger(countdownHex).Value, Value = new HexBigInteger(valueHex).Value, RedeemFee = new HexBigInteger(redeemFeeHex).Value, Active = new HexBigInteger(active).Value != 0 }); }
public async void GetAddedEventTest() { var api = new EtherScanApi(Common.EthTestNet); var eventSignatureHash = EventSignatureExtractor.GetSignatureHash <AddedEventDTO>(); var eventsAsyncResult = await api.GetContractEventsAsync( address : "0x527d1049837edf5f99c287a41a87702686082bf8", fromBlock : Common.EthTestNet.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : eventSignatureHash, topic1 : "0xbe51acca480dba043159355d597e39744ad7140d325f6cb3c1554db6b33947d6") .ConfigureAwait(false); Assert.False(eventsAsyncResult.HasError); var events = eventsAsyncResult.Value?.ToList(); Assert.NotNull(events); Assert.Single(events); Assert.True(events.First().IsAddedEvent()); var addedEvent = events.First().ParseAddedEvent(); Assert.NotNull(addedEvent); Assert.Equal("be51acca480dba043159355d597e39744ad7140d325f6cb3c1554db6b33947d6", addedEvent.HashedSecret.ToHexString()); Assert.Equal("0xe4aec93f3c0807b66b3fd043623e21dbbb0a3a82", addedEvent.Initiator); Assert.Equal(289637150000000000, (long)addedEvent.Value); }
public async void GetInitiatedEventTest() { var api = new EtherScanApi(Common.EthTestNet); var eventSignatureHash = EventSignatureExtractor.GetSignatureHash <InitiatedEventDTO>(); var eventsAsyncResult = await api.GetContractEventsAsync( address : "0x527d1049837edf5f99c287a41a87702686082bf8", fromBlock : Common.EthTestNet.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : eventSignatureHash, topic1 : "0x87639bcb4d5e61e52398acb13181ddec825744f8fd90a3f8efa68c129a968d0f") .ConfigureAwait(false); Assert.False(eventsAsyncResult.HasError); var events = eventsAsyncResult.Value?.ToList(); Assert.NotNull(events); Assert.Single(events); Assert.True(events.First().IsInitiatedEvent()); var initiatedEvent = events.First().ParseInitiatedEvent(); Assert.NotNull(initiatedEvent); Assert.Equal("87639bcb4d5e61e52398acb13181ddec825744f8fd90a3f8efa68c129a968d0f", initiatedEvent.HashedSecret.ToHexString()); Assert.Equal("0xcd38a31acf4db224a20052acb1934c993680b3e2", initiatedEvent.Participant); Assert.Equal("0x981c7251a11a1614d4c70c0f3507bbda54808065", initiatedEvent.Initiator); Assert.Equal(1569198635, (long)initiatedEvent.RefundTimestamp); Assert.Equal(27645001080510000, (long)initiatedEvent.Value); Assert.Equal(0, (long)initiatedEvent.RedeemFee); }
public static async Task <BigInteger> GetTransferValue( Currency currency, string from, string to, string blockNumber, CancellationToken cancellationToken = default) { try { Log.Debug("Ethereum ERC20: check transfer event"); var erc20 = (EthereumTokens.ERC20)currency; var api = new EtherScanApi(erc20); var transferEventsResult = await api .GetContractEventsAsync( address : erc20.ERC20ContractAddress, fromBlock : (ulong)new HexBigInteger(blockNumber).Value, toBlock : ulong.MaxValue, topic0 : EventSignatureExtractor.GetSignatureHash <ERC20TransferEventDTO>(), topic1 : "0x000000000000000000000000" + from, topic2 : "0x000000000000000000000000" + to, cancellationToken : cancellationToken) .ConfigureAwait(false); if (transferEventsResult == null) { return(0); } if (transferEventsResult.HasError) { return(0); } var events = transferEventsResult.Value?.ToList(); if (events == null || !events.Any()) { return(0); } var transferEvent = events.Last().ParseERC20TransferEvent(); //todo: get last return(transferEvent.Value); } catch (Exception e) { Log.Error(e, "Ethereum ERC20 get transfer value task error"); return(0); } }
public static async Task <Result <byte[]> > IsRedeemedAsync( Swap swap, Currency currency, CancellationToken cancellationToken = default) { try { Log.Debug("Ethereum: check redeem event"); var ethereum = (Atomex.Ethereum)currency; var api = new EtherScanApi(ethereum); var redeemEventsResult = await api .GetContractEventsAsync( address : ethereum.SwapContractAddress, fromBlock : ethereum.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : EventSignatureExtractor.GetSignatureHash <RedeemedEventDTO>(), topic1 : "0x" + swap.SecretHash.ToHexString(), cancellationToken : cancellationToken) .ConfigureAwait(false); if (redeemEventsResult == null) { return(new Error(Errors.RequestError, $"Connection error while getting contract {ethereum.SwapContractAddress} redeem events")); } if (redeemEventsResult.HasError) { return(redeemEventsResult.Error); } var events = redeemEventsResult.Value?.ToList(); if (events == null || !events.Any()) { return((byte[])null); } var secret = events.First().ParseRedeemedEvent().Secret; Log.Debug("Redeem event received with secret {@secret}", Convert.ToBase64String(secret)); return(secret); } catch (Exception e) { Log.Error(e, "Ethereum redeem control task error"); return(new Error(Errors.InternalError, e.Message)); } }
public static async Task <Result <bool> > IsRefundedAsync( Swap swap, CurrencyConfig currency, CancellationToken cancellationToken = default) { try { Log.Debug("Ethereum: check refund event"); var ethereum = (Atomex.EthereumConfig)currency; var api = new EtherScanApi(ethereum); var refundEventsResult = await api .GetContractEventsAsync( address : ethereum.SwapContractAddress, fromBlock : ethereum.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : EventSignatureExtractor.GetSignatureHash <RefundedEventDTO>(), topic1 : "0x" + swap.SecretHash.ToHexString(), cancellationToken : cancellationToken) .ConfigureAwait(false); if (refundEventsResult == null) { return(new Error(Errors.RequestError, $"Connection error while getting contract {ethereum.SwapContractAddress} refund event")); } if (refundEventsResult.HasError) { return(refundEventsResult.Error); } var events = refundEventsResult.Value?.ToList(); if (events == null || !events.Any()) { return(false); } Log.Debug("Refund event received for swap {@swap}", swap.Id); return(true); } catch (Exception e) { Log.Error(e, "Ethereum refund control task error"); return(new Error(Errors.InternalError, e.Message)); } }
public static ERC20RefundedEventDTO ParseRefundedEvent( this EtherScanApi.ContractEvent contractEvent) { var eventSignatureHash = EventSignatureExtractor.GetSignatureHash <ERC20RefundedEventDTO>(); if (contractEvent.Topics == null || contractEvent.Topics.Count != 2 || contractEvent.EventSignatureHash() != eventSignatureHash) { throw new Exception("Invalid contract event"); } return(new ERC20RefundedEventDTO { HashedSecret = Hex.FromString(contractEvent.Topics[1], true), }); }
public static ERC20AddedEventDTO ParseERC20AddedEvent( this EtherScanApi.ContractEvent contractEvent) { var eventSignatureHash = EventSignatureExtractor.GetSignatureHash <ERC20AddedEventDTO>(); if (contractEvent.Topics == null || contractEvent.Topics.Count != 2 || contractEvent.EventSignatureHash() != eventSignatureHash) { throw new Exception("Invalid contract event"); } var initiatorHex = contractEvent.HexData.Substring(PrefixOffset, TopicSizeInHex); var valueHex = contractEvent.HexData.Substring(PrefixOffset + TopicSizeInHex, TopicSizeInHex); return(new ERC20AddedEventDTO { HashedSecret = Hex.FromString(contractEvent.Topics[1], true), Initiator = $"0x{initiatorHex.Substring(initiatorHex.Length - AddressLengthInHex)}", Value = new HexBigInteger(valueHex).Value }); }
public static ERC20TransferEventDTO ParseERC20TransferEvent( this EtherScanApi.ContractEvent contractEvent) { var eventSignatureHash = EventSignatureExtractor.GetSignatureHash <ERC20TransferEventDTO>(); if (contractEvent.Topics == null || contractEvent.Topics.Count != 3 || contractEvent.EventSignatureHash() != eventSignatureHash) { throw new Exception("Invalid ERC20 token contract event"); } var valueHex = contractEvent.HexData.Substring(PrefixOffset, TopicSizeInHex); return(new ERC20TransferEventDTO { From = $"0x{contractEvent.Topics[1].Substring(contractEvent.Topics[1].Length - AddressLengthInHex)}", To = $"0x{contractEvent.Topics[2].Substring(contractEvent.Topics[2].Length - AddressLengthInHex)}", Value = new HexBigInteger(valueHex).Value }); }
public static async Task <Result <bool> > IsInitiatedAsync( Swap swap, Currency currency, long lockTimeInSec, CancellationToken cancellationToken = default) { try { Log.Debug("Ethereum ERC20: check initiated event"); var erc20 = (EthereumTokens.ERC20)currency; var side = swap.Symbol .OrderSideForBuyCurrency(swap.PurchasedCurrency) .Opposite(); var refundTimeStamp = new DateTimeOffset(swap.TimeStamp.ToUniversalTime().AddSeconds(lockTimeInSec)).ToUnixTimeSeconds(); var requiredAmountInERC20 = AmountHelper.QtyToAmount(side, swap.Qty, swap.Price, erc20.DigitsMultiplier); var requiredAmountInDecimals = erc20.TokensToTokenDigits(requiredAmountInERC20); var receivedAmountInDecimals = new BigInteger(0); var requiredRewardForRedeemInDecimals = swap.IsAcceptor ? erc20.TokensToTokenDigits(swap.RewardForRedeem) : 0; var api = new EtherScanApi(erc20); var initiateEventsResult = await api .GetContractEventsAsync( address : erc20.SwapContractAddress, fromBlock : erc20.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : EventSignatureExtractor.GetSignatureHash <ERC20InitiatedEventDTO>(), topic1 : "0x" + swap.SecretHash.ToHexString(), topic2 : "0x000000000000000000000000" + erc20.ERC20ContractAddress.Substring(2), //?? topic3 : "0x000000000000000000000000" + swap.ToAddress.Substring(2), cancellationToken : cancellationToken) .ConfigureAwait(false); if (initiateEventsResult == null) { return(new Error(Errors.RequestError, $"Connection error while trying to get contract {erc20.SwapContractAddress} initiate event")); } if (initiateEventsResult.HasError) { return(initiateEventsResult.Error); } var events = initiateEventsResult.Value?.ToList(); if (events == null || !events.Any()) { return(false); } var contractInitEvent = events.Last(); var initiatedEvent = contractInitEvent.ParseERC20InitiatedEvent(); if (initiatedEvent.RefundTimestamp != refundTimeStamp) { Log.Debug( "Invalid refund time in initiated event. Expected value is {@expected}, actual is {@actual}", refundTimeStamp, (long)initiatedEvent.RefundTimestamp); return(new Error( code: Errors.InvalidRefundLockTime, description: $"Invalid refund time in initiated event. Expected value is {refundTimeStamp}, actual is {(long)initiatedEvent.RefundTimestamp}")); } if (initiatedEvent.Countdown != lockTimeInSec) //todo: use it { Log.Debug( "Invalid countdown in initiated event. Expected value is {@expected}, actual is {@actual}", lockTimeInSec, (long)initiatedEvent.Countdown); return(new Error( code: Errors.InvalidRewardForRedeem, description: $"Invalid countdown in initiated event. Expected value is {lockTimeInSec}, actual is {(long)initiatedEvent.Countdown}")); } if (initiatedEvent.RedeemFee != requiredRewardForRedeemInDecimals) { Log.Debug( "Invalid redeem fee in initiated event. Expected value is {@expected}, actual is {@actual}", requiredRewardForRedeemInDecimals, (long)initiatedEvent.RedeemFee); return(new Error( code: Errors.InvalidRewardForRedeem, description: $"Invalid redeem fee in initiated event. Expected value is {requiredRewardForRedeemInDecimals}, actual is {(long)initiatedEvent.RedeemFee}")); } if (!initiatedEvent.Active) { Log.Debug( "Invalid active value in initiated event. Expected value is {@expected}, actual is {@actual}", true, initiatedEvent.Active); return(new Error( code: Errors.InvalidRewardForRedeem, description: $"Invalid active value in initiated event. Expected value is {true}, actual is {initiatedEvent.Active}")); } var erc20TransferValue = await GetTransferValue( currency : currency, from : initiatedEvent.Initiator.Substring(2), to : erc20.SwapContractAddress.Substring(2), blockNumber : contractInitEvent.HexBlockNumber, cancellationToken : cancellationToken) .ConfigureAwait(false); if (erc20TransferValue != initiatedEvent.Value + initiatedEvent.RedeemFee) { Log.Debug( "Invalid transfer value in erc20 initiated event. Expected value is {@expected}, actual is {@actual}", initiatedEvent.Value, erc20TransferValue); return(new Error( code: Errors.InvalidSwapPaymentTx, description: $"Invalid transfer value in erc20 initiated event. Expected value is {initiatedEvent.Value}, actual is {initiatedEvent.Active}")); } receivedAmountInDecimals = initiatedEvent.Value; if (receivedAmountInDecimals >= requiredAmountInDecimals - requiredRewardForRedeemInDecimals) { return(true); } Log.Debug( "Ethereum ERC20 value is not enough. Expected value is {@expected}. Actual value is {@actual}", (decimal)(requiredAmountInDecimals - requiredRewardForRedeemInDecimals), (decimal)initiatedEvent.Value); var addEventsResult = await api .GetContractEventsAsync( address : erc20.SwapContractAddress, fromBlock : erc20.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : EventSignatureExtractor.GetSignatureHash <ERC20AddedEventDTO>(), topic1 : "0x" + swap.SecretHash.ToHexString(), cancellationToken : cancellationToken) .ConfigureAwait(false); if (addEventsResult == null) { return(new Error(Errors.RequestError, $"Connection error while trying to get contract {erc20.SwapContractAddress} add event")); } if (addEventsResult.HasError) { return(addEventsResult.Error); } events = addEventsResult.Value?.ToList(); if (events == null || !events.Any()) { return(false); } foreach (var @event in events.Select(e => e.ParseERC20AddedEvent())) { erc20TransferValue = await GetTransferValue( currency : currency, from : @event.Initiator.Substring(2), to : erc20.SwapContractAddress.Substring(2), blockNumber : contractInitEvent.HexBlockNumber, cancellationToken : cancellationToken) .ConfigureAwait(false); if (erc20TransferValue != @event.Value - receivedAmountInDecimals) { Log.Debug( "Invalid transfer value in added event. Expected value is {@expected}, actual is {@actual}", @event.Value - receivedAmountInDecimals, erc20TransferValue); return(new Error( code: Errors.InvalidSwapPaymentTx, description: $"Invalid transfer value in initiated event. Expected value is {@event.Value - receivedAmountInDecimals}, actual is {erc20TransferValue}")); } receivedAmountInDecimals = @event.Value; if (receivedAmountInDecimals >= requiredAmountInDecimals - requiredRewardForRedeemInDecimals) { return(true); } Log.Debug( "Ethereum ERC20 value is not enough. Expected value is {@expected}. Actual value is {@actual}", requiredAmountInDecimals - requiredRewardForRedeemInDecimals, (long)@event.Value); } } catch (Exception e) { Log.Error(e, "Ethereum ERC20 swap initiated control task error"); return(new Error(Errors.InternalError, e.Message)); } return(false); }
private async Task <List <ContractEvent> > GetERC20EventsAsync( string address, CancellationToken cancellationToken = default) { var currency = Currency; var api = new EtherScanApi(currency); var approveEventsResult = await api .GetContractEventsAsync( address : currency.ERC20ContractAddress, fromBlock : currency.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : EventSignatureExtractor.GetSignatureHash <ERC20ApprovalEventDTO>(), topic1 : "0x000000000000000000000000" + address.Substring(2), topic2 : "0x000000000000000000000000" + currency.SwapContractAddress.Substring(2), cancellationToken : cancellationToken) .ConfigureAwait(false); if (approveEventsResult == null) { Log.Error("Connection error while get approve events"); return(null); } if (approveEventsResult.HasError) { Log.Error( "Error while scan address transactions for {@address} with code {@code} and description {@description}", address, approveEventsResult.Error.Code, approveEventsResult.Error.Description); return(null); } var outEventsResult = await api .GetContractEventsAsync( address : currency.ERC20ContractAddress, fromBlock : currency.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : EventSignatureExtractor.GetSignatureHash <ERC20TransferEventDTO>(), topic1 : "0x000000000000000000000000" + address.Substring(2), topic2 : null, cancellationToken : cancellationToken) .ConfigureAwait(false); if (outEventsResult == null) { Log.Error("Connection error while get output events"); return(null); } if (outEventsResult.HasError) { Log.Error( "Error while scan address transactions for {@address} with code {@code} and description {@description}", address, outEventsResult.Error.Code, outEventsResult.Error.Description); return(null); } var inEventsResult = await api .GetContractEventsAsync( address : currency.ERC20ContractAddress, fromBlock : currency.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : EventSignatureExtractor.GetSignatureHash <ERC20TransferEventDTO>(), topic1 : null, topic2 : "0x000000000000000000000000" + address.Substring(2), cancellationToken : cancellationToken) .ConfigureAwait(false); if (inEventsResult == null) { Log.Error("Connection error while get input events"); return(null); } if (inEventsResult.HasError) { Log.Error( "Error while scan address transactions for {@address} with code {@code} and description {@description}", address, inEventsResult.Error.Code, inEventsResult.Error.Description); return(null); } var events = approveEventsResult.Value? .Concat(outEventsResult.Value?.Concat(inEventsResult.Value)) .ToList(); if (events == null || !events.Any()) // address without activity { return(null); } return(events); }
public static bool IsERC20RefundedEvent(this EtherScanApi.ContractEvent contractEvent) { return(contractEvent.EventSignatureHash() == EventSignatureExtractor.GetSignatureHash <ERC20RefundedEventDTO>()); }
public static async Task <Result <bool> > IsInitiatedAsync( Swap swap, Currency currency, long refundTimeStamp, CancellationToken cancellationToken = default) { try { Log.Debug("Ethereum: check initiated event"); var ethereum = (Atomex.Ethereum)currency; var sideOpposite = swap.Symbol .OrderSideForBuyCurrency(swap.PurchasedCurrency) .Opposite(); var requiredAmountInEth = AmountHelper.QtyToAmount(sideOpposite, swap.Qty, swap.Price, ethereum.DigitsMultiplier); var requiredAmountInWei = Atomex.Ethereum.EthToWei(requiredAmountInEth); var requiredRewardForRedeemInWei = Atomex.Ethereum.EthToWei(swap.RewardForRedeem); var api = new EtherScanApi(ethereum); var initiateEventsResult = await api .GetContractEventsAsync( address : ethereum.SwapContractAddress, fromBlock : ethereum.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : EventSignatureExtractor.GetSignatureHash <InitiatedEventDTO>(), topic1 : "0x" + swap.SecretHash.ToHexString(), topic2 : "0x000000000000000000000000" + swap.ToAddress.Substring(2), cancellationToken : cancellationToken) .ConfigureAwait(false); if (initiateEventsResult == null) { return(new Error(Errors.RequestError, $"Connection error while getting contract {ethereum.SwapContractAddress} initiate event")); } if (initiateEventsResult.HasError) { return(initiateEventsResult.Error); } var events = initiateEventsResult.Value?.ToList(); if (events == null || !events.Any()) { return(false); } var initiatedEvent = events.First().ParseInitiatedEvent(); if (initiatedEvent.Value >= requiredAmountInWei - requiredRewardForRedeemInWei) { if (initiatedEvent.RefundTimestamp != refundTimeStamp) { Log.Debug( "Invalid refund time in initiated event. Expected value is {@expected}, actual is {@actual}", refundTimeStamp, (long)initiatedEvent.RefundTimestamp); return(new Error( code: Errors.InvalidRefundLockTime, description: $"Invalid refund time in initiated event. Expected value is {refundTimeStamp}, actual is {(long)initiatedEvent.RefundTimestamp}")); } if (swap.IsAcceptor) { if (initiatedEvent.RedeemFee != requiredRewardForRedeemInWei) { Log.Debug( "Invalid redeem fee in initiated event. Expected value is {@expected}, actual is {@actual}", requiredRewardForRedeemInWei, (long)initiatedEvent.RedeemFee); return(new Error( code: Errors.InvalidRewardForRedeem, description: $"Invalid redeem fee in initiated event. Expected value is {requiredRewardForRedeemInWei}, actual is {(long)initiatedEvent.RedeemFee}")); } } return(true); } Log.Debug( "Eth value is not enough. Expected value is {@expected}. Actual value is {@actual}", (decimal)(requiredAmountInWei - requiredRewardForRedeemInWei), (decimal)initiatedEvent.Value); var addEventsResult = await api .GetContractEventsAsync( address : ethereum.SwapContractAddress, fromBlock : ethereum.SwapContractBlockNumber, toBlock : ulong.MaxValue, topic0 : EventSignatureExtractor.GetSignatureHash <AddedEventDTO>(), topic1 : "0x" + swap.SecretHash.ToHexString(), cancellationToken : cancellationToken) .ConfigureAwait(false); if (addEventsResult == null) { return(new Error(Errors.RequestError, $"Connection error while getting contract {ethereum.SwapContractAddress} add event")); } if (addEventsResult.HasError) { return(addEventsResult.Error); } events = addEventsResult.Value?.ToList(); if (events == null || !events.Any()) { return(false); } foreach (var @event in events.Select(e => e.ParseAddedEvent())) { if (@event.Value >= requiredAmountInWei - requiredRewardForRedeemInWei) { return(true); } Log.Debug( "Eth value is not enough. Expected value is {@expected}. Actual value is {@actual}", requiredAmountInWei - requiredRewardForRedeemInWei, (long)@event.Value); } } catch (Exception e) { Log.Error(e, "Ethereum swap initiated control task error"); return(new Error(Errors.InternalError, e.Message)); } return(false); }