Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gas optimization #24

Merged
merged 1 commit into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.1.6

* Remove repetated function call in safe plugin
* Split gas overrides individually
* Change point of gas override

## 0.1.5

* improve gas fees estimation
Expand Down
138 changes: 73 additions & 65 deletions lib/src/4337/wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,61 +85,66 @@ class SmartWallet with _PluginManager, _GasSettings implements SmartWalletBase {
UserOperation buildUserOperation({
required Uint8List callData,
BigInt? customNonce,
}) =>
UserOperation.partial(
callData: callData,
initCode: _initCode,
sender: _walletAddress,
nonce: customNonce);
}) {
return UserOperation.partial(
callData: callData,
initCode: _initCode,
sender: _walletAddress,
nonce: customNonce);
}

@override
Future<UserOperationResponse> send(
EthereumAddress recipient, EtherAmount amount) =>
sendUserOperation(buildUserOperation(
callData: Contract.execute(_walletAddress,
to: recipient, amount: amount, isSafe: isSafe)));
EthereumAddress recipient, EtherAmount amount) {
final cd = Contract.execute(_walletAddress,
to: recipient, amount: amount, isSafe: isSafe);
return sendUserOperation(buildUserOperation(callData: cd));
}

@override
Future<UserOperationResponse> sendTransaction(
EthereumAddress to, Uint8List encodedFunctionData,
{EtherAmount? amount}) =>
sendUserOperation(buildUserOperation(
callData: Contract.execute(_walletAddress,
to: to,
amount: amount,
innerCallData: encodedFunctionData,
isSafe: isSafe)));
EthereumAddress to, Uint8List encodedFunctionData,
{EtherAmount? amount}) {
final cd = Contract.execute(_walletAddress,
to: to,
amount: amount,
innerCallData: encodedFunctionData,
isSafe: isSafe);
return sendUserOperation(buildUserOperation(callData: cd));
}

@override
Future<UserOperationResponse> sendBatchedTransaction(
List<EthereumAddress> recipients, List<Uint8List> calls,
{List<EtherAmount>? amounts}) {
Uint8List cd;
if (isSafe) {
final innerCall = plugin<_SafePlugin>('safe')
.getSafeMultisendCallData(recipients, amounts, calls);
return sendUserOperation(buildUserOperation(
callData: Contract.executeBatch(
walletAddress: _walletAddress,
recipients: [Constants.safeMultiSendaddress],
amounts: [],
innerCalls: [innerCall],
isSafe: true)));
cd = Contract.executeBatch(
walletAddress: _walletAddress,
recipients: [Constants.safeMultiSendaddress],
amounts: [],
innerCalls: [innerCall],
isSafe: true);
return sendUserOperation(buildUserOperation(callData: cd));
} else {
return sendUserOperation(buildUserOperation(
callData: Contract.executeBatch(
walletAddress: _walletAddress,
recipients: recipients,
amounts: amounts,
innerCalls: calls)));
cd = Contract.executeBatch(
walletAddress: _walletAddress,
recipients: recipients,
amounts: amounts,
innerCalls: calls);
return sendUserOperation(buildUserOperation(callData: cd));
}
}

@override
Future<UserOperationResponse> sendSignedUserOperation(UserOperation op) =>
plugin<BundlerProviderBase>('bundler')
.sendUserOperation(
op.toMap(_chain.entrypoint.version), _chain.entrypoint)
.catchError((e) => throw SendError(e.toString(), op));
Future<UserOperationResponse> sendSignedUserOperation(UserOperation op) {
return plugin<BundlerProviderBase>('bundler')
.sendUserOperation(
op.toMap(_chain.entrypoint.version), _chain.entrypoint)
.catchError((e) => throw SendError(e.toString(), op));
}

