public async Task <bool> ValidateTransactionAsync(Transaction transaction)
        {
            // Skip if this is a system transaction.
            if (_feeExemptionService.IsFree(transaction))
            {
                return(true);
            }

            var chain = await _blockchainService.GetChainAsync();

            var chainContext = new ChainContext
            {
                BlockHash   = chain.BestChainHash,
                BlockHeight = chain.BestChainHeight
            };

            // Skip if the sender is a contract.
            if (_deployedContractAddressProvider.CheckContractAddress(chainContext, transaction.From))
            {
                return(true);
            }

            // Skip this validation at the very beginning of current chain.
            if (chain.LastIrreversibleBlockHeight == Constants.GenesisBlockHeight)
            {
                return(true);
            }

            var tokenStub = _tokenContractReaderFactory.Create(chainContext);
            var balance   = (await tokenStub.GetBalance.CallAsync(new GetBalanceInput
            {
                Owner = transaction.From,
                Symbol = await _primaryTokenSymbolProvider.GetPrimaryTokenSymbol()
            }))?.Balance;

            // balance == null means token contract hasn't deployed.
            if (balance == null || balance > 0)
            {
                return(true);
            }

            Logger.LogWarning($"Empty balance of tx from address: {transaction}");
            return(false);
        }
Exemplo n.º 2
0
        public async Task <IEnumerable <Transaction> > GetPreTransactionsAsync(
            IReadOnlyList <ServiceDescriptor> descriptors, ITransactionContext transactionContext)
        {
            try
            {
                var context = _contextService.Create();

                if (_transactionFeeExemptionService.IsFree(transactionContext.Transaction))
                {
                    return(new List <Transaction>());
                }

                context.TransactionContext = transactionContext;
                var tokenContractAddress = context.GetContractAddressByName(TokenSmartContractAddressNameProvider.Name);

                if (context.CurrentHeight < Constants.GenesisBlockHeight + 1 || tokenContractAddress == null)
                {
                    return(new List <Transaction>());
                }

                if (!IsAcs1(descriptors) && transactionContext.Transaction.To != tokenContractAddress)
                {
                    return(new List <Transaction>());
                }

                var tokenStub = GetTokenContractStub(transactionContext.Transaction.From, tokenContractAddress);
                if (transactionContext.Transaction.To == tokenContractAddress &&
                    transactionContext.Transaction.MethodName == nameof(tokenStub.ChargeTransactionFees))
                {
                    // Skip ChargeTransactionFees itself
                    return(new List <Transaction>());
                }

                var txSize       = transactionContext.Transaction.Size();
                var chainContext = new ChainContext
                {
                    BlockHash   = transactionContext.PreviousBlockHash,
                    BlockHeight = transactionContext.BlockHeight - 1
                };
                var txCost = await _calStrategy.GetCostAsync(chainContext, txSize);

                var chargeTransactionFeesInput = new ChargeTransactionFeesInput
                {
                    MethodName         = transactionContext.Transaction.MethodName,
                    ContractAddress    = transactionContext.Transaction.To,
                    TransactionSizeFee = txCost,
                    PrimaryTokenSymbol = await _primaryTokenSymbolProvider.GetPrimaryTokenSymbol(),
                };
                var symbolListToPayTxSizeFee =
                    await _symbolListToPayTxFeeService.GetExtraAcceptedTokensInfoAsync(chainContext);

                if (symbolListToPayTxSizeFee != null)
                {
                    foreach (var tokenInfo in symbolListToPayTxSizeFee)
                    {
                        chargeTransactionFeesInput.SymbolsToPayTxSizeFee.Add(new SymbolToPayTXSizeFee
                        {
                            TokenSymbol      = tokenInfo.TokenSymbol,
                            BaseTokenWeight  = tokenInfo.BaseTokenWeight,
                            AddedTokenWeight = tokenInfo.AddedTokenWeight
                        });
                    }
                }

                var chargeFeeTransaction = (await tokenStub.ChargeTransactionFees.SendAsync(chargeTransactionFeesInput))
                                           .Transaction;
                return(new List <Transaction>
                {
                    chargeFeeTransaction
                });
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Failed to generate ChargeTransactionFees tx.");
                throw;
            }
        }
Exemplo n.º 3
0
        public async Task <IEnumerable <Transaction> > GetPreTransactionsAsync(
            IReadOnlyList <ServiceDescriptor> descriptors, ITransactionContext transactionContext)
        {
            try
            {
                var context = _contextService.Create();

                if (_transactionFeeExemptionService.IsFree(transactionContext.Transaction))
                {
                    return(new List <Transaction>());
                }

                context.TransactionContext = transactionContext;
                var tokenContractAddress = context.GetContractAddressByName(TokenSmartContractAddressNameProvider.Name);

                if (context.CurrentHeight < Constants.GenesisBlockHeight + 1 || tokenContractAddress == null)
                {
                    return(new List <Transaction>());
                }

                if (!IsAcs1(descriptors) && transactionContext.Transaction.To != tokenContractAddress)
                {
                    return(new List <Transaction>());
                }

                var tokenStub = new TokenContractContainer.TokenContractStub
                {
                    __factory = new TransactionGeneratingOnlyMethodStubFactory
                    {
                        Sender          = transactionContext.Transaction.From,
                        ContractAddress = tokenContractAddress
                    }
                };
                if (transactionContext.Transaction.To == tokenContractAddress &&
                    transactionContext.Transaction.MethodName == nameof(tokenStub.ChargeTransactionFees))
                {
                    // Skip ChargeTransactionFees itself
                    return(new List <Transaction>());
                }

                var txSize = transactionContext.Transaction.Size();
                var txCost = _calService.CalculateFee(FeeType.Tx, txSize);
                var chargeFeeTransaction = (await tokenStub.ChargeTransactionFees.SendAsync(
                                                new ChargeTransactionFeesInput
                {
                    MethodName = transactionContext.Transaction.MethodName,
                    ContractAddress = transactionContext.Transaction.To,
                    TransactionSizeFee = txCost,
                    PrimaryTokenSymbol = await _primaryTokenSymbolProvider.GetPrimaryTokenSymbol()
                })).Transaction;
                return(new List <Transaction>
                {
                    chargeFeeTransaction
                });
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Failed to generate ChargeTransactionFees tx.");
                throw;
            }
        }