Skip to content

Commit c63c348

Browse files
committed
EIP-7702 Integration
Experimenting on Odyssey for now
1 parent b0631e7 commit c63c348

File tree

6 files changed

+99
-4
lines changed

6 files changed

+99
-4
lines changed

Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,33 @@ public static async Task<string> Send(ThirdwebTransaction transaction)
357357

358358
var rpc = ThirdwebRPC.GetRpcInstance(transaction._wallet.Client, transaction.Input.ChainId.Value);
359359
string hash;
360-
if (await Utils.IsZkSync(transaction._wallet.Client, transaction.Input.ChainId.Value).ConfigureAwait(false) && transaction.Input.ZkSync.HasValue)
360+
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)
361387
{
362388
var zkTx = await ConvertToZkSyncTransaction(transaction).ConfigureAwait(false);
363389
var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet).ConfigureAwait(false);

Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ public ThirdwebTransactionInput(
2626
string data = null,
2727
BigInteger? maxFeePerGas = null,
2828
BigInteger? maxPriorityFeePerGas = null,
29-
ZkSyncOptions? zkSync = null
29+
ZkSyncOptions? zkSync = null,
30+
EIP7702Authorization? authorization = null
3031
)
3132
{
3233
this.ChainId = chainId > 0 ? new HexBigInteger(chainId) : throw new ArgumentException("Invalid Chain ID");
@@ -40,6 +41,7 @@ public ThirdwebTransactionInput(
4041
this.MaxFeePerGas = maxFeePerGas == null ? null : new HexBigInteger(maxFeePerGas.Value);
4142
this.MaxPriorityFeePerGas = maxPriorityFeePerGas == null ? null : new HexBigInteger(maxPriorityFeePerGas.Value);
4243
this.ZkSync = zkSync;
44+
this.AuthorizationList = authorization == null ? null : new List<EIP7702Authorization> { authorization.Value };
4345
}
4446

4547
/// <summary>
@@ -123,6 +125,11 @@ public string Data
123125
/// </summary>
124126
[JsonProperty(PropertyName = "zkSyncOptions", NullValueHandling = NullValueHandling.Ignore)]
125127
public ZkSyncOptions? ZkSync { get; set; }
128+
129+
#nullable enable
130+
[JsonProperty(PropertyName = "authorizationList", NullValueHandling = NullValueHandling.Ignore)]
131+
public List<EIP7702Authorization>? AuthorizationList { get; set; }
132+
#nullable disable
126133
}
127134

128135
/// <summary>
@@ -179,3 +186,34 @@ public ZkSyncOptions(string paymaster = null, string paymasterInput = null, BigI
179186
}
180187
}
181188
}
189+
190+
public struct EIP7702Authorization
191+
{
192+
[JsonProperty(PropertyName = "chainId")]
193+
public string ChainId { get; set; }
194+
195+
[JsonProperty(PropertyName = "address")]
196+
public string Address { get; set; }
197+
198+
[JsonProperty(PropertyName = "nonce")]
199+
public string Nonce { get; set; }
200+
201+
[JsonProperty(PropertyName = "yParity")]
202+
public string YParity { get; set; }
203+
204+
[JsonProperty(PropertyName = "r")]
205+
public string R { get; set; }
206+
207+
[JsonProperty(PropertyName = "s")]
208+
public string S { get; set; }
209+
210+
public EIP7702Authorization(BigInteger chainId, string address, BigInteger nonce, byte[] yParity, byte[] r, byte[] s)
211+
{
212+
this.ChainId = new HexBigInteger(chainId).HexValue;
213+
this.Address = address.EnsureHexPrefix();
214+
this.Nonce = new HexBigInteger(nonce).HexValue;
215+
this.YParity = yParity.BytesToHex();
216+
this.R = r.BytesToHex();
217+
this.S = s.BytesToHex();
218+
}
219+
}

Thirdweb/Thirdweb.Wallets/IThirdwebWallet.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Nethereum.ABI.EIP712;
1+
using System.Numerics;
2+
using Nethereum.ABI.EIP712;
23
using Newtonsoft.Json;
34

45
namespace Thirdweb;
@@ -150,7 +151,7 @@ Task<List<LinkedAccount>> LinkAccount(
150151
Action<string> browserOpenAction = null,
151152
string mobileRedirectScheme = "thirdweb://",
152153
IThirdwebBrowser browser = null,
153-
System.Numerics.BigInteger? chainId = null,
154+
BigInteger? chainId = null,
154155
string jwt = null,
155156
string payload = null
156157
);
@@ -166,6 +167,14 @@ Task<List<LinkedAccount>> LinkAccount(
166167
/// </summary>
167168
/// <returns>A list of <see cref="LinkedAccount"/> objects.</returns>
168169
Task<List<LinkedAccount>> GetLinkedAccounts();
170+
171+
/// <summary>
172+
/// Signs an EIP-7702 authorization to invoke contract functions to an externally owned account.
173+
/// </summary>
174+
/// <param name="chainId">The chain ID of the contract.</param>
175+
/// <param name="contractAddress">The address of the contract.</param>
176+
/// <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);
169178
}
170179

171180
/// <summary>

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,5 +931,10 @@ 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)
935+
{
936+
throw new NotImplementedException();
937+
}
938+
934939
#endregion
935940
}

Thirdweb/Thirdweb.Wallets/PrivateKeyWallet/PrivateKeyWallet.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Nethereum.Hex.HexConvertors.Extensions;
55
using Nethereum.Hex.HexTypes;
66
using Nethereum.Model;
7+
using Nethereum.RLP;
78
using Nethereum.Signer;
89
using Nethereum.Signer.EIP712;
910

@@ -385,5 +386,16 @@ public Task<List<LinkedAccount>> UnlinkAccount(LinkedAccount accountToUnlink)
385386
throw new InvalidOperationException("UnlinkAccount is not supported for private key wallets.");
386387
}
387388

389+
public async Task<EIP7702Authorization> SignAuthorization(BigInteger chainId, string contractAddress)
390+
{
391+
var nonce = await this.GetTransactionCount(chainId);
392+
var authorizationHash = Utils.HashMessage(
393+
Utils.HexConcat("0x05", RLP.EncodeList(new HexBigInteger(chainId).HexValue.HexToBytes(), contractAddress.HexToBytes(), new HexBigInteger(nonce).HexValue.HexToBytes()).BytesToHex()[2..])
394+
);
395+
var authorizationSignature = await this.PersonalSign(authorizationHash);
396+
var ecdsa = EthECDSASignatureFactory.ExtractECDSASignature(authorizationSignature);
397+
return new EIP7702Authorization(chainId, contractAddress, nonce, ecdsa.V, ecdsa.R, ecdsa.S);
398+
}
399+
388400
#endregion
389401
}

Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,5 +1225,10 @@ public async Task<List<LinkedAccount>> GetLinkedAccounts()
12251225
}
12261226
}
12271227

1228+
public Task<EIP7702Authorization> SignAuthorization(BigInteger chainId, string contractAddress)
1229+
{
1230+
return this._personalAccount.SignAuthorization(chainId, contractAddress);
1231+
}
1232+
12281233
#endregion
12291234
}

0 commit comments

Comments
 (0)