@override
Future<UserOperationResponse> sendUserOperation(UserOperation op) =>
Expand Down Expand Up @@ -198,39 +203,41 @@ class SmartWallet with _PluginManager, _GasSettings implements SmartWalletBase {
/// Otherwise, retrieves the nonce by calling the 'getNonce' function on the entrypoint.
///
/// If an error occurs during the nonce retrieval process, a [NonceError] exception is thrown.
Future<Uint256> _getNonce() => isDeployed.then((deployed) => !deployed
? Future.value(Uint256.zero)
: plugin<Contract>("contract")
.read(_chain.entrypoint.address, ContractAbis.get('getNonce'),
"getNonce",
params: [_walletAddress, BigInt.zero])
.then((value) => Uint256(value[0]))
.catchError((e) => throw NonceError(e.toString(), _walletAddress)));
Future<Uint256> _getNonce() {
return isDeployed.then((deployed) => !deployed
? Future.value(Uint256.zero)
: plugin<Contract>("contract")
.read(_chain.entrypoint.address, ContractAbis.get('getNonce'),
"getNonce",
params: [_walletAddress, BigInt.zero])
.then((value) => Uint256(value[0]))
.catchError((e) => throw NonceError(e.toString(), _walletAddress)));
}

/// Returns the balance for the Smart Wallet address.
///
/// If an error occurs during the balance retrieval process, a [FetchBalanceError] exception is thrown.
Future<EtherAmount> _getBalance() => plugin<Contract>("contract")
.getBalance(_walletAddress)
.catchError((e) => throw FetchBalanceError(e.toString(), _walletAddress));
Future<EtherAmount> _getBalance() {
return plugin<Contract>("contract").getBalance(_walletAddress).catchError(
(e) => throw FetchBalanceError(e.toString(), _walletAddress));
}

/// Updates the user operation with the latest nonce and gas prices.
///
/// [op] is the user operation to update.
///
/// Returns a [Future] that resolves to the updated [UserOperation] object.
Future<UserOperation> _updateUserOperation(UserOperation op) =>
Future.wait<dynamic>([
_getNonce(),
plugin<JsonRPCProviderBase>('jsonRpc').getGasPrice()
]).then((responses) {
op = op.copyWith(
nonce: op.nonce > BigInt.zero ? op.nonce : responses[0].value,
initCode: responses[0] > Uint256.zero ? Uint8List(0) : null,
signature: dummySignature);

return _updateUserOperationGas(op, responses[1]);
});
Future<UserOperation> _updateUserOperation(UserOperation op) async {
final responses = await Future.wait<dynamic>(
[_getNonce(), plugin<JsonRPCProviderBase>('jsonRpc').getGasPrice()]);

op = op.copyWith(
nonce: op.nonce > BigInt.zero ? op.nonce : responses[0].value,
initCode: responses[0] > Uint256.zero ? Uint8List(0) : null,
signature: dummySignature);

return _updateUserOperationGas(op, responses[1]);
}

/// Updates the gas information for the user operation.
///
Expand All @@ -240,10 +247,11 @@ class SmartWallet with _PluginManager, _GasSettings implements SmartWalletBase {
/// Returns a [Future] that resolves to the updated [UserOperation] object.
///
/// If an error occurs during the gas estimation process, a [GasEstimationError] exception is thrown.
Future<UserOperation> _updateUserOperationGas(UserOperation op, Fee fee) =>
plugin<BundlerProviderBase>('bundler')
.estimateUserOperationGas(
op.toMap(_chain.entrypoint.version), _chain.entrypoint)
.then((opGas) => op.updateOpGas(opGas, fee))
.catchError((e) => throw GasEstimationError(e.toString(), op));
Future<UserOperation> _updateUserOperationGas(UserOperation op, Fee fee) {
return plugin<BundlerProviderBase>('bundler')
.estimateUserOperationGas(
op.toMap(_chain.entrypoint.version), _chain.entrypoint)
.then((opGas) => op.updateOpGas(opGas, fee))
.catchError((e) => throw GasEstimationError(e.toString(), op));
}
}
7 changes: 5 additions & 2 deletions lib/src/common/factories.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,17 @@ class _SafeProxyFactory extends SafeProxyFactory
final setup = {
"owners": owners.toList(),
"threshold": BigInt.from(threshold),
"to": module.setup,
"data": encodeModuleSetup(),
"to": null,
"data": null,
"fallbackHandler": module.address,
};

if (encodeWebauthnSetup != null) {
setup["to"] = Constants.safeMultiSendaddress;
setup["data"] = encodeWebauthnSetup(encodeModuleSetup);
} else {
setup["to"] = module.setup;
setup["data"] = encodeModuleSetup();
}

return Contract.encodeFunctionCall(
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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.1.5
version: 0.1.6
documentation: https://docs.variance.space
homepage: https://variance.space
repository: https://github.com/vaariance/variance-dart
Expand Down
Loading