matter-labs / foundry-zksync

Fork of Foundry tailored for zkSync environment
Apache License 2.0
298 stars 130 forks source link

Add paymaster support #560

Closed lutr0 closed 1 month ago

lutr0 commented 2 months ago

Component

Forge, Cast

Describe the feature you would like

I would love to be able to deploy a contract or send a transaction while using a paymaster.

Native AA is a core feature of zkSync Era, and with many zkchains coming (and projects trying to migrate their foundry repos), I see this as necessary to provide a good developer experience.

For example, Sophon will implement paymaster as a service solutions from the early days

Additional context

Currently it's possible to use the zksync-ethers and hardhat-zksync-deploy plugins to deploy a contract (also with proxy) or perform any transaction using a paymaster.

Example:

import { utils } from "zksync-ethers";
const deployer = new Deployer(hre, deployerWallet);
const params = utils.getPaymasterParams(  
    "0x950e3Bb8C6bab20b56a70550EC037E22032A413e", // Paymaster address  
    {  
      type: "General",  
      innerInput: new Uint8Array(),  
    }  
  );  
  
const erc20 = await deployer.deploy(erc20Artifact, ["USDC", "USDC", 18], {  
    customData: {  
      paymasterParams: params,  
      gasPerPubdata: utils.DEFAULT_GAS_PER_PUBDATA_LIMIT,  
    },  
  });
dutterbutter commented 1 month ago

Thanks @lutr0 ! Yes, paymaster and AA support is in the works.

dutterbutter commented 1 month ago

Related: https://github.com/matter-labs/foundry-zksync/pull/591, https://github.com/matter-labs/foundry-zksync/pull/596, https://github.com/matter-labs/foundry-zksync-book/pull/24

lutr0 commented 1 month ago

I see there have been some work on adding paymaster support. What is the recommended flow to deploy a contract using a paymaster?

Trying to deploy the standard Counter contract:

pragma solidity ^0.8.13;

import {Script, console} from "forge-std/Script.sol";
import {Counter} from "../src/Counter.sol";

contract CounterScript is Script {
    Counter public counter;
    address private paymaster;
    bytes private paymaster_encoded_input;

    function setUp() public {}

    function run() public {
        paymaster = address(0x950e3Bb8C6bab20b56a70550EC037E22032A413e);
        paymaster_encoded_input = abi.encodeWithSelector(
            bytes4(keccak256("general(bytes)")),
            bytes("0x")
        );
        vm.startBroadcast();
        (bool success, ) = address(vm).call(
            abi.encodeWithSignature(
                "zkUsePaymaster(address,bytes)",
                paymaster,
                paymaster_encoded_input
            )
        );
        require(success, "zkUsePaymaster call failed");

        counter = new Counter();

        vm.stopBroadcast();
    }
}

Returns me the error:

[⠒] Compiling...
[⠢] Compiling 1 files with Solc 0.8.27
[⠆] Solc 0.8.27 finished in 990.71ms
Compiler run successful!
[⠃] Using zksolc-1.5.3
[⠊] Compiling (zksync)
[⠑] Compiling 1 files with zksolc and solc 0.8.26
[⠘] zksolc and solc 0.8.26 finished in 3.57s
Compiler run successful!
2024-10-09T09:39:54.379528Z ERROR foundry_zksync_core::vm::inspect: tx execution halted: Paymaster validation error: Failed to transfer tx fee to the Bootloader. Paymaster balance might not be enough.
Traces:
  [383321] → new CounterScript@0x5b73C5498c1E3b4dbA84de0F1833c4a029d90519
    └─ ← [Return] 1804 bytes of code

  [97] CounterScript::setUp()
    └─ ← [Stop] 

  [150803] CounterScript::run()
    ├─ [0] VM::startBroadcast()
    │   └─ ← [Return] 
    ├─ [0] VM::zkUsePaymaster(0x950e3Bb8C6bab20b56a70550EC037E22032A413e, 0x8c5a3445000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000023078000000000000000000000000000000000000000000000000000000000000)
    │   └─ ← [Return] 
    ├─ [0] → new <unknown>@0xC7f2Cf4845C6db0e1a1e91ED41Bcd0FcC1b0E141
    │   ├─ [38557] 0x950e3Bb8C6bab20b56a70550EC037E22032A413e::validateAndPayForPaymasterTransaction(0x712848c4c7e7ad958d129cddd0f68b28ae53d6b0cbc623e8f708ab44ee12a5a1, 0xeef86b1b60ab2b97d0335858ffbfe8076a8d59804b06a1cdd8c65069440bb7bd, (113, 392798523078449971314983384720685506674972504705 [3.927e47], 32774 [3.277e4], 1073741824 [1.073e9], 20000 [2e4], 10000000000000 [1e13], 0, 850957037786513526690287050907908076139998495038 [8.509e47], 55, 0, [0, 0, 0, 0], 0x9c4d535b0000000000000000000000000000000000000000000000000000000000000000010000190d2dfa05e2ecec33b5b396d4a6cb9f02269f882d6055c0da36e7cedf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b, [0x010000190d2dfa05e2ecec33b5b396d4a6cb9f02269f882d6055c0da36e7cedf], 0x8c5a3445000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000023078000000000000000000000000000000000000000000000000000000000000, 0x))
    │   │   └─ ← [Revert] Failed to transfer tx fee to the Bootloader. Paymaster balance might not be enough.
    │   └─ ← [Revert] zk vm halted
    └─ ← [Revert] zk vm halted

Error: 
script failed: zk vm halted

This may be due to Sophon having a CBT, but paymaster balance shouldn't be a problem

dutterbutter commented 1 month ago

I know test usage was the first chunk of work to be delivered. I haven't tested script execution usage yet @Jrigada could you provide some insight here?

lutr0 commented 1 month ago

Update, @Jrigada and I were able to deploy successfully using a paymaster: e.g. https://explorer.testnet.sophon.xyz/tx/0xf48f01898c1db3e6542e389176b0fed5343d6aa818373b50389b53c59eaeb393

Closing this issue, thanks for the great work