public async Task <Keccak?> ClaimEarlyRefundAsync(Address onBehalfOf, EarlyRefundClaim earlyRefundClaim,
                                                          UInt256 gasPrice)
        {
            byte[] txData = _abiEncoder.Encode(AbiEncodingStyle.IncludeSignature, ContractData.ClaimEarlyRefundSig,
                                               earlyRefundClaim.AssetId.Bytes, earlyRefundClaim.Units, earlyRefundClaim.Value,
                                               earlyRefundClaim.ExpiryTime, earlyRefundClaim.Pepper, earlyRefundClaim.Provider,
                                               earlyRefundClaim.ClaimableAfter, earlyRefundClaim.Signature.V, earlyRefundClaim.Signature.R,
                                               earlyRefundClaim.Signature.S, onBehalfOf);
            Transaction transaction = new Transaction();

            transaction.Value         = 0;
            transaction.Data          = txData;
            transaction.To            = _contractAddress;
            transaction.SenderAddress = onBehalfOf;
            transaction.GasLimit      = (long)GasLimit;
            transaction.GasPrice      = gasPrice;
            transaction.Nonce         = await _blockchainBridge.GetNonceAsync(onBehalfOf);

            _wallet.Sign(transaction, await _blockchainBridge.GetNetworkIdAsync());

            if (_logger.IsInfo)
            {
                _logger.Info($"Sending an early refund claim transaction on {earlyRefundClaim.DepositId} to be refunded to {earlyRefundClaim.RefundTo}");
            }

            return(await _blockchainBridge.SendOwnTransactionAsync(transaction));
        }
Exemple #2
0
        public async Task TryClaimEarlyRefundAsync(DepositDetails deposit, Address refundTo)
        {
            var now = (ulong)_blockchainBridge.Head.Timestamp;

            if (!deposit.CanClaimEarlyRefund(now))
            {
                return;
            }

            var depositId       = deposit.Deposit.Id;
            var transactionHash = deposit.ClaimedRefundTransactionHash;

            if (transactionHash is null)
            {
                var provider         = deposit.DataAsset.Provider.Address;
                var ticket           = deposit.EarlyRefundTicket;
                var earlyRefundClaim = new EarlyRefundClaim(ticket.DepositId, deposit.DataAsset.Id,
                                                            deposit.Deposit.Units, deposit.Deposit.Value, deposit.Deposit.ExpiryTime, deposit.Pepper, provider,
                                                            ticket.ClaimableAfter, ticket.Signature, refundTo);
                transactionHash = _refundService.ClaimEarlyRefund(refundTo, earlyRefundClaim);
                deposit.SetClaimedRefundTransactionHash(transactionHash);
                await _depositRepository.UpdateAsync(deposit);

                if (_logger.IsInfo)
                {
                    _logger.Info($"Claimed an early refund for deposit: '{depositId}', transaction hash: '{transactionHash}' (awaits a confirmation).");
                }
            }

            await TryConfirmClaimAsync(deposit, "early ");
        }
Exemple #3
0
        public async Task <RefundClaimStatus> TryClaimEarlyRefundAsync(DepositDetails deposit, Address refundTo)
        {
            var now = _timestamper.EpochSeconds;

            if (!deposit.CanClaimEarlyRefund(now))
            {
                return(RefundClaimStatus.Empty);
            }

            var latestBlock = await _blockchainBridge.GetLatestBlockAsync();

            now = (ulong)latestBlock.Timestamp;
            if (!deposit.CanClaimEarlyRefund(now))
            {
                return(RefundClaimStatus.Empty);
            }

            var depositId       = deposit.Deposit.Id;
            var transactionHash = deposit.ClaimedRefundTransaction?.Hash;

            if (transactionHash is null)
            {
                var provider         = deposit.DataAsset.Provider.Address;
                var ticket           = deposit.EarlyRefundTicket;
                var earlyRefundClaim = new EarlyRefundClaim(ticket.DepositId, deposit.DataAsset.Id,
                                                            deposit.Deposit.Units, deposit.Deposit.Value, deposit.Deposit.ExpiryTime, deposit.Pepper, provider,
                                                            ticket.ClaimableAfter, ticket.Signature, refundTo);
                var gasPrice = await _gasPriceService.GetCurrentAsync();

                transactionHash = await _refundService.ClaimEarlyRefundAsync(refundTo, earlyRefundClaim, gasPrice);

                if (transactionHash is null)
                {
                    if (_logger.IsError)
                    {
                        _logger.Error("There was an error when trying to claim early refund (no transaction hash returned).");
                    }
                    return(RefundClaimStatus.Empty);
                }

                deposit.SetClaimedRefundTransaction(new TransactionInfo(transactionHash, 0, gasPrice,
                                                                        _refundService.GasLimit, _timestamper.EpochSeconds));
                await _depositRepository.UpdateAsync(deposit);

                if (_logger.IsInfo)
                {
                    _logger.Info($"Claimed an early refund for deposit: '{depositId}', gas price: {gasPrice} wei, transaction hash: '{transactionHash}' (awaits a confirmation).");
                }
            }

            var confirmed = await TryConfirmClaimAsync(deposit, "early ");

            return(confirmed
                ? RefundClaimStatus.Confirmed(transactionHash)
                : RefundClaimStatus.Unconfirmed(transactionHash));
        }
