mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-03-11 17:06:34 +00:00
Fix int overflow
This commit is contained in:
parent
2e0b02766e
commit
87d414a34c
3 changed files with 52 additions and 21 deletions
|
@ -1,6 +1,28 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
const ethereumAmountLength = 12;
|
||||||
|
const ethereumAmountDivider = 1000000000000;
|
||||||
|
final ethereumAmountFormat = NumberFormat()
|
||||||
|
..maximumFractionDigits = ethereumAmountLength
|
||||||
|
..minimumFractionDigits = 1;
|
||||||
|
|
||||||
class EthereumFormatter {
|
class EthereumFormatter {
|
||||||
static int parseEthereumAmount(String amount) =>
|
static int parseEthereumAmount(String amount) {
|
||||||
BigInt.from(double.parse(amount) * (pow(10, 18))).toInt();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,31 +6,34 @@ class EthereumTransactionInfo extends TransactionInfo {
|
||||||
EthereumTransactionInfo({
|
EthereumTransactionInfo({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.height,
|
required this.height,
|
||||||
required this.amount,
|
required this.ethAmount,
|
||||||
required this.fee,
|
required this.ethFee,
|
||||||
this.tokenSymbol = "ETH",
|
this.tokenSymbol = "ETH",
|
||||||
this.exponent = 18,
|
this.exponent = 18,
|
||||||
required this.direction,
|
required this.direction,
|
||||||
required this.isPending,
|
required this.isPending,
|
||||||
required this.date,
|
required this.date,
|
||||||
required this.confirmations,
|
required this.confirmations,
|
||||||
});
|
}) : this.amount = ethAmount.toInt(),
|
||||||
|
this.fee = ethFee.toInt();
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
final int height;
|
final int height;
|
||||||
final int amount;
|
final int amount;
|
||||||
|
final BigInt ethAmount;
|
||||||
final int exponent;
|
final int exponent;
|
||||||
final TransactionDirection direction;
|
final TransactionDirection direction;
|
||||||
final DateTime date;
|
final DateTime date;
|
||||||
final bool isPending;
|
final bool isPending;
|
||||||
final int fee;
|
final int fee;
|
||||||
|
final BigInt ethFee;
|
||||||
final int confirmations;
|
final int confirmations;
|
||||||
final String tokenSymbol;
|
final String tokenSymbol;
|
||||||
String? _fiatAmount;
|
String? _fiatAmount;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String amountFormatted() =>
|
String amountFormatted() =>
|
||||||
'${formatAmount((BigInt.from(amount) / BigInt.from(10).pow(exponent)).toString())} $tokenSymbol';
|
'${formatAmount((ethAmount / BigInt.from(10).pow(exponent)).toString())} $tokenSymbol';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String fiatAmount() => _fiatAmount ?? '';
|
String fiatAmount() => _fiatAmount ?? '';
|
||||||
|
@ -39,15 +42,15 @@ class EthereumTransactionInfo extends TransactionInfo {
|
||||||
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
|
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
|
||||||
|
|
||||||
@override
|
@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) {
|
factory EthereumTransactionInfo.fromJson(Map<String, dynamic> data) {
|
||||||
return EthereumTransactionInfo(
|
return EthereumTransactionInfo(
|
||||||
id: data['id'] as String,
|
id: data['id'] as String,
|
||||||
height: data['height'] as int,
|
height: data['height'] as int,
|
||||||
amount: data['amount'] as int,
|
ethAmount: data['amount'] as BigInt,
|
||||||
exponent: data['exponent'] as int,
|
exponent: data['exponent'] as int,
|
||||||
fee: data['fee'] as int,
|
ethFee: data['fee'] as BigInt,
|
||||||
direction: parseTransactionDirectionFromInt(data['direction'] as int),
|
direction: parseTransactionDirectionFromInt(data['direction'] as int),
|
||||||
date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int),
|
date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int),
|
||||||
isPending: data['isPending'] as bool,
|
isPending: data['isPending'] as bool,
|
||||||
|
@ -59,9 +62,9 @@ class EthereumTransactionInfo extends TransactionInfo {
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
'id': id,
|
'id': id,
|
||||||
'height': height,
|
'height': height,
|
||||||
'amount': amount,
|
'amount': ethAmount,
|
||||||
'exponent': exponent,
|
'exponent': exponent,
|
||||||
'fee': fee,
|
'fee': ethFee,
|
||||||
'direction': direction.index,
|
'direction': direction.index,
|
||||||
'date': date.millisecondsSinceEpoch,
|
'date': date.millisecondsSinceEpoch,
|
||||||
'isPending': isPending,
|
'isPending': isPending,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/node.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/erc20_balance.dart';
|
||||||
import 'package:cw_ethereum/ethereum_client.dart';
|
import 'package:cw_ethereum/ethereum_client.dart';
|
||||||
import 'package:cw_ethereum/ethereum_exceptions.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_credentials.dart';
|
||||||
import 'package:cw_ethereum/ethereum_transaction_history.dart';
|
import 'package:cw_ethereum/ethereum_transaction_history.dart';
|
||||||
import 'package:cw_ethereum/ethereum_transaction_info.dart';
|
import 'package:cw_ethereum/ethereum_transaction_info.dart';
|
||||||
|
@ -144,26 +146,30 @@ abstract class EthereumWalletBase
|
||||||
final outputs = _credentials.outputs;
|
final outputs = _credentials.outputs;
|
||||||
final hasMultiDestination = outputs.length > 1;
|
final hasMultiDestination = outputs.length > 1;
|
||||||
final _erc20Balance = balance[_credentials.currency]!;
|
final _erc20Balance = balance[_credentials.currency]!;
|
||||||
int totalAmount = 0;
|
BigInt totalAmount = BigInt.zero;
|
||||||
|
BigInt amountToEthereumMultiplier = BigInt.from(pow(10, 18 - ethereumAmountLength));
|
||||||
|
|
||||||
if (hasMultiDestination) {
|
if (hasMultiDestination) {
|
||||||
if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) {
|
if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) {
|
||||||
throw EthereumTransactionCreationException();
|
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();
|
throw EthereumTransactionCreationException();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final output = outputs.first;
|
final output = outputs.first;
|
||||||
final int allAmount = _erc20Balance.balance.toInt() - feeRate(_credentials.priority!);
|
final BigInt allAmount = _erc20Balance.balance - BigInt.from(feeRate(_credentials.priority!));
|
||||||
totalAmount = output.sendAll ? allAmount : output.formattedCryptoAmount ?? 0;
|
totalAmount = output.sendAll
|
||||||
|
? allAmount
|
||||||
|
: BigInt.from(output.formattedCryptoAmount ?? 0) * amountToEthereumMultiplier;
|
||||||
|
|
||||||
if ((output.sendAll &&
|
if ((output.sendAll && _erc20Balance.balance < totalAmount) ||
|
||||||
_erc20Balance.balance < EtherAmount.inWei(totalAmount as BigInt).getInWei) ||
|
(!output.sendAll && _erc20Balance.balance <= BigInt.zero)) {
|
||||||
(!output.sendAll && _erc20Balance.balance.toInt() <= 0)) {
|
|
||||||
throw EthereumTransactionCreationException();
|
throw EthereumTransactionCreationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,14 +234,14 @@ abstract class EthereumWalletBase
|
||||||
result[transactionModel.hash] = EthereumTransactionInfo(
|
result[transactionModel.hash] = EthereumTransactionInfo(
|
||||||
id: transactionModel.hash,
|
id: transactionModel.hash,
|
||||||
height: transactionModel.blockNumber,
|
height: transactionModel.blockNumber,
|
||||||
amount: transactionModel.amount.toInt(),
|
ethAmount: transactionModel.amount,
|
||||||
direction: transactionModel.from == address
|
direction: transactionModel.from == address
|
||||||
? TransactionDirection.outgoing
|
? TransactionDirection.outgoing
|
||||||
: TransactionDirection.incoming,
|
: TransactionDirection.incoming,
|
||||||
isPending: false,
|
isPending: false,
|
||||||
date: transactionModel.date,
|
date: transactionModel.date,
|
||||||
confirmations: transactionModel.confirmations,
|
confirmations: transactionModel.confirmations,
|
||||||
fee: transactionModel.gasUsed * transactionModel.gasPrice.toInt(),
|
ethFee: BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice,
|
||||||
exponent: transactionModel.tokenDecimal ?? 18,
|
exponent: transactionModel.tokenDecimal ?? 18,
|
||||||
tokenSymbol: transactionModel.tokenSymbol ?? "ETH",
|
tokenSymbol: transactionModel.tokenSymbol ?? "ETH",
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue