From 6c3c27eb81cfd32a4033427f9ae8710b634e3eef Mon Sep 17 00:00:00 2001 From: Peter Anyaogu Date: Tue, 16 Jan 2024 11:14:45 +0100 Subject: [PATCH] fix: gas estimations and redundat calls --- CHANGELOG.md | 10 ++++++ lib/src/4337/wallet.dart | 71 +++++++++++++++++++++++++++++++--------- pubspec.yaml | 2 +- 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 394ebdc..27bff91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.0.5 + +* Added missing required blockParam to `eth_call` + +* Reduced default callgasLimit and verificationGasLimit to 250K and 750k respectively in `eth_estimateUserOperationGas` + +* Prevent redundant eth_call's in fetching nonce/deployment status + +* Reduced strict internal op callGasLimit validation from 21k gas 12k gas requirement + ## 0.0.4 * Added a Secure Storage Repository for saving credentials to encrypted android shared-preference and iOS keychain diff --git a/lib/src/4337/wallet.dart b/lib/src/4337/wallet.dart index 1dd8052..5af58ca 100644 --- a/lib/src/4337/wallet.dart +++ b/lib/src/4337/wallet.dart @@ -206,7 +206,9 @@ class SmartWallet with _PluginManager implements SmartWalletBase { @override Future sendSignedUserOperation(UserOperation op) => plugin('bundler') - .sendUserOperation(op.toMap(), _chain.entrypoint); + .sendUserOperation(op.toMap(), _chain.entrypoint) + .catchError( + (e) => throw SmartWalletError.sendError(op, e.toString())); @override Future sendUserOperation(UserOperation op, @@ -241,34 +243,40 @@ class SmartWallet with _PluginManager implements SmartWalletBase { .function(functionName) .encodeCall(params); - Future _getNonce() => plugin("contract") - .call(_chain.entrypoint, ContractAbis.get('getNonce'), "getNonce", - params: [_walletAddress, BigInt.zero]) - .then((value) => Uint256(value[0])) - .catchError((e) => throw SmartWalletError( - "Error getting nonce for address: $_walletAddress. ${e.toString()}")); + Future _getNonce() => _deployed == false + ? Future.value(Uint256.zero) + : plugin("contract") + .call(_chain.entrypoint, ContractAbis.get('getNonce'), "getNonce", + params: [_walletAddress, BigInt.zero]) + .then((value) => Uint256(value[0])) + .catchError((e) => + throw SmartWalletError.nonceError(_walletAddress, e.toString())); Future _updateUserOperation(UserOperation op) async { List responses = await Future.wait([ + Future.microtask(() async => _deployed == null || _deployed == false + ? _deployed = await deployed + : _deployed), plugin('ethRpc').getGasPrice(), - _getNonce(), - Future.microtask(() async => _deployed = await deployed) + _getNonce() ]); op = UserOperation.update(op.toMap(), sender: _walletAddress, - nonce: responses[1].value, - initCode: responses[2] ? "0x" : null); + nonce: responses[2].value, + initCode: responses[0] ? "0x" : null); op.maxFeePerGas = - (responses[0] as Map)["maxFeePerGas"]!.getInWei; + (responses[1] as Map)["maxFeePerGas"]!.getInWei; op.maxPriorityFeePerGas = - (responses[0] as Map)["maxPriorityFeePerGas"]! + (responses[1] as Map)["maxPriorityFeePerGas"]! .getInWei; op.signature = plugin('signer').dummySignature; return plugin('bundler') .estimateUserOperationGas(op.toMap(), _chain.entrypoint) - .then((opGas) => UserOperation.update(op.toMap(), opGas: opGas)); + .then((opGas) => UserOperation.update(op.toMap(), opGas: opGas)) + .catchError( + (e) => throw SmartWalletError.estimateError(op, e.toString())); } Future _validateUserOperation(UserOperation op) async { @@ -285,8 +293,8 @@ class SmartWallet with _PluginManager implements SmartWalletBase { ? hexlify(op.initCode).toLowerCase() == "0x" : hexlify(op.initCode).toLowerCase() == initCode.toLowerCase(), "Init code mismatch"); - require(op.callGasLimit >= BigInt.from(21000), - "Call gas limit too small expected value greater than 21000"); + require(op.callGasLimit >= BigInt.from(12000), + "Call gas limit too small expected value greater than 12000"); require(op.verificationGasLimit >= BigInt.from(39000), "Verification gas limit too small expected value greater than 39000"); require(op.preVerificationGas >= BigInt.from(5000), @@ -301,6 +309,37 @@ class SmartWalletError extends Error { SmartWalletError(this.message); + factory SmartWalletError.sendError(UserOperation op, String message) { + return SmartWalletError(''' + \x1B[31m ************************************************** + Error sending user operation! Failed with error: $message + -------------------------------------------------- + \x1B[33m User operation: ${op.toJson()}. \x1B[31m + ************************************************** \x1B[0m + '''); + } + + factory SmartWalletError.estimateError(UserOperation op, String message) { + return SmartWalletError(''' + \x1B[31m ************************************************** + Error estimating user operation gas! Failed with error: $message + -------------------------------------------------- + \x1B[33m User operation: ${op.toJson()}. \x1B[31m + ************************************************** \x1B[0m + '''); + } + + factory SmartWalletError.nonceError( + EthereumAddress? address, String message) { + return SmartWalletError(''' + \x1B[31m ************************************************** + Error fetching user account nonce for address \x1B[33m ${address?.hex}! \x1B[31m + -------------------------------------------------- + Failed with error: $message + ************************************************** \x1B[0m + '''); + } + @override String toString() { return message; diff --git a/pubspec.yaml b/pubspec.yaml index 9d97ea7..0632ba5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: variance_dart description: An Account Abstraction (4337) Development kit, for quickly building mobile web3 apps and smart wallets. -version: 0.0.4 +version: 0.0.5 documentation: https://docs.variance.space homepage: https://variance.space repository: https://github.com/vaariance/variance-dart