Skip to content

Support EIP 7702 #4916

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
chaitanyapotti opened this issue Jan 14, 2025 · 26 comments
Open

Support EIP 7702 #4916

chaitanyapotti opened this issue Jan 14, 2025 · 26 comments
Labels
enhancement New feature or improvement. fixed/complete This Bug is fixed or Enhancement is complete and published. v6 Issues regarding v6

Comments

@chaitanyapotti
Copy link

Describe the Feature

Add support for tx type 0x04 and authorization_list in transaction types

https://eips.ethereum.org/EIPS/eip-7702

Code Example

No response

@chaitanyapotti chaitanyapotti added the enhancement New feature or improvement. label Jan 14, 2025
@ricmoo
Copy link
Member

ricmoo commented Jan 14, 2025

Oh! Is it finally deployed on a testnet? I’ve been waiting for that, as that is a good indication the spec of likely done changing. Plus it enables trying it out to test it. :)

Initially this will be available on signer._authorization() and once official, will be signer.authorization().

@ricmoo ricmoo added on-deck This Enhancement or Bug is currently being worked on. v6 Issues regarding v6 next-patch Issues scheduled for the next arch release. labels Jan 14, 2025
@Oxbobby
Copy link

Oxbobby commented Jan 16, 2025

@ricmoo it's deployed on Pectra Devnet, Odyssey and a few others. Looking forward to this

@marcelomorgado
Copy link

FYI https://blog.ethereum.org/2025/02/14/pectra-testnet-announcement

It will go live on Holesky at epoch 115968 (Feb. 24, 21:55 UTC) and then on Sepolia at epoch 222464 (Mar. 5, 7:29 UTC).

@ricmoo
Copy link
Member

ricmoo commented Feb 21, 2025

Thanks! Yes, I have a local implementation (in BaseWallet and Transaction) ready to release on the 24th once I can test it out. :)

@Mannan-Goyal
Copy link

@ricmoo let me know if this requires any contribution, as I've already tested this out on mekong

@Phillip-Kemper
Copy link

any way I can initiate the new transaction type already with ethers?

@ricmoo
Copy link
Member

ricmoo commented Mar 5, 2025

Almost. I have a PR I'll be pushing up later. I'm just waiting for it to go live on Sepolia so I can make sure my tests work. :)

@ricmoo
Copy link
Member

ricmoo commented Mar 5, 2025

Does anyone know of a JSON-RPC endpoint for Sepolia that this works on? It should have definitely activated by now. I've tried Infura, but I get the error:

// Error:
{
  code: -32602,
  message: 'transaction could not be decoded: unsupported transaction type'
}

// Payload:
{
  method: 'eth_sendRawTransaction',
  params: [
    '0x04f8c383aa36a70e80808252089401234567890123456789012345678901234567898080c0f85cf85a809401234567890123456789012345678901234567898080a0f063d1abb04fa98cfa4dfd92d509efcd398ab63b6d9c2944a1827d631f310b50a065c40ea1fa228700da4a53bdd1fc94d2b67ee23121466af3cf56f37ecc70c37a01a074c7c3b64a353009ab12c1c81406e381c83a7452be4513c23356816922e09c38a052d74f0486ac363f2c83b4dca8f099f09d3400a7469efb553195efa6fe94aca8'
  ],
  id: 8,
  jsonrpc: '2.0'
}

But that could just mean my encoding is incorrect or there is some other issue and the error is half red-herring. If someone has a know good JSON-RPC endpoint, it'd be appreciated. :)

ricmoo added a commit that referenced this issue Mar 10, 2025
@ricmoo
Copy link
Member

ricmoo commented Mar 10, 2025

I've added a branch with initial support. I'm going to test it a bit more and then publish it as an alpha release on npm.

@ricmoo
Copy link
Member

ricmoo commented Mar 10, 2025

To use it:

// You may optionally specify a nonce and chainId; if omitted the current provider is used
// to get the chain ID and nonce. A chainID of 0 must be explicitly set.
const auth = await authSigner.authorize({ address })

// The sending wallet can be the same signer or any other signer
const tx = await sendSigner.sendTransaction({
  type: 4,
  to: someAddress,
  authorizationList: [ auth ]
});
console.log(tx);

const receipt = await tx.wait();
console.log(receipt);

@marcelomorgado
Copy link

Is there a way to delegate and call in the same tx, something like this?

import { parseEther } from 'viem'
import { walletClient } from './config'
import { abi, contractAddress } from './contract'
 
// 1. Authorize injection of the Contract's bytecode into our Account.
const authorization = await walletClient.signAuthorization({
  contractAddress,
})
 
