Ejemplo n.º 1
0
        private static Transaction[] GenerateTxsForRefunds(IGrouping <Address, DepositDetails> depositGroup, DevKeyStoreWallet wallet)
        {
            Console.WriteLine();
            Console.Write($"Provide nonce for {depositGroup.Key}: ");
            int nonce = int.Parse(Console.ReadLine());

            Console.Write($"Provide address to send the refund to: ");
            string  hexAddress = Console.ReadLine();
            Address refundTo   = new Address(hexAddress);

            SecureString securedPassword = ConsoleUtils.ReadSecret("Provide password: "******"Password has been accepted.");
                Console.WriteLine();
                Console.WriteLine($"Great, will generate refund transactions for deposits of {depositGroup.Key} starting with nonce {nonce}. ETH/DAI will be sent to {refundTo}.");
                List <Transaction> transactions = new List <Transaction>(depositGroup.Count());
                foreach (DepositDetails depositDetails in depositGroup)
                {
                    Deposit     deposit     = depositDetails.Deposit;
                    RefundClaim refundClaim = new RefundClaim(deposit.Id, depositDetails.DataAsset.Id, deposit.Units,
                                                              deposit.Value, deposit.ExpiryTime, depositDetails.Pepper, depositDetails.DataAsset.Provider.Address, refundTo);
                    UInt256 gasPrice = 20.GWei();

                    AbiEncoder  abiEncoder  = new AbiEncoder();
                    byte[]      txData      = abiEncoder.Encode(AbiEncodingStyle.IncludeSignature, ContractData.ClaimRefundSig, depositDetails.DataAsset.Id, refundClaim.Units, refundClaim.Value, refundClaim.ExpiryTime, refundClaim.Pepper, refundClaim.Provider, depositDetails.Consumer);
                    Transaction transaction = new Transaction();
                    transaction.Value         = 0;
                    transaction.Data          = txData;
                    transaction.To            = new Address("0xb1AD03b75bD9E5AB89968D7a37d99F9dd220796D");
                    transaction.SenderAddress = depositDetails.Consumer;
                    transaction.GasLimit      = 100000;
                    transaction.GasPrice      = gasPrice;
                    transaction.Nonce         = (UInt256)nonce++;
                    wallet.Sign(transaction, ChainId.Mainnet);

                    EthereumEcdsa ecdsa            = new EthereumEcdsa(ChainId.Mainnet, LimboLogs.Instance);
                    Address       recoveredAddress = ecdsa.RecoverAddress(transaction);
                    if (recoveredAddress != transaction.SenderAddress)
                    {
                        Console.WriteLine("Signature failure");
                        return(new Transaction[0]);
                    }

                    transactions.Add(transaction);
                }

                return(transactions.ToArray());
            }

            Console.WriteLine("Incorrect password.");
            return(new Transaction[0]);
        }
Ejemplo n.º 2
0
        public async Task TryClaimRefundAsync(DepositDetails deposit, Address refundTo)
        {
            var now = (ulong)_blockchainBridge.Head.Timestamp;

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

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

            if (transactionHash is null)
            {
                var provider    = deposit.DataAsset.Provider.Address;
                var refundClaim = new RefundClaim(depositId, deposit.DataAsset.Id, deposit.Deposit.Units,
                                                  deposit.Deposit.Value, deposit.Deposit.ExpiryTime, deposit.Pepper, provider, refundTo);
                transactionHash = _refundService.ClaimRefund(refundTo, refundClaim);
                deposit.SetClaimedRefundTransactionHash(transactionHash);
                await _depositRepository.UpdateAsync(deposit);

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

            await TryConfirmClaimAsync(deposit, string.Empty);
        }
Ejemplo n.º 3
0
        public async Task <RefundClaimStatus> TryClaimRefundAsync(DepositDetails deposit, Address refundTo)
        {
            ulong now = _timestamper.EpochSeconds;

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

            Block?latestBlock = await _blockchainBridge.GetLatestBlockAsync();

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

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

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

            if (transactionHash is null)
            {
                Address     provider    = deposit.DataAsset.Provider.Address;
                RefundClaim refundClaim = new RefundClaim(depositId, deposit.DataAsset.Id, deposit.Deposit.Units,
                                                          deposit.Deposit.Value, deposit.Deposit.ExpiryTime, deposit.Pepper, provider, refundTo);
                UInt256 gasPrice = await _gasPriceService.GetCurrentAsync();

                transactionHash = await _refundService.ClaimRefundAsync(refundTo, refundClaim, gasPrice);

                if (transactionHash is null)
                {
                    if (_logger.IsError)
                    {
                        _logger.Error("There was an error when trying to claim 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 a refund for deposit: '{depositId}', gas price: {gasPrice} wei, transaction hash: '{transactionHash}' (awaits a confirmation).");
                }
            }

            bool confirmed = await TryConfirmClaimAsync(deposit, string.Empty);

            return(confirmed
                ? RefundClaimStatus.Confirmed(transactionHash)
                : RefundClaimStatus.Unconfirmed(transactionHash));
        }
Ejemplo n.º 4
0
        public async Task can_claim_refund()
        {
            uint timestamp = 1546871954;

            _bridge.NextBlockPlease(timestamp);

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

            byte[] salt = 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, salt, _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");

            RefundService refundService = new RefundService(_ndmBridge, _abiEncoder, _depositRepository,
                                                            _contractAddress, LimboLogs.Instance, _wallet);

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

            _bridge.NextBlockPlease(expiryTime + 1);
            RefundClaim refundClaim   = new RefundClaim(depositId, assetId, units, value, expiryTime, salt, _providerAccount, _consumerAccount);
            UInt256     balanceBefore = _state.GetBalance(_consumerAccount);
            Keccak      refundTxHash  = await refundService.ClaimRefundAsync(_consumerAccount, refundClaim, 20.GWei());

            TxReceipt refundReceipt = _bridge.GetReceipt(refundTxHash);

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

            Assert.Greater(balanceAfter, balanceBefore);
        }
Ejemplo n.º 5
0
        public async Task <Keccak?> ClaimRefundAsync(Address onBehalfOf, RefundClaim refundClaim, UInt256 gasPrice)
        {
            byte[]      txData      = _abiEncoder.Encode(AbiEncodingStyle.IncludeSignature, ContractData.ClaimRefundSig, refundClaim.AssetId.Bytes, refundClaim.Units, refundClaim.Value, refundClaim.ExpiryTime, refundClaim.Pepper, refundClaim.Provider, onBehalfOf);
            Transaction transaction = new Transaction();

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

            if (_logger.IsInfo)
            {
                _logger.Info($"Sending a refund claim transaction for {refundClaim.DepositId} to be refunded to {refundClaim.RefundTo}");
            }

            return(await _blockchainBridge.SendOwnTransactionAsync(transaction));
        }
Ejemplo n.º 6
0
        public Keccak ClaimRefund(Address onBehalfOf, RefundClaim refundClaim)
        {
            byte[]      txData      = _abiEncoder.Encode(AbiEncodingStyle.IncludeSignature, ContractData.ClaimRefundSig, refundClaim.AssetId.Bytes, refundClaim.Units, refundClaim.Value, refundClaim.ExpiryTime, refundClaim.Pepper, refundClaim.Provider, 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);
            _wallet.Sign(transaction, _blockchainBridge.GetNetworkId());

            if (_logger.IsInfo)
            {
                _logger.Info($"Sending a refund claim transaction for {refundClaim.DepositId} to be refunded to {refundClaim.RefundTo}");
            }

            return(_blockchainBridge.SendTransaction(transaction, true));
        }