.NET SDK x ZkSync


New release, .NET SDK 0.3.0

A release packed with features you never knew you needed!

How ZkSync Native Account Abstraction Works in .NET

Let's start with an example:

// Prepare a transaction directly, or with Contract.Prepare
var tx = await ThirdwebTransaction.Create(
client: client,
wallet: privateKeyWallet,
txInput: new ThirdwebTransactionInput()
From = await privateKeyWallet.GetAddress(),
To = await privateKeyWallet.GetAddress(),
Value = new HexBigInteger(BigInteger.Zero),
chainId: 300
// Set zkSync options
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}");

Here, we're interacting with ZkSync Sepolia by setting the chain id to 300, using a simple GaslessPaymaster we funded with a little bit of ETH. We set its contract address in the paymaster field. The second required parameter is paymasterInput which is the encoded function related to your paymaster, with whatever inner input it requires. In this case, it's just the function selector of the IPaymasterFlow.general function, which is plenty for our use case. You could extend this to use a SignatureBasedPaymaster instead and append some signed typed data from an authorized private key to approve each transaction before sending it into your paymaster. Some example paymasters can be found here.

You'll also notice that the internal TransactionInput is now ThirdwebTransactionInput - as we expand support for different transaction types, we'll be using this custom input type and keep adding options to it!

Additional documentation can be found here.

Support for EIP-1559

We now support 1559 transaction types in .NET, and prioritize them over legacy type transactions. We'll deal with this in the background if you don't explicitly set gas fees when creating your transaction. If you want to use a legacy type transaction, simply set the Gas Price and we'll respect it.

Here's how you'd override 1559 fees on your transaction object:

_ = transaction.SetMaxFeePerGas(1000000000);
_ = transaction.SetMaxPriorityFeePerGas(1000000000);

What's Next?

Managed ZkSync Paymasters so you don't even have to deal with input? Through creating a SmartWallet? Perhaps!

Maybe a WalletConnectSharp integration, and MAUI starter template to keep Godot's company - stay tuned!