Skip to content

verif/preverif/maxfee/maxpriority manual // single sig #72

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ internal async Task<RpcResponseMessage> Request(RpcRequestMessage requestMessage
private async Task<RpcResponseMessage> CreateUserOpAndSend(RpcRequestMessage requestMessage)
{
// Deserialize the transaction input from the request message
Debug.Log("Creating UserOp...");

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

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

var partialUserOp = new EntryPointContract.UserOperation()
{
Expand All @@ -155,51 +153,33 @@ private async Task<RpcResponseMessage> CreateUserOpAndSend(RpcRequestMessage req
InitCode = initData.initCode,
CallData = executeInput.Data.HexStringToByteArray(),
CallGasLimit = transactionInput.Gas.Value,
VerificationGasLimit = 150000 + initData.gas,
PreVerificationGas = 50000,
MaxFeePerGas = latestBlock.BaseFeePerGas.Value + 2,
MaxPriorityFeePerGas = 2,
VerificationGasLimit = 100000 + initData.gas,
PreVerificationGas = 21000,
MaxFeePerGas = latestBlock.BaseFeePerGas.Value * 2 + BigInteger.Parse("1500000000"),
MaxPriorityFeePerGas = BigInteger.Parse("1500000000"),
PaymasterAndData = Constants.DUMMY_PAYMASTER_AND_DATA_HEX.HexStringToByteArray(),
Signature = dummySig,
};
partialUserOp.PreVerificationGas = partialUserOp.CalcPreVerificationGas();
var partialUserOpHexified = partialUserOp.EncodeUserOperation();

// Update paymaster data if any
Debug.Log("Update paymaster data if any...");

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

partialUserOp.Signature = await partialUserOp.HashAndSignUserOp(Config.entryPointAddress);
partialUserOpHexified = partialUserOp.EncodeUserOperation();

// Estimate gas with updated paymaster data
Debug.Log("Estimate gas with updated paymaster data...");
// Hash, sign and encode the user operation

var gasEstimates = await BundlerClient.EthEstimateUserOperationGas(Config.bundlerUrl, Config.thirdwebApiKey, requestMessage.Id, partialUserOpHexified, Config.entryPointAddress);
partialUserOp.CallGasLimit = new HexBigInteger(gasEstimates.CallGasLimit).Value;
partialUserOp.VerificationGasLimit = new HexBigInteger(gasEstimates.VerificationGas).Value;
partialUserOp.PreVerificationGas = new HexBigInteger(gasEstimates.PreVerificationGas).Value;

partialUserOp.Signature = await partialUserOp.HashAndSignUserOp(Config.entryPointAddress);
partialUserOpHexified = partialUserOp.EncodeUserOperation();

// Update paymaster data post estimates again
Debug.Log("Update paymaster data post estimates again...");

partialUserOp.PaymasterAndData = await GetPaymasterAndData(requestMessage.Id, partialUserOpHexified);
partialUserOp.Signature = await partialUserOp.HashAndSignUserOp(Config.entryPointAddress);
partialUserOpHexified = partialUserOp.EncodeUserOperation();

// Send the user operation
Debug.Log("Send the user operation...");

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

// Wait for the transaction to be mined
Debug.Log("Wait for the transaction to be mined...");

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

// Check if successful
Debug.Log("Check if successful...");

var receipt = await new Web3(ThirdwebManager.Instance.SDK.session.RPC).Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txHash);
var decodedEvents = receipt.DecodeAllEvents<EntryPointContract.UserOperationEventEventDTO>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,75 @@ public static UserOperationHexified EncodeUserOperation(this EntryPointContract.
signature = userOperation.Signature.ByteArrayToHexString()
};
}

public static int CalcPreVerificationGas(this EntryPointContract.UserOperation userOp, GasOverheads gasOverheads = null)
{
GasOverheads ov = gasOverheads ?? new GasOverheads();

userOp.Signature = new byte[ov.sigSize];
userOp.PreVerificationGas = 21000;

byte[] packed = userOp.PackUserOp(false);
int lengthInWord = (packed.Length + 31) / 32;

int callDataCost = 0;
foreach (byte b in packed)
{
callDataCost += (b == 0) ? ov.zeroByte : ov.nonZeroByte;
}

int totalGas = callDataCost + ov.fixedGas / ov.bundleSize + ov.perUserOp + ov.perUserOpWord * lengthInWord;

return totalGas;
}

public static byte[] PackUserOp(this EntryPointContract.UserOperation op, bool forSignature = true)
{
var abiEncode = new Nethereum.ABI.ABIEncode();
var sha3Keccak = new Nethereum.Util.Sha3Keccack();

if (forSignature)
{
return abiEncode.GetABIEncoded(
op.Sender,
op.Nonce,
sha3Keccak.CalculateHash(op.InitCode),
sha3Keccak.CalculateHash(op.CallData),
op.CallGasLimit,
op.VerificationGasLimit,
op.PreVerificationGas,
op.MaxFeePerGas,
op.MaxPriorityFeePerGas,
sha3Keccak.CalculateHash(op.PaymasterAndData)
);
}
else
{
return abiEncode.GetABIEncodedPacked(
op.Sender,
op.Nonce,
op.InitCode,
op.CallData,
op.CallGasLimit,
op.VerificationGasLimit,
op.PreVerificationGas,
op.MaxFeePerGas,
op.MaxPriorityFeePerGas,
op.PaymasterAndData,
op.Signature
);
}
}
}

public class GasOverheads
{
public int fixedGas = 21000;
public int perUserOp = 18300;
public int perUserOpWord = 4;
public int zeroByte = 4;
public int nonZeroByte = 16;
public int bundleSize = 1;
public int sigSize = Constants.DUMMY_SIG_LENGTH;
}
}