Skip to content

Commit

Permalink
gas optimization for optimism
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewwahid authored and Sednaoui committed Jul 3, 2023
1 parent fa1b34c commit 70063d3
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 48 deletions.
17 changes: 8 additions & 9 deletions lib/models/gas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ class GasEstimate {
BigInt verificationGasLimit;
BigInt maxPriorityFeePerGas;
BigInt maxFeePerGas;
late BigInt extraPreVerificationGas; //specific for L2s
late BigInt l1GasUsed; //specific for L2s
late BigInt l1BaseFee; //specific for L2s
late BigInt l1Fee; //specific for L2s
late BigInt l1FeeWithPaymaster; //specific for L2s

GasEstimate(
{required this.callGasLimit, // set by bundler
Expand All @@ -16,10 +15,10 @@ class GasEstimate {
required this.verificationGasLimit, // set by bundler
required this.maxPriorityFeePerGas,
required this.maxFeePerGas,
BigInt? l1GasUsed,
BigInt? l1BaseFee}) {
this.l1GasUsed = l1GasUsed ?? BigInt.zero;
this.l1BaseFee = l1BaseFee ?? BigInt.zero;
BigInt? l1Fee,
BigInt? l1FeeWithPaymaster}) {
this.l1Fee = l1Fee ?? BigInt.zero;
this.l1FeeWithPaymaster = l1FeeWithPaymaster ?? BigInt.zero;
}

GasEstimate copy() {
Expand All @@ -30,8 +29,8 @@ class GasEstimate {
verificationGasLimit: verificationGasLimit,
maxPriorityFeePerGas: maxPriorityFeePerGas,
maxFeePerGas: maxFeePerGas,
l1GasUsed: l1GasUsed,
l1BaseFee: l1BaseFee,
l1Fee: l1Fee,
l1FeeWithPaymaster: l1FeeWithPaymaster,
);
}
}
2 changes: 1 addition & 1 deletion lib/models/gas_estimators/gas_estimator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ abstract class GasEstimator {

GasEstimator({required this.chainId});

Future<List<int>?> getNetworkGasFees();
Future<List<BigInt>?> getNetworkGasFees();
Future<GasEstimate?> getGasEstimates(UserOperation userOp, {GasEstimate? prevEstimate, bool includesPaymaster = false});
}
18 changes: 8 additions & 10 deletions lib/models/gas_estimators/l1_gas_estimator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,23 @@ import 'dart:typed_data';
import 'package:candide_mobile_app/models/gas.dart';
import 'package:candide_mobile_app/models/gas_estimators/gas_estimator.dart';
import 'package:candide_mobile_app/services/bundler.dart';
import 'package:decimal/decimal.dart';
import 'package:dio/dio.dart';
import 'package:wallet_dart/wallet/user_operation.dart';
import 'package:web3dart/crypto.dart';
import 'package:web3dart/web3dart.dart';

