Skip to content

Commit 37ea6f7

Browse files
committed
progress push
1 parent c63c348 commit 37ea6f7

File tree

8 files changed

+237
-76
lines changed

8 files changed

+237
-76
lines changed

Thirdweb.Console/Program.cs

Lines changed: 85 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,94 @@
1818
// Do not use private keys client side, use InAppWallet/SmartWallet instead
1919
var privateKey = Environment.GetEnvironmentVariable("PRIVATE_KEY");
2020

21-
// Fetch timeout options are optional, default is 120000ms
22-
var client = ThirdwebClient.Create(secretKey: secretKey, fetchTimeoutOptions: new TimeoutOptions(storage: 120000, rpc: 120000, other: 120000));
23-
24-
// Create a private key wallet
25-
var privateKeyWallet = await PrivateKeyWallet.Generate(client: client);
26-
27-
// var walletAddress = await privateKeyWallet.GetAddress();
28-
// Console.WriteLine($"PK Wallet address: {walletAddress}");
21+
// Initialize client
22+
var client = ThirdwebClient.Create(secretKey: secretKey);
23+
24+
// Chain and contract addresses
25+
var chainWith7702 = 7078815900;
26+
var erc20ContractAddress = "0x852e8247A55C49dc3b7e6f8788347813e562F597"; // Mekong Token
27+
var delegationContractAddress = "0x7B9E7AFd452666302352D82161B083dF792f7Cf4"; // BatchCallDelegation
28+
29+
// Initialize contracts normally
30+
var erc20Contract = await ThirdwebContract.Create(client: client, address: erc20ContractAddress, chain: chainWith7702);
31+
var delegationContract = await ThirdwebContract.Create(
32+
client: client,
33+
address: delegationContractAddress,
34+
chain: chainWith7702,
35+
abi: /*lang=json,strict*/
36+
"[{\"anonymous\": false,\"inputs\": [{\"indexed\": true,\"internalType\": \"address\",\"name\": \"to\",\"type\": \"address\"},{\"indexed\": false,\"internalType\": \"uint256\",\"name\": \"value\",\"type\": \"uint256\"},{\"indexed\": false,\"internalType\": \"bytes\",\"name\": \"data\",\"type\": \"bytes\"}],\"name\": \"Executed\",\"type\": \"event\"},{\"inputs\": [{\"components\": [{\"internalType\": \"bytes\",\"name\": \"data\",\"type\": \"bytes\"},{\"internalType\": \"address\",\"name\": \"to\",\"type\": \"address\"},{\"internalType\": \"uint256\",\"name\": \"value\",\"type\": \"uint256\"}],\"internalType\": \"struct BatchCallDelegation.Call[]\",\"name\": \"calls\",\"type\": \"tuple[]\"}],\"name\": \"execute\",\"outputs\": [],\"stateMutability\": \"payable\",\"type\": \"function\"}]"
37+
);
38+
39+
// Initialize a 7702 EOA
40+
var eoaWallet = await PrivateKeyWallet.Generate(client);
41+
var eoaWalletAddress = await eoaWallet.GetAddress();
42+
Console.WriteLine($"EOA address: {eoaWalletAddress}");
43+
44+
// Temporary - fund eoa wallet
45+
var fundingWallet = await PrivateKeyWallet.Create(client, privateKey);
46+
await ThirdwebTransaction.SendAndWaitForTransactionReceipt(
47+
await ThirdwebTransaction.Create(fundingWallet, new ThirdwebTransactionInput(chainId: chainWith7702, to: eoaWalletAddress, value: BigInteger.Parse("0.1".ToWei())))
48+
);
49+
50+
// Sign the authorization to make it point to the delegation contract
51+
var authorization = await eoaWallet.SignAuthorization(chainId: chainWith7702, contractAddress: delegationContractAddress, willSelfExecute: true);
52+
Console.WriteLine($"Authorization: {JsonConvert.SerializeObject(authorization, Formatting.Indented)}");
53+
54+
// Execute the delegation
55+
var tx = await ThirdwebTransaction.Create(eoaWallet, new ThirdwebTransactionInput(chainId: chainWith7702, to: eoaWalletAddress, authorization: authorization));
56+
var hash = (await ThirdwebTransaction.SendAndWaitForTransactionReceipt(tx)).TransactionHash;
57+
Console.WriteLine($"Transaction hash: {hash}");
58+
59+
// Initialize another wallet, the "executor" that will hit the eoa's execute function
60+
var executorWallet = await InAppWallet.Create(client: client, authProvider: AuthProvider.Google);
61+
if (!await executorWallet.IsConnected())
62+
{
63+
_ = await executorWallet.LoginWithOauth(
64+
isMobile: false,
65+
browserOpenAction: (url) =>
66+
{
67+
var psi = new ProcessStartInfo { FileName = url, UseShellExecute = true };
68+
_ = Process.Start(psi);
69+
}
70+
);
71+
}
72+
var executorWalletAddress = await executorWallet.GetAddress();
73+
Console.WriteLine($"Executor address: {executorWalletAddress}");
74+
75+
// Log erc20 balance of executor before the claim
76+
var executorBalanceBefore = await erc20Contract.ERC20_BalanceOf(executorWalletAddress);
77+
Console.WriteLine($"Executor balance before: {executorBalanceBefore}");
78+
79+
// Prepare the claim call
80+
var claimCallData = erc20Contract.CreateCallData(
81+
"claim",
82+
new object[]
83+
{
84+
executorWalletAddress, // receiver
85+
100, // quantity
86+
Constants.NATIVE_TOKEN_ADDRESS, // currency
87+
0, // pricePerToken
88+
new object[] { Array.Empty<byte>(), BigInteger.Zero, BigInteger.Zero, Constants.ADDRESS_ZERO }, // allowlistProof
89+
Array.Empty<byte>() // data
90+
}
91+
);
92+
93+
// Embed the claim call in the execute call
94+
var executeCallData = delegationContract.CreateCallData("execute", new object[] { new object[] { claimCallData, eoaWalletAddress, BigInteger.Zero } });
95+
96+
// Execute from the executor wallet targeting the eoa which is pointing to the delegation contract
97+
var tx2 = await ThirdwebTransaction.Create(executorWallet, new ThirdwebTransactionInput(chainId: chainWith7702, to: eoaWalletAddress, data: executeCallData));
98+
var hash2 = (await ThirdwebTransaction.SendAndWaitForTransactionReceipt(tx2)).TransactionHash;
99+
Console.WriteLine($"Transaction hash: {hash2}");
100+
101+
// Log erc20 balance of executor after the claim
102+
var executorBalanceAfter = await erc20Contract.ERC20_BalanceOf(executorWalletAddress);
103+
Console.WriteLine($"Executor balance after: {executorBalanceAfter}");
29104

