Skip to content

Commit

Permalink
Support 1559 and 113 (ZkSync) Transaction Types (#22)
Browse files Browse the repository at this point in the history
* Support 1559 and 113 (ZkSync) Transaction Types

* RLP

* Cleanup types

* decodeRlpError RlpIncorrectListLen

* Update ThirdwebTransaction.cs

* Proper flow, failing RLP

* Fix encoding, missing 2 chars

* fix factorydeps, encode as empty list 0xc0

* yParity, types

* signature method correct, hash incorrect

* It works!

* cleanup, move params to ThirdwebTransactionInput next

* zkSync SmartWallet auto paymaster poc

* def

* Revert "def"

This reverts commit a4ce773.

* Revert "zkSync SmartWallet auto paymaster poc"

This reverts commit a3097c4.

* Move zksyncoptions to type, use zk rpc fees

* Setters and Tests

* add tests

* Update Thirdweb.Transactions.Tests.cs

* raw sign, partial

* sep for cov

* y parity be explicit
  • Loading branch information
0xFirekeeper authored May 23, 2024
1 parent bfb46cc commit 1bd6acb
Show file tree
Hide file tree
Showing 16 changed files with 612 additions and 105 deletions.
45 changes: 37 additions & 8 deletions Thirdweb.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
var inAppWallet = await InAppWallet.Create(client: client, authprovider: AuthProvider.Google); // or email: null, phoneNumber: "+1234567890"

// Reset InAppWallet (optional step for testing login flow)
if (await inAppWallet.IsConnected())
{
await inAppWallet.Disconnect();
}
// if (await inAppWallet.IsConnected())
// {
// await inAppWallet.Disconnect();
// }

// Relog if InAppWallet not logged in
if (!await inAppWallet.IsConnected())
Expand Down Expand Up @@ -64,10 +64,39 @@
// }
}

// 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
tx.SetZkSyncOptions(
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}");



// Create smart wallet with InAppWallet signer
var smartWallet = await SmartWallet.Create(client: client, personalWallet: inAppWallet, factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", gasless: true, chainId: 421614);
var res = await smartWallet.Authenticate("http://localhost:8000", 421614);
Console.WriteLine($"Smart wallet auth result: {res}");
// var smartWallet = await SmartWallet.Create(client: client, personalWallet: inAppWallet, factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", gasless: true, chainId: 421614);
// var res = await smartWallet.Authenticate("http://localhost:8000", 421614);
// Console.WriteLine($"Smart wallet auth result: {res}");

// // Grant a session key to pk wallet (advanced use case)
// _ = await smartWallet.CreateSessionKey(
Expand Down Expand Up @@ -124,7 +153,7 @@
// Console.WriteLine($"Transaction receipt: {JsonConvert.SerializeObject(receipt)}");

// // Transaction Builder - raw transfer
// var rawTx = new TransactionInput
// var rawTx = new ThirdwebTransactionInput
// {
// From = await smartWallet.GetAddress(),
// To = await smartWallet.GetAddress(),
Expand Down
15 changes: 11 additions & 4 deletions Thirdweb.Tests/Thirdweb.Contracts.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,17 @@ public async Task WriteTest_PrivateKeyAccount()
var pricePerToken = BigInteger.Zero;
var allowlistProof = new object[] { new byte[] { }, BigInteger.Zero, BigInteger.Zero, Constants.ADDRESS_ZERO };
var data = new byte[] { };
var exception = await Assert.ThrowsAsync<Exception>(
async () => await ThirdwebContract.Write(privateKeyAccount, contract, "claim", 0, receiver, quantity, currency, pricePerToken, allowlistProof, data)
);
Assert.Contains("insufficient funds", exception.Message);
try
{
var res = await ThirdwebContract.Write(privateKeyAccount, contract, "claim", 0, receiver, quantity, currency, pricePerToken, allowlistProof, data);
Assert.NotNull(res);
Assert.NotNull(res.TransactionHash);
Assert.Equal(66, res.TransactionHash.Length);
}
catch (Exception ex)
{
Assert.Contains("insufficient funds", ex.Message);
}
}

private async Task<SmartWallet> GetAccount()
Expand Down
40 changes: 27 additions & 13 deletions Thirdweb.Tests/Thirdweb.PrivateKeyWallet.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,27 @@ public async Task EthSign_Success()
public async Task EthSign_NullMessage()
{
var account = await GetAccount();
var ex = await Assert.ThrowsAsync<ArgumentNullException>(() => account.EthSign(null));
var ex = await Assert.ThrowsAsync<ArgumentNullException>(() => account.EthSign(null as string));
Assert.Equal("Message to sign cannot be null. (Parameter 'message')", ex.Message);
}

[Fact]
public async Task EthSignRaw_Success()
{
var account = await GetAccount();
var message = "Hello, World!";
var signature = await account.EthSign(System.Text.Encoding.UTF8.GetBytes(message));
Assert.True(signature.Length == 132);
}

[Fact]
public async Task EthSignRaw_NullMessage()
{
var account = await GetAccount();
var ex = await Assert.ThrowsAsync<ArgumentNullException>(() => account.EthSign(null as byte[]));
Assert.Equal("Message to sign cannot be null. (Parameter 'rawMessage')", ex.Message);
}

