Пример #1
0
            public async void ShouldSendTransactionWithAccessLists()
            {
                var chainId = 444444444500;

                var accessLists = new List <AccessListItem>();

                accessLists.Add(new AccessListItem("0x527306090abaB3A6e1400e9345bC60c78a8BEf57",
                                                   new List <byte[]>
                {
                    "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abab".HexToByteArray(),
                    "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abac".HexToByteArray()
                }
                                                   ));
                accessLists.Add(new AccessListItem("0x427306090abaB3A6e1400e9345bC60c78a8BEf5c",
                                                   new List <byte[]>
                {
                    "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abaa".HexToByteArray(),
                    "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abad".HexToByteArray()
                }
                                                   ));

                var web3  = _ethereumClientIntegrationFixture.GetWeb3();
                var nonce = await web3.Eth.TransactionManager.Account.NonceService.GetNextNonceAsync();

                var lastBlock =
                    await web3.Eth.Blocks.GetBlockWithTransactionsHashesByNumber.SendRequestAsync(
                        BlockParameter.CreateLatest());

                var baseFee = lastBlock.BaseFeePerGas;
                var maxPriorityFeePerGas = 2000000000;
                var maxFeePerGas         = baseFee.Value * 2 + 2000000000;

                var transaction1559 = new Transaction1559(chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, 45000,
                                                          "0x1ad91ee08f21be3de0ba2ba6918e714da6b45836", 10, "", accessLists);

                transaction1559.Sign(new EthECKey(EthereumClientIntegrationFixture.AccountPrivateKey));


                var txnHash =
                    await web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(transaction1559.GetRLPEncoded()
                                                                                    .ToHex());

                // create recover signature
                var txn = await web3.Eth.Transactions.GetTransactionByHash.SendRequestAsync(txnHash);

                Assert.True(txn.To.IsTheSameAddress("0x1ad91ee08f21be3de0ba2ba6918e714da6b45836"));
                Assert.Equal(10, txn.Value.Value);
            }
Пример #2
0
        public void ShouldEncodeDecodeSignTransaction(ulong chainId, ulong nonce, ulong maxPriorityFeePerGas, ulong maxFeePerGas,
                                                      ulong gasLimit, string receiverAddress, ulong amount, string data)
        {
            var transaction1559 = new Transaction1559(chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, receiverAddress, amount, data, null);

            transaction1559.Sign(new EthECKey("0xb5b1870957d373ef0eeffecc6e4812c0fd08f554b37b233526acc331bf1544f7"));
            var encodedData = transaction1559.GetRLPEncodedRaw();
            var signedData  = transaction1559.GetRLPEncoded();

            Debug.WriteLine(chainId + "," + nonce + "," + maxPriorityFeePerGas + "," + maxFeePerGas + "," + gasLimit + "," + receiverAddress + "," + amount + "," + data);
            Debug.WriteLine(encodedData.ToHex());
            Debug.WriteLine(signedData.ToHex());
            var decodedTransaction1559 = Transaction1559Encoder.Current.Decode(signedData);

            Assert.Equal(transaction1559.Amount, decodedTransaction1559.Amount);
            Assert.Equal(transaction1559.Nonce, decodedTransaction1559.Nonce);
            Assert.Equal(transaction1559.ChainId, decodedTransaction1559.ChainId);
            if (string.IsNullOrEmpty(transaction1559.Data))
            {
                Assert.Null(decodedTransaction1559.Data);
            }
            else
            {
                Assert.Equal(transaction1559.Data, decodedTransaction1559.Data);
            }

            Assert.Equal(transaction1559.GasLimit, decodedTransaction1559.GasLimit);
            Assert.Equal(transaction1559.MaxFeePerGas, decodedTransaction1559.MaxFeePerGas);
            Assert.Equal(transaction1559.MaxPriorityFeePerGas, decodedTransaction1559.MaxPriorityFeePerGas);

            if (string.IsNullOrEmpty(transaction1559.ReceiverAddress))
            {
                Assert.Null(decodedTransaction1559.ReceiverAddress);
            }
            else
            {
                Assert.Equal(transaction1559.ReceiverAddress, decodedTransaction1559.ReceiverAddress);
            }


            Assert.Equal(transaction1559.Signature.V.ToHex(), decodedTransaction1559.Signature.V.ToHex());
            Assert.Equal(transaction1559.Signature.R.ToHex(), decodedTransaction1559.Signature.R.ToHex());
            Assert.Equal(transaction1559.Signature.S.ToHex(), decodedTransaction1559.Signature.S.ToHex());

            Assert.True(decodedTransaction1559.VerifyTransaction());
            Assert.True(decodedTransaction1559.GetSenderAddress().IsTheSameAddress("0x12890D2cce102216644c59daE5baed380d84830c"));
        }