// 2. Invoke the Contract's `execute` function to perform batch calls.
const hash = await walletClient.sendTransaction({
  authorizationList: [authorization],
  data: encodeFunctionData({
    abi,
    functionName: 'execute',
    args: [
      [
        {
          data: '0x',
          to: '0xcb98643b8786950F0461f3B0edf99D88F274574D',
          value: parseEther('0.001'),
        },
        {
          data: '0x',
          to: '0xd2135CfB216b74109775236E36d4b433F1DF507B', 
          value: parseEther('0.002'), 
        },  
      ],
    ]
  }),
  to: walletClient.account.address,
})

Refs: https://viem.sh/experimental/eip7702/sending-transactions

@ricmoo
Copy link
Member

ricmoo commented Mar 10, 2025

Yes, the above code (converted to ethers syntax) would work just fine on the new branch.

But if that is a common pattern, I think it also makes sense to add authorizationList to the ContractOverrides interface, so a more object-oriented usage can be used like contract.execute([ arg0, arg1 ], { authorizationList: [ authorization ] }). I can add that to the Contract class tomorrow. :)

@Amxx
Copy link

Amxx commented Mar 10, 2025

Having that in the contract class is a must IMO

@jxom
Copy link

jxom commented Mar 10, 2025

It is worth noting in the current Ethers implementation that the below usage will break when authSigner is the actor signing the authorization and sending the transaction as the authorization tuple’s nonce must be incremented by an extra one (ie. the next nonce after the 7702 tx).

const auth = await authSigner.authorize({ address })

const tx = await authSigner.sendTransaction({
  type: 4,
  to: someAddress,
  authorizationList: [ auth ]
});
console.log(tx);

const receipt = await tx.wait();
console.log(receipt);

@ricmoo
Copy link
Member

ricmoo commented Mar 11, 2025

Good to know! Thanks. Does Viem have special logic to detect this and populate it? Or does it rely on the authSigner to manually supply the bumped nonce?

@jxom
Copy link

jxom commented Mar 11, 2025

There's no special logic unfortunately – we have a sponsor flag on signAuthorization (a la authorize) which will indicate that the authorization will be executed by another signer. Our 7702 is still experimental, so still thinking about the best approach for this though.

It's a shame that this behavior isn't handled on the execution layer though.

@ricmoo
Copy link
Member

ricmoo commented Mar 11, 2025

Yeah. Ditto, still experimenting with ideas.

I wonder if it would make sense to have some sort of DeferredNonce object or callback that TransactionRequest would allow in authorizationList items, which would get called with the populated transaction, giving it a chance to update before the actually signing based on the populated transaction…

Something like (tx: TransactionRequest) => Promise<Authorization> and a helper function that takes in a Signer and returns a function that checks if the tx.from matches, account for it, otherwise use the default action.

@jxom
Copy link

jxom commented Mar 11, 2025

Yeah, I thought about getting smart like that. I wonder if the implementation complexity is worth it though if this feature will only be used by Wallets (who I would assume know what they are doing :P) – whereby, the current Ethers implementation would be fine, and they can just increment the nonce themself if they want the EOA to self-upgrade... and maybe self-upgrading wouldn't be a much common case anyway?

@douglance
Copy link

will this ship for both v5 and v6?

@ricmoo
Copy link
Member

ricmoo commented Apr 1, 2025

@douglance

This is already available in v6 (on the experimental eip-7703 branch and the npm beta-eip-7702 tagged version).

There are no plans to make any feature changes to v5. There was recently a v5 release to address two security concerns in its dependencies (keep in mind the elliptic issue did not actually affect Ethers, but did trigger audit warnings), prior to that the v5 code has not been touched in 3 years.

In general, any new projects should be using v6, which has new features added as the Ethereum networks add them (recent examples include BLoB and EIP-7702 support). The v5 code is primarily maintained for those that require pre-2017 era browser support. If you need any help migrating to v6 though, please reach out. :)

@yann300
Copy link

yann300 commented May 1, 2025

Is there any date for including this in a release?

@ricmoo
Copy link
Member

ricmoo commented May 1, 2025

This is available on npm via the above tag and I believe the release on mainnet is scheduled for May 8th.

I haven’t had any negative feedback yet for the current API and know it’s been in use, so I plan to get it out in the latest tag in the next couple of days. :)

But please try it out and provide any additional feedback. :)

@ernestognw
Copy link

Hey @ricmoo, I see 6.13.7 was released a few days ago.