[Fact]
public async Task PersonalSign_Success()
{
Expand Down Expand Up @@ -155,7 +172,7 @@ public async Task SignTypedDataV4_Typed_NullData()
public async Task SignTransaction_Success()
{
var account = await GetAccount();
var transaction = new TransactionInput
var transaction = new ThirdwebTransactionInput
{
From = await account.GetAddress(),
To = Constants.ADDRESS_ZERO,
Expand All @@ -173,7 +190,7 @@ public async Task SignTransaction_Success()
public async Task SignTransaction_NoFrom_Success()
{
var account = await GetAccount();
var transaction = new TransactionInput
var transaction = new ThirdwebTransactionInput
{
To = Constants.ADDRESS_ZERO,
// Value = new HexBigInteger(0),
Expand All @@ -198,7 +215,7 @@ public async Task SignTransaction_NullTransaction()
public async Task SignTransaction_NoNonce()
{
var account = await GetAccount();
var transaction = new TransactionInput
var transaction = new ThirdwebTransactionInput
{
From = await account.GetAddress(),
To = Constants.ADDRESS_ZERO,
Expand All @@ -214,7 +231,7 @@ public async Task SignTransaction_NoNonce()
public async Task SignTransaction_WrongFrom()
{
var account = await GetAccount();
var transaction = new TransactionInput
var transaction = new ThirdwebTransactionInput
{
From = Constants.ADDRESS_ZERO,
To = Constants.ADDRESS_ZERO,
Expand All @@ -231,7 +248,7 @@ public async Task SignTransaction_WrongFrom()
public async Task SignTransaction_NoGasPrice()
{
var account = await GetAccount();
var transaction = new TransactionInput
var transaction = new ThirdwebTransactionInput
{
From = await account.GetAddress(),
To = Constants.ADDRESS_ZERO,
Expand All @@ -241,22 +258,21 @@ public async Task SignTransaction_NoGasPrice()
Nonce = new HexBigInteger(99999999999)
};
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => account.SignTransaction(transaction, 421614));
Assert.Equal("Transaction gas price must be set for legacy transactions", ex.Message);
Assert.Equal("Transaction MaxPriorityFeePerGas and MaxFeePerGas must be set for EIP-1559 transactions", ex.Message);
}

[Fact]
public async Task SignTransaction_1559_Success()
{
var account = await GetAccount();
var transaction = new TransactionInput
var transaction = new ThirdwebTransactionInput
{
From = await account.GetAddress(),
To = Constants.ADDRESS_ZERO,
Value = new HexBigInteger(0),
Gas = new HexBigInteger(21000),
Data = "0x",
Nonce = new HexBigInteger(99999999999),
Type = new HexBigInteger(2),
MaxFeePerGas = new HexBigInteger(10000000000),
MaxPriorityFeePerGas = new HexBigInteger(10000000000)
};
Expand All @@ -268,15 +284,14 @@ public async Task SignTransaction_1559_Success()
public async Task SignTransaction_1559_NoMaxFeePerGas()
{
var account = await GetAccount();
var transaction = new TransactionInput
var transaction = new ThirdwebTransactionInput
{
From = await account.GetAddress(),
To = Constants.ADDRESS_ZERO,
Value = new HexBigInteger(0),
Gas = new HexBigInteger(21000),
Data = "0x",
Nonce = new HexBigInteger(99999999999),
Type = new HexBigInteger(2),
MaxPriorityFeePerGas = new HexBigInteger(10000000000)
};
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => account.SignTransaction(transaction, 421614));
Expand All @@ -287,15 +302,14 @@ public async Task SignTransaction_1559_NoMaxFeePerGas()
public async Task SignTransaction_1559_NoMaxPriorityFeePerGas()
{
var account = await GetAccount();
var transaction = new TransactionInput
var transaction = new ThirdwebTransactionInput
{
From = await account.GetAddress(),
To = Constants.ADDRESS_ZERO,
Value = new HexBigInteger(0),
Gas = new HexBigInteger(21000),
Data = "0x",
Nonce = new HexBigInteger(99999999999),
Type = new HexBigInteger(2),
MaxFeePerGas = new HexBigInteger(10000000000)
};
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => account.SignTransaction(transaction, 421614));
Expand Down
4 changes: 2 additions & 2 deletions Thirdweb.Tests/Thirdweb.SmartWallet.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public async Task SendTransaction_Success()
{
var account = await GetSmartAccount();
var tx = await account.SendTransaction(
new TransactionInput()
new ThirdwebTransactionInput()
{
From = await account.GetAddress(),
To = await account.GetAddress(),
Expand All @@ -91,7 +91,7 @@ public async Task SendTransaction_ClientBundleId_Success()
var privateKeyAccount = await PrivateKeyWallet.Create(client, _testPrivateKey);
var smartAccount = await SmartWallet.Create(client, personalWallet: privateKeyAccount, factoryAddress: "0xbf1C9aA4B1A085f7DA890a44E82B0A1289A40052", gasless: true, chainId: 421614);
var tx = await smartAccount.SendTransaction(
new TransactionInput()
new ThirdwebTransactionInput()
{
From = await smartAccount.GetAddress(),
To = await smartAccount.GetAddress(),
Expand Down
Loading

0 comments on commit 1bd6acb

Please sign in to comment.