Пример #3
0
            public async void ShouldSendTransactionCalculatingTheDefaultFees()
            {
                var chainId = 444444444500;
                var web3    = _ethereumClientIntegrationFixture.GetWeb3();
                var nonce   = await web3.Eth.TransactionManager.Account.NonceService.GetNextNonceAsync();

                var lastBlock =
                    await web3.Eth.Blocks.GetBlockWithTransactionsHashesByNumber.SendRequestAsync(
                        BlockParameter.CreateLatest());

                var baseFee = lastBlock.BaseFeePerGas;
                var maxPriorityFeePerGas = 2000000000;
                var maxFeePerGas         = baseFee.Value * 2 + 2000000000;

                var transaction1559 = new Transaction1559(chainId, nonce.Value, maxPriorityFeePerGas, maxFeePerGas,
                                                          45000,
                                                          "0x1ad91ee08f21be3de0ba2ba6918e714da6b45836", 10, "", null);

                transaction1559.Sign(new EthECKey(EthereumClientIntegrationFixture.AccountPrivateKey));


                var txnHash =
                    await web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(transaction1559.GetRLPEncoded()
                                                                                    .ToHex());

                // create recover signature
                var txn = await web3.Eth.Transactions.GetTransactionByHash.SendRequestAsync(txnHash);

                //what I want is to get the right Transaction checking the type or chainid etc and do a recovery
                Assert.True(txn.To.IsTheSameAddress("0x1ad91ee08f21be3de0ba2ba6918e714da6b45836"));
                Assert.Equal(10, txn.Value.Value);

                var transaction1559FromChain = TransactionFactory.CreateTransaction(chainId, (byte)txn.Type.Value,
                                                                                    txn.Nonce, txn.MaxPriorityFeePerGas,
                                                                                    txn.MaxFeePerGas, null, txn.Gas, txn.To, txn.Value, txn.Input, null, txn.R, txn.S, txn.V);

                Assert.True(transaction1559FromChain.GetSenderAddress()
                            .IsTheSameAddress("0x12890D2cce102216644c59daE5baed380d84830c"));

                var transactionReceipt =
                    await new TransactionReceiptPollingService(web3.TransactionManager).PollForReceiptAsync(txnHash,
                                                                                                            new CancellationTokenSource());
            }
