Skip to content

Commit

Permalink
Fix encoding, missing 2 chars
Browse files Browse the repository at this point in the history
  • Loading branch information
0xFirekeeper committed May 21, 2024
1 parent 877b50e commit 292223d
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 44 deletions.
12 changes: 8 additions & 4 deletions Thirdweb.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
Expand Down
10 changes: 4 additions & 6 deletions Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,16 @@ public static async Task<string> 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;
}
Expand Down Expand Up @@ -232,13 +230,13 @@ public static async Task<string> 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<string>("eth_getTransactionCount", transaction.Input.From, "latest")),
Value = transaction.Input.Value.Value,
Data = transaction.Input.Data.HexToByteArray(),
FactoryDeps = Array.Empty<byte>(),
FactoryDeps = new byte[][] { },
PaymasterInput = zkSyncPaymasterInput.HexToByteArray()
};
Console.WriteLine($"ZkSync transaction: {JsonConvert.SerializeObject(zkTx)}");
Expand Down
93 changes: 60 additions & 33 deletions Thirdweb/Thirdweb.Wallets/EIP712.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -48,14 +49,15 @@ public static async Task<string> 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;
}

Expand Down Expand Up @@ -91,23 +93,22 @@ public static TypedData<Domain> GetTypedDefinition_SmartAccount_AccountMessage(s
};
}

public static TypedData<Domain> GetTypedDefinition_ZkSyncTransaction(string domainName, string version, BigInteger chainId, string verifyingContract)
public static TypedData<DomainWithNameVersionAndChainId> GetTypedDefinition_ZkSyncTransaction(string domainName, string version, BigInteger chainId)
{
return new TypedData<Domain>
return new TypedData<DomainWithNameVersionAndChainId>
{
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)
{
Expand All @@ -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<byte>().ToHex().ToBytesForRLPEncoding(),
signatureHex.ToBytesForRLPEncoding(),
transaction.Paymaster.ToBytesForRLPEncoding(),
transaction.PaymasterInput.ToHex().ToBytesForRLPEncoding()
)
.ToHex();
var fields = new List<byte[]>
{
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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down

0 comments on commit 292223d

Please sign in to comment.