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); }
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; } }
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; } }