Пример #4
0
        public void ShouldEncodeDecodeSignTransactionAccessLists(ulong chainId, ulong nonce, ulong maxPriorityFeePerGas, ulong maxFeePerGas,
                                                                 ulong gasLimit, string receiverAddress, ulong amount, string data)
        {
            var accessLists = new List <AccessListItem>();

            accessLists.Add(new AccessListItem("0x527306090abaB3A6e1400e9345bC60c78a8BEf57",
                                               new List <byte[]>
            {
                "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abab".HexToByteArray(),
                "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abac".HexToByteArray()
            }
                                               ));
            accessLists.Add(new AccessListItem("0x427306090abaB3A6e1400e9345bC60c78a8BEf5c",
                                               new List <byte[]>
            {
                "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abaa".HexToByteArray(),
                "0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abad".HexToByteArray()
            }
                                               ));

            var transaction1559 = new Transaction1559(chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, receiverAddress, amount, data, accessLists);

            transaction1559.Sign(new EthECKey("0xb5b1870957d373ef0eeffecc6e4812c0fd08f554b37b233526acc331bf1544f7"));

            var encodedData = transaction1559.GetRLPEncodedRaw();
            var signedData  = transaction1559.GetRLPEncoded();

            Debug.WriteLine(chainId + "," + nonce + "," + maxPriorityFeePerGas + "," + maxFeePerGas + "," + gasLimit + "," + receiverAddress + "," + amount + "," + data);
            Debug.WriteLine("");
            Debug.WriteLine(encodedData.ToHex());
            Debug.WriteLine(signedData.ToHex());
            var decodedTransaction1559 = Transaction1559Encoder.Current.Decode(signedData);

            Assert.Equal(transaction1559.Amount, decodedTransaction1559.Amount);
            Assert.Equal(transaction1559.Nonce, decodedTransaction1559.Nonce);
            Assert.Equal(transaction1559.ChainId, decodedTransaction1559.ChainId);
            if (string.IsNullOrEmpty(transaction1559.Data))
            {
                Assert.Null(decodedTransaction1559.Data);
            }
            else
            {
                Assert.Equal(transaction1559.Data, decodedTransaction1559.Data);
            }

            Assert.Equal(transaction1559.GasLimit, decodedTransaction1559.GasLimit);
            Assert.Equal(transaction1559.MaxFeePerGas, decodedTransaction1559.MaxFeePerGas);
            Assert.Equal(transaction1559.MaxPriorityFeePerGas, decodedTransaction1559.MaxPriorityFeePerGas);

            var decodedRlp = decodedTransaction1559.AccessList;

            Assert.True(accessLists[0].Address.IsTheSameAddress(decodedRlp[0].Address));
            Assert.Equal(accessLists[0].StorageKeys[0].ToHex(true), decodedRlp[0].StorageKeys[0].ToHex(true));
            Assert.Equal(accessLists[0].StorageKeys[1].ToHex(true), decodedRlp[0].StorageKeys[1].ToHex(true));
            Assert.True(accessLists[1].Address.IsTheSameAddress(decodedRlp[1].Address));
            Assert.Equal(accessLists[1].StorageKeys[0].ToHex(true), decodedRlp[1].StorageKeys[0].ToHex(true));
            Assert.Equal(accessLists[1].StorageKeys[1].ToHex(true), decodedRlp[1].StorageKeys[1].ToHex(true));

            if (string.IsNullOrEmpty(transaction1559.ReceiverAddress))
            {
                Assert.Null(decodedTransaction1559.ReceiverAddress);
            }
            else
            {
                Assert.Equal(transaction1559.ReceiverAddress, decodedTransaction1559.ReceiverAddress);
            }


            Assert.Equal(transaction1559.Signature.V.ToHex(), decodedTransaction1559.Signature.V.ToHex());
            Assert.Equal(transaction1559.Signature.R.ToHex(), decodedTransaction1559.Signature.R.ToHex());
            Assert.Equal(transaction1559.Signature.S.ToHex(), decodedTransaction1559.Signature.S.ToHex());
        }
        public string SignTransaction(Account account, TransactionInput transaction, BigInteger?overridingAccountChainId = null)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException(nameof(transaction));
            }
            if (string.IsNullOrWhiteSpace(transaction.From))
            {
                transaction.From = account.Address;
            }
            else if (!transaction.From.IsTheSameAddress(account.Address))
            {
                throw new Exception("Invalid account used for signing, does not match the transaction input");
            }

            var chainId = overridingAccountChainId;

            if (chainId == null)
            {
                chainId = account.ChainId;
            }

            var nonce = transaction.Nonce;

            if (nonce == null)
            {
                throw new ArgumentNullException(nameof(transaction), "Transaction nonce has not been set");
            }

            var    gasLimit = transaction.Gas;
            var    value    = transaction.Value ?? new HexBigInteger(0);
            string signedTransaction;

            if (transaction.Type != null && transaction.Type.Value == TransactionType.EIP1559.AsByte())
            {
                var maxPriorityFeePerGas = transaction.MaxPriorityFeePerGas.Value;
                var maxFeePerGas         = transaction.MaxFeePerGas.Value;
                if (chainId == null)
                {
                    throw new ArgumentException("ChainId required for TransactionType 0X02 EIP1559");
                }

                var transaction1559 = new Transaction1559(chainId.Value, nonce, maxPriorityFeePerGas, maxFeePerGas,
                                                          gasLimit, transaction.To, value, transaction.Data,
                                                          transaction.AccessList.ToSignerAccessListItemArray());
                transaction1559.Sign(new EthECKey(account.PrivateKey));
                signedTransaction = transaction1559.GetRLPEncoded().ToHex();
            }
            else
            {
                var gasPrice = transaction.GasPrice;

                if (chainId == null)
                {
                    signedTransaction = _legacyTransactionSigner.SignTransaction(account.PrivateKey,
                                                                                 transaction.To,
                                                                                 value.Value, nonce,
                                                                                 gasPrice.Value, gasLimit.Value, transaction.Data);
                }
                else
                {
                    signedTransaction = _legacyTransactionSigner.SignTransaction(account.PrivateKey, chainId.Value,
                                                                                 transaction.To,
                                                                                 value.Value, nonce,
                                                                                 gasPrice.Value, gasLimit.Value, transaction.Data);
                }
            }

            return(signedTransaction);
        }