Currently, I'm trying to enable 6.13.6-beta.1 to use authorizations in OZ Contracts. However, on every installation it jumps straight to 6.13.7 so I gotta fix the version package. All this is cool, but fixing the version creates a dependency conflict:

npm error code ERESOLVE
npm error ERESOLVE could not resolve
npm error
npm error While resolving: @nomicfoundation/[email protected]
npm error Found: [email protected]
npm error node_modules/ethers
npm error   dev ethers@"6.13.6-beta.1" from the root project
npm error
npm error Could not resolve dependency:
npm error peer ethers@"^6.1.0" from @nomicfoundation/[email protected]
npm error node_modules/@nomicfoundation/hardhat-chai-matchers
npm error   dev @nomicfoundation/hardhat-chai-matchers@"^2.0.6" from the root project
npm error
npm error Conflicting peer dependency: [email protected]
npm error node_modules/ethers
npm error   peer ethers@"^6.1.0" from @nomicfoundation/[email protected]
npm error   node_modules/@nomicfoundation/hardhat-chai-matchers
npm error     dev @nomicfoundation/hardhat-chai-matchers@"^2.0.6" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry
npm error this command with --force or --legacy-peer-deps

As seen in this PR, we'll rely on --legacy-peer-deps for now. But, it'd be cool if we can have a 6.3.8 with 7702 support soon, otherwise a 6.3.8-beta.1 just to get rid of the dependency issue would be fine

@ricmoo
Copy link
Member

ricmoo commented May 7, 2025

The v6.13.6 version was meant to be a -beta.1 release and is identical to the release at the tag beta-eip-7702. The v6.13.6 was never made latest intentionally. The Changeling has been updated.

That said, v6.14.0 is now latest on npm, which has EIP-7702 support, so you no longer need to use the beta-eip-7702 tag. The standard release has it.

Let me know how your EIP-7702 adventures go. :)

@ricmoo ricmoo added fixed/complete This Bug is fixed or Enhancement is complete and published. and removed on-deck This Enhancement or Bug is currently being worked on. next-patch Issues scheduled for the next arch release. labels May 7, 2025
@ernestognw
Copy link

All working good now, thanks @ricmoo 😄

@smallyunet
Copy link

smallyunet commented May 7, 2025

Why can't I send a type 4 transaction using a different "from" address?

  const tx = await c.sendTransaction({
    type: 4,
    from: a.address,
    authorizationList: [auth],
    paymaster: PAYMASTER,
    paymasterInput: "0x",
    to: B,
    value: parseEther("100"),
    gasLimit: 120_000
  });

  console.log("hash =", tx.hash);
  const rcpt = await tx.wait();
  console.log("gasUsed =", rcpt.gasUsed.toString());

And get error:

TypeError: transaction from mismatch (argument="tx.from", value="0x8943545177806ED17B9F23F0a21ee5948eCaa776", code=INVALID_ARGUMENT, version=6.14.0)
    at makeError (file:///Users/smallyu/work/github/eip-7702-demo/node_modules/ethers/lib.esm/utils/errors.js:117:21)
    at assert (file:///Users/smallyu/work/github/eip-7702-demo/node_modules/ethers/lib.esm/utils/errors.js:143:15)
    at assertArgument (file:///Users/smallyu/work/github/eip-7702-demo/node_modules/ethers/lib.esm/utils/errors.js:154:5)
    at file:///Users/smallyu/work/github/eip-7702-demo/node_modules/ethers/lib.esm/providers/abstract-signer.js:29:13
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 1)
    at async resolveProperties (file:///Users/smallyu/work/github/eip-7702-demo/node_modules/ethers/lib.esm/utils/properties.js:33:21)
    at async populate (file:///Users/smallyu/work/github/eip-7702-demo/node_modules/ethers/lib.esm/providers/abstract-signer.js:36:12)
    at async Wallet.populateTransaction (file:///Users/smallyu/work/github/eip-7702-demo/node_modules/ethers/lib.esm/providers/abstract-signer.js:64:21)
    at async Wallet.sendTransaction (file:///Users/smallyu/work/github/eip-7702-demo/node_modules/ethers/lib.esm/providers/abstract-signer.js:196:21) {
  code: 'INVALID_ARGUMENT',
  argument: 'tx.from',
  value: '0x8943545177806ED17B9F23F0a21ee5948eCaa776',
  shortMessage: 'transaction from mismatch'
}

ethersjs version:

    "ethers": "^6.14.0"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or improvement. fixed/complete This Bug is fixed or Enhancement is complete and published. v6 Issues regarding v6
Projects
None yet
Development

No branches or pull requests