Skip to content

Commit b8b21ff

Browse files
authored
verif/preverif/maxfee/maxpriority manual // single sig (#72)
1 parent fa653fb commit b8b21ff

File tree

2 files changed

+76
-27
lines changed

2 files changed

+76
-27
lines changed

Assets/Thirdweb/Core/Scripts/AccountAbstraction/Core/SmartWallet.cs

+6-27
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ internal async Task<RpcResponseMessage> Request(RpcRequestMessage requestMessage
124124
private async Task<RpcResponseMessage> CreateUserOpAndSend(RpcRequestMessage requestMessage)
125125
{
126126
// Deserialize the transaction input from the request message
127-
Debug.Log("Creating UserOp...");
128127

129128
var paramList = JsonConvert.DeserializeObject<List<object>>(JsonConvert.SerializeObject(requestMessage.RawParameters));
130129
var transactionInput = JsonConvert.DeserializeObject<TransactionInput>(JsonConvert.SerializeObject(paramList[0]));
@@ -146,7 +145,6 @@ private async Task<RpcResponseMessage> CreateUserOpAndSend(RpcRequestMessage req
146145
var executeInput = executeFn.CreateTransactionInput(Accounts[0]);
147146

148147
// Create the user operation and its safe (hexified) version
149-
Debug.Log("Create the user operation and its safe (hexified) version...");
150148

151149
var partialUserOp = new EntryPointContract.UserOperation()
152150
{
@@ -155,51 +153,33 @@ private async Task<RpcResponseMessage> CreateUserOpAndSend(RpcRequestMessage req
155153
InitCode = initData.initCode,
156154
CallData = executeInput.Data.HexStringToByteArray(),
157155
CallGasLimit = transactionInput.Gas.Value,
158-
VerificationGasLimit = 150000 + initData.gas,
159-
PreVerificationGas = 50000,
160-
MaxFeePerGas = latestBlock.BaseFeePerGas.Value + 2,
161-
MaxPriorityFeePerGas = 2,
156+
VerificationGasLimit = 100000 + initData.gas,
157+
PreVerificationGas = 21000,
158+
MaxFeePerGas = latestBlock.BaseFeePerGas.Value * 2 + BigInteger.Parse("1500000000"),
159+
MaxPriorityFeePerGas = BigInteger.Parse("1500000000"),
162160
PaymasterAndData = Constants.DUMMY_PAYMASTER_AND_DATA_HEX.HexStringToByteArray(),
163161
Signature = dummySig,
164162
};
163+
partialUserOp.PreVerificationGas = partialUserOp.CalcPreVerificationGas();
165164
var partialUserOpHexified = partialUserOp.EncodeUserOperation();
166165

167166
// Update paymaster data if any
168-
Debug.Log("Update paymaster data if any...");
169167

170168
partialUserOp.PaymasterAndData = await GetPaymasterAndData(requestMessage.Id, partialUserOpHexified);
171169

172-
partialUserOp.Signature = await partialUserOp.HashAndSignUserOp(Config.entryPointAddress);
173-
partialUserOpHexified = partialUserOp.EncodeUserOperation();
174-
175-
// Estimate gas with updated paymaster data
176-
Debug.Log("Estimate gas with updated paymaster data...");
170+
// Hash, sign and encode the user operation
177171

178-
var gasEstimates = await BundlerClient.EthEstimateUserOperationGas(Config.bundlerUrl, Config.thirdwebApiKey, requestMessage.Id, partialUserOpHexified, Config.entryPointAddress);
179-
partialUserOp.CallGasLimit = new HexBigInteger(gasEstimates.CallGasLimit).Value;
180-
partialUserOp.VerificationGasLimit = new HexBigInteger(gasEstimates.VerificationGas).Value;
181-
partialUserOp.PreVerificationGas = new HexBigInteger(gasEstimates.PreVerificationGas).Value;
182-
183-
partialUserOp.Signature = await partialUserOp.HashAndSignUserOp(Config.entryPointAddress);
184-
partialUserOpHexified = partialUserOp.EncodeUserOperation();
185-
186-
// Update paymaster data post estimates again
187-
Debug.Log("Update paymaster data post estimates again...");
188-
189-
partialUserOp.PaymasterAndData = await GetPaymasterAndData(requestMessage.Id, partialUserOpHexified);
190172
partialUserOp.Signature = await partialUserOp.HashAndSignUserOp(Config.entryPointAddress);
191173
partialUserOpHexified = partialUserOp.EncodeUserOperation();
192174

193175
// Send the user operation
194-
Debug.Log("Send the user operation...");
195176

196177
Debug.Log("Valid UserOp: " + JsonConvert.SerializeObject(partialUserOp));
197178
Debug.Log("Valid Encoded UserOp: " + JsonConvert.SerializeObject(partialUserOpHexified));
198179
var userOpHash = await BundlerClient.EthSendUserOperation(Config.bundlerUrl, Config.thirdwebApiKey, requestMessage.Id, partialUserOpHexified, Config.entryPointAddress);
199180
Debug.Log("UserOp Hash: " + userOpHash);
200181

201182
// Wait for the transaction to be mined
202-
Debug.Log("Wait for the transaction to be mined...");
203183

204184
string txHash = null;
205185
while (txHash == null && Application.isPlaying)
@@ -211,7 +191,6 @@ private async Task<RpcResponseMessage> CreateUserOpAndSend(RpcRequestMessage req
211191
Debug.Log("Tx Hash: " + txHash);
212192

213193
// Check if successful
214-
Debug.Log("Check if successful...");
215194

216195
var receipt = await new Web3(ThirdwebManager.Instance.SDK.session.RPC).Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txHash);
217196
var decodedEvents = receipt.DecodeAllEvents<EntryPointContract.UserOperationEventEventDTO>();

Assets/Thirdweb/Core/Scripts/AccountAbstraction/Core/UserOpUtils.cs

+70
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,75 @@ public static UserOperationHexified EncodeUserOperation(this EntryPointContract.
4444
signature = userOperation.Signature.ByteArrayToHexString()
4545
};
4646
}
47+
48+
public static int CalcPreVerificationGas(this EntryPointContract.UserOperation userOp, GasOverheads gasOverheads = null)
49+
{
50+
GasOverheads ov = gasOverheads ?? new GasOverheads();
51+
52+
userOp.Signature = new byte[ov.sigSize];
53+
userOp.PreVerificationGas = 21000;
54+
55+
byte[] packed = userOp.PackUserOp(false);
56+
int lengthInWord = (packed.Length + 31) / 32;
57+
58+
int callDataCost = 0;
59+
foreach (byte b in packed)
60+
{
61+
callDataCost += (b == 0) ? ov.zeroByte : ov.nonZeroByte;
62+
}
63+
64+
int totalGas = callDataCost + ov.fixedGas / ov.bundleSize + ov.perUserOp + ov.perUserOpWord * lengthInWord;
65+
66+
return totalGas;
67+
}
68+
69+
public static byte[] PackUserOp(this EntryPointContract.UserOperation op, bool forSignature = true)
70+
{
71+
var abiEncode = new Nethereum.ABI.ABIEncode();
72+
var sha3Keccak = new Nethereum.Util.Sha3Keccack();
73+
74+
if (forSignature)
75+
{
76+
return abiEncode.GetABIEncoded(
77+
op.Sender,
78+
op.Nonce,
79+
sha3Keccak.CalculateHash(op.InitCode),
80+
sha3Keccak.CalculateHash(op.CallData),
81+
op.CallGasLimit,
82+
op.VerificationGasLimit,
83+
op.PreVerificationGas,
84+
op.MaxFeePerGas,
85+
op.MaxPriorityFeePerGas,
86+
sha3Keccak.CalculateHash(op.PaymasterAndData)
87+
);
88+
}
89+
else
90+
{
91+
return abiEncode.GetABIEncodedPacked(
92+
op.Sender,
93+
op.Nonce,
94+
op.InitCode,
95+
op.CallData,
96+
op.CallGasLimit,
97+
op.VerificationGasLimit,
98+
op.PreVerificationGas,
99+
op.MaxFeePerGas,
100+
op.MaxPriorityFeePerGas,
101+
op.PaymasterAndData,
102+
op.Signature
103+
);
104+
}
105+
}
106+
}
107+
108+
public class GasOverheads
109+
{
110+
public int fixedGas = 21000;
111+
public int perUserOp = 18300;
112+
public int perUserOpWord = 4;
113+
public int zeroByte = 4;
114+
public int nonZeroByte = 16;
115+
public int bundleSize = 1;
116+
public int sigSize = Constants.DUMMY_SIG_LENGTH;
47117
}
48118
}

0 commit comments

Comments
 (0)