Skip to content

Commit

Permalink
Cleanup types
Browse files Browse the repository at this point in the history
  • Loading branch information
0xFirekeeper committed May 20, 2024
1 parent 490bde1 commit 5772296
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 126 deletions.
28 changes: 14 additions & 14 deletions Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,21 +225,21 @@ public static async Task<string> 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<string>("eth_getTransactionCount", transaction.Input.From, "latest")),
value = transaction.Input.Value.Value,
data = transaction.Input.Data,
factoryDeps = Array.Empty<byte>(),
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<string>("eth_getTransactionCount", transaction.Input.From, "latest")),
Value = transaction.Input.Value.Value,
Data = transaction.Input.Data.HexToByteArray(),
FactoryDeps = Array.Empty<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);
Expand Down
195 changes: 84 additions & 111 deletions Thirdweb/Thirdweb.Wallets/EIP712.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,38 @@ IThirdwebWallet signer
return await signer.SignTypedDataV4(accountMessage, typedData);
}

public static async Task<string> GenerateSignature_ZkSyncTransaction(string domainName, string version, BigInteger chainId, dynamic transaction, IThirdwebWallet signer)
public static async Task<string> 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<Domain> GetTypedDefinition_SmartAccount(string domainName, string version, BigInteger chainId, string verifyingContract)
{
Expand Down Expand Up @@ -102,103 +112,66 @@ public static TypedData<Domain> GetTypedDefinition_ZkSyncTransaction(string doma
Version = version,
ChainId = chainId
},
Types = new Dictionary<string, MemberDescription[]>
{
["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<byte[]>
{
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<byte>()));
fields.Add(RLP.EncodeElement(Array.Empty<byte>()));
}

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<byte>()));

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<byte>()));
}

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<byte[]>
// {
// 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<byte>()));
// fields.Add(RLP.EncodeElement(Array.Empty<byte>()));
// }

// 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<byte[]>()));

// 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<byte[]>()));
// }

// var rlpEncoded = RLP.EncodeList(fields.ToArray());
// return "0x" + BitConverter.ToString(rlpEncoded).Replace("-", "");
// }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
}

0 comments on commit 5772296

Please sign in to comment.