class L1GasEstimator extends GasEstimator {

L1GasEstimator({required super.chainId});

@override
Future<List<int>?> getNetworkGasFees() async {
if (chainId == 11155111) return [1510000000, 1500000000];
Future<List<BigInt>?> getNetworkGasFees() async {
if (chainId == 11155111) return [BigInt.from(1510000000), BigInt.from(1500000000)];
try{
var response = await Dio().get("https://gas-api.metaswap.codefi.network/networks/$chainId/suggestedGasFees");
//
int suggestedMaxFeePerGas = (double.parse(response.data["medium"]["suggestedMaxFeePerGas"]) * 1000).ceil();
int suggestedMaxPriorityFeePerGas = (double.parse(response.data["medium"]["suggestedMaxPriorityFeePerGas"]) * 1000).ceil();
suggestedMaxFeePerGas = EtherAmount.fromUnitAndValue(EtherUnit.mwei, suggestedMaxFeePerGas).getInWei.toInt();
suggestedMaxPriorityFeePerGas = EtherAmount.fromUnitAndValue(EtherUnit.mwei, suggestedMaxPriorityFeePerGas).getInWei.toInt();
BigInt suggestedMaxFeePerGas = Decimal.parse(response.data["medium"]["suggestedMaxFeePerGas"]).shift(9).toBigInt();
BigInt suggestedMaxPriorityFeePerGas = Decimal.parse(response.data["medium"]["suggestedMaxPriorityFeePerGas"]).shift(9).toBigInt();
//
return [suggestedMaxFeePerGas, suggestedMaxPriorityFeePerGas];
} on DioError catch(e){
Expand All @@ -43,11 +41,11 @@ class L1GasEstimator extends GasEstimator {
dummyOp.signature = bytesToHex(Uint8List.fromList(List<int>.filled(65, 1)), include0x: true);
//
if (prevEstimate == null){
List<int> networkFees = await getNetworkGasFees() ?? [0, 0];
List<BigInt> networkFees = await getNetworkGasFees() ?? [BigInt.zero, BigInt.zero];
gasEstimate = await Bundler.getUserOperationGasEstimates(dummyOp, chainId);
if (gasEstimate == null) return null;
gasEstimate.maxFeePerGas = BigInt.from(networkFees[0]);
gasEstimate.maxPriorityFeePerGas = BigInt.from(networkFees[1]);
gasEstimate.maxFeePerGas = networkFees[0];
gasEstimate.maxPriorityFeePerGas = networkFees[1];
}else{
gasEstimate = prevEstimate.copy();
}
Expand Down
67 changes: 42 additions & 25 deletions lib/models/gas_estimators/l2_gas_estimator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import 'package:candide_mobile_app/models/gas_estimators/gas_estimator.dart';
import 'package:candide_mobile_app/models/gas_estimators/source/ovm_gas_oracle.g.dart';
import 'package:candide_mobile_app/services/bundler.dart';
import 'package:candide_mobile_app/utils/constants.dart';
import 'package:candide_mobile_app/utils/extensions/bigint_extensions.dart';
import 'package:decimal/decimal.dart';
import 'package:dio/dio.dart';
import 'package:eth_sig_util/util/utils.dart';
import 'package:wallet_dart/contracts/factories/EntryPoint.g.dart';
import 'package:wallet_dart/wallet/user_operation.dart';
Expand All @@ -17,8 +20,23 @@ class L2GasEstimator extends GasEstimator {
L2GasEstimator({required this.ovmGasOracle, required super.chainId});

@override
Future<List<int>?> getNetworkGasFees() async {
return [1100000, 1100000]; // same value so block.baseFee doesn't get invoked from EP https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/core/EntryPoint.sol#L594
Future<List<BigInt>?> getNetworkGasFees() async {
//;
if (chainId == 420){
BigInt baseFee = (await Networks.selected().client.getGasPrice()).getInWei;
return [baseFee.scale(1.10), baseFee.scale(1.05)];
}
try{
var response = await Dio().get("https://gas-api.metaswap.codefi.network/networks/$chainId/suggestedGasFees");
//
BigInt suggestedMaxFeePerGas = Decimal.parse(response.data["medium"]["suggestedMaxFeePerGas"]).shift(9).toBigInt();
BigInt suggestedMaxPriorityFeePerGas = Decimal.parse(response.data["medium"]["suggestedMaxPriorityFeePerGas"]).shift(9).toBigInt();
//
return [suggestedMaxFeePerGas, suggestedMaxPriorityFeePerGas];
} on DioError catch(e){
print("Error occurred ${e.type.toString()}");
return null;
}
}

@override
Expand All @@ -34,42 +52,41 @@ class L2GasEstimator extends GasEstimator {
dummyOp.signature = bytesToHex(Uint8List.fromList(List<int>.filled(65, 1)), include0x: true);
//
if (prevEstimate == null){
List<int> networkFees = await getNetworkGasFees() ?? [0, 0];
List<BigInt> networkFees = await getNetworkGasFees() ?? [BigInt.zero, BigInt.zero];
gasEstimate = await Bundler.getUserOperationGasEstimates(dummyOp, chainId);
if (gasEstimate == null) return null;
gasEstimate.maxFeePerGas = BigInt.from(networkFees[0]);
gasEstimate.maxPriorityFeePerGas = BigInt.from(networkFees[1]);
gasEstimate.maxFeePerGas = networkFees[0];
gasEstimate.maxPriorityFeePerGas = networkFees[1];
}else{
gasEstimate = prevEstimate.copy();
}
//
if (gasEstimate.l1GasUsed == BigInt.zero){
if (gasEstimate.l1Fee == BigInt.zero || (gasEstimate.l1FeeWithPaymaster == BigInt.zero && includesPaymaster)){
Web3Client client = Networks.getByChainId(chainId)!.client;
OVMGasOracle gasOracle = OVMGasOracle(address: ovmGasOracle, client: client);
late BigInt l1GasUsed;
late BigInt l1BaseFee;
late BigInt l1Fee;
//
if (includesPaymaster){
dummyOp.paymasterAndData = bytesToHex(Uint8List.fromList(List<int>.filled(176, 1)), include0x: true);
}
//
EntryPoint entryPoint = EntryPoint(address: Constants.addressZero, client: client);
var callData = entryPoint.self.function("handleOps").encodeCall([
[dummyOp.toList()],
dummyOp.sender
]);
await Future.wait([
gasOracle.getL1GasUsed(callData).then((value) => l1GasUsed = value),
gasOracle.l1BaseFee().then((value) => l1BaseFee = value),
EthereumAddress.fromHex("0xffffffffffffffffffffffffffffffffffffffff")
]);
gasEstimate.l1BaseFee = l1BaseFee;
gasEstimate.l1GasUsed = l1GasUsed;
}
BigInt l1GasUsed = gasEstimate.l1GasUsed;
if (includesPaymaster){
l1GasUsed += BigInt.from(84); // To accommodate for GnosisTransaction.approveAmount which would be 0 before estimation
l1GasUsed += BigInt.from(2496); // to accommodate for paymasterAndData (156 bytes * 16)
}
BigInt scale = gasEstimate.l1BaseFee ~/ gasEstimate.maxFeePerGas;
if (scale == BigInt.zero){
scale = BigInt.one;
//
l1Fee = await gasOracle.getL1Fee(callData);
if (includesPaymaster){
gasEstimate.l1FeeWithPaymaster = l1Fee;
}else{
gasEstimate.l1Fee = l1Fee;
}
}
gasEstimate.preVerificationGas = gasEstimate.basePreVerificationGas + (l1GasUsed * (scale));
BigInt l1Fee = includesPaymaster ? gasEstimate.l1FeeWithPaymaster : gasEstimate.l1Fee;
BigInt _l1Fee = l1Fee ~/ gasEstimate.maxFeePerGas;
if (_l1Fee == BigInt.zero) _l1Fee = BigInt.from(7500);
gasEstimate.preVerificationGas = gasEstimate.basePreVerificationGas + _l1Fee;
//
return gasEstimate;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/screens/home/send/send_amount_sheet.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:candide_mobile_app/config/network.dart';
import 'package:candide_mobile_app/config/theme.dart';
import 'package:candide_mobile_app/controller/persistent_data.dart';
import 'package:candide_mobile_app/controller/token_info_storage.dart';
Expand Down Expand Up @@ -25,7 +26,7 @@ class SendAmountSheet extends StatefulWidget {
class _SendAmountSheetState extends State<SendAmountSheet> {
final FocusNode _amountFocus = FocusNode();
final TextEditingController _amountController = TextEditingController();
TokenInfo selectedToken = TokenInfoStorage.getTokenBySymbol("ETH")!;
TokenInfo selectedToken = TokenInfoStorage.getTokenBySymbol(Networks.selected().nativeCurrency)!;
String errorMessage = "Sending amount must be greater than zero";
final _errors = {
"balance": "Insufficient Balance",
Expand Down
5 changes: 3 additions & 2 deletions lib/services/paymaster.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:convert';

import 'package:candide_mobile_app/config/env.dart';
import 'package:candide_mobile_app/config/network.dart';
import 'package:candide_mobile_app/controller/token_info_storage.dart';
import 'package:candide_mobile_app/models/paymaster/fee_token.dart';
import 'package:candide_mobile_app/models/paymaster/paymaster_data.dart';
Expand All @@ -15,9 +16,9 @@ class Paymaster {

static Future<PaymasterResponse?> fetchPaymasterFees(int chainId) async {
List<FeeToken> result = [];
TokenInfo? _ethereum = TokenInfoStorage.getTokenByAddress(Constants.addressZeroHex);
TokenInfo? _nativeToken = TokenInfoStorage.getTokenByAddress(Networks.getByChainId(chainId)!.nativeCurrencyAddress.hex);
result.add(FeeToken(
token: _ethereum!,
token: _nativeToken!,
fee: BigInt.zero,
paymasterFee: BigInt.zero,
exchangeRate: BigInt.parse("1000000000000000000")
Expand Down

0 comments on commit 70063d3

Please sign in to comment.