30105
#region Contract Interaction
31106

32107
// var contract = await ThirdwebContract.Create(client: client, address: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d", chain: 1);
33-
// var nfts = await contract.ERC721_GetAllNFTs();
34-
// Console.WriteLine($"NFTs: {JsonConvert.SerializeObject(nfts, Formatting.Indented)}");
108+
// var result = await contract.
35109

36110
#endregion
37111

@@ -44,13 +118,7 @@
44118

45119
#region AA 0.6
46120

47-
// var smartWallet06 = await SmartWallet.Create(
48-
// personalWallet: privateKeyWallet,
49-
// chainId: 421614,
50-
// gasless: true,
51-
// factoryAddress: "0xa8deE7854fb1eA8c13b713585C81d91ea86dAD84",
52-
// entryPoint: Constants.ENTRYPOINT_ADDRESS_V06
53-
// );
121+
// var smartWallet06 = await SmartWallet.Create(personalWallet: privateKeyWallet, chainId: 421614);
54122

55123
// var receipt06 = await smartWallet06.ExecuteTransaction(new ThirdwebTransactionInput(chainId: 421614, to: await smartWallet06.GetAddress(), value: 0, data: "0x"));
56124

Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -262,16 +262,32 @@ public static async Task<BigInteger> EstimateGasLimit(ThirdwebTransaction transa
262262
{
263263
var rpc = ThirdwebRPC.GetRpcInstance(transaction._wallet.Client, transaction.Input.ChainId.Value);
264264

265-
if (await Utils.IsZkSync(transaction._wallet.Client, transaction.Input.ChainId.Value).ConfigureAwait(false))
265+
// Remove when https://github.com/ethereum/execution-apis/issues/561 is in
266+
var txInput = new ThirdwebTransactionInput(
267+
chainId: transaction.Input.ChainId,
268+
from: transaction.Input.From,
269+
to: transaction.Input.To,
270+
nonce: transaction.Input.Nonce,
271+
value: transaction.Input.Value,
272+
data: transaction.Input.Data,
273+
zkSync: transaction.Input.ZkSync
274+
);
275+
276+
var extraGas = transaction.Input.AuthorizationList == null ? 0 : 100000;
277+
BigInteger finalGas;
278+
279+
if (await Utils.IsZkSync(transaction._wallet.Client, txInput.ChainId.Value).ConfigureAwait(false))
266280
{
267-
var hex = (await rpc.SendRequestAsync<JToken>("zks_estimateFee", transaction.Input).ConfigureAwait(false))["gas_limit"].ToString();
268-
return new HexBigInteger(hex).Value * 10 / 5;
281+
var hex = (await rpc.SendRequestAsync<JToken>("zks_estimateFee", txInput).ConfigureAwait(false))["gas_limit"].ToString();
282+
finalGas = hex.HexToBigInt() * 2;
269283
}
270284
else
271285
{
272-
var hex = await rpc.SendRequestAsync<string>("eth_estimateGas", transaction.Input).ConfigureAwait(false);
273-
return new HexBigInteger(hex).Value * 10 / 7;
286+
var hex = await rpc.SendRequestAsync<string>("eth_estimateGas", txInput).ConfigureAwait(false);
287+
finalGas = hex.HexToBigInt() * 2;
274288
}
289+
290+
return finalGas + extraGas;
275291
}
276292

277293
/// <summary>
@@ -358,32 +374,7 @@ public static async Task<string> Send(ThirdwebTransaction transaction)
358374
var rpc = ThirdwebRPC.GetRpcInstance(transaction._wallet.Client, transaction.Input.ChainId.Value);
359375
string hash;
360376

361-
if (transaction.Input.AuthorizationList != null)
362-
{
363-
var authorization = transaction.Input.AuthorizationList[0];
364-
hash = await rpc.SendRequestAsync<string>(
365-
"wallet_sendTransaction",
366-
new
367-
{
368-
authorizationList = new[]
369-
{
370-
new
371-
{
372-
address = authorization.Address,
373-
chainId = authorization.ChainId.HexToBigInt(),
374-
nonce = authorization.Nonce.HexToBigInt(),
375-
r = authorization.R,
376-
s = authorization.S,
377-
yParity = authorization.YParity == "0x00" ? 0 : 1
378-
}
379-
},
380-
data = transaction.Input.Data,
381-
to = transaction.Input.To,
382-
}
383-
)
384-
.ConfigureAwait(false);
385-
}
386-
else if (await Utils.IsZkSync(transaction._wallet.Client, transaction.Input.ChainId.Value).ConfigureAwait(false) && transaction.Input.ZkSync.HasValue)
377+
if (await Utils.IsZkSync(transaction._wallet.Client, transaction.Input.ChainId.Value).ConfigureAwait(false) && transaction.Input.ZkSync.HasValue)
387378
{
388379
var zkTx = await ConvertToZkSyncTransaction(transaction).ConfigureAwait(false);
389380
var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet).ConfigureAwait(false);

Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,12 @@ public struct EIP7702Authorization
207207
[JsonProperty(PropertyName = "s")]
208208
public string S { get; set; }
209209

210-
public EIP7702Authorization(BigInteger chainId, string address, BigInteger nonce, byte[] yParity, byte[] r, byte[] s)
210+
public EIP7702Authorization(BigInteger chainId, string address, BigInteger nonce, byte[] v, byte[] r, byte[] s)
211211
{
212212
this.ChainId = new HexBigInteger(chainId).HexValue;
213-
this.Address = address.EnsureHexPrefix();
213+
this.Address = address;
214214
this.Nonce = new HexBigInteger(nonce).HexValue;
215-
this.YParity = yParity.BytesToHex();
215+
this.YParity = v.BytesToHex();
216216
this.R = r.BytesToHex();
217217
this.S = s.BytesToHex();
218218
}

Thirdweb/Thirdweb.Utils/Utils.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,4 +1034,26 @@ public static string SerializeErc6492Signature(string address, byte[] data, byte
10341034
var encodedParams = encoder.GetABIEncoded(new ABIValue("address", address), new ABIValue("bytes", data), new ABIValue("bytes", signature));
10351035
return HexConcat(encodedParams.BytesToHex(), Constants.ERC_6492_MAGIC_VALUE);
10361036
}
1037+
1038+
/// <summary>
1039+
/// Removes leading zeroes from the given byte array.
1040+
/// </summary>
1041+
public static byte[] TrimZeroes(this byte[] bytes)
1042+
{
1043+
var trimmed = new List<byte>();
1044+
var previousByteWasZero = true;
1045+
1046+
for (var i = 0; i < bytes.Length; i++)
1047+
{
1048+
if (previousByteWasZero && bytes[i] == 0)
1049+
{
1050+
continue;
1051+
}
1052+
1053+
previousByteWasZero = false;
1054+
trimmed.Add(bytes[i]);
1055+
}
1056+
1057+
return trimmed.ToArray();
1058+
}
10371059
}