Exemple #4
0
        public Keccak ClaimEarlyRefund(Address onBehalfOf, EarlyRefundClaim earlyRefundClaim)
        {
            byte[]      txData      = _abiEncoder.Encode(AbiEncodingStyle.IncludeSignature, ContractData.ClaimEarlyRefundSig, earlyRefundClaim.AssetId.Bytes, earlyRefundClaim.Units, earlyRefundClaim.Value, earlyRefundClaim.ExpiryTime, earlyRefundClaim.Pepper, earlyRefundClaim.Provider, earlyRefundClaim.ClaimableAfter, earlyRefundClaim.Signature.V, earlyRefundClaim.Signature.R, earlyRefundClaim.Signature.S, onBehalfOf);
            Transaction transaction = new Transaction();

            transaction.Value         = 0;
            transaction.Data          = txData;
            transaction.To            = _contractAddress;
            transaction.SenderAddress = onBehalfOf;
            transaction.GasLimit      = 90000; // check
            transaction.GasPrice      = 20.GWei();
            transaction.Nonce         = _txPool.ReserveOwnTransactionNonce(onBehalfOf);

            if (_logger.IsInfo)
            {
                _logger.Info($"Sending an early refund claim transaction on {earlyRefundClaim.DepositId} to be refunded to {earlyRefundClaim.RefundTo}");
            }

            _wallet.Sign(transaction, _blockchainBridge.GetNetworkId());
            return(_blockchainBridge.SendTransaction(transaction, true));
        }
        public async Task Can_claim_early_refund()
        {
            uint timestamp = 1546871954;

            _bridge.NextBlockPlease(timestamp);

            DepositService depositService = new DepositService(_ndmBridge, _abiEncoder, _wallet, _contractAddress);
            Keccak         assetId        = Keccak.Compute("data asset");
            uint           expiryTime     = timestamp + (uint)TimeSpan.FromDays(4).TotalSeconds;
            UInt256        value          = 1.Ether();
            uint           units          = 10U;

            byte[] pepper = new byte[16];

            AbiSignature depositAbiDef = new AbiSignature("deposit",
                                                          new AbiBytes(32),
                                                          new AbiUInt(32),
                                                          new AbiUInt(96),
                                                          new AbiUInt(32),
                                                          new AbiBytes(16),
                                                          AbiType.Address,
                                                          AbiType.Address);

            byte[] depositData = _abiEncoder.Encode(AbiEncodingStyle.Packed, depositAbiDef, assetId.Bytes, units, value, expiryTime, pepper, _providerAccount, _consumerAccount);
            Keccak depositId   = Keccak.Compute(depositData);

            Deposit deposit       = new Deposit(depositId, units, expiryTime, value);
            Keccak  depositTxHash = await depositService.MakeDepositAsync(_consumerAccount, deposit, 20.GWei());

            _bridge.IncrementNonce(_consumerAccount);
            TxReceipt depositTxReceipt = _bridge.GetReceipt(depositTxHash);

            TestContext.WriteLine("GAS USED FOR DEPOSIT: {0}", depositTxReceipt.GasUsed);
            Assert.AreEqual(StatusCode.Success, depositTxReceipt.StatusCode, $"deposit made {depositTxReceipt.Error} {Encoding.UTF8.GetString(depositTxReceipt.ReturnValue ?? new byte[0])}");

            // calls revert and cannot reuse the same state - use only for manual debugging
            // Assert.True(depositService.VerifyDeposit(deposit.Id), "deposit verified");

            uint         claimableAfter    = timestamp + (uint)TimeSpan.FromDays(1).TotalSeconds;
            AbiSignature earlyRefundAbiDef = new AbiSignature("earlyRefund", new AbiBytes(32), new AbiUInt(32));

            byte[]        earlyRefundData = _abiEncoder.Encode(AbiEncodingStyle.Packed, earlyRefundAbiDef, depositId.Bytes, claimableAfter);
            RefundService refundService   = new RefundService(_ndmBridge, _abiEncoder, _depositRepository, _contractAddress, LimboLogs.Instance);

            // it will not work so far as we do everything within the same block and timestamp is wrong

            uint newTimestamp = 1546871954 + (uint)TimeSpan.FromDays(2).TotalSeconds;

            _bridge.NextBlockPlease(newTimestamp);

            Signature        earlySig         = _wallet.Sign(Keccak.Compute(earlyRefundData), _providerAccount);
            EarlyRefundClaim earlyRefundClaim = new EarlyRefundClaim(depositId, assetId, units, value, expiryTime, pepper, _providerAccount, claimableAfter, earlySig, _consumerAccount);
            UInt256          balanceBefore    = _state.GetBalance(_consumerAccount);

            Keccak refundTxHash = await refundService.ClaimEarlyRefundAsync(_consumerAccount, earlyRefundClaim, 20.GWei());

            TxReceipt refundReceipt = _bridge.GetReceipt(refundTxHash);

            TestContext.WriteLine("GAS USED FOR EARLY REFUND CLAIM: {0}", refundReceipt.GasUsed);
            Assert.AreEqual(StatusCode.Success, refundReceipt.StatusCode, $"early refund claim {refundReceipt.Error} {Encoding.UTF8.GetString(refundReceipt.ReturnValue ?? new byte[0])}");
            UInt256 balanceAfter = _state.GetBalance(_consumerAccount);

            Assert.Greater(balanceAfter, balanceBefore);
        }
        public async Task <RefundClaimStatus> TryClaimEarlyRefundAsync(DepositDetails deposit, Address refundTo)
        {
            ulong now = _timestamper.EpochSeconds;

            if (!deposit.CanClaimEarlyRefund(now, deposit.Timestamp))
            {
                return(RefundClaimStatus.Empty);
            }

            Block?latestBlock = await _blockchainBridge.GetLatestBlockAsync();

            if (latestBlock == null)
            {
                return(RefundClaimStatus.Empty);
            }

            now = (ulong)latestBlock.Timestamp;
            if (!deposit.CanClaimEarlyRefund(now, deposit.Timestamp))
            {
                return(RefundClaimStatus.Empty);
            }

            Keccak depositId       = deposit.Deposit.Id;
            Keccak?transactionHash = deposit.ClaimedRefundTransaction?.Hash;

            if (transactionHash is null)
            {
                Address provider = deposit.DataAsset.Provider.Address;
                if (deposit.EarlyRefundTicket == null)
                {
                    throw new InvalidDataException($"Early refund ticket is null on a claimable deposit {depositId}");
                }

                EarlyRefundTicket ticket           = deposit.EarlyRefundTicket;
                EarlyRefundClaim  earlyRefundClaim = new EarlyRefundClaim(ticket.DepositId, deposit.DataAsset.Id,
                                                                          deposit.Deposit.Units, deposit.Deposit.Value, deposit.Deposit.ExpiryTime, deposit.Pepper, provider,
                                                                          ticket.ClaimableAfter, ticket.Signature, refundTo);
                UInt256 gasPrice = await _gasPriceService.GetCurrentRefundAsync();

                transactionHash = await _refundService.ClaimEarlyRefundAsync(refundTo, earlyRefundClaim, gasPrice);

                if (transactionHash is null)
                {
                    if (_logger.IsError)
                    {
                        _logger.Error("There was an error when trying to claim early refund (no transaction hash returned).");
                    }
                    return(RefundClaimStatus.Empty);
                }

                deposit.AddClaimedRefundTransaction(TransactionInfo.Default(transactionHash, 0, gasPrice,
                                                                            _refundService.GasLimit, _timestamper.EpochSeconds));
                await _depositRepository.UpdateAsync(deposit);

                if (_logger.IsInfo)
                {
                    _logger.Info($"Claimed an early refund for deposit: '{depositId}', gas price: {gasPrice} wei, transaction hash: '{transactionHash}' (awaits a confirmation).");
                }
            }

            bool confirmed = await TryConfirmClaimAsync(deposit, "early ");

            return(confirmed
                ? RefundClaimStatus.Confirmed(transactionHash)
                : RefundClaimStatus.Unconfirmed(transactionHash));
        }