Fix int overflow

This commit is contained in:
OmarHatem 2023-07-22 03:39:10 +03:00
parent 2e0b02766e
commit 87d414a34c
3 changed files with 52 additions and 21 deletions

View file

@ -1,6 +1,28 @@
import 'dart:math';
import 'package:intl/intl.dart';
const ethereumAmountLength = 12;
const ethereumAmountDivider = 1000000000000;
final ethereumAmountFormat = NumberFormat()
..maximumFractionDigits = ethereumAmountLength
..minimumFractionDigits = 1;
class EthereumFormatter {
static int parseEthereumAmount(String amount) =>
BigInt.from(double.parse(amount) * (pow(10, 18))).toInt();
static int parseEthereumAmount(String amount) {
try {
return (double.parse(amount) * ethereumAmountDivider).round();
} catch (_) {
return 0;
}
}
static int parseEthereumBigIntAmount(BigInt amount) {
try {
double result = amount / BigInt.from(pow(10, 18 - ethereumAmountLength));
return result.toInt();
} catch (_) {
return 0;
}
}
}

View file

@ -6,31 +6,34 @@ class EthereumTransactionInfo extends TransactionInfo {
EthereumTransactionInfo({
required this.id,
required this.height,
required this.amount,
required this.fee,
required this.ethAmount,
required this.ethFee,
this.tokenSymbol = "ETH",
this.exponent = 18,
required this.direction,
required this.isPending,
required this.date,
required this.confirmations,
});
}) : this.amount = ethAmount.toInt(),
this.fee = ethFee.toInt();
final String id;
final int height;
final int amount;
final BigInt ethAmount;
final int exponent;
final TransactionDirection direction;
final DateTime date;
final bool isPending;
final int fee;
final BigInt ethFee;
final int confirmations;
final String tokenSymbol;
String? _fiatAmount;
@override
String amountFormatted() =>
'${formatAmount((BigInt.from(amount) / BigInt.from(10).pow(exponent)).toString())} $tokenSymbol';
'${formatAmount((ethAmount / BigInt.from(10).pow(exponent)).toString())} $tokenSymbol';
@override
String fiatAmount() => _fiatAmount ?? '';
@ -39,15 +42,15 @@ class EthereumTransactionInfo extends TransactionInfo {
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
@override
String feeFormatted() => '${(BigInt.from(fee) / BigInt.from(10).pow(18)).toString()} ETH';
String feeFormatted() => '${(ethFee / BigInt.from(10).pow(18)).toString()} ETH';
factory EthereumTransactionInfo.fromJson(Map<String, dynamic> data) {
return EthereumTransactionInfo(
id: data['id'] as String,
height: data['height'] as int,
amount: data['amount'] as int,
ethAmount: data['amount'] as BigInt,
exponent: data['exponent'] as int,
fee: data['fee'] as int,
ethFee: data['fee'] as BigInt,
direction: parseTransactionDirectionFromInt(data['direction'] as int),
date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int),
isPending: data['isPending'] as bool,
@ -59,9 +62,9 @@ class EthereumTransactionInfo extends TransactionInfo {
Map<String, dynamic> toJson() => {
'id': id,
'height': height,
'amount': amount,
'amount': ethAmount,
'exponent': exponent,
'fee': fee,
'fee': ethFee,
'direction': direction.index,
'date': date.millisecondsSinceEpoch,
'isPending': isPending,

View file

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/node.dart';
@ -16,6 +17,7 @@ import 'package:cw_ethereum/default_erc20_tokens.dart';
import 'package:cw_ethereum/erc20_balance.dart';
import 'package:cw_ethereum/ethereum_client.dart';
import 'package:cw_ethereum/ethereum_exceptions.dart';
import 'package:cw_ethereum/ethereum_formatter.dart';
import 'package:cw_ethereum/ethereum_transaction_credentials.dart';
import 'package:cw_ethereum/ethereum_transaction_history.dart';
import 'package:cw_ethereum/ethereum_transaction_info.dart';
@ -144,26 +146,30 @@ abstract class EthereumWalletBase
final outputs = _credentials.outputs;
final hasMultiDestination = outputs.length > 1;
final _erc20Balance = balance[_credentials.currency]!;
int totalAmount = 0;
BigInt totalAmount = BigInt.zero;
BigInt amountToEthereumMultiplier = BigInt.from(pow(10, 18 - ethereumAmountLength));
if (hasMultiDestination) {
if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) {
throw EthereumTransactionCreationException();
}
totalAmount = outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0));
totalAmount =
BigInt.from(outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0))) *
amountToEthereumMultiplier;
if (_erc20Balance.balance < EtherAmount.inWei(totalAmount as BigInt).getInWei) {
if (_erc20Balance.balance < totalAmount) {
throw EthereumTransactionCreationException();
}
} else {
final output = outputs.first;
final int allAmount = _erc20Balance.balance.toInt() - feeRate(_credentials.priority!);
totalAmount = output.sendAll ? allAmount : output.formattedCryptoAmount ?? 0;
final BigInt allAmount = _erc20Balance.balance - BigInt.from(feeRate(_credentials.priority!));
totalAmount = output.sendAll
? allAmount
: BigInt.from(output.formattedCryptoAmount ?? 0) * amountToEthereumMultiplier;
if ((output.sendAll &&
_erc20Balance.balance < EtherAmount.inWei(totalAmount as BigInt).getInWei) ||
(!output.sendAll && _erc20Balance.balance.toInt() <= 0)) {
if ((output.sendAll && _erc20Balance.balance < totalAmount) ||
(!output.sendAll && _erc20Balance.balance <= BigInt.zero)) {
throw EthereumTransactionCreationException();
}
}
@ -228,14 +234,14 @@ abstract class EthereumWalletBase
result[transactionModel.hash] = EthereumTransactionInfo(
id: transactionModel.hash,
height: transactionModel.blockNumber,
amount: transactionModel.amount.toInt(),
ethAmount: transactionModel.amount,
direction: transactionModel.from == address
? TransactionDirection.outgoing
: TransactionDirection.incoming,
isPending: false,
date: transactionModel.date,
confirmations: transactionModel.confirmations,
fee: transactionModel.gasUsed * transactionModel.gasPrice.toInt(),
ethFee: BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice,
exponent: transactionModel.tokenDecimal ?? 18,
tokenSymbol: transactionModel.tokenSymbol ?? "ETH",
);