Thirdweb/Thirdweb.Wallets/IThirdwebWallet.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,9 @@ Task<List<LinkedAccount>> LinkAccount(
173173
/// </summary>
174174
/// <param name="chainId">The chain ID of the contract.</param>
175175
/// <param name="contractAddress">The address of the contract.</param>
176+
/// <param name="willSelfExecute">Set to true if the wallet will also be the executor of the transaction, otherwise false.</param>
176177
/// <returns>The signed authorization as an <see cref="EIP7702Authorization"/> that can be used with <see cref="ThirdwebTransactionInput.AuthorizationList"/>.</returns>
177-
Task<EIP7702Authorization> SignAuthorization(BigInteger chainId, string contractAddress);
178+
Task<EIP7702Authorization> SignAuthorization(BigInteger chainId, string contractAddress, bool willSelfExecute);
178179
}
179180

180181
/// <summary>

Thirdweb/Thirdweb.Wallets/InAppWallet/EcosystemWallet/EcosystemWallet.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,7 @@ public virtual Task<string> RecoverAddressFromTypedDataV4<T, TDomain>(T data, Ty
931931
return Task.FromResult(address);
932932
}
933933

934-
public Task<EIP7702Authorization> SignAuthorization(BigInteger chainId, string contractAddress)
934+
public Task<EIP7702Authorization> SignAuthorization(BigInteger chainId, string contractAddress, bool willSelfExecute)
935935
{
936936
throw new NotImplementedException();
937937
}

0 commit comments

Comments
 (0)