From 90e90d1bfeb17f0ca451cfabeb5fead2d5444919 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Mon, 20 May 2024 23:28:55 +0300 Subject: [PATCH 01/23] Support 1559 and 113 (ZkSync) Transaction Types --- Thirdweb.Console/Program.cs | 34 ++++-- .../Thirdweb.PrivateKeyWallet.Tests.cs | 16 +-- Thirdweb.Tests/Thirdweb.SmartWallet.Tests.cs | 4 +- Thirdweb.Tests/Thirdweb.Transactions.Tests.cs | 29 +++-- Thirdweb.Tests/Thirdweb.Wallets.Tests.cs | 2 +- .../Thirdweb.Contracts/ThirdwebContract.cs | 2 +- .../ThirdwebTransaction.cs | 115 ++++++++++++++++-- .../ThirdwebTransactionInput.cs | 57 +++++++++ Thirdweb/Thirdweb.Utils/Utils.cs | 11 ++ Thirdweb/Thirdweb.Wallets/EIP712.cs | 52 ++++++++ Thirdweb/Thirdweb.Wallets/IThirdwebWallet.cs | 3 +- .../PrivateKeyWallet/PrivateKeyWallet.cs | 45 ++++--- .../SmartWallet/SmartWallet.cs | 26 ++-- 13 files changed, 327 insertions(+), 69 deletions(-) create mode 100644 Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs index 8af4723..9a7c5c6 100644 --- a/Thirdweb.Console/Program.cs +++ b/Thirdweb.Console/Program.cs @@ -28,10 +28,10 @@ var inAppWallet = await InAppWallet.Create(client: client, authprovider: AuthProvider.Google); // or email: null, phoneNumber: "+1234567890" // Reset InAppWallet (optional step for testing login flow) -if (await inAppWallet.IsConnected()) -{ - await inAppWallet.Disconnect(); -} +// if (await inAppWallet.IsConnected()) +// { +// await inAppWallet.Disconnect(); +// } // Relog if InAppWallet not logged in if (!await inAppWallet.IsConnected()) @@ -64,10 +64,28 @@ // } } +// Test 113 +var tx = await ThirdwebTransaction.Create( + client, + inAppWallet, + new ThirdwebTransactionInput() + { + From = await inAppWallet.GetAddress(), + To = await inAppWallet.GetAddress(), + Value = new HexBigInteger(BigInteger.Zero), + Data = "0x" + }, + 300 +); +var txHash = await ThirdwebTransaction.Send(tx); +Console.WriteLine($"Transaction hash: {txHash}"); + + + // Create smart wallet with InAppWallet signer -var smartWallet = await SmartWallet.Create(client: client, personalWallet: inAppWallet, factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", gasless: true, chainId: 421614); -var res = await smartWallet.Authenticate("http://localhost:8000", 421614); -Console.WriteLine($"Smart wallet auth result: {res}"); +// var smartWallet = await SmartWallet.Create(client: client, personalWallet: inAppWallet, factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", gasless: true, chainId: 421614); +// var res = await smartWallet.Authenticate("http://localhost:8000", 421614); +// Console.WriteLine($"Smart wallet auth result: {res}"); // // Grant a session key to pk wallet (advanced use case) // _ = await smartWallet.CreateSessionKey( @@ -124,7 +142,7 @@ // Console.WriteLine($"Transaction receipt: {JsonConvert.SerializeObject(receipt)}"); // // Transaction Builder - raw transfer -// var rawTx = new TransactionInput +// var rawTx = new ThirdwebTransactionInput // { // From = await smartWallet.GetAddress(), // To = await smartWallet.GetAddress(), diff --git a/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs b/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs index 383e16c..a74fc70 100644 --- a/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs @@ -155,7 +155,7 @@ public async Task SignTypedDataV4_Typed_NullData() public async Task SignTransaction_Success() { var account = await GetAccount(); - var transaction = new TransactionInput + var transaction = new ThirdwebTransactionInput { From = await account.GetAddress(), To = Constants.ADDRESS_ZERO, @@ -173,7 +173,7 @@ public async Task SignTransaction_Success() public async Task SignTransaction_NoFrom_Success() { var account = await GetAccount(); - var transaction = new TransactionInput + var transaction = new ThirdwebTransactionInput { To = Constants.ADDRESS_ZERO, // Value = new HexBigInteger(0), @@ -198,7 +198,7 @@ public async Task SignTransaction_NullTransaction() public async Task SignTransaction_NoNonce() { var account = await GetAccount(); - var transaction = new TransactionInput + var transaction = new ThirdwebTransactionInput { From = await account.GetAddress(), To = Constants.ADDRESS_ZERO, @@ -214,7 +214,7 @@ public async Task SignTransaction_NoNonce() public async Task SignTransaction_WrongFrom() { var account = await GetAccount(); - var transaction = new TransactionInput + var transaction = new ThirdwebTransactionInput { From = Constants.ADDRESS_ZERO, To = Constants.ADDRESS_ZERO, @@ -231,7 +231,7 @@ public async Task SignTransaction_WrongFrom() public async Task SignTransaction_NoGasPrice() { var account = await GetAccount(); - var transaction = new TransactionInput + var transaction = new ThirdwebTransactionInput { From = await account.GetAddress(), To = Constants.ADDRESS_ZERO, @@ -248,7 +248,7 @@ public async Task SignTransaction_NoGasPrice() public async Task SignTransaction_1559_Success() { var account = await GetAccount(); - var transaction = new TransactionInput + var transaction = new ThirdwebTransactionInput { From = await account.GetAddress(), To = Constants.ADDRESS_ZERO, @@ -268,7 +268,7 @@ public async Task SignTransaction_1559_Success() public async Task SignTransaction_1559_NoMaxFeePerGas() { var account = await GetAccount(); - var transaction = new TransactionInput + var transaction = new ThirdwebTransactionInput { From = await account.GetAddress(), To = Constants.ADDRESS_ZERO, @@ -287,7 +287,7 @@ public async Task SignTransaction_1559_NoMaxFeePerGas() public async Task SignTransaction_1559_NoMaxPriorityFeePerGas() { var account = await GetAccount(); - var transaction = new TransactionInput + var transaction = new ThirdwebTransactionInput { From = await account.GetAddress(), To = Constants.ADDRESS_ZERO, diff --git a/Thirdweb.Tests/Thirdweb.SmartWallet.Tests.cs b/Thirdweb.Tests/Thirdweb.SmartWallet.Tests.cs index 2efb62e..f2c62e8 100644 --- a/Thirdweb.Tests/Thirdweb.SmartWallet.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.SmartWallet.Tests.cs @@ -74,7 +74,7 @@ public async Task SendTransaction_Success() { var account = await GetSmartAccount(); var tx = await account.SendTransaction( - new TransactionInput() + new ThirdwebTransactionInput() { From = await account.GetAddress(), To = await account.GetAddress(), @@ -91,7 +91,7 @@ public async Task SendTransaction_ClientBundleId_Success() var privateKeyAccount = await PrivateKeyWallet.Create(client, _testPrivateKey); var smartAccount = await SmartWallet.Create(client, personalWallet: privateKeyAccount, factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", gasless: true, chainId: 421614); var tx = await smartAccount.SendTransaction( - new TransactionInput() + new ThirdwebTransactionInput() { From = await smartAccount.GetAddress(), To = await smartAccount.GetAddress(), diff --git a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs index e5620e6..fccb480 100644 --- a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs @@ -15,7 +15,7 @@ private async Task CreateSampleTransaction() var wallet = await PrivateKeyWallet.Create(client, _testPrivateKey); var chainId = new BigInteger(1); - var transaction = await ThirdwebTransaction.Create(client, wallet, new TransactionInput(), chainId); + var transaction = await ThirdwebTransaction.Create(client, wallet, new ThirdwebTransactionInput(), chainId); return transaction; } @@ -24,7 +24,7 @@ public async Task Create_ValidatesInputParameters() { var client = ThirdwebClient.Create(secretKey: _secretKey); var wallet = await PrivateKeyWallet.Create(client, _testPrivateKey); - var txInput = new TransactionInput() { From = await wallet.GetAddress() }; + var txInput = new ThirdwebTransactionInput() { From = await wallet.GetAddress() }; var chainId = new BigInteger(1); var transaction = await ThirdwebTransaction.Create(client, wallet, txInput, chainId); Assert.NotNull(transaction); @@ -35,7 +35,7 @@ public async Task Create_ThrowsOnInvalidAddress() { var client = ThirdwebClient.Create(secretKey: _secretKey); var wallet = await PrivateKeyWallet.Create(client, _testPrivateKey); - var txInput = new TransactionInput() { From = "0x123" }; + var txInput = new ThirdwebTransactionInput() { From = "0x123" }; var ex = await Assert.ThrowsAsync(() => ThirdwebTransaction.Create(client, wallet, txInput, BigInteger.Zero)); Assert.Contains("Transaction sender (from) must match wallet address", ex.Message); } @@ -45,7 +45,7 @@ public async Task Create_ThrowsOnInvalidChainId() { var client = ThirdwebClient.Create(secretKey: _secretKey); var wallet = await PrivateKeyWallet.Create(client, _testPrivateKey); - var txInput = new TransactionInput(); + var txInput = new ThirdwebTransactionInput(); _ = await Assert.ThrowsAsync(() => ThirdwebTransaction.Create(client, wallet, txInput, BigInteger.Zero)); } @@ -101,7 +101,7 @@ public async Task Sign_SmartWallet_SignsTransaction() var transaction = await ThirdwebTransaction.Create( client, smartAccount, - new TransactionInput() + new ThirdwebTransactionInput() { To = Constants.ADDRESS_ZERO, Value = new HexBigInteger(0), @@ -199,13 +199,13 @@ public async Task EstimateGasCosts_SmartWalletHigherThanPrivateKeyWallet() var privateKeyAccount = await PrivateKeyWallet.Create(client, _testPrivateKey); var smartAccount = await SmartWallet.Create(client, personalWallet: privateKeyAccount, factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", gasless: true, chainId: 421614); - var transaction = await ThirdwebTransaction.Create(client, smartAccount, new TransactionInput(), 421614); + var transaction = await ThirdwebTransaction.Create(client, smartAccount, new ThirdwebTransactionInput(), 421614); _ = transaction.SetTo(Constants.ADDRESS_ZERO); _ = transaction.SetValue(new BigInteger(1000)); var smartCosts = await ThirdwebTransaction.EstimateGasCosts(transaction); - transaction = await ThirdwebTransaction.Create(client, privateKeyAccount, new TransactionInput(), 421614); + transaction = await ThirdwebTransaction.Create(client, privateKeyAccount, new ThirdwebTransactionInput(), 421614); _ = transaction.SetTo(Constants.ADDRESS_ZERO); _ = transaction.SetValue(new BigInteger(1000)); @@ -230,6 +230,19 @@ public async Task EstimateTotalCosts_HigherThanGasCostsByValue() Assert.True(costs[0].wei - costs[1].wei == transaction.Input.Value.Value); } + [Fact] + public async Task EstimateGasFees_ReturnsCorrectly() + { + var transaction = await CreateSampleTransaction(); + _ = transaction.SetValue(new BigInteger(1000)); + _ = transaction.SetTo(Constants.ADDRESS_ZERO); + + (var maxFee, var maxPrio) = await ThirdwebTransaction.EstimateGasFees(transaction); + + Assert.NotEqual(BigInteger.Zero, maxFee); + Assert.NotEqual(BigInteger.Zero, maxPrio); + } + [Fact] public async Task EstimateGasPrice_BumpsCorrectly() { @@ -257,7 +270,7 @@ public async Task Simulate_ReturnsData() var client = ThirdwebClient.Create(secretKey: _secretKey); var privateKeyAccount = await PrivateKeyWallet.Create(client, _testPrivateKey); var smartAccount = await SmartWallet.Create(client, personalWallet: privateKeyAccount, factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", gasless: true, chainId: 421614); - var transaction = await ThirdwebTransaction.Create(client, smartAccount, new TransactionInput(), 421614); + var transaction = await ThirdwebTransaction.Create(client, smartAccount, new ThirdwebTransactionInput(), 421614); _ = transaction.SetValue(new BigInteger(0)); _ = transaction.SetGasLimit(250000); diff --git a/Thirdweb.Tests/Thirdweb.Wallets.Tests.cs b/Thirdweb.Tests/Thirdweb.Wallets.Tests.cs index 5aec1aa..2e11d28 100644 --- a/Thirdweb.Tests/Thirdweb.Wallets.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Wallets.Tests.cs @@ -104,7 +104,7 @@ await wallet.GetAddress(), public async Task SignTransaction() { var wallet = await GetAccount(); - var transaction = new TransactionInput + var transaction = new ThirdwebTransactionInput { To = await wallet.GetAddress(), Data = "0x", diff --git a/Thirdweb/Thirdweb.Contracts/ThirdwebContract.cs b/Thirdweb/Thirdweb.Contracts/ThirdwebContract.cs index 70472d1..cb45ef6 100644 --- a/Thirdweb/Thirdweb.Contracts/ThirdwebContract.cs +++ b/Thirdweb/Thirdweb.Contracts/ThirdwebContract.cs @@ -68,7 +68,7 @@ public static async Task Prepare(IThirdwebWallet wallet, Th var service = new Nethereum.Contracts.Contract(null, contract.Abi, contract.Address); var function = service.GetFunction(method); var data = function.GetData(parameters); - var transaction = new TransactionInput + var transaction = new ThirdwebTransactionInput { From = await wallet.GetAddress(), To = contract.Address, diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index 8979dac..fbd69e5 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -5,6 +5,7 @@ using Nethereum.Contracts; using Nethereum.ABI.FunctionEncoding; using Nethereum.Hex.HexConvertors.Extensions; +using Newtonsoft.Json.Linq; namespace Thirdweb { @@ -16,12 +17,12 @@ public struct TotalCosts public class ThirdwebTransaction { - public TransactionInput Input { get; private set; } + public ThirdwebTransactionInput Input { get; private set; } private readonly ThirdwebClient _client; private readonly IThirdwebWallet _wallet; - private ThirdwebTransaction(ThirdwebClient client, IThirdwebWallet wallet, TransactionInput txInput, BigInteger chainId) + private ThirdwebTransaction(ThirdwebClient client, IThirdwebWallet wallet, ThirdwebTransactionInput txInput, BigInteger chainId) { Input = txInput; _client = client; @@ -29,7 +30,7 @@ private ThirdwebTransaction(ThirdwebClient client, IThirdwebWallet wallet, Trans Input.ChainId = chainId.ToHexBigInteger(); } - public static async Task Create(ThirdwebClient client, IThirdwebWallet wallet, TransactionInput txInput, BigInteger chainId) + public static async Task Create(ThirdwebClient client, IThirdwebWallet wallet, ThirdwebTransactionInput txInput, BigInteger chainId) { var address = await wallet.GetAddress(); txInput.From ??= address; @@ -108,6 +109,44 @@ public static async Task EstimateGasPrice(ThirdwebTransaction transa return withBump ? hex.Value * 10 / 9 : hex.Value; } + public static async Task<(BigInteger, BigInteger)> EstimateGasFees(ThirdwebTransaction transaction, bool withBump = true) + { + var rpc = ThirdwebRPC.GetRpcInstance(transaction._client, transaction.Input.ChainId.Value); + var chainId = transaction.Input.ChainId.Value; + var gasPrice = await EstimateGasPrice(transaction, withBump); + + try + { + var block = await rpc.SendRequestAsync("eth_getBlockByNumber", "latest", true); + var maxPriorityFeePerGas = await rpc.SendRequestAsync("eth_maxPriorityFeePerGas"); + var baseBlockFee = block["result"]?["baseFeePerGas"]?.ToObject() ?? new BigInteger(100); + + if (chainId == 42220 || chainId == 44787 || chainId == 62320) + { + return (gasPrice, gasPrice); + } + + if (!maxPriorityFeePerGas.HasValue) + { + maxPriorityFeePerGas = new BigInteger(2); + } + + var preferredMaxPriorityFeePerGas = maxPriorityFeePerGas.Value * 10 / 9; + var maxFeePerGas = (baseBlockFee * 2) + preferredMaxPriorityFeePerGas; + + if (withBump) + { + maxFeePerGas *= 10 / 9; + } + + return (maxFeePerGas, preferredMaxPriorityFeePerGas); + } + catch + { + return (gasPrice, gasPrice); + } + } + public static async Task Simulate(ThirdwebTransaction transaction) { var rpc = ThirdwebRPC.GetRpcInstance(transaction._client, transaction.Input.ChainId.Value); @@ -142,13 +181,30 @@ public static async Task Send(ThirdwebTransaction transaction) throw new ArgumentException("To address must be provided"); } + if (transaction.Input.GasPrice != null && (transaction.Input.MaxFeePerGas != null || transaction.Input.MaxPriorityFeePerGas != null)) + { + throw new InvalidOperationException("Transaction GasPrice and MaxFeePerGas/MaxPriorityFeePerGas cannot be set at the same time"); + } + transaction.Input.From ??= await transaction._wallet.GetAddress(); transaction.Input.Value ??= new HexBigInteger(0); transaction.Input.Data ??= "0x"; - transaction.Input.MaxFeePerGas = null; - transaction.Input.MaxPriorityFeePerGas = null; transaction.Input.Gas ??= new HexBigInteger(await EstimateGasLimit(transaction)); - transaction.Input.GasPrice ??= new HexBigInteger(await EstimateGasPrice(transaction)); + if (transaction.Input.MaxFeePerGas == null && transaction.Input.MaxPriorityFeePerGas == null && transaction.Input.GasPrice == null) + { + Console.WriteLine("Sending as EIP-1559 tx"); + var (maxFeePerGas, maxPriorityFeePerGas) = await EstimateGasFees(transaction); + transaction.Input.MaxFeePerGas ??= maxFeePerGas.ToHexBigInteger(); + transaction.Input.MaxPriorityFeePerGas ??= maxPriorityFeePerGas.ToHexBigInteger(); + transaction.Input.GasPrice = null; + } + else + { + Console.WriteLine("Sending as legacy tx"); + transaction.Input.GasPrice ??= new HexBigInteger(await EstimateGasPrice(transaction)); + transaction.Input.MaxFeePerGas = null; + transaction.Input.MaxPriorityFeePerGas = null; + } var rpc = ThirdwebRPC.GetRpcInstance(transaction._client, transaction.Input.ChainId.Value); string hash; @@ -160,9 +216,50 @@ public static async Task Send(ThirdwebTransaction transaction) hash = await rpc.SendRequestAsync("eth_sendRawTransaction", signedTx); break; case ThirdwebAccountType.SmartAccount: - var smartAccount = transaction._wallet as SmartWallet; - hash = await smartAccount.SendTransaction(transaction.Input); - break; + // zksync native AA + if (transaction.Input.ChainId.Value.Equals(324) || transaction.Input.ChainId.Value.Equals(300)) + { + // Field name Type + // txType uint256 + // from uint256 + // to uint256 + // gasLimit uint256 + // gasPerPubdataByteLimit uint256 + // maxFeePerGas uint256 + // maxPriorityFeePerGas uint256 + // paymaster uint256 + // nonce uint256 + // value uint256 + // data bytes + // factoryDeps bytes32[] + // paymasterInput bytes + var zkTx = new + { + txType = 113, // 712 can't be used as it has to be one byte long + from = transaction.Input.From, + to = transaction.Input.To, + gasLimit = transaction.Input.Gas.Value, + gasPerPubdataByteLimit = 50000, + maxFeePerGas = transaction.Input.MaxFeePerGas.Value, + maxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas.Value, + paymaster = "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", + nonce = transaction.Input.Nonce.Value, + value = transaction.Input.Value.Value, + data = transaction.Input.Data, + factoryDeps = Array.Empty(), + paymasterInput = "0x" + }; + var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet); + hash = await rpc.SendRequestAsync("eth_sendRawTransaction", zkTxSigned); + break; + } + else + { + var smartAccount = transaction._wallet as SmartWallet; + hash = await smartAccount.SendTransaction(transaction.Input); + break; + } + default: throw new NotImplementedException("Account type not supported"); } diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs new file mode 100644 index 0000000..2f31a68 --- /dev/null +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs @@ -0,0 +1,57 @@ +using Nethereum.Hex.HexConvertors.Extensions; +using Nethereum.Hex.HexTypes; +using Newtonsoft.Json; + +namespace Thirdweb +{ + public class ThirdwebTransactionInput + { + public ThirdwebTransactionInput() { } + + [JsonProperty(PropertyName = "nonce")] + public HexBigInteger Nonce { get; set; } + + private string _from; + private string _to; + private string _data; + + [JsonProperty(PropertyName = "from")] + public string From + { + get => _from.EnsureHexPrefix(); + set => _from = value; + } + + [JsonProperty(PropertyName = "to")] + public string To + { + get => _to.EnsureHexPrefix(); + set => _to = value; + } + + [JsonProperty(PropertyName = "gas")] + public HexBigInteger Gas { get; set; } + + [JsonProperty(PropertyName = "gasPrice")] + public HexBigInteger GasPrice { get; set; } + + [JsonProperty(PropertyName = "value")] + public HexBigInteger Value { get; set; } + + [JsonProperty(PropertyName = "data")] + public string Data + { + get => _data.EnsureHexPrefix(); + set => _data = value; + } + + [JsonProperty(PropertyName = "maxFeePerGas")] + public HexBigInteger MaxFeePerGas { get; set; } + + [JsonProperty(PropertyName = "maxPriorityFeePerGas")] + public HexBigInteger MaxPriorityFeePerGas { get; set; } + + [JsonProperty(PropertyName = "chainId")] + public HexBigInteger ChainId { get; set; } + } +} diff --git a/Thirdweb/Thirdweb.Utils/Utils.cs b/Thirdweb/Thirdweb.Utils/Utils.cs index 1b96423..f32bcbf 100644 --- a/Thirdweb/Thirdweb.Utils/Utils.cs +++ b/Thirdweb/Thirdweb.Utils/Utils.cs @@ -4,6 +4,7 @@ using System.Text; using Nethereum.Hex.HexConvertors.Extensions; using Nethereum.Signer; +using Nethereum.Util; namespace Thirdweb { @@ -40,6 +41,16 @@ public static string HashPrefixedMessage(this string message) return signer.HashPrefixedMessage(Encoding.UTF8.GetBytes(message)).ToHex(true); } + public static byte[] HashMessage(this byte[] messageBytes) + { + return Sha3Keccack.Current.CalculateHash(messageBytes); + } + + public static string HashMessage(this string message) + { + return Sha3Keccack.Current.CalculateHash(Encoding.UTF8.GetBytes(message)).ToHex(true); + } + public static string BytesToHex(byte[] bytes) { return bytes.ToHex(true); diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index f845b3b..2dc77c0 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -1,5 +1,7 @@ using System.Numerics; using Nethereum.ABI.EIP712; +using Nethereum.Hex.HexConvertors.Extensions; +using Nethereum.Signer.EIP712; namespace Thirdweb { @@ -32,6 +34,17 @@ IThirdwebWallet signer return await signer.SignTypedDataV4(accountMessage, typedData); } + public static async Task GenerateSignature_ZkSyncTransaction(string domainName, string version, BigInteger chainId, object transaction, IThirdwebWallet signer) + { + var typedData = GetTypedDefinition_ZkSyncTransaction(domainName, version, chainId); + + var typedDataSigner = new Eip712TypedDataSigner(); + var encodedTypedData = typedDataSigner.EncodeTypedData(transaction, typedData); + + var hash = Utils.HashMessage(encodedTypedData); + return await signer.EthSign(hash); + } + public static TypedData GetTypedDefinition_SmartAccount(string domainName, string version, BigInteger chainId, string verifyingContract) { return new TypedData @@ -63,5 +76,44 @@ public static TypedData GetTypedDefinition_SmartAccount_AccountMessage(s PrimaryType = nameof(AccountAbstraction.AccountMessage), }; } + + public static TypedData GetTypedDefinition_ZkSyncTransaction(string domainName, string version, BigInteger chainId) + { + return new TypedData + { + Domain = new Domain + { + Name = domainName, + Version = version, + ChainId = chainId + }, + Types = new Dictionary + { + ["EIP712Domain"] = new[] + { + new MemberDescription { Name = "name", Type = "string" }, + new MemberDescription { Name = "version", Type = "string" }, + new MemberDescription { Name = "chainId", Type = "uint256" } + }, + ["Transaction"] = new[] + { + new MemberDescription { Name = "txType", Type = "uint256" }, + new MemberDescription { Name = "from", Type = "address" }, + new MemberDescription { Name = "to", Type = "address" }, + new MemberDescription { Name = "gasLimit", Type = "uint256" }, + new MemberDescription { Name = "gasPerPubdataByteLimit", Type = "uint256" }, + new MemberDescription { Name = "maxFeePerGas", Type = "uint256" }, + new MemberDescription { Name = "maxPriorityFeePerGas", Type = "uint256" }, + new MemberDescription { Name = "paymaster", Type = "address" }, + new MemberDescription { Name = "nonce", Type = "uint256" }, + new MemberDescription { Name = "value", Type = "uint256" }, + new MemberDescription { Name = "data", Type = "bytes" }, + new MemberDescription { Name = "factoryDeps", Type = "bytes32[]" }, + new MemberDescription { Name = "paymasterInput", Type = "bytes" } + } + }, + PrimaryType = "Transaction" + }; + } } } diff --git a/Thirdweb/Thirdweb.Wallets/IThirdwebWallet.cs b/Thirdweb/Thirdweb.Wallets/IThirdwebWallet.cs index 2832c5d..03f7dee 100644 --- a/Thirdweb/Thirdweb.Wallets/IThirdwebWallet.cs +++ b/Thirdweb/Thirdweb.Wallets/IThirdwebWallet.cs @@ -9,6 +9,7 @@ public interface IThirdwebWallet { public ThirdwebAccountType AccountType { get; } public Task GetAddress(); + public Task EthSign(byte[] rawMessage); public Task EthSign(string message); public Task PersonalSign(byte[] rawMessage); public Task PersonalSign(string message); @@ -16,7 +17,7 @@ public interface IThirdwebWallet public Task SignTypedDataV4(T data, TypedData typedData) where TDomain : IDomain; public Task IsConnected(); - public Task SignTransaction(TransactionInput transaction, BigInteger chainId); + public Task SignTransaction(ThirdwebTransactionInput transaction, BigInteger chainId); public Task Authenticate(string domain, BigInteger chainId, string authPayloadPath = "/auth/payload", string authLoginPath = "/auth/login", HttpClient httpClient = null); } diff --git a/Thirdweb/Thirdweb.Wallets/PrivateKeyWallet/PrivateKeyWallet.cs b/Thirdweb/Thirdweb.Wallets/PrivateKeyWallet/PrivateKeyWallet.cs index bc89740..3fd85fe 100644 --- a/Thirdweb/Thirdweb.Wallets/PrivateKeyWallet/PrivateKeyWallet.cs +++ b/Thirdweb/Thirdweb.Wallets/PrivateKeyWallet/PrivateKeyWallet.cs @@ -37,6 +37,18 @@ public virtual Task GetAddress() return Task.FromResult(_ecKey.GetPublicAddress()); } + public virtual Task EthSign(byte[] rawMessage) + { + if (rawMessage == null) + { + throw new ArgumentNullException(nameof(rawMessage), "Message to sign cannot be null."); + } + + var signer = new MessageSigner(); + var signature = signer.Sign(rawMessage, _ecKey); + return Task.FromResult(signature); + } + public virtual Task EthSign(string message) { if (message == null) @@ -98,7 +110,7 @@ public virtual Task SignTypedDataV4(T data, TypedData SignTransaction(TransactionInput transaction, BigInteger chainId) + public virtual async Task SignTransaction(ThirdwebTransactionInput transaction, BigInteger chainId) { if (transaction == null) { @@ -120,7 +132,14 @@ public virtual async Task SignTransaction(TransactionInput transaction, var value = transaction.Value ?? new HexBigInteger(0); string signedTransaction; - if (transaction.Type != null && transaction.Type.Value == TransactionType.EIP1559.AsByte()) + + if (transaction.GasPrice != null) + { + var gasPrice = transaction.GasPrice; + var legacySigner = new LegacyTransactionSigner(); + signedTransaction = legacySigner.SignTransaction(_ecKey.GetPrivateKey(), chainId, transaction.To, value.Value, nonce, gasPrice.Value, gasLimit.Value, transaction.Data); + } + else { if (transaction.MaxPriorityFeePerGas == null || transaction.MaxFeePerGas == null) { @@ -128,32 +147,12 @@ public virtual async Task SignTransaction(TransactionInput transaction, } var maxPriorityFeePerGas = transaction.MaxPriorityFeePerGas.Value; var maxFeePerGas = transaction.MaxFeePerGas.Value; - var transaction1559 = new Transaction1559( - chainId, - nonce, - maxPriorityFeePerGas, - maxFeePerGas, - gasLimit, - transaction.To, - value, - transaction.Data, - transaction.AccessList.ToSignerAccessListItemArray() - ); + var transaction1559 = new Transaction1559(chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, transaction.To, value, transaction.Data, null); var signer = new Transaction1559Signer(); signer.SignTransaction(_ecKey, transaction1559); signedTransaction = transaction1559.GetRLPEncoded().ToHex(); } - else - { - if (transaction.GasPrice == null) - { - throw new InvalidOperationException("Transaction gas price must be set for legacy transactions"); - } - var gasPrice = transaction.GasPrice; - var legacySigner = new LegacyTransactionSigner(); - signedTransaction = legacySigner.SignTransaction(_ecKey.GetPrivateKey(), chainId, transaction.To, value.Value, nonce, gasPrice.Value, gasLimit.Value, transaction.Data); - } return "0x" + signedTransaction; } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs index ec77b8e..b045fa8 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs @@ -98,7 +98,7 @@ public async Task IsDeployed() return code != "0x"; } - public async Task SendTransaction(TransactionInput transaction) + public async Task SendTransaction(ThirdwebTransactionInput transaction) { if (transaction == null) { @@ -120,7 +120,7 @@ private async Task GetInitCode() return data.HexToByteArray(); } - private async Task SignUserOp(TransactionInput transactionInput, int? requestId = null) + private async Task SignUserOp(ThirdwebTransactionInput transactionInput, int? requestId = null) { requestId ??= 1; @@ -246,7 +246,12 @@ private UserOperationHexified EncodeUserOperation(UserOperation userOperation) public async Task ForceDeploy() { - var input = new TransactionInput("0x", _accountContract.Address, new HexBigInteger(0)); + var input = new ThirdwebTransactionInput() + { + Data = "0x", + To = _accountContract.Address, + Value = new HexBigInteger(0) + }; var txHash = await SendTransaction(input); _ = await ThirdwebTransaction.WaitForTransactionReceipt(_client, _chainId, txHash); } @@ -261,6 +266,11 @@ public Task GetAddress() return Task.FromResult(_accountContract.Address); } + public Task EthSign(byte[] rawMessage) + { + return _personalAccount.EthSign(rawMessage); + } + public Task EthSign(string message) { return _personalAccount.EthSign(message); @@ -344,7 +354,7 @@ string reqValidityEndTimestamp var signature = await EIP712.GenerateSignature_SmartAccount("Account", "1", _chainId, await GetAddress(), request, _personalAccount); var data = new Contract(null, _accountContract.Abi, _accountContract.Address).GetFunction("setPermissionsForSigner").GetData(request, signature.HexToByteArray()); - var txInput = new TransactionInput() + var txInput = new ThirdwebTransactionInput() { From = await GetAddress(), To = _accountContract.Address, @@ -372,7 +382,7 @@ public async Task AddAdmin(string admin) var signature = await EIP712.GenerateSignature_SmartAccount("Account", "1", _chainId, await GetAddress(), request, _personalAccount); var data = new Contract(null, _accountContract.Abi, _accountContract.Address).GetFunction("setPermissionsForSigner").GetData(request, signature.HexToByteArray()); - var txInput = new TransactionInput() + var txInput = new ThirdwebTransactionInput() { From = await GetAddress(), To = _accountContract.Address, @@ -400,7 +410,7 @@ public async Task RemoveAdmin(string admin) var signature = await EIP712.GenerateSignature_SmartAccount("Account", "1", _chainId, await GetAddress(), request, _personalAccount); var data = new Contract(null, _accountContract.Abi, _accountContract.Address).GetFunction("setPermissionsForSigner").GetData(request, signature.HexToByteArray()); - var txInput = new TransactionInput() + var txInput = new ThirdwebTransactionInput() { From = await GetAddress(), To = _accountContract.Address, @@ -422,14 +432,14 @@ public Task SignTypedDataV4(T data, TypedData typed return _personalAccount.SignTypedDataV4(data, typedData); } - public async Task EstimateUserOperationGas(TransactionInput transaction, BigInteger chainId) + public async Task EstimateUserOperationGas(ThirdwebTransactionInput transaction, BigInteger chainId) { var signedOp = await SignUserOp(transaction); var cost = signedOp.CallGasLimit + signedOp.VerificationGasLimit + signedOp.PreVerificationGas; return cost; } - public async Task SignTransaction(TransactionInput transaction, BigInteger chainId) + public async Task SignTransaction(ThirdwebTransactionInput transaction, BigInteger chainId) { return JsonConvert.SerializeObject(EncodeUserOperation(await SignUserOp(transaction))); } From 490bde12f71afafb34e1d150e1d271cb7c56773f Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 21 May 2024 00:09:21 +0300 Subject: [PATCH 02/23] RLP --- Thirdweb.Console/Program.cs | 6 +- .../ThirdwebTransaction.cs | 100 +++++++++--------- Thirdweb/Thirdweb.Wallets/EIP712.cs | 89 +++++++++++++++- 3 files changed, 142 insertions(+), 53 deletions(-) diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs index 9a7c5c6..fad32de 100644 --- a/Thirdweb.Console/Program.cs +++ b/Thirdweb.Console/Program.cs @@ -77,7 +77,11 @@ }, 300 ); -var txHash = await ThirdwebTransaction.Send(tx); +var txHash = await ThirdwebTransaction.Send( + transaction: tx, + zkSyncPaymaster: "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", + zkSyncPaymasterInput: "0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000" +); Console.WriteLine($"Transaction hash: {txHash}"); diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index fbd69e5..e4bbb71 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -174,7 +174,7 @@ public static async Task Sign(ThirdwebTransaction transaction) return await transaction._wallet.SignTransaction(transaction.Input, transaction.Input.ChainId.Value); } - public static async Task Send(ThirdwebTransaction transaction) + public static async Task Send(ThirdwebTransaction transaction, string zkSyncPaymaster = null, string zkSyncPaymasterInput = null) { if (transaction.Input.To == null) { @@ -208,60 +208,60 @@ public static async Task Send(ThirdwebTransaction transaction) var rpc = ThirdwebRPC.GetRpcInstance(transaction._client, transaction.Input.ChainId.Value); string hash; - switch (transaction._wallet.AccountType) + var isZkAA = zkSyncPaymaster != null && zkSyncPaymasterInput != null; + if (isZkAA && (transaction.Input.ChainId.Value.Equals(324) || transaction.Input.ChainId.Value.Equals(300))) { - case ThirdwebAccountType.PrivateKeyAccount: - transaction.Input.Nonce ??= new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", await transaction._wallet.GetAddress(), "latest")); - var signedTx = await Sign(transaction); - hash = await rpc.SendRequestAsync("eth_sendRawTransaction", signedTx); - break; - case ThirdwebAccountType.SmartAccount: - // zksync native AA - if (transaction.Input.ChainId.Value.Equals(324) || transaction.Input.ChainId.Value.Equals(300)) - { - // Field name Type - // txType uint256 - // from uint256 - // to uint256 - // gasLimit uint256 - // gasPerPubdataByteLimit uint256 - // maxFeePerGas uint256 - // maxPriorityFeePerGas uint256 - // paymaster uint256 - // nonce uint256 - // value uint256 - // data bytes - // factoryDeps bytes32[] - // paymasterInput bytes - var zkTx = new - { - txType = 113, // 712 can't be used as it has to be one byte long - from = transaction.Input.From, - to = transaction.Input.To, - gasLimit = transaction.Input.Gas.Value, - gasPerPubdataByteLimit = 50000, - maxFeePerGas = transaction.Input.MaxFeePerGas.Value, - maxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas.Value, - paymaster = "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", - nonce = transaction.Input.Nonce.Value, - value = transaction.Input.Value.Value, - data = transaction.Input.Data, - factoryDeps = Array.Empty(), - paymasterInput = "0x" - }; - var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet); - hash = await rpc.SendRequestAsync("eth_sendRawTransaction", zkTxSigned); + // Field name Type + // txType uint256 + // from uint256 + // to uint256 + // gasLimit uint256 + // gasPerPubdataByteLimit uint256 + // maxFeePerGas uint256 + // maxPriorityFeePerGas uint256 + // paymaster uint256 + // nonce uint256 + // value uint256 + // data bytes + // factoryDeps bytes32[] + // paymasterInput bytes + var zkTx = new + { + txType = 113, // 712 can't be used as it has to be one byte long + from = transaction.Input.From, + to = transaction.Input.To, + gasLimit = transaction.Input.Gas.Value, + gasPerPubdataByteLimit = 50000, + maxFeePerGas = transaction.Input.MaxFeePerGas.Value, + maxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas.Value, + paymaster = zkSyncPaymaster, + nonce = transaction.Input.Nonce ?? new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", transaction.Input.From, "latest")), + value = transaction.Input.Value.Value, + data = transaction.Input.Data, + factoryDeps = Array.Empty(), + paymasterInput = zkSyncPaymasterInput + }; + Console.WriteLine($"ZkSync transaction: {JsonConvert.SerializeObject(zkTx)}"); + var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet); + hash = await rpc.SendRequestAsync("eth_sendRawTransaction", zkTxSigned); + } + else + { + switch (transaction._wallet.AccountType) + { + case ThirdwebAccountType.PrivateKeyAccount: + transaction.Input.Nonce ??= new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", await transaction._wallet.GetAddress(), "latest")); + var signedTx = await Sign(transaction); + hash = await rpc.SendRequestAsync("eth_sendRawTransaction", signedTx); break; - } - else - { + case ThirdwebAccountType.SmartAccount: + var smartAccount = transaction._wallet as SmartWallet; hash = await smartAccount.SendTransaction(transaction.Input); break; - } - - default: - throw new NotImplementedException("Account type not supported"); + default: + throw new NotImplementedException("Account type not supported"); + } } Console.WriteLine($"Transaction hash: {hash}"); return hash; diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index 2dc77c0..5154a64 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -1,7 +1,10 @@ using System.Numerics; using Nethereum.ABI.EIP712; using Nethereum.Hex.HexConvertors.Extensions; +using Nethereum.RLP; +using Nethereum.Signer; using Nethereum.Signer.EIP712; +using Newtonsoft.Json; namespace Thirdweb { @@ -34,7 +37,7 @@ IThirdwebWallet signer return await signer.SignTypedDataV4(accountMessage, typedData); } - public static async Task GenerateSignature_ZkSyncTransaction(string domainName, string version, BigInteger chainId, object transaction, IThirdwebWallet signer) + public static async Task GenerateSignature_ZkSyncTransaction(string domainName, string version, BigInteger chainId, dynamic transaction, IThirdwebWallet signer) { var typedData = GetTypedDefinition_ZkSyncTransaction(domainName, version, chainId); @@ -42,7 +45,19 @@ public static async Task GenerateSignature_ZkSyncTransaction(string doma var encodedTypedData = typedDataSigner.EncodeTypedData(transaction, typedData); var hash = Utils.HashMessage(encodedTypedData); - return await signer.EthSign(hash); + var signature = await signer.EthSign(hash); + var signatureHex = signature.ToHex(); + + transaction.customData = new + { + gasPerPubdata = transaction.gasPerPubdataByteLimit, + paymasterParams = transaction.paymasterParams, + customSignature = signatureHex, + }; + + var serializedTx = SerializeEip712(transaction, signature); + Console.WriteLine($"Serialized tx: {serializedTx}"); + return serializedTx; } public static TypedData GetTypedDefinition_SmartAccount(string domainName, string version, BigInteger chainId, string verifyingContract) @@ -115,5 +130,75 @@ public static TypedData GetTypedDefinition_ZkSyncTransaction(string doma PrimaryType = "Transaction" }; } + + private static string SerializeEip712(dynamic transaction, EthECDSASignature signature) + { + if (transaction.chainId == null) + { + throw new ArgumentException("Transaction chainId isn't set!"); + } + + if (transaction.from == null) + { + throw new ArgumentException("Explicitly providing `from` field is required for EIP712 transactions!"); + } + + var fields = new List + { + RLP.EncodeElement(transaction.nonce.ToByteArray()), + RLP.EncodeElement(transaction.maxPriorityFeePerGas.ToByteArray()), + RLP.EncodeElement(transaction.maxFeePerGas.ToByteArray()), + RLP.EncodeElement(transaction.gasLimit.ToByteArray()), + RLP.EncodeElement(transaction.to.HexToByteArray()), + RLP.EncodeElement(transaction.value.ToByteArray()), + RLP.EncodeElement(transaction.data.HexToByteArray()) + }; + + if (signature != null) + { + fields.Add(RLP.EncodeElement(signature.V)); + fields.Add(RLP.EncodeElement(signature.R)); + fields.Add(RLP.EncodeElement(signature.S)); + } + else + { + fields.Add(RLP.EncodeElement(transaction.chainId.ToByteArray())); + fields.Add(RLP.EncodeElement(Array.Empty())); + fields.Add(RLP.EncodeElement(Array.Empty())); + } + + fields.Add(RLP.EncodeElement(transaction.chainId.ToByteArray())); + fields.Add(RLP.EncodeElement(transaction.from.HexToByteArray())); + + // Add meta + fields.Add(RLP.EncodeElement(transaction.customData.gasPerPubdata.ToByteArray())); + fields.Add(RLP.EncodeList(Array.Empty())); + + if (transaction.customData.customSignature.Length == 0) + { + throw new ArgumentException("Empty signatures are not supported!"); + } + fields.Add(RLP.EncodeElement(transaction.customData.customSignature.HexToByteArray())); + + if (transaction.customData.paymasterParams != null) + { + fields.Add( + RLP.EncodeList( + new byte[] + { + RLP.EncodeElement(transaction.customData.paymasterParams.paymaster.HexToByteArray()), + RLP.EncodeElement(transaction.customData.paymasterParams.paymasterInput.HexToByteArray()) + } + ) + ); + } + else + { + fields.Add(RLP.EncodeList(Array.Empty())); + } + + var rlpEncoded = RLP.EncodeList(fields.ToArray()); + return "0x" + BitConverter.ToString(rlpEncoded).Replace("-", ""); + } } } From 577229688d631dfe5c934cb2fa36aef0d4fd68c3 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 21 May 2024 00:46:34 +0300 Subject: [PATCH 03/23] Cleanup types --- .../ThirdwebTransaction.cs | 28 +-- Thirdweb/Thirdweb.Wallets/EIP712.cs | 195 ++++++++---------- .../Thirdweb.AccountAbstraction/AATypes.cs | 44 +++- 3 files changed, 141 insertions(+), 126 deletions(-) diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index e4bbb71..61da2c0 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -225,21 +225,21 @@ public static async Task Send(ThirdwebTransaction transaction, string zk // data bytes // factoryDeps bytes32[] // paymasterInput bytes - var zkTx = new + var zkTx = new AccountAbstraction.ZkSyncAATransaction { - txType = 113, // 712 can't be used as it has to be one byte long - from = transaction.Input.From, - to = transaction.Input.To, - gasLimit = transaction.Input.Gas.Value, - gasPerPubdataByteLimit = 50000, - maxFeePerGas = transaction.Input.MaxFeePerGas.Value, - maxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas.Value, - paymaster = zkSyncPaymaster, - nonce = transaction.Input.Nonce ?? new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", transaction.Input.From, "latest")), - value = transaction.Input.Value.Value, - data = transaction.Input.Data, - factoryDeps = Array.Empty(), - paymasterInput = zkSyncPaymasterInput + TxType = 113, // 712 can't be used as it has to be one byte long + From = transaction.Input.From, + To = transaction.Input.To, + GasLimit = transaction.Input.Gas.Value, + GasPerPubdataByteLimit = 50000, + MaxFeePerGas = transaction.Input.MaxFeePerGas.Value, + MaxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas.Value, + Paymaster = zkSyncPaymaster, + Nonce = transaction.Input.Nonce ?? new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", transaction.Input.From, "latest")), + Value = transaction.Input.Value.Value, + Data = transaction.Input.Data.HexToByteArray(), + FactoryDeps = Array.Empty(), + PaymasterInput = zkSyncPaymasterInput.HexToByteArray() }; Console.WriteLine($"ZkSync transaction: {JsonConvert.SerializeObject(zkTx)}"); var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet); diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index 5154a64..0abda2e 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -37,28 +37,38 @@ IThirdwebWallet signer return await signer.SignTypedDataV4(accountMessage, typedData); } - public static async Task GenerateSignature_ZkSyncTransaction(string domainName, string version, BigInteger chainId, dynamic transaction, IThirdwebWallet signer) + public static async Task GenerateSignature_ZkSyncTransaction( + string domainName, + string version, + BigInteger chainId, + AccountAbstraction.ZkSyncAATransaction transaction, + IThirdwebWallet signer + ) { var typedData = GetTypedDefinition_ZkSyncTransaction(domainName, version, chainId); + return await signer.SignTypedDataV4(transaction, typedData); + } - var typedDataSigner = new Eip712TypedDataSigner(); - var encodedTypedData = typedDataSigner.EncodeTypedData(transaction, typedData); + // private static EthECDSASignature ParseSignature(string signatureHex) + // { + // var signatureBytes = signatureHex.HexToByteArray(); + // if (signatureBytes.Length != 65) + // { + // throw new ArgumentException("Invalid signature length."); + // } - var hash = Utils.HashMessage(encodedTypedData); - var signature = await signer.EthSign(hash); - var signatureHex = signature.ToHex(); + // var r = new byte[32]; + // var s = new byte[32]; + // var v = new byte[1]; - transaction.customData = new - { - gasPerPubdata = transaction.gasPerPubdataByteLimit, - paymasterParams = transaction.paymasterParams, - customSignature = signatureHex, - }; + // Array.Copy(signatureBytes, 0, r, 0, 32); + // Array.Copy(signatureBytes, 32, s, 0, 32); + // Array.Copy(signatureBytes, 64, v, 0, 1); - var serializedTx = SerializeEip712(transaction, signature); - Console.WriteLine($"Serialized tx: {serializedTx}"); - return serializedTx; - } + // var vValue = (v[0] == 0 || v[0] == 1) ? v[0] + 27 : v[0]; // Adjust v value if necessary + + // return new EthECDSASignature(new Org.BouncyCastle.Math.BigInteger(r), new Org.BouncyCastle.Math.BigInteger(s), vValue.ToBytesForRLPEncoding()); + // } public static TypedData GetTypedDefinition_SmartAccount(string domainName, string version, BigInteger chainId, string verifyingContract) { @@ -102,103 +112,66 @@ public static TypedData GetTypedDefinition_ZkSyncTransaction(string doma Version = version, ChainId = chainId }, - Types = new Dictionary - { - ["EIP712Domain"] = new[] - { - new MemberDescription { Name = "name", Type = "string" }, - new MemberDescription { Name = "version", Type = "string" }, - new MemberDescription { Name = "chainId", Type = "uint256" } - }, - ["Transaction"] = new[] - { - new MemberDescription { Name = "txType", Type = "uint256" }, - new MemberDescription { Name = "from", Type = "address" }, - new MemberDescription { Name = "to", Type = "address" }, - new MemberDescription { Name = "gasLimit", Type = "uint256" }, - new MemberDescription { Name = "gasPerPubdataByteLimit", Type = "uint256" }, - new MemberDescription { Name = "maxFeePerGas", Type = "uint256" }, - new MemberDescription { Name = "maxPriorityFeePerGas", Type = "uint256" }, - new MemberDescription { Name = "paymaster", Type = "address" }, - new MemberDescription { Name = "nonce", Type = "uint256" }, - new MemberDescription { Name = "value", Type = "uint256" }, - new MemberDescription { Name = "data", Type = "bytes" }, - new MemberDescription { Name = "factoryDeps", Type = "bytes32[]" }, - new MemberDescription { Name = "paymasterInput", Type = "bytes" } - } - }, - PrimaryType = "Transaction" + Types = MemberDescriptionFactory.GetTypesMemberDescription(typeof(Domain), typeof(AccountAbstraction.ZkSyncAATransaction)), + PrimaryType = nameof(AccountAbstraction.ZkSyncAATransaction) }; } - private static string SerializeEip712(dynamic transaction, EthECDSASignature signature) - { - if (transaction.chainId == null) - { - throw new ArgumentException("Transaction chainId isn't set!"); - } - - if (transaction.from == null) - { - throw new ArgumentException("Explicitly providing `from` field is required for EIP712 transactions!"); - } - - var fields = new List - { - RLP.EncodeElement(transaction.nonce.ToByteArray()), - RLP.EncodeElement(transaction.maxPriorityFeePerGas.ToByteArray()), - RLP.EncodeElement(transaction.maxFeePerGas.ToByteArray()), - RLP.EncodeElement(transaction.gasLimit.ToByteArray()), - RLP.EncodeElement(transaction.to.HexToByteArray()), - RLP.EncodeElement(transaction.value.ToByteArray()), - RLP.EncodeElement(transaction.data.HexToByteArray()) - }; - - if (signature != null) - { - fields.Add(RLP.EncodeElement(signature.V)); - fields.Add(RLP.EncodeElement(signature.R)); - fields.Add(RLP.EncodeElement(signature.S)); - } - else - { - fields.Add(RLP.EncodeElement(transaction.chainId.ToByteArray())); - fields.Add(RLP.EncodeElement(Array.Empty())); - fields.Add(RLP.EncodeElement(Array.Empty())); - } - - fields.Add(RLP.EncodeElement(transaction.chainId.ToByteArray())); - fields.Add(RLP.EncodeElement(transaction.from.HexToByteArray())); - - // Add meta - fields.Add(RLP.EncodeElement(transaction.customData.gasPerPubdata.ToByteArray())); - fields.Add(RLP.EncodeList(Array.Empty())); - - if (transaction.customData.customSignature.Length == 0) - { - throw new ArgumentException("Empty signatures are not supported!"); - } - fields.Add(RLP.EncodeElement(transaction.customData.customSignature.HexToByteArray())); - - if (transaction.customData.paymasterParams != null) - { - fields.Add( - RLP.EncodeList( - new byte[] - { - RLP.EncodeElement(transaction.customData.paymasterParams.paymaster.HexToByteArray()), - RLP.EncodeElement(transaction.customData.paymasterParams.paymasterInput.HexToByteArray()) - } - ) - ); - } - else - { - fields.Add(RLP.EncodeList(Array.Empty())); - } - - var rlpEncoded = RLP.EncodeList(fields.ToArray()); - return "0x" + BitConverter.ToString(rlpEncoded).Replace("-", ""); - } + // private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction transaction, EthECDSASignature signature, BigInteger chainId) + // { + // if (transaction.From == null) + // { + // throw new ArgumentException("Explicitly providing `from` field is required for EIP712 transactions!"); + // } + + // var fields = new List + // { + // RLP.EncodeElement(transaction.Nonce.ToByteArray()), + // RLP.EncodeElement(transaction.MaxPriorityFeePerGas.ToByteArray()), + // RLP.EncodeElement(transaction.MaxFeePerGas.ToByteArray()), + // RLP.EncodeElement(transaction.GasLimit.ToByteArray()), + // RLP.EncodeElement(transaction.To.HexToByteArray()), + // RLP.EncodeElement(transaction.Value.ToByteArray()), + // RLP.EncodeElement(transaction.Data) + // }; + + // if (signature != null) + // { + // fields.Add(RLP.EncodeElement(signature.V)); + // fields.Add(RLP.EncodeElement(signature.R)); + // fields.Add(RLP.EncodeElement(signature.S)); + // } + // else + // { + // fields.Add(RLP.EncodeElement(chainId.ToByteArray())); + // fields.Add(RLP.EncodeElement(Array.Empty())); + // fields.Add(RLP.EncodeElement(Array.Empty())); + // } + + // fields.Add(RLP.EncodeElement(chainId.ToByteArray())); + // fields.Add(RLP.EncodeElement(transaction.From.HexToByteArray())); + + // // Add meta + // fields.Add(RLP.EncodeElement(transaction.GasPerPubdataByteLimit.ToByteArray())); + // fields.Add(RLP.EncodeList(Array.Empty())); + + // if (transaction.PaymasterInput.Length == 0) + // { + // throw new ArgumentException("Empty signatures are not supported!"); + // } + // fields.Add(RLP.EncodeElement(transaction.PaymasterInput)); + + // if (transaction.Paymaster != null) + // { + // fields.Add(RLP.EncodeList(new byte[][] { RLP.EncodeElement(transaction.Paymaster.HexToByteArray()), RLP.EncodeElement(transaction.PaymasterInput) })); + // } + // else + // { + // fields.Add(RLP.EncodeList(Array.Empty())); + // } + + // var rlpEncoded = RLP.EncodeList(fields.ToArray()); + // return "0x" + BitConverter.ToString(rlpEncoded).Replace("-", ""); + // } } } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs index 3e9bf72..34113a0 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs @@ -170,7 +170,49 @@ public class SignerPermissionRequest public class AccountMessage { - [Nethereum.ABI.FunctionEncoding.Attributes.Parameter("bytes", "message", 1)] + [Parameter("bytes", "message", 1)] public virtual byte[] Message { get; set; } } + + public class ZkSyncAATransaction + { + [Parameter("uint256", "txType", 1)] + public virtual BigInteger TxType { get; set; } + + [Parameter("address", "from", 2)] + public virtual string From { get; set; } + + [Parameter("address", "to", 3)] + public virtual string To { get; set; } + + [Parameter("uint256", "gasLimit", 4)] + public virtual BigInteger GasLimit { get; set; } + + [Parameter("uint256", "gasPerPubdataByteLimit", 5)] + public virtual BigInteger GasPerPubdataByteLimit { get; set; } + + [Parameter("uint256", "maxFeePerGas", 6)] + public virtual BigInteger MaxFeePerGas { get; set; } + + [Parameter("uint256", "maxPriorityFeePerGas", 7)] + public virtual BigInteger MaxPriorityFeePerGas { get; set; } + + [Parameter("address", "paymaster", 8)] + public virtual string Paymaster { get; set; } + + [Parameter("uint256", "nonce", 9)] + public virtual BigInteger Nonce { get; set; } + + [Parameter("uint256", "value", 10)] + public virtual BigInteger Value { get; set; } + + [Parameter("bytes", "data", 11)] + public virtual byte[] Data { get; set; } + + [Parameter("bytes32[]", "factoryDeps", 12)] + public virtual byte[] FactoryDeps { get; set; } + + [Parameter("bytes", "paymasterInput", 13)] + public virtual byte[] PaymasterInput { get; set; } + } } From a3f0a9c92ea300e7d77e906bd1e0d4a1ce989185 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 21 May 2024 01:01:48 +0300 Subject: [PATCH 04/23] decodeRlpError RlpIncorrectListLen --- Thirdweb/Thirdweb.Wallets/EIP712.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index 0abda2e..6d6541b 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -45,7 +45,7 @@ public static async Task GenerateSignature_ZkSyncTransaction( IThirdwebWallet signer ) { - var typedData = GetTypedDefinition_ZkSyncTransaction(domainName, version, chainId); + var typedData = GetTypedDefinition_ZkSyncTransaction(domainName, version, chainId, transaction.From); return await signer.SignTypedDataV4(transaction, typedData); } @@ -102,7 +102,7 @@ public static TypedData GetTypedDefinition_SmartAccount_AccountMessage(s }; } - public static TypedData GetTypedDefinition_ZkSyncTransaction(string domainName, string version, BigInteger chainId) + public static TypedData GetTypedDefinition_ZkSyncTransaction(string domainName, string version, BigInteger chainId, string verifyingContract) { return new TypedData { @@ -110,10 +110,11 @@ public static TypedData GetTypedDefinition_ZkSyncTransaction(string doma { Name = domainName, Version = version, - ChainId = chainId + ChainId = chainId, + VerifyingContract = verifyingContract }, Types = MemberDescriptionFactory.GetTypesMemberDescription(typeof(Domain), typeof(AccountAbstraction.ZkSyncAATransaction)), - PrimaryType = nameof(AccountAbstraction.ZkSyncAATransaction) + PrimaryType = nameof(AccountAbstraction.ZkSyncAATransaction), }; } From a63a7b460f07f10b5b71d8e4e783f49c0217527c Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 21 May 2024 01:07:39 +0300 Subject: [PATCH 05/23] Update ThirdwebTransaction.cs --- Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index 61da2c0..561902f 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -227,7 +227,7 @@ public static async Task Send(ThirdwebTransaction transaction, string zk // paymasterInput bytes var zkTx = new AccountAbstraction.ZkSyncAATransaction { - TxType = 113, // 712 can't be used as it has to be one byte long + TxType = 0x71, // 712 can't be used as it has to be one byte long From = transaction.Input.From, To = transaction.Input.To, GasLimit = transaction.Input.Gas.Value, From 877b50e8a56aa413045f8d716958ab82b95a1387 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 21 May 2024 02:42:43 +0300 Subject: [PATCH 06/23] Proper flow, failing RLP --- .../ThirdwebTransaction.cs | 1 + Thirdweb/Thirdweb.Wallets/EIP712.cs | 121 +++++++----------- 2 files changed, 45 insertions(+), 77 deletions(-) diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index 561902f..e26e4f6 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -243,6 +243,7 @@ public static async Task Send(ThirdwebTransaction transaction, string zk }; Console.WriteLine($"ZkSync transaction: {JsonConvert.SerializeObject(zkTx)}"); var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet); + Console.WriteLine($"ZkSync transaction signed: {zkTxSigned}"); hash = await rpc.SendRequestAsync("eth_sendRawTransaction", zkTxSigned); } else diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index 6d6541b..0298be1 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -1,9 +1,12 @@ using System.Numerics; using Nethereum.ABI.EIP712; using Nethereum.Hex.HexConvertors.Extensions; +using Nethereum.Model; using Nethereum.RLP; using Nethereum.Signer; +using Nethereum.Signer.Crypto; using Nethereum.Signer.EIP712; +using Nethereum.Util; using Newtonsoft.Json; namespace Thirdweb @@ -46,29 +49,15 @@ IThirdwebWallet signer ) { var typedData = GetTypedDefinition_ZkSyncTransaction(domainName, version, chainId, transaction.From); - return await signer.SignTypedDataV4(transaction, typedData); - } - - // private static EthECDSASignature ParseSignature(string signatureHex) - // { - // var signatureBytes = signatureHex.HexToByteArray(); - // if (signatureBytes.Length != 65) - // { - // throw new ArgumentException("Invalid signature length."); - // } - - // var r = new byte[32]; - // var s = new byte[32]; - // var v = new byte[1]; - - // Array.Copy(signatureBytes, 0, r, 0, 32); - // Array.Copy(signatureBytes, 32, s, 0, 32); - // Array.Copy(signatureBytes, 64, v, 0, 1); - // var vValue = (v[0] == 0 || v[0] == 1) ? v[0] + 27 : v[0]; // Adjust v value if necessary - - // return new EthECDSASignature(new Org.BouncyCastle.Math.BigInteger(r), new Org.BouncyCastle.Math.BigInteger(s), vValue.ToBytesForRLPEncoding()); - // } + var typedDataSigner = new Eip712TypedDataSigner(); + var encodedTypedData = typedDataSigner.EncodeTypedData(transaction, typedData); + var hash = new Sha3Keccack().CalculateHash(encodedTypedData); + var signatureHex = await signer.EthSign(hash); + var signatureRaw = ECDSASignatureFactory.ExtractECDSASignature(signatureHex); + var serializedTx = SerializeEip712(transaction, signatureRaw, signatureHex, chainId); + return serializedTx; + } public static TypedData GetTypedDefinition_SmartAccount(string domainName, string version, BigInteger chainId, string verifyingContract) { @@ -118,61 +107,39 @@ public static TypedData GetTypedDefinition_ZkSyncTransaction(string doma }; } - // private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction transaction, EthECDSASignature signature, BigInteger chainId) - // { - // if (transaction.From == null) - // { - // throw new ArgumentException("Explicitly providing `from` field is required for EIP712 transactions!"); - // } - - // var fields = new List - // { - // RLP.EncodeElement(transaction.Nonce.ToByteArray()), - // RLP.EncodeElement(transaction.MaxPriorityFeePerGas.ToByteArray()), - // RLP.EncodeElement(transaction.MaxFeePerGas.ToByteArray()), - // RLP.EncodeElement(transaction.GasLimit.ToByteArray()), - // RLP.EncodeElement(transaction.To.HexToByteArray()), - // RLP.EncodeElement(transaction.Value.ToByteArray()), - // RLP.EncodeElement(transaction.Data) - // }; - - // if (signature != null) - // { - // fields.Add(RLP.EncodeElement(signature.V)); - // fields.Add(RLP.EncodeElement(signature.R)); - // fields.Add(RLP.EncodeElement(signature.S)); - // } - // else - // { - // fields.Add(RLP.EncodeElement(chainId.ToByteArray())); - // fields.Add(RLP.EncodeElement(Array.Empty())); - // fields.Add(RLP.EncodeElement(Array.Empty())); - // } - - // fields.Add(RLP.EncodeElement(chainId.ToByteArray())); - // fields.Add(RLP.EncodeElement(transaction.From.HexToByteArray())); - - // // Add meta - // fields.Add(RLP.EncodeElement(transaction.GasPerPubdataByteLimit.ToByteArray())); - // fields.Add(RLP.EncodeList(Array.Empty())); - - // if (transaction.PaymasterInput.Length == 0) - // { - // throw new ArgumentException("Empty signatures are not supported!"); - // } - // fields.Add(RLP.EncodeElement(transaction.PaymasterInput)); - - // if (transaction.Paymaster != null) - // { - // fields.Add(RLP.EncodeList(new byte[][] { RLP.EncodeElement(transaction.Paymaster.HexToByteArray()), RLP.EncodeElement(transaction.PaymasterInput) })); - // } - // else - // { - // fields.Add(RLP.EncodeList(Array.Empty())); - // } + private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction transaction, ECDSASignature signature, string signatureHex, BigInteger chainId) + { + if (chainId == 0) + { + throw new ArgumentException("Chain ID must be provided for EIP712 transactions!"); + } - // var rlpEncoded = RLP.EncodeList(fields.ToArray()); - // return "0x" + BitConverter.ToString(rlpEncoded).Replace("-", ""); - // } + if (string.IsNullOrEmpty(transaction.From)) + { + throw new ArgumentException("From address must be provided for EIP712 transactions!"); + } + + return "0x71" + + RLP.EncodeList( + transaction.Nonce.ToBytesForRLPEncoding(), + transaction.MaxPriorityFeePerGas.ToBytesForRLPEncoding(), + transaction.MaxFeePerGas.ToBytesForRLPEncoding(), + transaction.GasLimit.ToBytesForRLPEncoding(), + transaction.To.ToBytesForRLPEncoding(), + transaction.Value.ToBytesForRLPEncoding(), + transaction.Data.ToHex().ToBytesForRLPEncoding(), + signature.V.ToHex().ToBytesForRLPEncoding(), + signature.R.ToByteArray().ToHex().ToBytesForRLPEncoding(), + signature.S.ToByteArray().ToHex().ToBytesForRLPEncoding(), + chainId.ToBytesForRLPEncoding(), + transaction.From.ToBytesForRLPEncoding(), + transaction.GasPerPubdataByteLimit.ToBytesForRLPEncoding(), + transaction.FactoryDeps.ToHex().ToBytesForRLPEncoding() ?? Array.Empty().ToHex().ToBytesForRLPEncoding(), + signatureHex.ToBytesForRLPEncoding(), + transaction.Paymaster.ToBytesForRLPEncoding(), + transaction.PaymasterInput.ToHex().ToBytesForRLPEncoding() + ) + .ToHex(); + } } } From 292223d5212d0572a62ed1a73e7b5bf5d7abfb17 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 21 May 2024 17:31:58 +0300 Subject: [PATCH 07/23] Fix encoding, missing 2 chars --- Thirdweb.Console/Program.cs | 12 ++- .../ThirdwebTransaction.cs | 10 +- Thirdweb/Thirdweb.Wallets/EIP712.cs | 93 ++++++++++++------- .../Thirdweb.AccountAbstraction/AATypes.cs | 2 +- 4 files changed, 73 insertions(+), 44 deletions(-) diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs index fad32de..b4b48e6 100644 --- a/Thirdweb.Console/Program.cs +++ b/Thirdweb.Console/Program.cs @@ -67,13 +67,17 @@ // Test 113 var tx = await ThirdwebTransaction.Create( client, - inAppWallet, + privateKeyWallet, new ThirdwebTransactionInput() { - From = await inAppWallet.GetAddress(), - To = await inAppWallet.GetAddress(), + From = await privateKeyWallet.GetAddress(), + To = await privateKeyWallet.GetAddress(), Value = new HexBigInteger(BigInteger.Zero), - Data = "0x" + Data = "0x", + MaxFeePerGas = new HexBigInteger(25000000), + MaxPriorityFeePerGas = new HexBigInteger(25000000), + Gas = new HexBigInteger(20000000), + ChainId = new HexBigInteger(300), }, 300 ); diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index e26e4f6..1c36078 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -190,18 +190,16 @@ public static async Task Send(ThirdwebTransaction transaction, string zk transaction.Input.Value ??= new HexBigInteger(0); transaction.Input.Data ??= "0x"; transaction.Input.Gas ??= new HexBigInteger(await EstimateGasLimit(transaction)); - if (transaction.Input.MaxFeePerGas == null && transaction.Input.MaxPriorityFeePerGas == null && transaction.Input.GasPrice == null) + if (transaction.Input.GasPrice == null) { Console.WriteLine("Sending as EIP-1559 tx"); var (maxFeePerGas, maxPriorityFeePerGas) = await EstimateGasFees(transaction); transaction.Input.MaxFeePerGas ??= maxFeePerGas.ToHexBigInteger(); transaction.Input.MaxPriorityFeePerGas ??= maxPriorityFeePerGas.ToHexBigInteger(); - transaction.Input.GasPrice = null; } else { Console.WriteLine("Sending as legacy tx"); - transaction.Input.GasPrice ??= new HexBigInteger(await EstimateGasPrice(transaction)); transaction.Input.MaxFeePerGas = null; transaction.Input.MaxPriorityFeePerGas = null; } @@ -232,13 +230,13 @@ public static async Task Send(ThirdwebTransaction transaction, string zk To = transaction.Input.To, GasLimit = transaction.Input.Gas.Value, GasPerPubdataByteLimit = 50000, - MaxFeePerGas = transaction.Input.MaxFeePerGas.Value, - MaxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas.Value, + MaxFeePerGas = transaction.Input.MaxFeePerGas?.Value ?? transaction.Input.GasPrice.Value, + MaxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas?.Value ?? transaction.Input.GasPrice.Value, Paymaster = zkSyncPaymaster, Nonce = transaction.Input.Nonce ?? new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", transaction.Input.From, "latest")), Value = transaction.Input.Value.Value, Data = transaction.Input.Data.HexToByteArray(), - FactoryDeps = Array.Empty(), + FactoryDeps = new byte[][] { }, PaymasterInput = zkSyncPaymasterInput.HexToByteArray() }; Console.WriteLine($"ZkSync transaction: {JsonConvert.SerializeObject(zkTx)}"); diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index 0298be1..9534889 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -1,6 +1,7 @@ using System.Numerics; using Nethereum.ABI.EIP712; using Nethereum.Hex.HexConvertors.Extensions; +using Nethereum.Hex.HexTypes; using Nethereum.Model; using Nethereum.RLP; using Nethereum.Signer; @@ -48,14 +49,15 @@ public static async Task GenerateSignature_ZkSyncTransaction( IThirdwebWallet signer ) { - var typedData = GetTypedDefinition_ZkSyncTransaction(domainName, version, chainId, transaction.From); - - var typedDataSigner = new Eip712TypedDataSigner(); - var encodedTypedData = typedDataSigner.EncodeTypedData(transaction, typedData); - var hash = new Sha3Keccack().CalculateHash(encodedTypedData); + var typedData = GetTypedDefinition_ZkSyncTransaction(domainName, version, chainId); + var typedDataEncoder = new Eip712TypedDataEncoder(); + var hash = typedDataEncoder.EncodeAndHashTypedData(transaction, typedData); + Console.WriteLine($"Hash: {hash.ToHex(true)}"); var signatureHex = await signer.EthSign(hash); - var signatureRaw = ECDSASignatureFactory.ExtractECDSASignature(signatureHex); + Console.WriteLine($"Signature: {signatureHex}"); + var signatureRaw = EthECDSASignatureFactory.ExtractECDSASignature(signatureHex); var serializedTx = SerializeEip712(transaction, signatureRaw, signatureHex, chainId); + Console.WriteLine($"Serialized: {serializedTx}"); return serializedTx; } @@ -91,23 +93,22 @@ public static TypedData GetTypedDefinition_SmartAccount_AccountMessage(s }; } - public static TypedData GetTypedDefinition_ZkSyncTransaction(string domainName, string version, BigInteger chainId, string verifyingContract) + public static TypedData GetTypedDefinition_ZkSyncTransaction(string domainName, string version, BigInteger chainId) { - return new TypedData + return new TypedData { - Domain = new Domain + Domain = new DomainWithNameVersionAndChainId { Name = domainName, Version = version, ChainId = chainId, - VerifyingContract = verifyingContract }, - Types = MemberDescriptionFactory.GetTypesMemberDescription(typeof(Domain), typeof(AccountAbstraction.ZkSyncAATransaction)), + Types = MemberDescriptionFactory.GetTypesMemberDescription(typeof(DomainWithNameVersionAndChainId), typeof(AccountAbstraction.ZkSyncAATransaction)), PrimaryType = nameof(AccountAbstraction.ZkSyncAATransaction), }; } - private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction transaction, ECDSASignature signature, string signatureHex, BigInteger chainId) + private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction transaction, EthECDSASignature signature, string signatureHex, BigInteger chainId) { if (chainId == 0) { @@ -119,27 +120,53 @@ private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction tra throw new ArgumentException("From address must be provided for EIP712 transactions!"); } - return "0x71" - + RLP.EncodeList( - transaction.Nonce.ToBytesForRLPEncoding(), - transaction.MaxPriorityFeePerGas.ToBytesForRLPEncoding(), - transaction.MaxFeePerGas.ToBytesForRLPEncoding(), - transaction.GasLimit.ToBytesForRLPEncoding(), - transaction.To.ToBytesForRLPEncoding(), - transaction.Value.ToBytesForRLPEncoding(), - transaction.Data.ToHex().ToBytesForRLPEncoding(), - signature.V.ToHex().ToBytesForRLPEncoding(), - signature.R.ToByteArray().ToHex().ToBytesForRLPEncoding(), - signature.S.ToByteArray().ToHex().ToBytesForRLPEncoding(), - chainId.ToBytesForRLPEncoding(), - transaction.From.ToBytesForRLPEncoding(), - transaction.GasPerPubdataByteLimit.ToBytesForRLPEncoding(), - transaction.FactoryDeps.ToHex().ToBytesForRLPEncoding() ?? Array.Empty().ToHex().ToBytesForRLPEncoding(), - signatureHex.ToBytesForRLPEncoding(), - transaction.Paymaster.ToBytesForRLPEncoding(), - transaction.PaymasterInput.ToHex().ToBytesForRLPEncoding() - ) - .ToHex(); + var fields = new List + { + transaction.Nonce.ToByteArray(isUnsigned: true, isBigEndian: true), + transaction.MaxPriorityFeePerGas.ToByteArray(isUnsigned: true, isBigEndian: true), + transaction.MaxFeePerGas.ToByteArray(isUnsigned: true, isBigEndian: true), + transaction.GasLimit.ToByteArray(isUnsigned: true, isBigEndian: true), + transaction.To.HexToByteArray(), + transaction.Value == 0 ? new byte[0] : transaction.Value.ToByteArray(isUnsigned: true, isBigEndian: true), + transaction.Data == null ? new byte[0] : transaction.Data, + }; + + if (signature != null) + { + fields.Add(new BigInteger(signature.V).ToByteArray(isUnsigned: false, isBigEndian: true)); + fields.Add(new BigInteger(signature.R).ToByteArray(isUnsigned: false, isBigEndian: true)); + fields.Add(new BigInteger(signature.S).ToByteArray(isUnsigned: false, isBigEndian: true)); + } + else + { + fields.Add(chainId.ToByteArray(isUnsigned: true, isBigEndian: true)); + fields.Add(new byte[0]); + fields.Add(new byte[0]); + } + + fields.Add(chainId.ToByteArray(isUnsigned: true, isBigEndian: true)); + fields.Add(transaction.From.HexToByteArray()); + + // Add meta + fields.Add(transaction.GasPerPubdataByteLimit.ToByteArray(isUnsigned: true, isBigEndian: true)); + fields.Add(RLP.EncodeList(transaction.FactoryDeps)); + fields.Add(signatureHex.HexToByteArray()); + + if (!string.IsNullOrEmpty(transaction.Paymaster) && transaction.PaymasterInput != null) + { + fields.Add(transaction.Paymaster.HexToByteArray()); + fields.Add(transaction.PaymasterInput); + } + else + { + fields.Add(new byte[0]); + } + + // 0x71f901250c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a780801ca095bdae3d9ee4919b95ccb65008fb834b876cf6daab54f08914a3682b692dac3ba007de707e93d03249ffcaac274caf27e513cbe96d78d24c0136ab8a2aae94a66782012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c35081c0b8413bac2d692b68a31489f054abdaf66c874b83fb0850b6cc959b91e49e3daebd9567a694ae2a8aab36014cd2786de9cb13e527af4c27accaff4932d0937e70de071c94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 + + // 0x71f901260c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a7808080a02ce7dea3c25ac28c69ef5d425933bf6195c7c5648e4e228e3dca1f62f147449ea06b626df4ccad17b8c472ddba39b113c0e8f49569572fdd4ac2f6e2ddfc29726682012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b8412ce7dea3c25ac28c69ef5d425933bf6195c7c5648e4e228e3dca1f62f147449e6b626df4ccad17b8c472ddba39b113c0e8f49569572fdd4ac2f6e2ddfc2972661bf85b94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 + + return "0x71" + RLP.EncodeDataItemsAsElementOrListAndCombineAsList(fields.ToArray()).ToHex(); } } } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs index 34113a0..591ff28 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs @@ -210,7 +210,7 @@ public class ZkSyncAATransaction public virtual byte[] Data { get; set; } [Parameter("bytes32[]", "factoryDeps", 12)] - public virtual byte[] FactoryDeps { get; set; } + public virtual byte[][] FactoryDeps { get; set; } [Parameter("bytes", "paymasterInput", 13)] public virtual byte[] PaymasterInput { get; set; } From 08c71f482ae166cfd239c83e77183794d002add1 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 21 May 2024 17:47:09 +0300 Subject: [PATCH 08/23] fix factorydeps, encode as empty list 0xc0 --- Thirdweb/Thirdweb.Wallets/EIP712.cs | 32 ++++++++--------------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index 9534889..95f9ca1 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -131,42 +131,26 @@ private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction tra transaction.Data == null ? new byte[0] : transaction.Data, }; - if (signature != null) - { - fields.Add(new BigInteger(signature.V).ToByteArray(isUnsigned: false, isBigEndian: true)); - fields.Add(new BigInteger(signature.R).ToByteArray(isUnsigned: false, isBigEndian: true)); - fields.Add(new BigInteger(signature.S).ToByteArray(isUnsigned: false, isBigEndian: true)); - } - else - { - fields.Add(chainId.ToByteArray(isUnsigned: true, isBigEndian: true)); - fields.Add(new byte[0]); - fields.Add(new byte[0]); - } + fields.Add(new BigInteger(signature.V).ToByteArray(isUnsigned: false, isBigEndian: true)); + fields.Add(new BigInteger(signature.R).ToByteArray(isUnsigned: false, isBigEndian: true)); + fields.Add(new BigInteger(signature.S).ToByteArray(isUnsigned: false, isBigEndian: true)); fields.Add(chainId.ToByteArray(isUnsigned: true, isBigEndian: true)); fields.Add(transaction.From.HexToByteArray()); // Add meta fields.Add(transaction.GasPerPubdataByteLimit.ToByteArray(isUnsigned: true, isBigEndian: true)); - fields.Add(RLP.EncodeList(transaction.FactoryDeps)); + fields.Add(new byte[] { }); // TODO: FactoryDeps fields.Add(signatureHex.HexToByteArray()); - if (!string.IsNullOrEmpty(transaction.Paymaster) && transaction.PaymasterInput != null) - { - fields.Add(transaction.Paymaster.HexToByteArray()); - fields.Add(transaction.PaymasterInput); - } - else - { - fields.Add(new byte[0]); - } + fields.Add(transaction.Paymaster.HexToByteArray()); + fields.Add(transaction.PaymasterInput); - // 0x71f901250c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a780801ca095bdae3d9ee4919b95ccb65008fb834b876cf6daab54f08914a3682b692dac3ba007de707e93d03249ffcaac274caf27e513cbe96d78d24c0136ab8a2aae94a66782012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c35081c0b8413bac2d692b68a31489f054abdaf66c874b83fb0850b6cc959b91e49e3daebd9567a694ae2a8aab36014cd2786de9cb13e527af4c27accaff4932d0937e70de071c94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 + // 0x71f901240c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a780801ca095bdae3d9ee4919b95ccb65008fb834b876cf6daab54f08914a3682b692dac3ba007de707e93d03249ffcaac274caf27e513cbe96d78d24c0136ab8a2aae94a66782012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b8413bac2d692b68a31489f054abdaf66c874b83fb0850b6cc959b91e49e3daebd9567a694ae2a8aab36014cd2786de9cb13e527af4c27accaff4932d0937e70de071c94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 // 0x71f901260c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a7808080a02ce7dea3c25ac28c69ef5d425933bf6195c7c5648e4e228e3dca1f62f147449ea06b626df4ccad17b8c472ddba39b113c0e8f49569572fdd4ac2f6e2ddfc29726682012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b8412ce7dea3c25ac28c69ef5d425933bf6195c7c5648e4e228e3dca1f62f147449e6b626df4ccad17b8c472ddba39b113c0e8f49569572fdd4ac2f6e2ddfc2972661bf85b94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 - return "0x71" + RLP.EncodeDataItemsAsElementOrListAndCombineAsList(fields.ToArray()).ToHex(); + return "0x71" + RLP.EncodeDataItemsAsElementOrListAndCombineAsList(fields.ToArray(), new int[] { 13 }).ToHex(); // 13 = FactoryDeps } } } From 09bcf62b3a7724364e03b328310647a839214067 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 21 May 2024 18:05:41 +0300 Subject: [PATCH 09/23] yParity, types --- .../Thirdweb.Transactions/ThirdwebTransaction.cs | 2 +- Thirdweb/Thirdweb.Wallets/EIP712.cs | 13 +++++++------ .../Thirdweb.AccountAbstraction/AATypes.cs | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index 1c36078..ade4184 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -236,7 +236,7 @@ public static async Task Send(ThirdwebTransaction transaction, string zk Nonce = transaction.Input.Nonce ?? new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", transaction.Input.From, "latest")), Value = transaction.Input.Value.Value, Data = transaction.Input.Data.HexToByteArray(), - FactoryDeps = new byte[][] { }, + FactoryDeps = new byte[] { }, PaymasterInput = zkSyncPaymasterInput.HexToByteArray() }; Console.WriteLine($"ZkSync transaction: {JsonConvert.SerializeObject(zkTx)}"); diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index 95f9ca1..f46b85b 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -1,5 +1,6 @@ using System.Numerics; using Nethereum.ABI.EIP712; +using Nethereum.ABI.FunctionEncoding.Attributes; using Nethereum.Hex.HexConvertors.Extensions; using Nethereum.Hex.HexTypes; using Nethereum.Model; @@ -56,7 +57,7 @@ IThirdwebWallet signer var signatureHex = await signer.EthSign(hash); Console.WriteLine($"Signature: {signatureHex}"); var signatureRaw = EthECDSASignatureFactory.ExtractECDSASignature(signatureHex); - var serializedTx = SerializeEip712(transaction, signatureRaw, signatureHex, chainId); + var serializedTx = SerializeEip712(transaction, signatureRaw, chainId); Console.WriteLine($"Serialized: {serializedTx}"); return serializedTx; } @@ -104,11 +105,11 @@ public static TypedData GetTypedDefinition_ZkSy ChainId = chainId, }, Types = MemberDescriptionFactory.GetTypesMemberDescription(typeof(DomainWithNameVersionAndChainId), typeof(AccountAbstraction.ZkSyncAATransaction)), - PrimaryType = nameof(AccountAbstraction.ZkSyncAATransaction), + PrimaryType = "Transaction", }; } - private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction transaction, EthECDSASignature signature, string signatureHex, BigInteger chainId) + private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction transaction, EthECDSASignature signature, BigInteger chainId) { if (chainId == 0) { @@ -131,7 +132,7 @@ private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction tra transaction.Data == null ? new byte[0] : transaction.Data, }; - fields.Add(new BigInteger(signature.V).ToByteArray(isUnsigned: false, isBigEndian: true)); + fields.Add(signature.IsVSignedForYParity() ? new byte[] { 0x1b } : new byte[] { }); fields.Add(new BigInteger(signature.R).ToByteArray(isUnsigned: false, isBigEndian: true)); fields.Add(new BigInteger(signature.S).ToByteArray(isUnsigned: false, isBigEndian: true)); @@ -141,12 +142,12 @@ private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction tra // Add meta fields.Add(transaction.GasPerPubdataByteLimit.ToByteArray(isUnsigned: true, isBigEndian: true)); fields.Add(new byte[] { }); // TODO: FactoryDeps - fields.Add(signatureHex.HexToByteArray()); + fields.Add(signature.CreateStringSignature().HexToByteArray()); fields.Add(transaction.Paymaster.HexToByteArray()); fields.Add(transaction.PaymasterInput); - // 0x71f901240c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a780801ca095bdae3d9ee4919b95ccb65008fb834b876cf6daab54f08914a3682b692dac3ba007de707e93d03249ffcaac274caf27e513cbe96d78d24c0136ab8a2aae94a66782012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b8413bac2d692b68a31489f054abdaf66c874b83fb0850b6cc959b91e49e3daebd9567a694ae2a8aab36014cd2786de9cb13e527af4c27accaff4932d0937e70de071c94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 + // 0x71f901240c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a7808080a0149015c6a2073d376059808a4302d736093646fff75e3b0b44e1f73a41bd00b2a08e4f98ece9fab20e1621e9ad7efe34561ff00d94392afd20469bdacbdd7f660a82012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b841b200bd413af7e1440b3b5ef7ff46360936d702438a805960373d07a2c61590140a667fddcbda9b4620fd2a39940df01f5634fe7eade921160eb2fae9ec984f8e1b94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 // 0x71f901260c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a7808080a02ce7dea3c25ac28c69ef5d425933bf6195c7c5648e4e228e3dca1f62f147449ea06b626df4ccad17b8c472ddba39b113c0e8f49569572fdd4ac2f6e2ddfc29726682012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b8412ce7dea3c25ac28c69ef5d425933bf6195c7c5648e4e228e3dca1f62f147449e6b626df4ccad17b8c472ddba39b113c0e8f49569572fdd4ac2f6e2ddfc2972661bf85b94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs index 591ff28..b0fb394 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs @@ -174,6 +174,7 @@ public class AccountMessage public virtual byte[] Message { get; set; } } + [Struct("Transaction")] public class ZkSyncAATransaction { [Parameter("uint256", "txType", 1)] @@ -210,7 +211,7 @@ public class ZkSyncAATransaction public virtual byte[] Data { get; set; } [Parameter("bytes32[]", "factoryDeps", 12)] - public virtual byte[][] FactoryDeps { get; set; } + public virtual byte[] FactoryDeps { get; set; } [Parameter("bytes", "paymasterInput", 13)] public virtual byte[] PaymasterInput { get; set; } From 8dca1b4842a11e3a83cd94d82edf8fcd19388a0a Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 21 May 2024 18:35:25 +0300 Subject: [PATCH 10/23] signature method correct, hash incorrect --- Thirdweb/Thirdweb.Wallets/EIP712.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index f46b85b..ed8670d 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -133,8 +133,8 @@ private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction tra }; fields.Add(signature.IsVSignedForYParity() ? new byte[] { 0x1b } : new byte[] { }); - fields.Add(new BigInteger(signature.R).ToByteArray(isUnsigned: false, isBigEndian: true)); - fields.Add(new BigInteger(signature.S).ToByteArray(isUnsigned: false, isBigEndian: true)); + fields.Add(signature.R); + fields.Add(signature.S); fields.Add(chainId.ToByteArray(isUnsigned: true, isBigEndian: true)); fields.Add(transaction.From.HexToByteArray()); @@ -147,7 +147,7 @@ private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction tra fields.Add(transaction.Paymaster.HexToByteArray()); fields.Add(transaction.PaymasterInput); - // 0x71f901240c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a7808080a0149015c6a2073d376059808a4302d736093646fff75e3b0b44e1f73a41bd00b2a08e4f98ece9fab20e1621e9ad7efe34561ff00d94392afd20469bdacbdd7f660a82012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b841b200bd413af7e1440b3b5ef7ff46360936d702438a805960373d07a2c61590140a667fddcbda9b4620fd2a39940df01f5634fe7eade921160eb2fae9ec984f8e1b94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 + // 0x71f901240c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a7808080a0b200bd413af7e1440b3b5ef7ff46360936d702438a805960373d07a2c6159014a00a667fddcbda9b4620fd2a39940df01f5634fe7eade921160eb2fae9ec984f8e82012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b841b200bd413af7e1440b3b5ef7ff46360936d702438a805960373d07a2c61590140a667fddcbda9b4620fd2a39940df01f5634fe7eade921160eb2fae9ec984f8e1b94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 // 0x71f901260c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a7808080a02ce7dea3c25ac28c69ef5d425933bf6195c7c5648e4e228e3dca1f62f147449ea06b626df4ccad17b8c472ddba39b113c0e8f49569572fdd4ac2f6e2ddfc29726682012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b8412ce7dea3c25ac28c69ef5d425933bf6195c7c5648e4e228e3dca1f62f147449e6b626df4ccad17b8c472ddba39b113c0e8f49569572fdd4ac2f6e2ddfc2972661bf85b94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 From 024da5ba7e4ee6deeb62e0f3f336bf511701d8d8 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Wed, 22 May 2024 00:42:38 +0300 Subject: [PATCH 11/23] It works! --- .../ThirdwebTransaction.cs | 12 +++----- Thirdweb/Thirdweb.Wallets/EIP712.cs | 30 +++++-------------- .../Thirdweb.AccountAbstraction/AATypes.cs | 12 ++++---- 3 files changed, 17 insertions(+), 37 deletions(-) diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index ade4184..e7dafd9 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -192,14 +192,12 @@ public static async Task Send(ThirdwebTransaction transaction, string zk transaction.Input.Gas ??= new HexBigInteger(await EstimateGasLimit(transaction)); if (transaction.Input.GasPrice == null) { - Console.WriteLine("Sending as EIP-1559 tx"); var (maxFeePerGas, maxPriorityFeePerGas) = await EstimateGasFees(transaction); transaction.Input.MaxFeePerGas ??= maxFeePerGas.ToHexBigInteger(); transaction.Input.MaxPriorityFeePerGas ??= maxPriorityFeePerGas.ToHexBigInteger(); } else { - Console.WriteLine("Sending as legacy tx"); transaction.Input.MaxFeePerGas = null; transaction.Input.MaxPriorityFeePerGas = null; } @@ -226,22 +224,21 @@ public static async Task Send(ThirdwebTransaction transaction, string zk var zkTx = new AccountAbstraction.ZkSyncAATransaction { TxType = 0x71, // 712 can't be used as it has to be one byte long - From = transaction.Input.From, - To = transaction.Input.To, + From = new HexBigInteger(transaction.Input.From).Value, + To = new HexBigInteger(transaction.Input.To).Value, GasLimit = transaction.Input.Gas.Value, GasPerPubdataByteLimit = 50000, MaxFeePerGas = transaction.Input.MaxFeePerGas?.Value ?? transaction.Input.GasPrice.Value, MaxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas?.Value ?? transaction.Input.GasPrice.Value, - Paymaster = zkSyncPaymaster, + // unsigned bigint of paymaster hex string + Paymaster = new HexBigInteger(zkSyncPaymaster).Value, Nonce = transaction.Input.Nonce ?? new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", transaction.Input.From, "latest")), Value = transaction.Input.Value.Value, Data = transaction.Input.Data.HexToByteArray(), FactoryDeps = new byte[] { }, PaymasterInput = zkSyncPaymasterInput.HexToByteArray() }; - Console.WriteLine($"ZkSync transaction: {JsonConvert.SerializeObject(zkTx)}"); var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet); - Console.WriteLine($"ZkSync transaction signed: {zkTxSigned}"); hash = await rpc.SendRequestAsync("eth_sendRawTransaction", zkTxSigned); } else @@ -262,7 +259,6 @@ public static async Task Send(ThirdwebTransaction transaction, string zk throw new NotImplementedException("Account type not supported"); } } - Console.WriteLine($"Transaction hash: {hash}"); return hash; } diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index ed8670d..2901e24 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -51,15 +51,9 @@ IThirdwebWallet signer ) { var typedData = GetTypedDefinition_ZkSyncTransaction(domainName, version, chainId); - var typedDataEncoder = new Eip712TypedDataEncoder(); - var hash = typedDataEncoder.EncodeAndHashTypedData(transaction, typedData); - Console.WriteLine($"Hash: {hash.ToHex(true)}"); - var signatureHex = await signer.EthSign(hash); - Console.WriteLine($"Signature: {signatureHex}"); + var signatureHex = await signer.SignTypedDataV4(transaction, typedData); var signatureRaw = EthECDSASignatureFactory.ExtractECDSASignature(signatureHex); - var serializedTx = SerializeEip712(transaction, signatureRaw, chainId); - Console.WriteLine($"Serialized: {serializedTx}"); - return serializedTx; + return SerializeEip712(transaction, signatureRaw, chainId); } public static TypedData GetTypedDefinition_SmartAccount(string domainName, string version, BigInteger chainId, string verifyingContract) @@ -116,18 +110,13 @@ private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction tra throw new ArgumentException("Chain ID must be provided for EIP712 transactions!"); } - if (string.IsNullOrEmpty(transaction.From)) - { - throw new ArgumentException("From address must be provided for EIP712 transactions!"); - } - var fields = new List { transaction.Nonce.ToByteArray(isUnsigned: true, isBigEndian: true), transaction.MaxPriorityFeePerGas.ToByteArray(isUnsigned: true, isBigEndian: true), transaction.MaxFeePerGas.ToByteArray(isUnsigned: true, isBigEndian: true), transaction.GasLimit.ToByteArray(isUnsigned: true, isBigEndian: true), - transaction.To.HexToByteArray(), + transaction.To.ToByteArray(isUnsigned: true, isBigEndian: true), transaction.Value == 0 ? new byte[0] : transaction.Value.ToByteArray(isUnsigned: true, isBigEndian: true), transaction.Data == null ? new byte[0] : transaction.Data, }; @@ -137,21 +126,16 @@ private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction tra fields.Add(signature.S); fields.Add(chainId.ToByteArray(isUnsigned: true, isBigEndian: true)); - fields.Add(transaction.From.HexToByteArray()); + fields.Add(transaction.From.ToByteArray(isUnsigned: true, isBigEndian: true)); // Add meta fields.Add(transaction.GasPerPubdataByteLimit.ToByteArray(isUnsigned: true, isBigEndian: true)); fields.Add(new byte[] { }); // TODO: FactoryDeps fields.Add(signature.CreateStringSignature().HexToByteArray()); + // add array of rlp encoded paymaster/paymasterinput + fields.Add(RLP.EncodeElement(transaction.Paymaster.ToByteArray(isUnsigned: true, isBigEndian: true)).Concat(RLP.EncodeElement(transaction.PaymasterInput)).ToArray()); - fields.Add(transaction.Paymaster.HexToByteArray()); - fields.Add(transaction.PaymasterInput); - - // 0x71f901240c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a7808080a0b200bd413af7e1440b3b5ef7ff46360936d702438a805960373d07a2c6159014a00a667fddcbda9b4620fd2a39940df01f5634fe7eade921160eb2fae9ec984f8e82012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b841b200bd413af7e1440b3b5ef7ff46360936d702438a805960373d07a2c61590140a667fddcbda9b4620fd2a39940df01f5634fe7eade921160eb2fae9ec984f8e1b94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 - - // 0x71f901260c84017d784084017d78408401312d009483e13cd6b1179be8b8cb5858accbba84394cf9a7808080a02ce7dea3c25ac28c69ef5d425933bf6195c7c5648e4e228e3dca1f62f147449ea06b626df4ccad17b8c472ddba39b113c0e8f49569572fdd4ac2f6e2ddfc29726682012c9483e13cd6b1179be8b8cb5858accbba84394cf9a782c350c0b8412ce7dea3c25ac28c69ef5d425933bf6195c7c5648e4e228e3dca1f62f147449e6b626df4ccad17b8c472ddba39b113c0e8f49569572fdd4ac2f6e2ddfc2972661bf85b94ba226d47cbb2731cbaa67c916c57d68484aa269fb8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 - - return "0x71" + RLP.EncodeDataItemsAsElementOrListAndCombineAsList(fields.ToArray(), new int[] { 13 }).ToHex(); // 13 = FactoryDeps + return "0x71" + RLP.EncodeDataItemsAsElementOrListAndCombineAsList(fields.ToArray(), new int[] { 13, 15 }).ToHex(); } } } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs index b0fb394..1a246f4 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs @@ -180,11 +180,11 @@ public class ZkSyncAATransaction [Parameter("uint256", "txType", 1)] public virtual BigInteger TxType { get; set; } - [Parameter("address", "from", 2)] - public virtual string From { get; set; } + [Parameter("uint256", "from", 2)] + public virtual BigInteger From { get; set; } - [Parameter("address", "to", 3)] - public virtual string To { get; set; } + [Parameter("uint256", "to", 3)] + public virtual BigInteger To { get; set; } [Parameter("uint256", "gasLimit", 4)] public virtual BigInteger GasLimit { get; set; } @@ -198,8 +198,8 @@ public class ZkSyncAATransaction [Parameter("uint256", "maxPriorityFeePerGas", 7)] public virtual BigInteger MaxPriorityFeePerGas { get; set; } - [Parameter("address", "paymaster", 8)] - public virtual string Paymaster { get; set; } + [Parameter("uint256", "paymaster", 8)] + public virtual BigInteger Paymaster { get; set; } [Parameter("uint256", "nonce", 9)] public virtual BigInteger Nonce { get; set; } From 549093d578333f6464fefa01bdc9de01e7033f67 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Wed, 22 May 2024 00:52:13 +0300 Subject: [PATCH 12/23] cleanup, move params to ThirdwebTransactionInput next --- .../ThirdwebTransaction.cs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index e7dafd9..b98c469 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -207,30 +207,15 @@ public static async Task Send(ThirdwebTransaction transaction, string zk var isZkAA = zkSyncPaymaster != null && zkSyncPaymasterInput != null; if (isZkAA && (transaction.Input.ChainId.Value.Equals(324) || transaction.Input.ChainId.Value.Equals(300))) { - // Field name Type - // txType uint256 - // from uint256 - // to uint256 - // gasLimit uint256 - // gasPerPubdataByteLimit uint256 - // maxFeePerGas uint256 - // maxPriorityFeePerGas uint256 - // paymaster uint256 - // nonce uint256 - // value uint256 - // data bytes - // factoryDeps bytes32[] - // paymasterInput bytes var zkTx = new AccountAbstraction.ZkSyncAATransaction { - TxType = 0x71, // 712 can't be used as it has to be one byte long + TxType = 0x71, From = new HexBigInteger(transaction.Input.From).Value, To = new HexBigInteger(transaction.Input.To).Value, GasLimit = transaction.Input.Gas.Value, GasPerPubdataByteLimit = 50000, MaxFeePerGas = transaction.Input.MaxFeePerGas?.Value ?? transaction.Input.GasPrice.Value, MaxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas?.Value ?? transaction.Input.GasPrice.Value, - // unsigned bigint of paymaster hex string Paymaster = new HexBigInteger(zkSyncPaymaster).Value, Nonce = transaction.Input.Nonce ?? new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", transaction.Input.From, "latest")), Value = transaction.Input.Value.Value, From a3097c4f8a6a029b9ed97631f5f6cd72e8f37680 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Wed, 22 May 2024 17:59:59 +0300 Subject: [PATCH 13/23] zkSync SmartWallet auto paymaster poc --- Thirdweb.Console/Program.cs | 43 +++-- .../Thirdweb.PrivateKeyWallet.Tests.cs | 5 +- .../ThirdwebTransaction.cs | 1 - .../SmartWallet/SmartWallet.cs | 152 ++++++++++++++---- .../Thirdweb.AccountAbstraction/AATypes.cs | 5 + .../BundlerClient.cs | 13 ++ 6 files changed, 168 insertions(+), 51 deletions(-) diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs index b4b48e6..96612ad 100644 --- a/Thirdweb.Console/Program.cs +++ b/Thirdweb.Console/Program.cs @@ -65,28 +65,45 @@ } // Test 113 -var tx = await ThirdwebTransaction.Create( - client, - privateKeyWallet, +// var tx = await ThirdwebTransaction.Create( +// client, +// privateKeyWallet, +// new ThirdwebTransactionInput() +// { +// From = await privateKeyWallet.GetAddress(), +// To = await privateKeyWallet.GetAddress(), +// Value = new HexBigInteger(BigInteger.Zero), +// Data = "0x", +// MaxFeePerGas = new HexBigInteger(25000000), +// MaxPriorityFeePerGas = new HexBigInteger(25000000), +// Gas = new HexBigInteger(20000000), +// ChainId = new HexBigInteger(300), +// }, +// 300 +// ); +// var rawZkSyncAaTxHash = await ThirdwebTransaction.Send( +// transaction: tx, +// zkSyncPaymaster: "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", +// zkSyncPaymasterInput: "0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000" +// ); +// Console.WriteLine($"Transaction hash: {rawZkSyncAaTxHash}"); + +var zkSmartWallet = await SmartWallet.Create(client: client, personalWallet: privateKeyWallet, chainId: 300, gasless: true, zkSyncPaymasterAddress: "0xE74eA4e1785F74016e0076754B5ca6d8ADC10934"); +var zkSyncSignatureBasedAaTxHash = await zkSmartWallet.SendTransaction( new ThirdwebTransactionInput() { - From = await privateKeyWallet.GetAddress(), - To = await privateKeyWallet.GetAddress(), + From = await zkSmartWallet.GetAddress(), + To = await zkSmartWallet.GetAddress(), Value = new HexBigInteger(BigInteger.Zero), Data = "0x", MaxFeePerGas = new HexBigInteger(25000000), MaxPriorityFeePerGas = new HexBigInteger(25000000), Gas = new HexBigInteger(20000000), ChainId = new HexBigInteger(300), - }, - 300 -); -var txHash = await ThirdwebTransaction.Send( - transaction: tx, - zkSyncPaymaster: "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", - zkSyncPaymasterInput: "0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000" + Nonce = await ThirdwebRPC.GetRpcInstance(client, 300).SendRequestAsync("eth_getTransactionCount", new object[] { await zkSmartWallet.GetAddress(), "latest" }) + } ); -Console.WriteLine($"Transaction hash: {txHash}"); +Console.WriteLine($"Transaction hash: {zkSyncSignatureBasedAaTxHash}"); diff --git a/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs b/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs index a74fc70..339cfcf 100644 --- a/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs @@ -59,7 +59,7 @@ public async Task EthSign_Success() public async Task EthSign_NullMessage() { var account = await GetAccount(); - var ex = await Assert.ThrowsAsync(() => account.EthSign(null)); + var ex = await Assert.ThrowsAsync(() => account.EthSign(null as string)); Assert.Equal("Message to sign cannot be null. (Parameter 'message')", ex.Message); } @@ -256,7 +256,6 @@ public async Task SignTransaction_1559_Success() Gas = new HexBigInteger(21000), Data = "0x", Nonce = new HexBigInteger(99999999999), - Type = new HexBigInteger(2), MaxFeePerGas = new HexBigInteger(10000000000), MaxPriorityFeePerGas = new HexBigInteger(10000000000) }; @@ -276,7 +275,6 @@ public async Task SignTransaction_1559_NoMaxFeePerGas() Gas = new HexBigInteger(21000), Data = "0x", Nonce = new HexBigInteger(99999999999), - Type = new HexBigInteger(2), MaxPriorityFeePerGas = new HexBigInteger(10000000000) }; var ex = await Assert.ThrowsAsync(() => account.SignTransaction(transaction, 421614)); @@ -295,7 +293,6 @@ public async Task SignTransaction_1559_NoMaxPriorityFeePerGas() Gas = new HexBigInteger(21000), Data = "0x", Nonce = new HexBigInteger(99999999999), - Type = new HexBigInteger(2), MaxFeePerGas = new HexBigInteger(10000000000) }; var ex = await Assert.ThrowsAsync(() => account.SignTransaction(transaction, 421614)); diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index b98c469..4fa985d 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -236,7 +236,6 @@ public static async Task Send(ThirdwebTransaction transaction, string zk hash = await rpc.SendRequestAsync("eth_sendRawTransaction", signedTx); break; case ThirdwebAccountType.SmartAccount: - var smartAccount = transaction._wallet as SmartWallet; hash = await smartAccount.SendTransaction(transaction.Input); break; diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs index b045fa8..b396361 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs @@ -24,6 +24,8 @@ public class SmartWallet : IThirdwebWallet protected BigInteger _chainId; protected string _bundlerUrl; protected string _paymasterUrl; + protected ThirdwebContract _zkSyncPaymaster; + protected bool IsZkSync => _chainId == 324 || _chainId == 300; protected SmartWallet( ThirdwebClient client, @@ -34,7 +36,8 @@ protected SmartWallet( string paymasterUrl, ThirdwebContract entryPointContract, ThirdwebContract factoryContract, - ThirdwebContract accountContract + ThirdwebContract accountContract, + ThirdwebContract zkSyncPaymaster ) { _client = client; @@ -46,18 +49,20 @@ ThirdwebContract accountContract _entryPointContract = entryPointContract; _factoryContract = factoryContract; _accountContract = accountContract; + _zkSyncPaymaster = zkSyncPaymaster; } public static async Task Create( ThirdwebClient client, IThirdwebWallet personalWallet, - string factoryAddress, - bool gasless, BigInteger chainId, + bool gasless = true, + string factoryAddress = null, string accountAddressOverride = null, string entryPoint = null, string bundlerUrl = null, - string paymasterUrl = null + string paymasterUrl = null, + string zkSyncPaymasterAddress = null ) { if (!await personalWallet.IsConnected()) @@ -69,43 +74,76 @@ public static async Task Create( paymasterUrl ??= $"https://{chainId}.bundler.thirdweb.com"; entryPoint ??= Constants.DEFAULT_ENTRYPOINT_ADDRESS; - var entryPointContract = await ThirdwebContract.Create( - client, - entryPoint, - chainId, - "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]" - ); - var factoryContract = await ThirdwebContract.Create( - client, - factoryAddress, - chainId, - "[{\"type\": \"constructor\",\"name\": \"\",\"inputs\": [{\"type\": \"address\",\"name\": \"_defaultAdmin\",\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"_entrypoint\",\"internalType\": \"contract IEntryPoint\"},{\"type\": \"tuple[]\",\"name\": \"_defaultExtensions\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension[]\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"error\",\"name\": \"InvalidCodeAtRange\",\"inputs\": [{\"type\": \"uint256\",\"name\": \"_size\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_start\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_end\",\"internalType\": \"uint256\"}],\"outputs\": []},{\"type\": \"error\",\"name\": \"WriteError\",\"inputs\": [],\"outputs\": []},{\"type\": \"event\",\"name\": \"AccountCreated\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"accountAdmin\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ContractURIUpdated\",\"inputs\": [{\"type\": \"string\",\"name\": \"prevURI\",\"indexed\": false,\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"newURI\",\"indexed\": false,\"internalType\": \"string\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionAdded\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionRemoved\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionReplaced\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"FunctionDisabled\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"indexed\": true,\"internalType\": \"bytes4\"},{\"type\": \"tuple\",\"name\": \"extMetadata\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"FunctionEnabled\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"indexed\": true,\"internalType\": \"bytes4\"},{\"type\": \"tuple\",\"name\": \"extFunction\",\"components\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"},{\"type\": \"string\",\"name\": \"functionSignature\",\"internalType\": \"string\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionFunction\"},{\"type\": \"tuple\",\"name\": \"extMetadata\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleAdminChanged\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"previousAdminRole\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"newAdminRole\",\"indexed\": true,\"internalType\": \"bytes32\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleGranted\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"sender\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleRevoked\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"sender\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"SignerAdded\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"signer\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"SignerRemoved\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"signer\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"fallback\",\"name\": \"\",\"inputs\": [],\"outputs\": [],\"stateMutability\": \"payable\"},{\"type\": \"function\",\"name\": \"DEFAULT_ADMIN_ROLE\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"_disableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"accountImplementation\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"addExtension\",\"inputs\": [{\"type\": \"tuple\",\"name\": \"_extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"contractURI\",\"inputs\": [],\"outputs\": [{\"type\": \"string\",\"name\": \"\",\"internalType\": \"string\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"createAccount\",\"inputs\": [{\"type\": \"address\",\"name\": \"_admin\",\"internalType\": \"address\"},{\"type\": \"bytes\",\"name\": \"_data\",\"internalType\": \"bytes\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"defaultExtensions\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"disableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"enableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"tuple\",\"name\": \"_function\",\"components\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"},{\"type\": \"string\",\"name\": \"functionSignature\",\"internalType\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"entrypoint\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAccounts\",\"inputs\": [{\"type\": \"uint256\",\"name\": \"_start\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_end\",\"internalType\": \"uint256\"}],\"outputs\": [{\"type\": \"address[]\",\"name\": \"accounts\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAccountsOfSigner\",\"inputs\": [{\"type\": \"address\",\"name\": \"signer\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"address[]\",\"name\": \"accounts\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAddress\",\"inputs\": [{\"type\": \"address\",\"name\": \"_adminSigner\",\"internalType\": \"address\"},{\"type\": \"bytes\",\"name\": \"_data\",\"internalType\": \"bytes\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAllAccounts\",\"inputs\": [],\"outputs\": [{\"type\": \"address[]\",\"name\": \"\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAllExtensions\",\"inputs\": [],\"outputs\": [{\"type\": \"tuple[]\",\"name\": \"allExtensions\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"extensionName\",\"internalType\": \"string\"}],\"outputs\": [{\"type\": \"tuple\",\"name\": \"\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getImplementationForFunction\",\"inputs\": [{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getMetadataForFunction\",\"inputs\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [{\"type\": \"tuple\",\"name\": \"\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleAdmin\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"}],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleMember\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"uint256\",\"name\": \"index\",\"internalType\": \"uint256\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"member\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleMemberCount\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"}],\"outputs\": [{\"type\": \"uint256\",\"name\": \"count\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"grantRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"hasRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"hasRoleWithSwitch\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"isRegistered\",\"inputs\": [{\"type\": \"address\",\"name\": \"_account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"multicall\",\"inputs\": [{\"type\": \"bytes[]\",\"name\": \"data\",\"internalType\": \"bytes[]\"}],\"outputs\": [{\"type\": \"bytes[]\",\"name\": \"results\",\"internalType\": \"bytes[]\"}],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onRegister\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onSignerAdded\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onSignerRemoved\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"removeExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"renounceRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"replaceExtension\",\"inputs\": [{\"type\": \"tuple\",\"name\": \"_extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"revokeRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"setContractURI\",\"inputs\": [{\"type\": \"string\",\"name\": \"_uri\",\"internalType\": \"string\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"totalAccounts\",\"inputs\": [],\"outputs\": [{\"type\": \"uint256\",\"name\": \"\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"}]" - ); - var accountAddress = accountAddressOverride ?? await ThirdwebContract.Read(factoryContract, "getAddress", await personalWallet.GetAddress(), new byte[0]); - var accountContract = await ThirdwebContract.Create( - client, - accountAddress, - chainId, - "[{type: \"constructor\",inputs: [{name: \"_entrypoint\",type: \"address\",internalType: \"contract IEntryPoint\",},{ name: \"_factory\", type: \"address\", internalType: \"address\" },],stateMutability: \"nonpayable\",},{ type: \"receive\", stateMutability: \"payable\" },{type: \"function\",name: \"addDeposit\",inputs: [],outputs: [],stateMutability: \"payable\",},{type: \"function\",name: \"contractURI\",inputs: [],outputs: [{ name: \"\", type: \"string\", internalType: \"string\" }],stateMutability: \"view\",},{type: \"function\",name: \"entryPoint\",inputs: [],outputs: [{ name: \"\", type: \"address\", internalType: \"contract IEntryPoint\" },],stateMutability: \"view\",},{type: \"function\",name: \"execute\",inputs: [{ name: \"_target\", type: \"address\", internalType: \"address\" },{ name: \"_value\", type: \"uint256\", internalType: \"uint256\" },{ name: \"_calldata\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"executeBatch\",inputs: [{ name: \"_target\", type: \"address[]\", internalType: \"address[]\" },{ name: \"_value\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"_calldata\", type: \"bytes[]\", internalType: \"bytes[]\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"factory\",inputs: [],outputs: [{ name: \"\", type: \"address\", internalType: \"address\" }],stateMutability: \"view\",},{type: \"function\",name: \"getAllActiveSigners\",inputs: [],outputs: [{name: \"signers\",type: \"tuple[]\",internalType: \"struct IAccountPermissions.SignerPermissions[]\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"getAllAdmins\",inputs: [],outputs: [{ name: \"\", type: \"address[]\", internalType: \"address[]\" }],stateMutability: \"view\",},{type: \"function\",name: \"getAllSigners\",inputs: [],outputs: [{name: \"signers\",type: \"tuple[]\",internalType: \"struct IAccountPermissions.SignerPermissions[]\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"getMessageHash\",inputs: [{ name: \"_hash\", type: \"bytes32\", internalType: \"bytes32\" }],outputs: [{ name: \"\", type: \"bytes32\", internalType: \"bytes32\" }],stateMutability: \"view\",},{type: \"function\",name: \"getNonce\",inputs: [],outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],stateMutability: \"view\",},{type: \"function\",name: \"getPermissionsForSigner\",inputs: [{ name: \"signer\", type: \"address\", internalType: \"address\" }],outputs: [{name: \"\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissions\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"initialize\",inputs: [{ name: \"_defaultAdmin\", type: \"address\", internalType: \"address\" },{ name: \"_data\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"isActiveSigner\",inputs: [{ name: \"signer\", type: \"address\", internalType: \"address\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"isAdmin\",inputs: [{ name: \"_account\", type: \"address\", internalType: \"address\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"isValidSignature\",inputs: [{ name: \"_hash\", type: \"bytes32\", internalType: \"bytes32\" },{ name: \"_signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"magicValue\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"view\",},{type: \"function\",name: \"isValidSigner\",inputs: [{ name: \"_signer\", type: \"address\", internalType: \"address\" },{name: \"_userOp\",type: \"tuple\",internalType: \"struct UserOperation\",components: [{ name: \"sender\", type: \"address\", internalType: \"address\" },{ name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },{ name: \"initCode\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callGasLimit\", type: \"uint256\", internalType: \"uint256\" },{name: \"verificationGasLimit\",type: \"uint256\",internalType: \"uint256\",},{name: \"preVerificationGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"maxFeePerGas\", type: \"uint256\", internalType: \"uint256\" },{name: \"maxPriorityFeePerGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"paymasterAndData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],},],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"multicall\",inputs: [{ name: \"data\", type: \"bytes[]\", internalType: \"bytes[]\" }],outputs: [{ name: \"results\", type: \"bytes[]\", internalType: \"bytes[]\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC1155BatchReceived\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC1155Received\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC721Received\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setContractURI\",inputs: [{ name: \"_uri\", type: \"string\", internalType: \"string\" }],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setEntrypointOverride\",inputs: [{name: \"_entrypointOverride\",type: \"address\",internalType: \"contract IEntryPoint\",},],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setPermissionsForSigner\",inputs: [{name: \"_req\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},{ name: \"_signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"supportsInterface\",inputs: [{ name: \"interfaceId\", type: \"bytes4\", internalType: \"bytes4\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"validateUserOp\",inputs: [{name: \"userOp\",type: \"tuple\",internalType: \"struct UserOperation\",components: [{ name: \"sender\", type: \"address\", internalType: \"address\" },{ name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },{ name: \"initCode\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callGasLimit\", type: \"uint256\", internalType: \"uint256\" },{name: \"verificationGasLimit\",type: \"uint256\",internalType: \"uint256\",},{name: \"preVerificationGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"maxFeePerGas\", type: \"uint256\", internalType: \"uint256\" },{name: \"maxPriorityFeePerGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"paymasterAndData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],},{ name: \"userOpHash\", type: \"bytes32\", internalType: \"bytes32\" },{ name: \"missingAccountFunds\", type: \"uint256\", internalType: \"uint256\" },],outputs: [{ name: \"validationData\", type: \"uint256\", internalType: \"uint256\" },],stateMutability: \"nonpayable\",},{type: \"function\",name: \"verifySignerPermissionRequest\",inputs: [{name: \"req\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"success\", type: \"bool\", internalType: \"bool\" },{ name: \"signer\", type: \"address\", internalType: \"address\" },],stateMutability: \"view\",},{type: \"function\",name: \"withdrawDepositTo\",inputs: [{name: \"withdrawAddress\",type: \"address\",internalType: \"address payable\",},{ name: \"amount\", type: \"uint256\", internalType: \"uint256\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"event\",name: \"AdminUpdated\",inputs: [{name: \"signer\",type: \"address\",indexed: true,internalType: \"address\",},{ name: \"isAdmin\", type: \"bool\", indexed: false, internalType: \"bool\" },],anonymous: false,},{type: \"event\",name: \"ContractURIUpdated\",inputs: [{name: \"prevURI\",type: \"string\",indexed: false,internalType: \"string\",},{name: \"newURI\",type: \"string\",indexed: false,internalType: \"string\",},],anonymous: false,},{type: \"event\",name: \"Initialized\",inputs: [{ name: \"version\", type: \"uint8\", indexed: false, internalType: \"uint8\" },],anonymous: false,},{type: \"event\",name: \"SignerPermissionsUpdated\",inputs: [{name: \"authorizingSigner\",type: \"address\",indexed: true,internalType: \"address\",},{name: \"targetSigner\",type: \"address\",indexed: true,internalType: \"address\",},{name: \"permissions\",type: \"tuple\",indexed: false,internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},],anonymous: false,},]" - ); - - return new SmartWallet(client, personalWallet, gasless, chainId, bundlerUrl, paymasterUrl, entryPointContract, factoryContract, accountContract); + ThirdwebContract entryPointContract = null; + ThirdwebContract factoryContract = null; + ThirdwebContract accountContract = null; + ThirdwebContract zkSyncPaymasterContract = null; + + if ((chainId == 324 || chainId == 300) && !string.IsNullOrEmpty(zkSyncPaymasterAddress)) + { + zkSyncPaymasterContract = await ThirdwebContract.Create( + client, + zkSyncPaymasterAddress, + chainId, + "[{\"type\": \"constructor\",\"name\": \"\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"error\",\"name\": \"InvalidShortString\",\"inputs\": [],\"outputs\": []},{\"type\": \"error\",\"name\": \"StringTooLong\",\"inputs\": [{\"type\": \"string\",\"name\": \"str\",\"internalType\": \"string\"}],\"outputs\": []},{\"type\": \"event\",\"name\": \"EIP712DomainChanged\",\"inputs\": [],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"OwnershipTransferred\",\"inputs\": [{\"type\": \"address\",\"name\": \"previousOwner\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"newOwner\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"function\",\"name\": \"SIGNATURE_TYPEHASH\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"cancelNonce\",\"inputs\": [{\"type\": \"address\",\"name\": \"_userAddress\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"changeSigner\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"domainSeparator\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"eip712Domain\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes1\",\"name\": \"fields\",\"internalType\": \"bytes1\"},{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"version\",\"internalType\": \"string\"},{\"type\": \"uint256\",\"name\": \"chainId\",\"internalType\": \"uint256\"},{\"type\": \"address\",\"name\": \"verifyingContract\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"salt\",\"internalType\": \"bytes32\"},{\"type\": \"uint256[]\",\"name\": \"extensions\",\"internalType\": \"uint256[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"nonces\",\"inputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"uint256\",\"name\": \"\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"owner\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"postTransaction\",\"inputs\": [{\"type\": \"bytes\",\"name\": \"_context\",\"internalType\": \"bytes\"},{\"type\": \"tuple\",\"name\": \"_transaction\",\"components\": [{\"type\": \"uint256\",\"name\": \"txType\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"from\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"to\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasPerPubdataByteLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxPriorityFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"paymaster\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"nonce\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"value\",\"internalType\": \"uint256\"},{\"type\": \"uint256[4]\",\"name\": \"reserved\",\"internalType\": \"uint256[4]\"},{\"type\": \"bytes\",\"name\": \"data\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"signature\",\"internalType\": \"bytes\"},{\"type\": \"bytes32[]\",\"name\": \"factoryDeps\",\"internalType\": \"bytes32[]\"},{\"type\": \"bytes\",\"name\": \"paymasterInput\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"reservedDynamic\",\"internalType\": \"bytes\"}],\"internalType\": \"struct Transaction\"},{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"uint8\",\"name\": \"_txResult\",\"internalType\": \"enum ExecutionResult\"},{\"type\": \"uint256\",\"name\": \"_maxRefundedGas\",\"internalType\": \"uint256\"}],\"outputs\": [],\"stateMutability\": \"payable\"},{\"type\": \"function\",\"name\": \"renounceOwnership\",\"inputs\": [],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"signer\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"transferOwnership\",\"inputs\": [{\"type\": \"address\",\"name\": \"newOwner\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"validateAndPayForPaymasterTransaction\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"tuple\",\"name\": \"_transaction\",\"components\": [{\"type\": \"uint256\",\"name\": \"txType\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"from\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"to\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasPerPubdataByteLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxPriorityFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"paymaster\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"nonce\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"value\",\"internalType\": \"uint256\"},{\"type\": \"uint256[4]\",\"name\": \"reserved\",\"internalType\": \"uint256[4]\"},{\"type\": \"bytes\",\"name\": \"data\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"signature\",\"internalType\": \"bytes\"},{\"type\": \"bytes32[]\",\"name\": \"factoryDeps\",\"internalType\": \"bytes32[]\"},{\"type\": \"bytes\",\"name\": \"paymasterInput\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"reservedDynamic\",\"internalType\": \"bytes\"}],\"internalType\": \"struct Transaction\"}],\"outputs\": [{\"type\": \"bytes4\",\"name\": \"magic\",\"internalType\": \"bytes4\"},{\"type\": \"bytes\",\"name\": \"context\",\"internalType\": \"bytes\"}],\"stateMutability\": \"payable\"},{\"type\": \"function\",\"name\": \"withdraw\",\"inputs\": [{\"type\": \"address\",\"name\": \"_to\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"receive\",\"name\": \"\",\"inputs\": [],\"outputs\": [],\"stateMutability\": \"payable\"}]" + ); + } + else + { + entryPointContract = await ThirdwebContract.Create( + client, + entryPoint, + chainId, + "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]" + ); + factoryContract = await ThirdwebContract.Create( + client, + factoryAddress, + chainId, + "[{\"type\": \"constructor\",\"name\": \"\",\"inputs\": [{\"type\": \"address\",\"name\": \"_defaultAdmin\",\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"_entrypoint\",\"internalType\": \"contract IEntryPoint\"},{\"type\": \"tuple[]\",\"name\": \"_defaultExtensions\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension[]\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"error\",\"name\": \"InvalidCodeAtRange\",\"inputs\": [{\"type\": \"uint256\",\"name\": \"_size\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_start\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_end\",\"internalType\": \"uint256\"}],\"outputs\": []},{\"type\": \"error\",\"name\": \"WriteError\",\"inputs\": [],\"outputs\": []},{\"type\": \"event\",\"name\": \"AccountCreated\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"accountAdmin\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ContractURIUpdated\",\"inputs\": [{\"type\": \"string\",\"name\": \"prevURI\",\"indexed\": false,\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"newURI\",\"indexed\": false,\"internalType\": \"string\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionAdded\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionRemoved\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionReplaced\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"FunctionDisabled\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"indexed\": true,\"internalType\": \"bytes4\"},{\"type\": \"tuple\",\"name\": \"extMetadata\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"FunctionEnabled\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"indexed\": true,\"internalType\": \"bytes4\"},{\"type\": \"tuple\",\"name\": \"extFunction\",\"components\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"},{\"type\": \"string\",\"name\": \"functionSignature\",\"internalType\": \"string\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionFunction\"},{\"type\": \"tuple\",\"name\": \"extMetadata\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleAdminChanged\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"previousAdminRole\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"newAdminRole\",\"indexed\": true,\"internalType\": \"bytes32\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleGranted\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"sender\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleRevoked\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"sender\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"SignerAdded\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"signer\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"SignerRemoved\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"signer\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"fallback\",\"name\": \"\",\"inputs\": [],\"outputs\": [],\"stateMutability\": \"payable\"},{\"type\": \"function\",\"name\": \"DEFAULT_ADMIN_ROLE\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"_disableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"accountImplementation\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"addExtension\",\"inputs\": [{\"type\": \"tuple\",\"name\": \"_extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"contractURI\",\"inputs\": [],\"outputs\": [{\"type\": \"string\",\"name\": \"\",\"internalType\": \"string\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"createAccount\",\"inputs\": [{\"type\": \"address\",\"name\": \"_admin\",\"internalType\": \"address\"},{\"type\": \"bytes\",\"name\": \"_data\",\"internalType\": \"bytes\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"defaultExtensions\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"disableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"enableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"tuple\",\"name\": \"_function\",\"components\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"},{\"type\": \"string\",\"name\": \"functionSignature\",\"internalType\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"entrypoint\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAccounts\",\"inputs\": [{\"type\": \"uint256\",\"name\": \"_start\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_end\",\"internalType\": \"uint256\"}],\"outputs\": [{\"type\": \"address[]\",\"name\": \"accounts\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAccountsOfSigner\",\"inputs\": [{\"type\": \"address\",\"name\": \"signer\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"address[]\",\"name\": \"accounts\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAddress\",\"inputs\": [{\"type\": \"address\",\"name\": \"_adminSigner\",\"internalType\": \"address\"},{\"type\": \"bytes\",\"name\": \"_data\",\"internalType\": \"bytes\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAllAccounts\",\"inputs\": [],\"outputs\": [{\"type\": \"address[]\",\"name\": \"\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAllExtensions\",\"inputs\": [],\"outputs\": [{\"type\": \"tuple[]\",\"name\": \"allExtensions\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"extensionName\",\"internalType\": \"string\"}],\"outputs\": [{\"type\": \"tuple\",\"name\": \"\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getImplementationForFunction\",\"inputs\": [{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getMetadataForFunction\",\"inputs\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [{\"type\": \"tuple\",\"name\": \"\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleAdmin\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"}],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleMember\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"uint256\",\"name\": \"index\",\"internalType\": \"uint256\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"member\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleMemberCount\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"}],\"outputs\": [{\"type\": \"uint256\",\"name\": \"count\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"grantRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"hasRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"hasRoleWithSwitch\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"isRegistered\",\"inputs\": [{\"type\": \"address\",\"name\": \"_account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"multicall\",\"inputs\": [{\"type\": \"bytes[]\",\"name\": \"data\",\"internalType\": \"bytes[]\"}],\"outputs\": [{\"type\": \"bytes[]\",\"name\": \"results\",\"internalType\": \"bytes[]\"}],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onRegister\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onSignerAdded\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onSignerRemoved\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"removeExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"renounceRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"replaceExtension\",\"inputs\": [{\"type\": \"tuple\",\"name\": \"_extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"revokeRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"setContractURI\",\"inputs\": [{\"type\": \"string\",\"name\": \"_uri\",\"internalType\": \"string\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"totalAccounts\",\"inputs\": [],\"outputs\": [{\"type\": \"uint256\",\"name\": \"\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"}]" + ); + var accountAddress = accountAddressOverride ?? await ThirdwebContract.Read(factoryContract, "getAddress", await personalWallet.GetAddress(), new byte[0]); + accountContract = await ThirdwebContract.Create( + client, + accountAddress, + chainId, + "[{type: \"constructor\",inputs: [{name: \"_entrypoint\",type: \"address\",internalType: \"contract IEntryPoint\",},{ name: \"_factory\", type: \"address\", internalType: \"address\" },],stateMutability: \"nonpayable\",},{ type: \"receive\", stateMutability: \"payable\" },{type: \"function\",name: \"addDeposit\",inputs: [],outputs: [],stateMutability: \"payable\",},{type: \"function\",name: \"contractURI\",inputs: [],outputs: [{ name: \"\", type: \"string\", internalType: \"string\" }],stateMutability: \"view\",},{type: \"function\",name: \"entryPoint\",inputs: [],outputs: [{ name: \"\", type: \"address\", internalType: \"contract IEntryPoint\" },],stateMutability: \"view\",},{type: \"function\",name: \"execute\",inputs: [{ name: \"_target\", type: \"address\", internalType: \"address\" },{ name: \"_value\", type: \"uint256\", internalType: \"uint256\" },{ name: \"_calldata\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"executeBatch\",inputs: [{ name: \"_target\", type: \"address[]\", internalType: \"address[]\" },{ name: \"_value\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"_calldata\", type: \"bytes[]\", internalType: \"bytes[]\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"factory\",inputs: [],outputs: [{ name: \"\", type: \"address\", internalType: \"address\" }],stateMutability: \"view\",},{type: \"function\",name: \"getAllActiveSigners\",inputs: [],outputs: [{name: \"signers\",type: \"tuple[]\",internalType: \"struct IAccountPermissions.SignerPermissions[]\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"getAllAdmins\",inputs: [],outputs: [{ name: \"\", type: \"address[]\", internalType: \"address[]\" }],stateMutability: \"view\",},{type: \"function\",name: \"getAllSigners\",inputs: [],outputs: [{name: \"signers\",type: \"tuple[]\",internalType: \"struct IAccountPermissions.SignerPermissions[]\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"getMessageHash\",inputs: [{ name: \"_hash\", type: \"bytes32\", internalType: \"bytes32\" }],outputs: [{ name: \"\", type: \"bytes32\", internalType: \"bytes32\" }],stateMutability: \"view\",},{type: \"function\",name: \"getNonce\",inputs: [],outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],stateMutability: \"view\",},{type: \"function\",name: \"getPermissionsForSigner\",inputs: [{ name: \"signer\", type: \"address\", internalType: \"address\" }],outputs: [{name: \"\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissions\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"initialize\",inputs: [{ name: \"_defaultAdmin\", type: \"address\", internalType: \"address\" },{ name: \"_data\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"isActiveSigner\",inputs: [{ name: \"signer\", type: \"address\", internalType: \"address\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"isAdmin\",inputs: [{ name: \"_account\", type: \"address\", internalType: \"address\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"isValidSignature\",inputs: [{ name: \"_hash\", type: \"bytes32\", internalType: \"bytes32\" },{ name: \"_signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"magicValue\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"view\",},{type: \"function\",name: \"isValidSigner\",inputs: [{ name: \"_signer\", type: \"address\", internalType: \"address\" },{name: \"_userOp\",type: \"tuple\",internalType: \"struct UserOperation\",components: [{ name: \"sender\", type: \"address\", internalType: \"address\" },{ name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },{ name: \"initCode\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callGasLimit\", type: \"uint256\", internalType: \"uint256\" },{name: \"verificationGasLimit\",type: \"uint256\",internalType: \"uint256\",},{name: \"preVerificationGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"maxFeePerGas\", type: \"uint256\", internalType: \"uint256\" },{name: \"maxPriorityFeePerGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"paymasterAndData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],},],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"multicall\",inputs: [{ name: \"data\", type: \"bytes[]\", internalType: \"bytes[]\" }],outputs: [{ name: \"results\", type: \"bytes[]\", internalType: \"bytes[]\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC1155BatchReceived\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC1155Received\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC721Received\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setContractURI\",inputs: [{ name: \"_uri\", type: \"string\", internalType: \"string\" }],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setEntrypointOverride\",inputs: [{name: \"_entrypointOverride\",type: \"address\",internalType: \"contract IEntryPoint\",},],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setPermissionsForSigner\",inputs: [{name: \"_req\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},{ name: \"_signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"supportsInterface\",inputs: [{ name: \"interfaceId\", type: \"bytes4\", internalType: \"bytes4\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"validateUserOp\",inputs: [{name: \"userOp\",type: \"tuple\",internalType: \"struct UserOperation\",components: [{ name: \"sender\", type: \"address\", internalType: \"address\" },{ name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },{ name: \"initCode\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callGasLimit\", type: \"uint256\", internalType: \"uint256\" },{name: \"verificationGasLimit\",type: \"uint256\",internalType: \"uint256\",},{name: \"preVerificationGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"maxFeePerGas\", type: \"uint256\", internalType: \"uint256\" },{name: \"maxPriorityFeePerGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"paymasterAndData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],},{ name: \"userOpHash\", type: \"bytes32\", internalType: \"bytes32\" },{ name: \"missingAccountFunds\", type: \"uint256\", internalType: \"uint256\" },],outputs: [{ name: \"validationData\", type: \"uint256\", internalType: \"uint256\" },],stateMutability: \"nonpayable\",},{type: \"function\",name: \"verifySignerPermissionRequest\",inputs: [{name: \"req\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"success\", type: \"bool\", internalType: \"bool\" },{ name: \"signer\", type: \"address\", internalType: \"address\" },],stateMutability: \"view\",},{type: \"function\",name: \"withdrawDepositTo\",inputs: [{name: \"withdrawAddress\",type: \"address\",internalType: \"address payable\",},{ name: \"amount\", type: \"uint256\", internalType: \"uint256\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"event\",name: \"AdminUpdated\",inputs: [{name: \"signer\",type: \"address\",indexed: true,internalType: \"address\",},{ name: \"isAdmin\", type: \"bool\", indexed: false, internalType: \"bool\" },],anonymous: false,},{type: \"event\",name: \"ContractURIUpdated\",inputs: [{name: \"prevURI\",type: \"string\",indexed: false,internalType: \"string\",},{name: \"newURI\",type: \"string\",indexed: false,internalType: \"string\",},],anonymous: false,},{type: \"event\",name: \"Initialized\",inputs: [{ name: \"version\", type: \"uint8\", indexed: false, internalType: \"uint8\" },],anonymous: false,},{type: \"event\",name: \"SignerPermissionsUpdated\",inputs: [{name: \"authorizingSigner\",type: \"address\",indexed: true,internalType: \"address\",},{name: \"targetSigner\",type: \"address\",indexed: true,internalType: \"address\",},{name: \"permissions\",type: \"tuple\",indexed: false,internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},],anonymous: false,},]" + ); + } + + return new SmartWallet(client, personalWallet, gasless, chainId, bundlerUrl, paymasterUrl, entryPointContract, factoryContract, accountContract, zkSyncPaymasterContract); } public async Task IsDeployed() { + if (IsZkSync) + { + return true; + } + var code = await ThirdwebRPC.GetRpcInstance(_client, _chainId).SendRequestAsync("eth_getCode", _accountContract.Address, "latest"); return code != "0x"; } - public async Task SendTransaction(ThirdwebTransactionInput transaction) + public async Task SendTransaction(ThirdwebTransactionInput transactionInput) { - if (transaction == null) + if (transactionInput == null) { throw new InvalidOperationException("SmartAccount.SendTransaction: Transaction input is required."); } - var signedOp = await SignUserOp(transaction); - return await SendUserOp(signedOp); + + if (IsZkSync) + { + var paymaster = _gasless ? _zkSyncPaymaster.Address : null; + var paymasterInput = await GetPaymasterInput(transactionInput); + var transaction = await ThirdwebTransaction.Create(_client, _personalAccount, transactionInput, _chainId); + return await ThirdwebTransaction.Send(transaction, paymaster, paymasterInput.ToHex(true)); + } + else + { + var signedOp = await SignUserOp(transactionInput); + return await SendUserOp(signedOp); + } } private async Task GetInitCode() @@ -206,6 +244,19 @@ private async Task GetNonce() return await ThirdwebContract.Read(_entryPointContract, "getNonce", await GetAddress(), randomInt192); } + private async Task GetPaymasterInput(ThirdwebTransactionInput transactionInput) + { + if (_gasless) + { + var paymasterInput = await BundlerClient.PMSponsorTransaction(_client, _paymasterUrl, 1, transactionInput, _entryPointContract.Address); + return paymasterInput.paymasterInput.HexToByteArray(); + } + else + { + return new byte[] { }; + } + } + private async Task GetPaymasterAndData(object requestId, UserOperationHexified userOp) { if (_gasless) @@ -246,6 +297,11 @@ private UserOperationHexified EncodeUserOperation(UserOperation userOperation) public async Task ForceDeploy() { + if (IsZkSync) + { + return; + } + var input = new ThirdwebTransactionInput() { Data = "0x", @@ -261,9 +317,9 @@ public Task GetPersonalAccount() return Task.FromResult(_personalAccount); } - public Task GetAddress() + public async Task GetAddress() { - return Task.FromResult(_accountContract.Address); + return IsZkSync ? await _personalAccount.GetAddress() : _accountContract.Address; } public Task EthSign(byte[] rawMessage) @@ -283,6 +339,11 @@ public Task PersonalSign(byte[] rawMessage) public async Task PersonalSign(string message) { + if (IsZkSync) + { + return await _personalAccount.PersonalSign(message); + } + if (!await IsDeployed()) { Console.WriteLine("SmartWallet not deployed, deploying before signing..."); @@ -339,6 +400,11 @@ public async Task CreateSessionKey( string reqValidityEndTimestamp ) { + if (IsZkSync) + { + throw new Exception("Account Permissions are not supported in ZkSync"); + } + var request = new SignerPermissionRequest() { Signer = signerAddress, @@ -367,6 +433,11 @@ string reqValidityEndTimestamp public async Task AddAdmin(string admin) { + if (IsZkSync) + { + throw new Exception("Account Permissions are not supported in ZkSync"); + } + var request = new SignerPermissionRequest() { Signer = admin, @@ -395,6 +466,11 @@ public async Task AddAdmin(string admin) public async Task RemoveAdmin(string admin) { + if (IsZkSync) + { + throw new Exception("Account Permissions are not supported in ZkSync"); + } + var request = new SignerPermissionRequest() { Signer = admin, @@ -434,6 +510,11 @@ public Task SignTypedDataV4(T data, TypedData typed public async Task EstimateUserOperationGas(ThirdwebTransactionInput transaction, BigInteger chainId) { + if (IsZkSync) + { + throw new Exception("User Operations are not supported in ZkSync"); + } + var signedOp = await SignUserOp(transaction); var cost = signedOp.CallGasLimit + signedOp.VerificationGasLimit + signedOp.PreVerificationGas; return cost; @@ -441,12 +522,17 @@ public async Task EstimateUserOperationGas(ThirdwebTransactionInput public async Task SignTransaction(ThirdwebTransactionInput transaction, BigInteger chainId) { + if (IsZkSync) + { + throw new Exception("Offline Signing is not supported in ZkSync"); + } + return JsonConvert.SerializeObject(EncodeUserOperation(await SignUserOp(transaction))); } - public Task IsConnected() + public async Task IsConnected() { - return Task.FromResult(_accountContract != null); + return IsZkSync ? await _personalAccount.IsConnected() : _accountContract != null; } public Task Disconnect() diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs index 1a246f4..f3f3bab 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs @@ -91,6 +91,11 @@ public class PMSponsorOperationResponse public string paymasterAndData { get; set; } } + public class PMSponsorTransactionResponse + { + public string paymasterInput { get; set; } + } + public class ThirdwebGetUserOperationGasPriceResponse { public string maxFeePerGas { get; set; } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs index 0a00caa..9744b47 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs @@ -42,6 +42,19 @@ public static async Task ThirdwebGetUs // Paymaster requests + public static async Task PMSponsorTransaction(ThirdwebClient client, string paymasterUrl, object requestId, ThirdwebTransactionInput userOp, string entryPoint) + { + var response = await BundlerRequest(client, paymasterUrl, requestId, "pm_sponsorTransaction", userOp, new EntryPointWrapper() { entryPoint = entryPoint }); + try + { + return JsonConvert.DeserializeObject(response.Result.ToString()); + } + catch + { + return new PMSponsorTransactionResponse() { paymasterInput = response.Result.ToString() }; + } + } + public static async Task PMSponsorUserOperation(ThirdwebClient client, string paymasterUrl, object requestId, UserOperationHexified userOp, string entryPoint) { var response = await BundlerRequest(client, paymasterUrl, requestId, "pm_sponsorUserOperation", userOp, new EntryPointWrapper() { entryPoint = entryPoint }); From a4ce773de65a78da49e3623f2adbd41e7e66bcc7 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Thu, 23 May 2024 02:11:37 +0300 Subject: [PATCH 14/23] def --- Thirdweb.Console/Program.cs | 2 +- Thirdweb/Thirdweb.Utils/Constants.cs | 1 + Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs index 96612ad..4767d0f 100644 --- a/Thirdweb.Console/Program.cs +++ b/Thirdweb.Console/Program.cs @@ -88,7 +88,7 @@ // ); // Console.WriteLine($"Transaction hash: {rawZkSyncAaTxHash}"); -var zkSmartWallet = await SmartWallet.Create(client: client, personalWallet: privateKeyWallet, chainId: 300, gasless: true, zkSyncPaymasterAddress: "0xE74eA4e1785F74016e0076754B5ca6d8ADC10934"); +var zkSmartWallet = await SmartWallet.Create(client: client, personalWallet: privateKeyWallet, chainId: 300, gasless: true); var zkSyncSignatureBasedAaTxHash = await zkSmartWallet.SendTransaction( new ThirdwebTransactionInput() { diff --git a/Thirdweb/Thirdweb.Utils/Constants.cs b/Thirdweb/Thirdweb.Utils/Constants.cs index 6727ccc..993ad5c 100644 --- a/Thirdweb/Thirdweb.Utils/Constants.cs +++ b/Thirdweb/Thirdweb.Utils/Constants.cs @@ -14,5 +14,6 @@ public static class Constants "0x0101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000001010101010100000000000000000000000000000000000000000000000000000000000000000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"; internal const string FALLBACK_IPFS_GATEWAY = "https://ipfs.io/ipfs/"; internal const string PIN_URI = "https://storage.thirdweb.com/ipfs/upload"; + internal const string ZKSYNC_SIGNATUREBASED_PAYMASTER = "0xE74eA4e1785F74016e0076754B5ca6d8ADC10934"; } } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs index b396361..d82b7ab 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs @@ -61,8 +61,7 @@ public static async Task Create( string accountAddressOverride = null, string entryPoint = null, string bundlerUrl = null, - string paymasterUrl = null, - string zkSyncPaymasterAddress = null + string paymasterUrl = null ) { if (!await personalWallet.IsConnected()) @@ -79,8 +78,9 @@ public static async Task Create( ThirdwebContract accountContract = null; ThirdwebContract zkSyncPaymasterContract = null; - if ((chainId == 324 || chainId == 300) && !string.IsNullOrEmpty(zkSyncPaymasterAddress)) + if (chainId == 324 || chainId == 300) { + var zkSyncPaymasterAddress = Constants.ZKSYNC_SIGNATUREBASED_PAYMASTER; zkSyncPaymasterContract = await ThirdwebContract.Create( client, zkSyncPaymasterAddress, From a0a6728d5eb3fc56959f69961ef0d5b70a48b5e4 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Thu, 23 May 2024 14:28:11 +0300 Subject: [PATCH 15/23] Revert "def" This reverts commit a4ce773de65a78da49e3623f2adbd41e7e66bcc7. --- Thirdweb.Console/Program.cs | 2 +- Thirdweb/Thirdweb.Utils/Constants.cs | 1 - Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs | 6 +++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs index 4767d0f..96612ad 100644 --- a/Thirdweb.Console/Program.cs +++ b/Thirdweb.Console/Program.cs @@ -88,7 +88,7 @@ // ); // Console.WriteLine($"Transaction hash: {rawZkSyncAaTxHash}"); -var zkSmartWallet = await SmartWallet.Create(client: client, personalWallet: privateKeyWallet, chainId: 300, gasless: true); +var zkSmartWallet = await SmartWallet.Create(client: client, personalWallet: privateKeyWallet, chainId: 300, gasless: true, zkSyncPaymasterAddress: "0xE74eA4e1785F74016e0076754B5ca6d8ADC10934"); var zkSyncSignatureBasedAaTxHash = await zkSmartWallet.SendTransaction( new ThirdwebTransactionInput() { diff --git a/Thirdweb/Thirdweb.Utils/Constants.cs b/Thirdweb/Thirdweb.Utils/Constants.cs index 993ad5c..6727ccc 100644 --- a/Thirdweb/Thirdweb.Utils/Constants.cs +++ b/Thirdweb/Thirdweb.Utils/Constants.cs @@ -14,6 +14,5 @@ public static class Constants "0x0101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000001010101010100000000000000000000000000000000000000000000000000000000000000000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"; internal const string FALLBACK_IPFS_GATEWAY = "https://ipfs.io/ipfs/"; internal const string PIN_URI = "https://storage.thirdweb.com/ipfs/upload"; - internal const string ZKSYNC_SIGNATUREBASED_PAYMASTER = "0xE74eA4e1785F74016e0076754B5ca6d8ADC10934"; } } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs index d82b7ab..b396361 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs @@ -61,7 +61,8 @@ public static async Task Create( string accountAddressOverride = null, string entryPoint = null, string bundlerUrl = null, - string paymasterUrl = null + string paymasterUrl = null, + string zkSyncPaymasterAddress = null ) { if (!await personalWallet.IsConnected()) @@ -78,9 +79,8 @@ public static async Task Create( ThirdwebContract accountContract = null; ThirdwebContract zkSyncPaymasterContract = null; - if (chainId == 324 || chainId == 300) + if ((chainId == 324 || chainId == 300) && !string.IsNullOrEmpty(zkSyncPaymasterAddress)) { - var zkSyncPaymasterAddress = Constants.ZKSYNC_SIGNATUREBASED_PAYMASTER; zkSyncPaymasterContract = await ThirdwebContract.Create( client, zkSyncPaymasterAddress, From a15eea35510bb9b96f38513400193bbc57e1f2f1 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Thu, 23 May 2024 14:28:25 +0300 Subject: [PATCH 16/23] Revert "zkSync SmartWallet auto paymaster poc" This reverts commit a3097c4f8a6a029b9ed97631f5f6cd72e8f37680. --- Thirdweb.Console/Program.cs | 43 ++--- .../Thirdweb.PrivateKeyWallet.Tests.cs | 5 +- .../ThirdwebTransaction.cs | 1 + .../SmartWallet/SmartWallet.cs | 152 ++++-------------- .../Thirdweb.AccountAbstraction/AATypes.cs | 5 - .../BundlerClient.cs | 13 -- 6 files changed, 51 insertions(+), 168 deletions(-) diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs index 96612ad..b4b48e6 100644 --- a/Thirdweb.Console/Program.cs +++ b/Thirdweb.Console/Program.cs @@ -65,45 +65,28 @@ } // Test 113 -// var tx = await ThirdwebTransaction.Create( -// client, -// privateKeyWallet, -// new ThirdwebTransactionInput() -// { -// From = await privateKeyWallet.GetAddress(), -// To = await privateKeyWallet.GetAddress(), -// Value = new HexBigInteger(BigInteger.Zero), -// Data = "0x", -// MaxFeePerGas = new HexBigInteger(25000000), -// MaxPriorityFeePerGas = new HexBigInteger(25000000), -// Gas = new HexBigInteger(20000000), -// ChainId = new HexBigInteger(300), -// }, -// 300 -// ); -// var rawZkSyncAaTxHash = await ThirdwebTransaction.Send( -// transaction: tx, -// zkSyncPaymaster: "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", -// zkSyncPaymasterInput: "0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000" -// ); -// Console.WriteLine($"Transaction hash: {rawZkSyncAaTxHash}"); - -var zkSmartWallet = await SmartWallet.Create(client: client, personalWallet: privateKeyWallet, chainId: 300, gasless: true, zkSyncPaymasterAddress: "0xE74eA4e1785F74016e0076754B5ca6d8ADC10934"); -var zkSyncSignatureBasedAaTxHash = await zkSmartWallet.SendTransaction( +var tx = await ThirdwebTransaction.Create( + client, + privateKeyWallet, new ThirdwebTransactionInput() { - From = await zkSmartWallet.GetAddress(), - To = await zkSmartWallet.GetAddress(), + From = await privateKeyWallet.GetAddress(), + To = await privateKeyWallet.GetAddress(), Value = new HexBigInteger(BigInteger.Zero), Data = "0x", MaxFeePerGas = new HexBigInteger(25000000), MaxPriorityFeePerGas = new HexBigInteger(25000000), Gas = new HexBigInteger(20000000), ChainId = new HexBigInteger(300), - Nonce = await ThirdwebRPC.GetRpcInstance(client, 300).SendRequestAsync("eth_getTransactionCount", new object[] { await zkSmartWallet.GetAddress(), "latest" }) - } + }, + 300 +); +var txHash = await ThirdwebTransaction.Send( + transaction: tx, + zkSyncPaymaster: "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", + zkSyncPaymasterInput: "0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000" ); -Console.WriteLine($"Transaction hash: {zkSyncSignatureBasedAaTxHash}"); +Console.WriteLine($"Transaction hash: {txHash}"); diff --git a/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs b/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs index 339cfcf..a74fc70 100644 --- a/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs @@ -59,7 +59,7 @@ public async Task EthSign_Success() public async Task EthSign_NullMessage() { var account = await GetAccount(); - var ex = await Assert.ThrowsAsync(() => account.EthSign(null as string)); + var ex = await Assert.ThrowsAsync(() => account.EthSign(null)); Assert.Equal("Message to sign cannot be null. (Parameter 'message')", ex.Message); } @@ -256,6 +256,7 @@ public async Task SignTransaction_1559_Success() Gas = new HexBigInteger(21000), Data = "0x", Nonce = new HexBigInteger(99999999999), + Type = new HexBigInteger(2), MaxFeePerGas = new HexBigInteger(10000000000), MaxPriorityFeePerGas = new HexBigInteger(10000000000) }; @@ -275,6 +276,7 @@ public async Task SignTransaction_1559_NoMaxFeePerGas() Gas = new HexBigInteger(21000), Data = "0x", Nonce = new HexBigInteger(99999999999), + Type = new HexBigInteger(2), MaxPriorityFeePerGas = new HexBigInteger(10000000000) }; var ex = await Assert.ThrowsAsync(() => account.SignTransaction(transaction, 421614)); @@ -293,6 +295,7 @@ public async Task SignTransaction_1559_NoMaxPriorityFeePerGas() Gas = new HexBigInteger(21000), Data = "0x", Nonce = new HexBigInteger(99999999999), + Type = new HexBigInteger(2), MaxFeePerGas = new HexBigInteger(10000000000) }; var ex = await Assert.ThrowsAsync(() => account.SignTransaction(transaction, 421614)); diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index 4fa985d..b98c469 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -236,6 +236,7 @@ public static async Task Send(ThirdwebTransaction transaction, string zk hash = await rpc.SendRequestAsync("eth_sendRawTransaction", signedTx); break; case ThirdwebAccountType.SmartAccount: + var smartAccount = transaction._wallet as SmartWallet; hash = await smartAccount.SendTransaction(transaction.Input); break; diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs index b396361..b045fa8 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs @@ -24,8 +24,6 @@ public class SmartWallet : IThirdwebWallet protected BigInteger _chainId; protected string _bundlerUrl; protected string _paymasterUrl; - protected ThirdwebContract _zkSyncPaymaster; - protected bool IsZkSync => _chainId == 324 || _chainId == 300; protected SmartWallet( ThirdwebClient client, @@ -36,8 +34,7 @@ protected SmartWallet( string paymasterUrl, ThirdwebContract entryPointContract, ThirdwebContract factoryContract, - ThirdwebContract accountContract, - ThirdwebContract zkSyncPaymaster + ThirdwebContract accountContract ) { _client = client; @@ -49,20 +46,18 @@ ThirdwebContract zkSyncPaymaster _entryPointContract = entryPointContract; _factoryContract = factoryContract; _accountContract = accountContract; - _zkSyncPaymaster = zkSyncPaymaster; } public static async Task Create( ThirdwebClient client, IThirdwebWallet personalWallet, + string factoryAddress, + bool gasless, BigInteger chainId, - bool gasless = true, - string factoryAddress = null, string accountAddressOverride = null, string entryPoint = null, string bundlerUrl = null, - string paymasterUrl = null, - string zkSyncPaymasterAddress = null + string paymasterUrl = null ) { if (!await personalWallet.IsConnected()) @@ -74,76 +69,43 @@ public static async Task Create( paymasterUrl ??= $"https://{chainId}.bundler.thirdweb.com"; entryPoint ??= Constants.DEFAULT_ENTRYPOINT_ADDRESS; - ThirdwebContract entryPointContract = null; - ThirdwebContract factoryContract = null; - ThirdwebContract accountContract = null; - ThirdwebContract zkSyncPaymasterContract = null; - - if ((chainId == 324 || chainId == 300) && !string.IsNullOrEmpty(zkSyncPaymasterAddress)) - { - zkSyncPaymasterContract = await ThirdwebContract.Create( - client, - zkSyncPaymasterAddress, - chainId, - "[{\"type\": \"constructor\",\"name\": \"\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"error\",\"name\": \"InvalidShortString\",\"inputs\": [],\"outputs\": []},{\"type\": \"error\",\"name\": \"StringTooLong\",\"inputs\": [{\"type\": \"string\",\"name\": \"str\",\"internalType\": \"string\"}],\"outputs\": []},{\"type\": \"event\",\"name\": \"EIP712DomainChanged\",\"inputs\": [],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"OwnershipTransferred\",\"inputs\": [{\"type\": \"address\",\"name\": \"previousOwner\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"newOwner\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"function\",\"name\": \"SIGNATURE_TYPEHASH\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"cancelNonce\",\"inputs\": [{\"type\": \"address\",\"name\": \"_userAddress\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"changeSigner\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"domainSeparator\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"eip712Domain\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes1\",\"name\": \"fields\",\"internalType\": \"bytes1\"},{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"version\",\"internalType\": \"string\"},{\"type\": \"uint256\",\"name\": \"chainId\",\"internalType\": \"uint256\"},{\"type\": \"address\",\"name\": \"verifyingContract\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"salt\",\"internalType\": \"bytes32\"},{\"type\": \"uint256[]\",\"name\": \"extensions\",\"internalType\": \"uint256[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"nonces\",\"inputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"uint256\",\"name\": \"\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"owner\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"postTransaction\",\"inputs\": [{\"type\": \"bytes\",\"name\": \"_context\",\"internalType\": \"bytes\"},{\"type\": \"tuple\",\"name\": \"_transaction\",\"components\": [{\"type\": \"uint256\",\"name\": \"txType\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"from\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"to\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasPerPubdataByteLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxPriorityFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"paymaster\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"nonce\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"value\",\"internalType\": \"uint256\"},{\"type\": \"uint256[4]\",\"name\": \"reserved\",\"internalType\": \"uint256[4]\"},{\"type\": \"bytes\",\"name\": \"data\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"signature\",\"internalType\": \"bytes\"},{\"type\": \"bytes32[]\",\"name\": \"factoryDeps\",\"internalType\": \"bytes32[]\"},{\"type\": \"bytes\",\"name\": \"paymasterInput\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"reservedDynamic\",\"internalType\": \"bytes\"}],\"internalType\": \"struct Transaction\"},{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"uint8\",\"name\": \"_txResult\",\"internalType\": \"enum ExecutionResult\"},{\"type\": \"uint256\",\"name\": \"_maxRefundedGas\",\"internalType\": \"uint256\"}],\"outputs\": [],\"stateMutability\": \"payable\"},{\"type\": \"function\",\"name\": \"renounceOwnership\",\"inputs\": [],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"signer\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"transferOwnership\",\"inputs\": [{\"type\": \"address\",\"name\": \"newOwner\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"validateAndPayForPaymasterTransaction\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"tuple\",\"name\": \"_transaction\",\"components\": [{\"type\": \"uint256\",\"name\": \"txType\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"from\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"to\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasPerPubdataByteLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxPriorityFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"paymaster\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"nonce\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"value\",\"internalType\": \"uint256\"},{\"type\": \"uint256[4]\",\"name\": \"reserved\",\"internalType\": \"uint256[4]\"},{\"type\": \"bytes\",\"name\": \"data\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"signature\",\"internalType\": \"bytes\"},{\"type\": \"bytes32[]\",\"name\": \"factoryDeps\",\"internalType\": \"bytes32[]\"},{\"type\": \"bytes\",\"name\": \"paymasterInput\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"reservedDynamic\",\"internalType\": \"bytes\"}],\"internalType\": \"struct Transaction\"}],\"outputs\": [{\"type\": \"bytes4\",\"name\": \"magic\",\"internalType\": \"bytes4\"},{\"type\": \"bytes\",\"name\": \"context\",\"internalType\": \"bytes\"}],\"stateMutability\": \"payable\"},{\"type\": \"function\",\"name\": \"withdraw\",\"inputs\": [{\"type\": \"address\",\"name\": \"_to\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"receive\",\"name\": \"\",\"inputs\": [],\"outputs\": [],\"stateMutability\": \"payable\"}]" - ); - } - else - { - entryPointContract = await ThirdwebContract.Create( - client, - entryPoint, - chainId, - "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]" - ); - factoryContract = await ThirdwebContract.Create( - client, - factoryAddress, - chainId, - "[{\"type\": \"constructor\",\"name\": \"\",\"inputs\": [{\"type\": \"address\",\"name\": \"_defaultAdmin\",\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"_entrypoint\",\"internalType\": \"contract IEntryPoint\"},{\"type\": \"tuple[]\",\"name\": \"_defaultExtensions\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension[]\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"error\",\"name\": \"InvalidCodeAtRange\",\"inputs\": [{\"type\": \"uint256\",\"name\": \"_size\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_start\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_end\",\"internalType\": \"uint256\"}],\"outputs\": []},{\"type\": \"error\",\"name\": \"WriteError\",\"inputs\": [],\"outputs\": []},{\"type\": \"event\",\"name\": \"AccountCreated\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"accountAdmin\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ContractURIUpdated\",\"inputs\": [{\"type\": \"string\",\"name\": \"prevURI\",\"indexed\": false,\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"newURI\",\"indexed\": false,\"internalType\": \"string\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionAdded\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionRemoved\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionReplaced\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"FunctionDisabled\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"indexed\": true,\"internalType\": \"bytes4\"},{\"type\": \"tuple\",\"name\": \"extMetadata\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"FunctionEnabled\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"indexed\": true,\"internalType\": \"bytes4\"},{\"type\": \"tuple\",\"name\": \"extFunction\",\"components\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"},{\"type\": \"string\",\"name\": \"functionSignature\",\"internalType\": \"string\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionFunction\"},{\"type\": \"tuple\",\"name\": \"extMetadata\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleAdminChanged\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"previousAdminRole\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"newAdminRole\",\"indexed\": true,\"internalType\": \"bytes32\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleGranted\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"sender\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleRevoked\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"sender\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"SignerAdded\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"signer\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"SignerRemoved\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"signer\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"fallback\",\"name\": \"\",\"inputs\": [],\"outputs\": [],\"stateMutability\": \"payable\"},{\"type\": \"function\",\"name\": \"DEFAULT_ADMIN_ROLE\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"_disableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"accountImplementation\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"addExtension\",\"inputs\": [{\"type\": \"tuple\",\"name\": \"_extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"contractURI\",\"inputs\": [],\"outputs\": [{\"type\": \"string\",\"name\": \"\",\"internalType\": \"string\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"createAccount\",\"inputs\": [{\"type\": \"address\",\"name\": \"_admin\",\"internalType\": \"address\"},{\"type\": \"bytes\",\"name\": \"_data\",\"internalType\": \"bytes\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"defaultExtensions\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"disableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"enableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"tuple\",\"name\": \"_function\",\"components\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"},{\"type\": \"string\",\"name\": \"functionSignature\",\"internalType\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"entrypoint\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAccounts\",\"inputs\": [{\"type\": \"uint256\",\"name\": \"_start\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_end\",\"internalType\": \"uint256\"}],\"outputs\": [{\"type\": \"address[]\",\"name\": \"accounts\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAccountsOfSigner\",\"inputs\": [{\"type\": \"address\",\"name\": \"signer\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"address[]\",\"name\": \"accounts\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAddress\",\"inputs\": [{\"type\": \"address\",\"name\": \"_adminSigner\",\"internalType\": \"address\"},{\"type\": \"bytes\",\"name\": \"_data\",\"internalType\": \"bytes\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAllAccounts\",\"inputs\": [],\"outputs\": [{\"type\": \"address[]\",\"name\": \"\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAllExtensions\",\"inputs\": [],\"outputs\": [{\"type\": \"tuple[]\",\"name\": \"allExtensions\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"extensionName\",\"internalType\": \"string\"}],\"outputs\": [{\"type\": \"tuple\",\"name\": \"\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getImplementationForFunction\",\"inputs\": [{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getMetadataForFunction\",\"inputs\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [{\"type\": \"tuple\",\"name\": \"\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleAdmin\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"}],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleMember\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"uint256\",\"name\": \"index\",\"internalType\": \"uint256\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"member\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleMemberCount\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"}],\"outputs\": [{\"type\": \"uint256\",\"name\": \"count\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"grantRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"hasRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"hasRoleWithSwitch\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"isRegistered\",\"inputs\": [{\"type\": \"address\",\"name\": \"_account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"multicall\",\"inputs\": [{\"type\": \"bytes[]\",\"name\": \"data\",\"internalType\": \"bytes[]\"}],\"outputs\": [{\"type\": \"bytes[]\",\"name\": \"results\",\"internalType\": \"bytes[]\"}],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onRegister\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onSignerAdded\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onSignerRemoved\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"removeExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"renounceRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"replaceExtension\",\"inputs\": [{\"type\": \"tuple\",\"name\": \"_extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"revokeRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"setContractURI\",\"inputs\": [{\"type\": \"string\",\"name\": \"_uri\",\"internalType\": \"string\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"totalAccounts\",\"inputs\": [],\"outputs\": [{\"type\": \"uint256\",\"name\": \"\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"}]" - ); - var accountAddress = accountAddressOverride ?? await ThirdwebContract.Read(factoryContract, "getAddress", await personalWallet.GetAddress(), new byte[0]); - accountContract = await ThirdwebContract.Create( - client, - accountAddress, - chainId, - "[{type: \"constructor\",inputs: [{name: \"_entrypoint\",type: \"address\",internalType: \"contract IEntryPoint\",},{ name: \"_factory\", type: \"address\", internalType: \"address\" },],stateMutability: \"nonpayable\",},{ type: \"receive\", stateMutability: \"payable\" },{type: \"function\",name: \"addDeposit\",inputs: [],outputs: [],stateMutability: \"payable\",},{type: \"function\",name: \"contractURI\",inputs: [],outputs: [{ name: \"\", type: \"string\", internalType: \"string\" }],stateMutability: \"view\",},{type: \"function\",name: \"entryPoint\",inputs: [],outputs: [{ name: \"\", type: \"address\", internalType: \"contract IEntryPoint\" },],stateMutability: \"view\",},{type: \"function\",name: \"execute\",inputs: [{ name: \"_target\", type: \"address\", internalType: \"address\" },{ name: \"_value\", type: \"uint256\", internalType: \"uint256\" },{ name: \"_calldata\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"executeBatch\",inputs: [{ name: \"_target\", type: \"address[]\", internalType: \"address[]\" },{ name: \"_value\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"_calldata\", type: \"bytes[]\", internalType: \"bytes[]\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"factory\",inputs: [],outputs: [{ name: \"\", type: \"address\", internalType: \"address\" }],stateMutability: \"view\",},{type: \"function\",name: \"getAllActiveSigners\",inputs: [],outputs: [{name: \"signers\",type: \"tuple[]\",internalType: \"struct IAccountPermissions.SignerPermissions[]\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"getAllAdmins\",inputs: [],outputs: [{ name: \"\", type: \"address[]\", internalType: \"address[]\" }],stateMutability: \"view\",},{type: \"function\",name: \"getAllSigners\",inputs: [],outputs: [{name: \"signers\",type: \"tuple[]\",internalType: \"struct IAccountPermissions.SignerPermissions[]\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"getMessageHash\",inputs: [{ name: \"_hash\", type: \"bytes32\", internalType: \"bytes32\" }],outputs: [{ name: \"\", type: \"bytes32\", internalType: \"bytes32\" }],stateMutability: \"view\",},{type: \"function\",name: \"getNonce\",inputs: [],outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],stateMutability: \"view\",},{type: \"function\",name: \"getPermissionsForSigner\",inputs: [{ name: \"signer\", type: \"address\", internalType: \"address\" }],outputs: [{name: \"\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissions\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"initialize\",inputs: [{ name: \"_defaultAdmin\", type: \"address\", internalType: \"address\" },{ name: \"_data\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"isActiveSigner\",inputs: [{ name: \"signer\", type: \"address\", internalType: \"address\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"isAdmin\",inputs: [{ name: \"_account\", type: \"address\", internalType: \"address\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"isValidSignature\",inputs: [{ name: \"_hash\", type: \"bytes32\", internalType: \"bytes32\" },{ name: \"_signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"magicValue\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"view\",},{type: \"function\",name: \"isValidSigner\",inputs: [{ name: \"_signer\", type: \"address\", internalType: \"address\" },{name: \"_userOp\",type: \"tuple\",internalType: \"struct UserOperation\",components: [{ name: \"sender\", type: \"address\", internalType: \"address\" },{ name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },{ name: \"initCode\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callGasLimit\", type: \"uint256\", internalType: \"uint256\" },{name: \"verificationGasLimit\",type: \"uint256\",internalType: \"uint256\",},{name: \"preVerificationGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"maxFeePerGas\", type: \"uint256\", internalType: \"uint256\" },{name: \"maxPriorityFeePerGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"paymasterAndData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],},],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"multicall\",inputs: [{ name: \"data\", type: \"bytes[]\", internalType: \"bytes[]\" }],outputs: [{ name: \"results\", type: \"bytes[]\", internalType: \"bytes[]\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC1155BatchReceived\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC1155Received\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC721Received\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setContractURI\",inputs: [{ name: \"_uri\", type: \"string\", internalType: \"string\" }],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setEntrypointOverride\",inputs: [{name: \"_entrypointOverride\",type: \"address\",internalType: \"contract IEntryPoint\",},],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setPermissionsForSigner\",inputs: [{name: \"_req\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},{ name: \"_signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"supportsInterface\",inputs: [{ name: \"interfaceId\", type: \"bytes4\", internalType: \"bytes4\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"validateUserOp\",inputs: [{name: \"userOp\",type: \"tuple\",internalType: \"struct UserOperation\",components: [{ name: \"sender\", type: \"address\", internalType: \"address\" },{ name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },{ name: \"initCode\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callGasLimit\", type: \"uint256\", internalType: \"uint256\" },{name: \"verificationGasLimit\",type: \"uint256\",internalType: \"uint256\",},{name: \"preVerificationGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"maxFeePerGas\", type: \"uint256\", internalType: \"uint256\" },{name: \"maxPriorityFeePerGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"paymasterAndData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],},{ name: \"userOpHash\", type: \"bytes32\", internalType: \"bytes32\" },{ name: \"missingAccountFunds\", type: \"uint256\", internalType: \"uint256\" },],outputs: [{ name: \"validationData\", type: \"uint256\", internalType: \"uint256\" },],stateMutability: \"nonpayable\",},{type: \"function\",name: \"verifySignerPermissionRequest\",inputs: [{name: \"req\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"success\", type: \"bool\", internalType: \"bool\" },{ name: \"signer\", type: \"address\", internalType: \"address\" },],stateMutability: \"view\",},{type: \"function\",name: \"withdrawDepositTo\",inputs: [{name: \"withdrawAddress\",type: \"address\",internalType: \"address payable\",},{ name: \"amount\", type: \"uint256\", internalType: \"uint256\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"event\",name: \"AdminUpdated\",inputs: [{name: \"signer\",type: \"address\",indexed: true,internalType: \"address\",},{ name: \"isAdmin\", type: \"bool\", indexed: false, internalType: \"bool\" },],anonymous: false,},{type: \"event\",name: \"ContractURIUpdated\",inputs: [{name: \"prevURI\",type: \"string\",indexed: false,internalType: \"string\",},{name: \"newURI\",type: \"string\",indexed: false,internalType: \"string\",},],anonymous: false,},{type: \"event\",name: \"Initialized\",inputs: [{ name: \"version\", type: \"uint8\", indexed: false, internalType: \"uint8\" },],anonymous: false,},{type: \"event\",name: \"SignerPermissionsUpdated\",inputs: [{name: \"authorizingSigner\",type: \"address\",indexed: true,internalType: \"address\",},{name: \"targetSigner\",type: \"address\",indexed: true,internalType: \"address\",},{name: \"permissions\",type: \"tuple\",indexed: false,internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},],anonymous: false,},]" - ); - } - - return new SmartWallet(client, personalWallet, gasless, chainId, bundlerUrl, paymasterUrl, entryPointContract, factoryContract, accountContract, zkSyncPaymasterContract); + var entryPointContract = await ThirdwebContract.Create( + client, + entryPoint, + chainId, + "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]" + ); + var factoryContract = await ThirdwebContract.Create( + client, + factoryAddress, + chainId, + "[{\"type\": \"constructor\",\"name\": \"\",\"inputs\": [{\"type\": \"address\",\"name\": \"_defaultAdmin\",\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"_entrypoint\",\"internalType\": \"contract IEntryPoint\"},{\"type\": \"tuple[]\",\"name\": \"_defaultExtensions\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension[]\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"error\",\"name\": \"InvalidCodeAtRange\",\"inputs\": [{\"type\": \"uint256\",\"name\": \"_size\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_start\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_end\",\"internalType\": \"uint256\"}],\"outputs\": []},{\"type\": \"error\",\"name\": \"WriteError\",\"inputs\": [],\"outputs\": []},{\"type\": \"event\",\"name\": \"AccountCreated\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"accountAdmin\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ContractURIUpdated\",\"inputs\": [{\"type\": \"string\",\"name\": \"prevURI\",\"indexed\": false,\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"newURI\",\"indexed\": false,\"internalType\": \"string\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionAdded\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionRemoved\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"ExtensionReplaced\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"tuple\",\"name\": \"extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"indexed\": false,\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"FunctionDisabled\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"indexed\": true,\"internalType\": \"bytes4\"},{\"type\": \"tuple\",\"name\": \"extMetadata\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"FunctionEnabled\",\"inputs\": [{\"type\": \"string\",\"name\": \"name\",\"indexed\": true,\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"indexed\": true,\"internalType\": \"bytes4\"},{\"type\": \"tuple\",\"name\": \"extFunction\",\"components\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"},{\"type\": \"string\",\"name\": \"functionSignature\",\"internalType\": \"string\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionFunction\"},{\"type\": \"tuple\",\"name\": \"extMetadata\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"indexed\": false,\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleAdminChanged\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"previousAdminRole\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"newAdminRole\",\"indexed\": true,\"internalType\": \"bytes32\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleGranted\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"sender\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"RoleRevoked\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"indexed\": true,\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"sender\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"SignerAdded\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"signer\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"SignerRemoved\",\"inputs\": [{\"type\": \"address\",\"name\": \"account\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"signer\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"fallback\",\"name\": \"\",\"inputs\": [],\"outputs\": [],\"stateMutability\": \"payable\"},{\"type\": \"function\",\"name\": \"DEFAULT_ADMIN_ROLE\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"_disableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"accountImplementation\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"addExtension\",\"inputs\": [{\"type\": \"tuple\",\"name\": \"_extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"contractURI\",\"inputs\": [],\"outputs\": [{\"type\": \"string\",\"name\": \"\",\"internalType\": \"string\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"createAccount\",\"inputs\": [{\"type\": \"address\",\"name\": \"_admin\",\"internalType\": \"address\"},{\"type\": \"bytes\",\"name\": \"_data\",\"internalType\": \"bytes\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"defaultExtensions\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"disableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"enableFunctionInExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"},{\"type\": \"tuple\",\"name\": \"_function\",\"components\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"},{\"type\": \"string\",\"name\": \"functionSignature\",\"internalType\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"entrypoint\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAccounts\",\"inputs\": [{\"type\": \"uint256\",\"name\": \"_start\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"_end\",\"internalType\": \"uint256\"}],\"outputs\": [{\"type\": \"address[]\",\"name\": \"accounts\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAccountsOfSigner\",\"inputs\": [{\"type\": \"address\",\"name\": \"signer\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"address[]\",\"name\": \"accounts\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAddress\",\"inputs\": [{\"type\": \"address\",\"name\": \"_adminSigner\",\"internalType\": \"address\"},{\"type\": \"bytes\",\"name\": \"_data\",\"internalType\": \"bytes\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAllAccounts\",\"inputs\": [],\"outputs\": [{\"type\": \"address[]\",\"name\": \"\",\"internalType\": \"address[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getAllExtensions\",\"inputs\": [],\"outputs\": [{\"type\": \"tuple[]\",\"name\": \"allExtensions\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"extensionName\",\"internalType\": \"string\"}],\"outputs\": [{\"type\": \"tuple\",\"name\": \"\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getImplementationForFunction\",\"inputs\": [{\"type\": \"bytes4\",\"name\": \"_functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getMetadataForFunction\",\"inputs\": [{\"type\": \"bytes4\",\"name\": \"functionSelector\",\"internalType\": \"bytes4\"}],\"outputs\": [{\"type\": \"tuple\",\"name\": \"\",\"components\": [{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"metadataURI\",\"internalType\": \"string\"},{\"type\": \"address\",\"name\": \"implementation\",\"internalType\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleAdmin\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"}],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleMember\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"uint256\",\"name\": \"index\",\"internalType\": \"uint256\"}],\"outputs\": [{\"type\": \"address\",\"name\": \"member\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"getRoleMemberCount\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"}],\"outputs\": [{\"type\": \"uint256\",\"name\": \"count\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"grantRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"hasRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"hasRoleWithSwitch\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"isRegistered\",\"inputs\": [{\"type\": \"address\",\"name\": \"_account\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"bool\",\"name\": \"\",\"internalType\": \"bool\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"multicall\",\"inputs\": [{\"type\": \"bytes[]\",\"name\": \"data\",\"internalType\": \"bytes[]\"}],\"outputs\": [{\"type\": \"bytes[]\",\"name\": \"results\",\"internalType\": \"bytes[]\"}],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onRegister\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onSignerAdded\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"onSignerRemoved\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"_salt\",\"internalType\": \"bytes32\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"removeExtension\",\"inputs\": [{\"type\": \"string\",\"name\": \"_extensionName\",\"internalType\": \"string\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"renounceRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"replaceExtension\",\"inputs\": [{\"type\": \"tuple\",\"name\": \"_extension\",\"components\": [{\"type\": \"tuple\",\"name\": \"metadata\",\"components\": [{\"internalType\": \"string\",\"name\": \"name\",\"type\": \"string\"},{\"internalType\": \"string\",\"name\": \"metadataURI\",\"type\": \"string\"},{\"internalType\": \"address\",\"name\": \"implementation\",\"type\": \"address\"}],\"internalType\": \"struct IExtension.ExtensionMetadata\"},{\"type\": \"tuple[]\",\"name\": \"functions\",\"components\": [{\"internalType\": \"bytes4\",\"name\": \"functionSelector\",\"type\": \"bytes4\"},{\"internalType\": \"string\",\"name\": \"functionSignature\",\"type\": \"string\"}],\"internalType\": \"struct IExtension.ExtensionFunction[]\"}],\"internalType\": \"struct IExtension.Extension\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"revokeRole\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"role\",\"internalType\": \"bytes32\"},{\"type\": \"address\",\"name\": \"account\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"setContractURI\",\"inputs\": [{\"type\": \"string\",\"name\": \"_uri\",\"internalType\": \"string\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"totalAccounts\",\"inputs\": [],\"outputs\": [{\"type\": \"uint256\",\"name\": \"\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"}]" + ); + var accountAddress = accountAddressOverride ?? await ThirdwebContract.Read(factoryContract, "getAddress", await personalWallet.GetAddress(), new byte[0]); + var accountContract = await ThirdwebContract.Create( + client, + accountAddress, + chainId, + "[{type: \"constructor\",inputs: [{name: \"_entrypoint\",type: \"address\",internalType: \"contract IEntryPoint\",},{ name: \"_factory\", type: \"address\", internalType: \"address\" },],stateMutability: \"nonpayable\",},{ type: \"receive\", stateMutability: \"payable\" },{type: \"function\",name: \"addDeposit\",inputs: [],outputs: [],stateMutability: \"payable\",},{type: \"function\",name: \"contractURI\",inputs: [],outputs: [{ name: \"\", type: \"string\", internalType: \"string\" }],stateMutability: \"view\",},{type: \"function\",name: \"entryPoint\",inputs: [],outputs: [{ name: \"\", type: \"address\", internalType: \"contract IEntryPoint\" },],stateMutability: \"view\",},{type: \"function\",name: \"execute\",inputs: [{ name: \"_target\", type: \"address\", internalType: \"address\" },{ name: \"_value\", type: \"uint256\", internalType: \"uint256\" },{ name: \"_calldata\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"executeBatch\",inputs: [{ name: \"_target\", type: \"address[]\", internalType: \"address[]\" },{ name: \"_value\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"_calldata\", type: \"bytes[]\", internalType: \"bytes[]\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"factory\",inputs: [],outputs: [{ name: \"\", type: \"address\", internalType: \"address\" }],stateMutability: \"view\",},{type: \"function\",name: \"getAllActiveSigners\",inputs: [],outputs: [{name: \"signers\",type: \"tuple[]\",internalType: \"struct IAccountPermissions.SignerPermissions[]\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"getAllAdmins\",inputs: [],outputs: [{ name: \"\", type: \"address[]\", internalType: \"address[]\" }],stateMutability: \"view\",},{type: \"function\",name: \"getAllSigners\",inputs: [],outputs: [{name: \"signers\",type: \"tuple[]\",internalType: \"struct IAccountPermissions.SignerPermissions[]\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"getMessageHash\",inputs: [{ name: \"_hash\", type: \"bytes32\", internalType: \"bytes32\" }],outputs: [{ name: \"\", type: \"bytes32\", internalType: \"bytes32\" }],stateMutability: \"view\",},{type: \"function\",name: \"getNonce\",inputs: [],outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],stateMutability: \"view\",},{type: \"function\",name: \"getPermissionsForSigner\",inputs: [{ name: \"signer\", type: \"address\", internalType: \"address\" }],outputs: [{name: \"\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissions\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{ name: \"startTimestamp\", type: \"uint128\", internalType: \"uint128\" },{ name: \"endTimestamp\", type: \"uint128\", internalType: \"uint128\" },],},],stateMutability: \"view\",},{type: \"function\",name: \"initialize\",inputs: [{ name: \"_defaultAdmin\", type: \"address\", internalType: \"address\" },{ name: \"_data\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"isActiveSigner\",inputs: [{ name: \"signer\", type: \"address\", internalType: \"address\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"isAdmin\",inputs: [{ name: \"_account\", type: \"address\", internalType: \"address\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"isValidSignature\",inputs: [{ name: \"_hash\", type: \"bytes32\", internalType: \"bytes32\" },{ name: \"_signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"magicValue\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"view\",},{type: \"function\",name: \"isValidSigner\",inputs: [{ name: \"_signer\", type: \"address\", internalType: \"address\" },{name: \"_userOp\",type: \"tuple\",internalType: \"struct UserOperation\",components: [{ name: \"sender\", type: \"address\", internalType: \"address\" },{ name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },{ name: \"initCode\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callGasLimit\", type: \"uint256\", internalType: \"uint256\" },{name: \"verificationGasLimit\",type: \"uint256\",internalType: \"uint256\",},{name: \"preVerificationGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"maxFeePerGas\", type: \"uint256\", internalType: \"uint256\" },{name: \"maxPriorityFeePerGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"paymasterAndData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],},],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"multicall\",inputs: [{ name: \"data\", type: \"bytes[]\", internalType: \"bytes[]\" }],outputs: [{ name: \"results\", type: \"bytes[]\", internalType: \"bytes[]\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC1155BatchReceived\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"\", type: \"uint256[]\", internalType: \"uint256[]\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC1155Received\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"onERC721Received\",inputs: [{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"address\", internalType: \"address\" },{ name: \"\", type: \"uint256\", internalType: \"uint256\" },{ name: \"\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"\", type: \"bytes4\", internalType: \"bytes4\" }],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setContractURI\",inputs: [{ name: \"_uri\", type: \"string\", internalType: \"string\" }],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setEntrypointOverride\",inputs: [{name: \"_entrypointOverride\",type: \"address\",internalType: \"contract IEntryPoint\",},],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"setPermissionsForSigner\",inputs: [{name: \"_req\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},{ name: \"_signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"function\",name: \"supportsInterface\",inputs: [{ name: \"interfaceId\", type: \"bytes4\", internalType: \"bytes4\" }],outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],stateMutability: \"view\",},{type: \"function\",name: \"validateUserOp\",inputs: [{name: \"userOp\",type: \"tuple\",internalType: \"struct UserOperation\",components: [{ name: \"sender\", type: \"address\", internalType: \"address\" },{ name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },{ name: \"initCode\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"callGasLimit\", type: \"uint256\", internalType: \"uint256\" },{name: \"verificationGasLimit\",type: \"uint256\",internalType: \"uint256\",},{name: \"preVerificationGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"maxFeePerGas\", type: \"uint256\", internalType: \"uint256\" },{name: \"maxPriorityFeePerGas\",type: \"uint256\",internalType: \"uint256\",},{ name: \"paymasterAndData\", type: \"bytes\", internalType: \"bytes\" },{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],},{ name: \"userOpHash\", type: \"bytes32\", internalType: \"bytes32\" },{ name: \"missingAccountFunds\", type: \"uint256\", internalType: \"uint256\" },],outputs: [{ name: \"validationData\", type: \"uint256\", internalType: \"uint256\" },],stateMutability: \"nonpayable\",},{type: \"function\",name: \"verifySignerPermissionRequest\",inputs: [{name: \"req\",type: \"tuple\",internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},{ name: \"signature\", type: \"bytes\", internalType: \"bytes\" },],outputs: [{ name: \"success\", type: \"bool\", internalType: \"bool\" },{ name: \"signer\", type: \"address\", internalType: \"address\" },],stateMutability: \"view\",},{type: \"function\",name: \"withdrawDepositTo\",inputs: [{name: \"withdrawAddress\",type: \"address\",internalType: \"address payable\",},{ name: \"amount\", type: \"uint256\", internalType: \"uint256\" },],outputs: [],stateMutability: \"nonpayable\",},{type: \"event\",name: \"AdminUpdated\",inputs: [{name: \"signer\",type: \"address\",indexed: true,internalType: \"address\",},{ name: \"isAdmin\", type: \"bool\", indexed: false, internalType: \"bool\" },],anonymous: false,},{type: \"event\",name: \"ContractURIUpdated\",inputs: [{name: \"prevURI\",type: \"string\",indexed: false,internalType: \"string\",},{name: \"newURI\",type: \"string\",indexed: false,internalType: \"string\",},],anonymous: false,},{type: \"event\",name: \"Initialized\",inputs: [{ name: \"version\", type: \"uint8\", indexed: false, internalType: \"uint8\" },],anonymous: false,},{type: \"event\",name: \"SignerPermissionsUpdated\",inputs: [{name: \"authorizingSigner\",type: \"address\",indexed: true,internalType: \"address\",},{name: \"targetSigner\",type: \"address\",indexed: true,internalType: \"address\",},{name: \"permissions\",type: \"tuple\",indexed: false,internalType: \"struct IAccountPermissions.SignerPermissionRequest\",components: [{ name: \"signer\", type: \"address\", internalType: \"address\" },{ name: \"isAdmin\", type: \"uint8\", internalType: \"uint8\" },{name: \"approvedTargets\",type: \"address[]\",internalType: \"address[]\",},{name: \"nativeTokenLimitPerTransaction\",type: \"uint256\",internalType: \"uint256\",},{name: \"permissionStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"permissionEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityStartTimestamp\",type: \"uint128\",internalType: \"uint128\",},{name: \"reqValidityEndTimestamp\",type: \"uint128\",internalType: \"uint128\",},{ name: \"uid\", type: \"bytes32\", internalType: \"bytes32\" },],},],anonymous: false,},]" + ); + + return new SmartWallet(client, personalWallet, gasless, chainId, bundlerUrl, paymasterUrl, entryPointContract, factoryContract, accountContract); } public async Task IsDeployed() { - if (IsZkSync) - { - return true; - } - var code = await ThirdwebRPC.GetRpcInstance(_client, _chainId).SendRequestAsync("eth_getCode", _accountContract.Address, "latest"); return code != "0x"; } - public async Task SendTransaction(ThirdwebTransactionInput transactionInput) + public async Task SendTransaction(ThirdwebTransactionInput transaction) { - if (transactionInput == null) + if (transaction == null) { throw new InvalidOperationException("SmartAccount.SendTransaction: Transaction input is required."); } - - if (IsZkSync) - { - var paymaster = _gasless ? _zkSyncPaymaster.Address : null; - var paymasterInput = await GetPaymasterInput(transactionInput); - var transaction = await ThirdwebTransaction.Create(_client, _personalAccount, transactionInput, _chainId); - return await ThirdwebTransaction.Send(transaction, paymaster, paymasterInput.ToHex(true)); - } - else - { - var signedOp = await SignUserOp(transactionInput); - return await SendUserOp(signedOp); - } + var signedOp = await SignUserOp(transaction); + return await SendUserOp(signedOp); } private async Task GetInitCode() @@ -244,19 +206,6 @@ private async Task GetNonce() return await ThirdwebContract.Read(_entryPointContract, "getNonce", await GetAddress(), randomInt192); } - private async Task GetPaymasterInput(ThirdwebTransactionInput transactionInput) - { - if (_gasless) - { - var paymasterInput = await BundlerClient.PMSponsorTransaction(_client, _paymasterUrl, 1, transactionInput, _entryPointContract.Address); - return paymasterInput.paymasterInput.HexToByteArray(); - } - else - { - return new byte[] { }; - } - } - private async Task GetPaymasterAndData(object requestId, UserOperationHexified userOp) { if (_gasless) @@ -297,11 +246,6 @@ private UserOperationHexified EncodeUserOperation(UserOperation userOperation) public async Task ForceDeploy() { - if (IsZkSync) - { - return; - } - var input = new ThirdwebTransactionInput() { Data = "0x", @@ -317,9 +261,9 @@ public Task GetPersonalAccount() return Task.FromResult(_personalAccount); } - public async Task GetAddress() + public Task GetAddress() { - return IsZkSync ? await _personalAccount.GetAddress() : _accountContract.Address; + return Task.FromResult(_accountContract.Address); } public Task EthSign(byte[] rawMessage) @@ -339,11 +283,6 @@ public Task PersonalSign(byte[] rawMessage) public async Task PersonalSign(string message) { - if (IsZkSync) - { - return await _personalAccount.PersonalSign(message); - } - if (!await IsDeployed()) { Console.WriteLine("SmartWallet not deployed, deploying before signing..."); @@ -400,11 +339,6 @@ public async Task CreateSessionKey( string reqValidityEndTimestamp ) { - if (IsZkSync) - { - throw new Exception("Account Permissions are not supported in ZkSync"); - } - var request = new SignerPermissionRequest() { Signer = signerAddress, @@ -433,11 +367,6 @@ string reqValidityEndTimestamp public async Task AddAdmin(string admin) { - if (IsZkSync) - { - throw new Exception("Account Permissions are not supported in ZkSync"); - } - var request = new SignerPermissionRequest() { Signer = admin, @@ -466,11 +395,6 @@ public async Task AddAdmin(string admin) public async Task RemoveAdmin(string admin) { - if (IsZkSync) - { - throw new Exception("Account Permissions are not supported in ZkSync"); - } - var request = new SignerPermissionRequest() { Signer = admin, @@ -510,11 +434,6 @@ public Task SignTypedDataV4(T data, TypedData typed public async Task EstimateUserOperationGas(ThirdwebTransactionInput transaction, BigInteger chainId) { - if (IsZkSync) - { - throw new Exception("User Operations are not supported in ZkSync"); - } - var signedOp = await SignUserOp(transaction); var cost = signedOp.CallGasLimit + signedOp.VerificationGasLimit + signedOp.PreVerificationGas; return cost; @@ -522,17 +441,12 @@ public async Task EstimateUserOperationGas(ThirdwebTransactionInput public async Task SignTransaction(ThirdwebTransactionInput transaction, BigInteger chainId) { - if (IsZkSync) - { - throw new Exception("Offline Signing is not supported in ZkSync"); - } - return JsonConvert.SerializeObject(EncodeUserOperation(await SignUserOp(transaction))); } - public async Task IsConnected() + public Task IsConnected() { - return IsZkSync ? await _personalAccount.IsConnected() : _accountContract != null; + return Task.FromResult(_accountContract != null); } public Task Disconnect() diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs index f3f3bab..1a246f4 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs @@ -91,11 +91,6 @@ public class PMSponsorOperationResponse public string paymasterAndData { get; set; } } - public class PMSponsorTransactionResponse - { - public string paymasterInput { get; set; } - } - public class ThirdwebGetUserOperationGasPriceResponse { public string maxFeePerGas { get; set; } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs index 9744b47..0a00caa 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs @@ -42,19 +42,6 @@ public static async Task ThirdwebGetUs // Paymaster requests - public static async Task PMSponsorTransaction(ThirdwebClient client, string paymasterUrl, object requestId, ThirdwebTransactionInput userOp, string entryPoint) - { - var response = await BundlerRequest(client, paymasterUrl, requestId, "pm_sponsorTransaction", userOp, new EntryPointWrapper() { entryPoint = entryPoint }); - try - { - return JsonConvert.DeserializeObject(response.Result.ToString()); - } - catch - { - return new PMSponsorTransactionResponse() { paymasterInput = response.Result.ToString() }; - } - } - public static async Task PMSponsorUserOperation(ThirdwebClient client, string paymasterUrl, object requestId, UserOperationHexified userOp, string entryPoint) { var response = await BundlerRequest(client, paymasterUrl, requestId, "pm_sponsorUserOperation", userOp, new EntryPointWrapper() { entryPoint = entryPoint }); From 13085549b68b071c7249f51cdd8c7e6a342ee81c Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Thu, 23 May 2024 15:44:21 +0300 Subject: [PATCH 17/23] Move zksyncoptions to type, use zk rpc fees --- Thirdweb.Console/Program.cs | 31 ++++++++------- Thirdweb.Tests/Thirdweb.Contracts.Tests.cs | 15 +++++-- .../Thirdweb.PrivateKeyWallet.Tests.cs | 7 +--- .../ThirdwebTransaction.cs | 39 +++++++++++++++---- .../ThirdwebTransactionInput.cs | 27 +++++++++++++ .../Thirdweb.AccountAbstraction/AATypes.cs | 2 +- 6 files changed, 90 insertions(+), 31 deletions(-) diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs index b4b48e6..689e7fb 100644 --- a/Thirdweb.Console/Program.cs +++ b/Thirdweb.Console/Program.cs @@ -64,28 +64,31 @@ // } } -// Test 113 +// Prepare a transaction directly, or with Contract.Prepare var tx = await ThirdwebTransaction.Create( - client, - privateKeyWallet, - new ThirdwebTransactionInput() + client: client, + wallet: privateKeyWallet, + txInput: new ThirdwebTransactionInput() { From = await privateKeyWallet.GetAddress(), To = await privateKeyWallet.GetAddress(), Value = new HexBigInteger(BigInteger.Zero), - Data = "0x", - MaxFeePerGas = new HexBigInteger(25000000), - MaxPriorityFeePerGas = new HexBigInteger(25000000), - Gas = new HexBigInteger(20000000), - ChainId = new HexBigInteger(300), }, - 300 + chainId: 300 ); -var txHash = await ThirdwebTransaction.Send( - transaction: tx, - zkSyncPaymaster: "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", - zkSyncPaymasterInput: "0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000" + +// Set zkSync options +tx.SetZkSyncOptions( + new ZkSyncOptions( + // Paymaster contract address + paymaster: "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", + // IPaymasterFlow interface encoded data + paymasterInput: "0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000" + ) ); + +// Send as usual, it's now gasless! +var txHash = await ThirdwebTransaction.Send(transaction: tx); Console.WriteLine($"Transaction hash: {txHash}"); diff --git a/Thirdweb.Tests/Thirdweb.Contracts.Tests.cs b/Thirdweb.Tests/Thirdweb.Contracts.Tests.cs index 83f9b64..dd2f7eb 100644 --- a/Thirdweb.Tests/Thirdweb.Contracts.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Contracts.Tests.cs @@ -116,10 +116,17 @@ public async Task WriteTest_PrivateKeyAccount() var pricePerToken = BigInteger.Zero; var allowlistProof = new object[] { new byte[] { }, BigInteger.Zero, BigInteger.Zero, Constants.ADDRESS_ZERO }; var data = new byte[] { }; - var exception = await Assert.ThrowsAsync( - async () => await ThirdwebContract.Write(privateKeyAccount, contract, "claim", 0, receiver, quantity, currency, pricePerToken, allowlistProof, data) - ); - Assert.Contains("insufficient funds", exception.Message); + try + { + var res = await ThirdwebContract.Write(privateKeyAccount, contract, "claim", 0, receiver, quantity, currency, pricePerToken, allowlistProof, data); + Assert.NotNull(res); + Assert.NotNull(res.TransactionHash); + Assert.Equal(66, res.TransactionHash.Length); + } + catch (Exception ex) + { + Assert.Contains("insufficient funds", ex.Message); + } } private async Task GetAccount() diff --git a/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs b/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs index a74fc70..507d065 100644 --- a/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs @@ -59,7 +59,7 @@ public async Task EthSign_Success() public async Task EthSign_NullMessage() { var account = await GetAccount(); - var ex = await Assert.ThrowsAsync(() => account.EthSign(null)); + var ex = await Assert.ThrowsAsync(() => account.EthSign(null as string)); Assert.Equal("Message to sign cannot be null. (Parameter 'message')", ex.Message); } @@ -241,7 +241,7 @@ public async Task SignTransaction_NoGasPrice() Nonce = new HexBigInteger(99999999999) }; var ex = await Assert.ThrowsAsync(() => account.SignTransaction(transaction, 421614)); - Assert.Equal("Transaction gas price must be set for legacy transactions", ex.Message); + Assert.Equal("Transaction MaxPriorityFeePerGas and MaxFeePerGas must be set for EIP-1559 transactions", ex.Message); } [Fact] @@ -256,7 +256,6 @@ public async Task SignTransaction_1559_Success() Gas = new HexBigInteger(21000), Data = "0x", Nonce = new HexBigInteger(99999999999), - Type = new HexBigInteger(2), MaxFeePerGas = new HexBigInteger(10000000000), MaxPriorityFeePerGas = new HexBigInteger(10000000000) }; @@ -276,7 +275,6 @@ public async Task SignTransaction_1559_NoMaxFeePerGas() Gas = new HexBigInteger(21000), Data = "0x", Nonce = new HexBigInteger(99999999999), - Type = new HexBigInteger(2), MaxPriorityFeePerGas = new HexBigInteger(10000000000) }; var ex = await Assert.ThrowsAsync(() => account.SignTransaction(transaction, 421614)); @@ -295,7 +293,6 @@ public async Task SignTransaction_1559_NoMaxPriorityFeePerGas() Gas = new HexBigInteger(21000), Data = "0x", Nonce = new HexBigInteger(99999999999), - Type = new HexBigInteger(2), MaxFeePerGas = new HexBigInteger(10000000000) }; var ex = await Assert.ThrowsAsync(() => account.SignTransaction(transaction, 421614)); diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index b98c469..d222d6c 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -87,6 +87,12 @@ public ThirdwebTransaction SetNonce(BigInteger nonce) return this; } + public ThirdwebTransaction SetZkSyncOptions(ZkSyncOptions zkSyncOptions) + { + Input.ZkSync = zkSyncOptions; + return this; + } + public static async Task EstimateGasCosts(ThirdwebTransaction transaction) { var gasPrice = transaction.Input.GasPrice?.Value ?? await EstimateGasPrice(transaction); @@ -113,6 +119,15 @@ public static async Task EstimateGasPrice(ThirdwebTransaction transa { var rpc = ThirdwebRPC.GetRpcInstance(transaction._client, transaction.Input.ChainId.Value); var chainId = transaction.Input.ChainId.Value; + + if (IsZkSyncTransaction(transaction)) + { + var fees = await rpc.SendRequestAsync("zks_estimateFee", transaction.Input, "latest"); + var maxFee = fees["max_fee_per_gas"].ToObject().Value; + var maxPriorityFee = fees["max_priority_fee_per_gas"].ToObject().Value; + return (maxFee, maxPriorityFee == 0 ? maxFee : maxPriorityFee); + } + var gasPrice = await EstimateGasPrice(transaction, withBump); try @@ -164,7 +179,9 @@ public static async Task EstimateGasLimit(ThirdwebTransaction transa else { var rpc = ThirdwebRPC.GetRpcInstance(transaction._client, transaction.Input.ChainId.Value); - var hex = await rpc.SendRequestAsync("eth_estimateGas", transaction.Input, "latest"); + var hex = IsZkSyncTransaction(transaction) + ? (await rpc.SendRequestAsync("zks_estimateFee", transaction.Input, "latest"))["gas_limit"].ToString() + : await rpc.SendRequestAsync("eth_estimateGas", transaction.Input, "latest"); return new HexBigInteger(hex).Value; } } @@ -174,7 +191,7 @@ public static async Task Sign(ThirdwebTransaction transaction) return await transaction._wallet.SignTransaction(transaction.Input, transaction.Input.ChainId.Value); } - public static async Task Send(ThirdwebTransaction transaction, string zkSyncPaymaster = null, string zkSyncPaymasterInput = null) + public static async Task Send(ThirdwebTransaction transaction) { if (transaction.Input.To == null) { @@ -204,8 +221,7 @@ public static async Task Send(ThirdwebTransaction transaction, string zk var rpc = ThirdwebRPC.GetRpcInstance(transaction._client, transaction.Input.ChainId.Value); string hash; - var isZkAA = zkSyncPaymaster != null && zkSyncPaymasterInput != null; - if (isZkAA && (transaction.Input.ChainId.Value.Equals(324) || transaction.Input.ChainId.Value.Equals(300))) + if (IsZkSyncTransaction(transaction)) { var zkTx = new AccountAbstraction.ZkSyncAATransaction { @@ -216,13 +232,14 @@ public static async Task Send(ThirdwebTransaction transaction, string zk GasPerPubdataByteLimit = 50000, MaxFeePerGas = transaction.Input.MaxFeePerGas?.Value ?? transaction.Input.GasPrice.Value, MaxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas?.Value ?? transaction.Input.GasPrice.Value, - Paymaster = new HexBigInteger(zkSyncPaymaster).Value, + Paymaster = transaction.Input.ZkSync.Paymaster, Nonce = transaction.Input.Nonce ?? new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", transaction.Input.From, "latest")), Value = transaction.Input.Value.Value, Data = transaction.Input.Data.HexToByteArray(), - FactoryDeps = new byte[] { }, - PaymasterInput = zkSyncPaymasterInput.HexToByteArray() + FactoryDeps = transaction.Input.ZkSync.FactoryDeps, + PaymasterInput = transaction.Input.ZkSync.PaymasterInput }; + Console.WriteLine("zkTx: " + JsonConvert.SerializeObject(zkTx)); var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet); hash = await rpc.SendRequestAsync("eth_sendRawTransaction", zkTxSigned); } @@ -295,5 +312,13 @@ public static async Task WaitForTransactionReceipt(ThirdwebC return receipt; } + + private static bool IsZkSyncTransaction(ThirdwebTransaction transaction) + { + return (transaction.Input.ChainId.Value.Equals(324) || transaction.Input.ChainId.Value.Equals(300)) + && transaction.Input.ZkSync != null + && transaction.Input.ZkSync.Paymaster != 0 + && transaction.Input.ZkSync.PaymasterInput != null; + } } } diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs index 2f31a68..d594c95 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs @@ -1,3 +1,4 @@ +using System.Numerics; using Nethereum.Hex.HexConvertors.Extensions; using Nethereum.Hex.HexTypes; using Newtonsoft.Json; @@ -53,5 +54,31 @@ public string Data [JsonProperty(PropertyName = "chainId")] public HexBigInteger ChainId { get; set; } + + [JsonProperty(PropertyName = "zkSyncOptions", NullValueHandling = NullValueHandling.Ignore)] + public ZkSyncOptions ZkSync { get; set; } + } + + public class ZkSyncOptions + { + [JsonProperty(PropertyName = "gasPerPubdataByteLimit")] + public BigInteger GasPerPubdataByteLimit { get; set; } + + [JsonProperty(PropertyName = "factoryDeps")] + public List FactoryDeps { get; set; } + + [JsonProperty(PropertyName = "paymaster")] + public BigInteger Paymaster { get; set; } + + [JsonProperty(PropertyName = "paymasterInput")] + public byte[] PaymasterInput { get; set; } + + public ZkSyncOptions(string paymaster, string paymasterInput, BigInteger? gasPerPubdataByteLimit = null, List factoryDeps = null) + { + Paymaster = new HexBigInteger(paymaster).Value; + PaymasterInput = paymasterInput.HexToByteArray(); + GasPerPubdataByteLimit = gasPerPubdataByteLimit ?? new BigInteger(50000); + FactoryDeps = factoryDeps ?? new List(); + } } } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs index 1a246f4..6b1591f 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs @@ -211,7 +211,7 @@ public class ZkSyncAATransaction public virtual byte[] Data { get; set; } [Parameter("bytes32[]", "factoryDeps", 12)] - public virtual byte[] FactoryDeps { get; set; } + public virtual List FactoryDeps { get; set; } [Parameter("bytes", "paymasterInput", 13)] public virtual byte[] PaymasterInput { get; set; } From 4b8f3a235abe7f4a15e6b50f16c1ff8650af2e92 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Thu, 23 May 2024 15:57:09 +0300 Subject: [PATCH 18/23] Setters and Tests --- Thirdweb.Tests/Thirdweb.Transactions.Tests.cs | 24 +++++++++++++-- .../ThirdwebTransaction.cs | 30 +++++++++++++++---- .../ThirdwebTransactionInput.cs | 4 +-- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs index fccb480..dd629ed 100644 --- a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs @@ -13,7 +13,7 @@ private async Task CreateSampleTransaction() { var client = ThirdwebClient.Create(secretKey: _secretKey); var wallet = await PrivateKeyWallet.Create(client, _testPrivateKey); - var chainId = new BigInteger(1); + var chainId = new BigInteger(421614); var transaction = await ThirdwebTransaction.Create(client, wallet, new ThirdwebTransactionInput(), chainId); return transaction; @@ -25,7 +25,7 @@ public async Task Create_ValidatesInputParameters() var client = ThirdwebClient.Create(secretKey: _secretKey); var wallet = await PrivateKeyWallet.Create(client, _testPrivateKey); var txInput = new ThirdwebTransactionInput() { From = await wallet.GetAddress() }; - var chainId = new BigInteger(1); + var chainId = new BigInteger(421614); var transaction = await ThirdwebTransaction.Create(client, wallet, txInput, chainId); Assert.NotNull(transaction); } @@ -132,6 +132,26 @@ public async Task Send_CorrectlyHandlesNonce() Assert.Equal("123", transaction.Input.Nonce.Value.ToString()); } + [Fact] + public async Task Send_ZkSync_TransfersGaslessly() + { + var transaction = await CreateSampleTransaction(); + _ = transaction.SetChainId(300); + _ = transaction.SetTo("0xbA226d47Cbb2731CBAA67C916c57d68484AA269F"); + _ = transaction.SetValue(BigInteger.Zero); + _ = transaction.SetZkSyncOptions( + new ZkSyncOptions( + paymaster: "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", + paymasterInput: "0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", + gasPerPubdataByteLimit: 50000, + factoryDeps: new List() + ) + ); + var receipt = await ThirdwebTransaction.SendAndWaitForTransactionReceipt(transaction); + Assert.NotNull(receipt); + Assert.StartsWith("0x", receipt.TransactionHash); + } + [Fact] public async Task EstimateTotalCosts_CalculatesCostsCorrectly() { diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index d222d6c..19a2282 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -87,6 +87,24 @@ public ThirdwebTransaction SetNonce(BigInteger nonce) return this; } + public ThirdwebTransaction SetMaxFeePerGas(BigInteger maxFeePerGas) + { + Input.MaxFeePerGas = maxFeePerGas.ToHexBigInteger(); + return this; + } + + public ThirdwebTransaction SetMaxPriorityFeePerGas(BigInteger maxPriorityFeePerGas) + { + Input.MaxPriorityFeePerGas = maxPriorityFeePerGas.ToHexBigInteger(); + return this; + } + + public ThirdwebTransaction SetChainId(BigInteger chainId) + { + Input.ChainId = chainId.ToHexBigInteger(); + return this; + } + public ThirdwebTransaction SetZkSyncOptions(ZkSyncOptions zkSyncOptions) { Input.ZkSync = zkSyncOptions; @@ -232,12 +250,12 @@ public static async Task Send(ThirdwebTransaction transaction) GasPerPubdataByteLimit = 50000, MaxFeePerGas = transaction.Input.MaxFeePerGas?.Value ?? transaction.Input.GasPrice.Value, MaxPriorityFeePerGas = transaction.Input.MaxPriorityFeePerGas?.Value ?? transaction.Input.GasPrice.Value, - Paymaster = transaction.Input.ZkSync.Paymaster, + Paymaster = transaction.Input.ZkSync.Value.Paymaster, Nonce = transaction.Input.Nonce ?? new HexBigInteger(await rpc.SendRequestAsync("eth_getTransactionCount", transaction.Input.From, "latest")), Value = transaction.Input.Value.Value, Data = transaction.Input.Data.HexToByteArray(), - FactoryDeps = transaction.Input.ZkSync.FactoryDeps, - PaymasterInput = transaction.Input.ZkSync.PaymasterInput + FactoryDeps = transaction.Input.ZkSync.Value.FactoryDeps, + PaymasterInput = transaction.Input.ZkSync.Value.PaymasterInput }; Console.WriteLine("zkTx: " + JsonConvert.SerializeObject(zkTx)); var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet); @@ -316,9 +334,9 @@ public static async Task WaitForTransactionReceipt(ThirdwebC private static bool IsZkSyncTransaction(ThirdwebTransaction transaction) { return (transaction.Input.ChainId.Value.Equals(324) || transaction.Input.ChainId.Value.Equals(300)) - && transaction.Input.ZkSync != null - && transaction.Input.ZkSync.Paymaster != 0 - && transaction.Input.ZkSync.PaymasterInput != null; + && transaction.Input.ZkSync.HasValue + && transaction.Input.ZkSync.Value.Paymaster != 0 + && transaction.Input.ZkSync.Value.PaymasterInput != null; } } } diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs index d594c95..6b15368 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs @@ -56,10 +56,10 @@ public string Data public HexBigInteger ChainId { get; set; } [JsonProperty(PropertyName = "zkSyncOptions", NullValueHandling = NullValueHandling.Ignore)] - public ZkSyncOptions ZkSync { get; set; } + public ZkSyncOptions? ZkSync { get; set; } } - public class ZkSyncOptions + public struct ZkSyncOptions { [JsonProperty(PropertyName = "gasPerPubdataByteLimit")] public BigInteger GasPerPubdataByteLimit { get; set; } From e936a5ef30ad34cff21eadecb073f63ab19f17ff Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Thu, 23 May 2024 16:12:39 +0300 Subject: [PATCH 19/23] add tests --- Thirdweb.Tests/Thirdweb.Transactions.Tests.cs | 34 +++++++++++++++++-- Thirdweb.Tests/Thirdweb.Utils.Tests.cs | 11 ++++++ Thirdweb.Tests/Thirdweb.Wallets.Tests.cs | 9 +++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs index dd629ed..b409767 100644 --- a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs @@ -75,7 +75,7 @@ public async Task SetValue_SetsValue() } [Fact] - public async Task SetValue_SetsData() + public async Task SetData_SetsData() { var transaction = await CreateSampleTransaction(); var data = "0x123456"; @@ -84,7 +84,7 @@ public async Task SetValue_SetsData() } [Fact] - public async Task SetValue_SetsGasPrice() + public async Task SetGasPrice_SetsGasPrice() { var transaction = await CreateSampleTransaction(); var gas = new BigInteger(1000); @@ -92,6 +92,36 @@ public async Task SetValue_SetsGasPrice() Assert.Equal(gas.ToHexBigInteger(), transaction.Input.GasPrice); } + [Fact] + public async Task SetMaxFeePerGas_SetsMaxFeePerGas() + { + var transaction = await CreateSampleTransaction(); + var gas = new BigInteger(1000); + _ = transaction.SetMaxFeePerGas(gas); + Assert.Equal(gas.ToHexBigInteger(), transaction.Input.MaxFeePerGas); + } + + [Fact] + public async Task SetMaxPriorityFeePerGas_SetsMaxPriorityFeePerGas() + { + var transaction = await CreateSampleTransaction(); + var gas = new BigInteger(1000); + _ = transaction.SetMaxPriorityFeePerGas(gas); + Assert.Equal(gas.ToHexBigInteger(), transaction.Input.MaxPriorityFeePerGas); + } + + [Fact] + public async Task SetAllGasParams_ThrowsInvalid() + { + var transaction = await CreateSampleTransaction(); + var gas = new BigInteger(1000); + _ = transaction.SetGasPrice(gas); + _ = transaction.SetMaxFeePerGas(gas); + _ = transaction.SetMaxPriorityFeePerGas(gas); + var ex = await Assert.ThrowsAsync(() => ThirdwebTransaction.Send(transaction)); + Assert.Contains("Transaction GasPrice and MaxFeePerGas/MaxPriorityFeePerGas cannot be set at the same time", ex.Message); + } + [Fact] public async Task Sign_SmartWallet_SignsTransaction() { diff --git a/Thirdweb.Tests/Thirdweb.Utils.Tests.cs b/Thirdweb.Tests/Thirdweb.Utils.Tests.cs index d850bf6..b2ac60d 100644 --- a/Thirdweb.Tests/Thirdweb.Utils.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Utils.Tests.cs @@ -31,6 +31,17 @@ public void HashPrefixedMessage() Assert.Equal("0xc8ee0d506e864589b799a645ddb88b08f5d39e8049f9f702b3b61fa15e55fc73", hashStr); } + [Fact] + public void HashMessage() + { + var messageStr = "Hello, World!"; + var message = System.Text.Encoding.UTF8.GetBytes(messageStr); + var hashStr = Utils.HashMessage(messageStr); + var hash = Utils.HashMessage(message); + Assert.Equal(hashStr, Utils.BytesToHex(hash)); + Assert.Equal("0xacaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f", hashStr); + } + [Fact] public void BytesToHex() { diff --git a/Thirdweb.Tests/Thirdweb.Wallets.Tests.cs b/Thirdweb.Tests/Thirdweb.Wallets.Tests.cs index 2e11d28..048749f 100644 --- a/Thirdweb.Tests/Thirdweb.Wallets.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Wallets.Tests.cs @@ -23,6 +23,15 @@ public async Task GetAddress() Assert.Equal(await wallet.GetAddress(), await wallet.GetAddress()); } + [Fact] + public async Task EthSignRaw() + { + var wallet = await GetAccount(); + var message = "Hello, world!"; + var signature = await wallet.EthSign(System.Text.Encoding.UTF8.GetBytes(message)); + Assert.NotNull(signature); + } + [Fact] public async Task EthSign() { From 76c71ad6fe06bd2451807035cd9ee9ebe0b1678a Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Thu, 23 May 2024 16:15:22 +0300 Subject: [PATCH 20/23] Update Thirdweb.Transactions.Tests.cs --- Thirdweb.Tests/Thirdweb.Transactions.Tests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs index b409767..99a3c13 100644 --- a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs @@ -115,6 +115,7 @@ public async Task SetAllGasParams_ThrowsInvalid() { var transaction = await CreateSampleTransaction(); var gas = new BigInteger(1000); + _ = transaction.SetTo(Constants.ADDRESS_ZERO); _ = transaction.SetGasPrice(gas); _ = transaction.SetMaxFeePerGas(gas); _ = transaction.SetMaxPriorityFeePerGas(gas); From 838b9bf18eeb2455d93f722982d08788031cb7bd Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Thu, 23 May 2024 16:32:15 +0300 Subject: [PATCH 21/23] raw sign, partial --- .../Thirdweb.PrivateKeyWallet.Tests.cs | 17 +++++++++++++++++ Thirdweb.Tests/Thirdweb.Transactions.Tests.cs | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs b/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs index 507d065..9596da1 100644 --- a/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs @@ -63,6 +63,23 @@ public async Task EthSign_NullMessage() Assert.Equal("Message to sign cannot be null. (Parameter 'message')", ex.Message); } + [Fact] + public async Task EthSignRaw_Success() + { + var account = await GetAccount(); + var message = "Hello, World!"; + var signature = await account.EthSign(System.Text.Encoding.UTF8.GetBytes(message)); + Assert.True(signature.Length == 132); + } + + [Fact] + public async Task EthSignRaw_NullMessage() + { + var account = await GetAccount(); + var ex = await Assert.ThrowsAsync(() => account.EthSign(null as byte[])); + Assert.Equal("Message to sign cannot be null. (Parameter 'rawMessage')", ex.Message); + } + [Fact] public async Task PersonalSign_Success() { diff --git a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs index 99a3c13..8edb1c2 100644 --- a/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs +++ b/Thirdweb.Tests/Thirdweb.Transactions.Tests.cs @@ -183,6 +183,24 @@ public async Task Send_ZkSync_TransfersGaslessly() Assert.StartsWith("0x", receipt.TransactionHash); } + [Fact] + public async Task Send_ZkSync_NoGasPerPubFactoryDepsTransfersGaslessly() + { + var transaction = await CreateSampleTransaction(); + _ = transaction.SetChainId(300); + _ = transaction.SetTo("0xbA226d47Cbb2731CBAA67C916c57d68484AA269F"); + _ = transaction.SetValue(BigInteger.Zero); + _ = transaction.SetZkSyncOptions( + new ZkSyncOptions( + paymaster: "0xbA226d47Cbb2731CBAA67C916c57d68484AA269F", + paymasterInput: "0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000" + ) + ); + var receipt = await ThirdwebTransaction.SendAndWaitForTransactionReceipt(transaction); + Assert.NotNull(receipt); + Assert.StartsWith("0x", receipt.TransactionHash); + } + [Fact] public async Task EstimateTotalCosts_CalculatesCostsCorrectly() { From 735ebc3eefe5a67fc7c2edf5dca18cfdc438afc5 Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Thu, 23 May 2024 16:45:54 +0300 Subject: [PATCH 22/23] sep for cov --- .../ThirdwebTransaction.cs | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs index 19a2282..023ff3a 100644 --- a/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs +++ b/Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs @@ -35,15 +35,28 @@ public static async Task Create(ThirdwebClient client, IThi var address = await wallet.GetAddress(); txInput.From ??= address; txInput.Data ??= "0x"; - return address != txInput.From - ? throw new ArgumentException("Transaction sender (from) must match wallet address") - : client == null - ? throw new ArgumentNullException(nameof(client)) - : wallet == null - ? throw new ArgumentNullException(nameof(wallet)) - : chainId == 0 - ? throw new ArgumentException("Invalid Chain ID") - : new ThirdwebTransaction(client, wallet, txInput, chainId); + + if (address != txInput.From) + { + throw new ArgumentException("Transaction sender (from) must match wallet address"); + } + + if (client == null) + { + throw new ArgumentNullException(nameof(client)); + } + + if (wallet == null) + { + throw new ArgumentNullException(nameof(wallet)); + } + + if (chainId == 0) + { + throw new ArgumentException("Invalid Chain ID"); + } + + return new ThirdwebTransaction(client, wallet, txInput, chainId); } public override string ToString() From 38ed94a5d38081e3f3de5e41b0af087c7dfb6bfc Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Thu, 23 May 2024 16:54:39 +0300 Subject: [PATCH 23/23] y parity be explicit --- Thirdweb/Thirdweb.Wallets/EIP712.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Thirdweb/Thirdweb.Wallets/EIP712.cs b/Thirdweb/Thirdweb.Wallets/EIP712.cs index 2901e24..b0e2539 100644 --- a/Thirdweb/Thirdweb.Wallets/EIP712.cs +++ b/Thirdweb/Thirdweb.Wallets/EIP712.cs @@ -121,7 +121,7 @@ private static string SerializeEip712(AccountAbstraction.ZkSyncAATransaction tra transaction.Data == null ? new byte[0] : transaction.Data, }; - fields.Add(signature.IsVSignedForYParity() ? new byte[] { 0x1b } : new byte[] { }); + fields.Add(signature.IsVSignedForYParity() ? new byte[] { 0x1b } : new byte[] { 0x1c }); fields.Add(signature.R); fields.Add(signature.S);