Пример #6
0
 public override Task SignAsync(Transaction1559 transaction) => SignHashTransactionAsync(transaction);
        public IEnumerator SignAndSendTransaction(TransactionInput transactionInput)
        {
            if (transactionInput == null)
            {
                throw new ArgumentNullException("transactionInput");
            }

            if (string.IsNullOrEmpty(transactionInput.From))
            {
                transactionInput.From = _account;
            }

            if (!transactionInput.From.IsTheSameAddress(_account))
            {
                throw new Exception("Transaction Input From address does not match private keys address");
            }

            if (transactionInput.Gas == null)
            {
                if (EstimateGas)
                {
                    yield return(_ethEstimateGasUnityRequest.SendRequest(transactionInput));

                    if (_ethEstimateGasUnityRequest.Exception == null)
                    {
                        var gas = _ethEstimateGasUnityRequest.Result;
                        transactionInput.Gas = gas;
                    }
                    else
                    {
                        this.Exception = _ethEstimateGasUnityRequest.Exception;
                        yield break;
                    }
                }
                else
                {
                    transactionInput.Gas = new HexBigInteger(LegacyTransaction.DEFAULT_GAS_LIMIT);
                }
            }

            if (IsTransactionToBeSendAsEIP1559(transactionInput))
            {
                transactionInput.Type = new HexBigInteger(TransactionType.EIP1559.AsByte());
                if (transactionInput.MaxPriorityFeePerGas != null)
                {
                    if (transactionInput.MaxFeePerGas == null)
                    {
                        yield return(Fee1559SuggestionStrategy.SuggestFee(transactionInput.MaxPriorityFeePerGas.Value));

                        if (Fee1559SuggestionStrategy.Exception != null)
                        {
                            transactionInput.MaxFeePerGas = new HexBigInteger(Fee1559SuggestionStrategy.Result.MaxFeePerGas.Value);
                        }
                        else
                        {
                            this.Exception = Fee1559SuggestionStrategy.Exception;
                            yield break;
                        }
                    }
                }
                else
                {
                    yield return(Fee1559SuggestionStrategy.SuggestFee());

                    if (Fee1559SuggestionStrategy.Exception != null)
                    {
                        if (transactionInput.MaxFeePerGas == null)
                        {
                            transactionInput.MaxFeePerGas =
                                new HexBigInteger(Fee1559SuggestionStrategy.Result.MaxFeePerGas.Value);

                            transactionInput.MaxPriorityFeePerGas =
                                new HexBigInteger(Fee1559SuggestionStrategy.Result.MaxPriorityFeePerGas.Value);
                        }
                        else
                        {
                            if (transactionInput.MaxFeePerGas < Fee1559SuggestionStrategy.Result.MaxPriorityFeePerGas)
                            {
                                transactionInput.MaxPriorityFeePerGas = transactionInput.MaxFeePerGas;
                            }
                            else
                            {
                                transactionInput.MaxPriorityFeePerGas = new HexBigInteger(Fee1559SuggestionStrategy.Result.MaxPriorityFeePerGas.Value);
                            }
                        }
                    }
                    else
                    {
                        this.Exception = Fee1559SuggestionStrategy.Exception;
                        yield break;
                    }
                }
            }
            else
            {
                if (transactionInput.GasPrice == null)
                {
                    yield return(_ethGasPriceUnityRequest.SendRequest());

                    if (_ethGasPriceUnityRequest.Exception == null)
                    {
                        var gasPrice = _ethGasPriceUnityRequest.Result;
                        transactionInput.GasPrice = gasPrice;
                    }
                    else
                    {
                        this.Exception = _ethGasPriceUnityRequest.Exception;
                        yield break;
                    }
                }
            }


            var nonce = transactionInput.Nonce;

            if (nonce == null)
            {
                yield return(_transactionCountRequest.SendRequest(_account, Nethereum.RPC.Eth.DTOs.BlockParameter.CreateLatest()));

                if (_transactionCountRequest.Exception == null)
                {
                    nonce = _transactionCountRequest.Result;
                }
                else
                {
                    this.Exception = _transactionCountRequest.Exception;
                    yield break;
                }
            }

            var value = transactionInput.Value;

            if (value == null)
            {
                value = new HexBigInteger(0);
            }

            string signedTransaction;

            if (IsTransactionToBeSendAsEIP1559(transactionInput))
            {
                var transaction1559 = new Transaction1559(_chainId.Value, nonce, transactionInput.MaxPriorityFeePerGas.Value, transactionInput.MaxFeePerGas.Value,
                                                          transactionInput.Gas.Value, transactionInput.To, value.Value, transactionInput.Data,
                                                          null);
                transaction1559.Sign(new EthECKey(_privateKey));
                signedTransaction = transaction1559.GetRLPEncoded().ToHex();
            }
            else
            {
                if (_chainId == null)
                {
                    signedTransaction = _transactionSigner.SignTransaction(_privateKey, transactionInput.To, value.Value, nonce,
                                                                           transactionInput.GasPrice.Value, transactionInput.Gas.Value, transactionInput.Data);
                }
                else
                {
                    signedTransaction = _transactionSigner.SignTransaction(_privateKey, _chainId.Value, transactionInput.To, value.Value, nonce,
                                                                           transactionInput.GasPrice.Value, transactionInput.Gas.Value, transactionInput.Data);
                }
            }

            yield return(_ethSendTransactionRequest.SendRequest(signedTransaction));

            if (_ethSendTransactionRequest.Exception == null)
            {
                this.Result = _ethSendTransactionRequest.Result;
            }
            else
            {
                this.Exception = _ethSendTransactionRequest.Exception;
                yield break;
            }
        }
        public async Task <string> SignTransactionExternallyAsync(TransactionInput transaction)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException(nameof(transaction));
            }
            if (!transaction.From.IsTheSameAddress(Account.Address))
            {
                throw new Exception("Invalid account used signing");
            }

            SetDefaultGasPriceAndCostIfNotSet(transaction);

            var nonce = transaction.Nonce;

            if (nonce == null)
            {
                throw new ArgumentNullException(nameof(transaction), "Transaction nonce has not been set");
            }

            var gasPrice = transaction.GasPrice;
            var gasLimit = transaction.Gas;

            var value = transaction.Value ?? new HexBigInteger(0);

            string signedTransaction;

            var externalSigner = ((ExternalAccount)Account).ExternalSigner;

            if (externalSigner.Supported1559 && transaction.Type != null &&
                transaction.Type.Value == TransactionType.EIP1559.AsByte())
            {
                var maxPriorityFeePerGas = transaction.MaxPriorityFeePerGas.Value;
                var maxFeePerGas         = transaction.MaxFeePerGas.Value;
                if (ChainId == null)
                {
                    throw new ArgumentException("ChainId required for TransactionType 0X02 EIP1559");
                }

                var transaction1559 = new Transaction1559(ChainId.Value, nonce, maxPriorityFeePerGas, maxFeePerGas,
                                                          gasLimit, transaction.To, value, transaction.Data,
                                                          transaction.AccessList.ToSignerAccessListItemArray());
                await transaction1559.SignExternallyAsync(externalSigner).ConfigureAwait(false);

                signedTransaction = transaction1559.GetRLPEncoded().ToHex();
            }
            else
            {
                if (ChainId == null)
                {
                    signedTransaction = await _transactionSigner.SignTransactionAsync(externalSigner,
                                                                                      transaction.To,
                                                                                      value.Value, nonce,
                                                                                      gasPrice.Value, gasLimit.Value, transaction.Data).ConfigureAwait(false);
                }
                else
                {
                    signedTransaction = await _transactionSigner.SignTransactionAsync(externalSigner, ChainId.Value,
                                                                                      transaction.To,
                                                                                      value.Value, nonce,
                                                                                      gasPrice.Value, gasLimit.Value, transaction.Data).ConfigureAwait(false);
                }
            }

            return(signedTransaction);
        }
Пример #9
0
 public override Task SignAsync(Transaction1559 transaction)
 {
     throw new NotSupportedException();
 }
Пример #10
0
 public override Task SignAsync(Transaction1559 transaction)
 {
     return(SignHashTransactionAsync(transaction));
 }