Skip to content
This repository was archived by the owner on Oct 20, 2024. It is now read-only.

Creating a UserOperation from scratch and then sending it to bundler for execution  #48

@iamgauravpant

Description

@iamgauravpant

I wanted to create a UserOperation from scratch and then send it to bundler . I am using stackup's bundler URL .
Below is the test I wrote to send a UserOperation to the bundler for inclusion but I am getting an error related to signature .
The smart account ( 0x1e87a1Eca600313aE1388D04e71ea473AD468CAE ) was created by calling SimpleAccountFactory contract deployed at 0x9406Cc6185a346906296840746125a0E44976454 .

Error Logged :
{
error: {
code: -32507,
data: null,
message: 'Invalid UserOp signature or paymaster signature'
},
id: 1,
jsonrpc: '2.0'
}

it("creating a user operation from scratch and then send it to bundler", async function () {
const EntryPoint_Addr = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789";
const RECEIVER_ADDR = "0x53C242Cc21d129155aCC5FAc321abDfe83C35Af7"; // sending ether to this address
const amount = '1000000000000000'; // amount to send to RECEIVER_ADDR

const sender = "0x1e87a1Eca600313aE1388D04e71ea473AD468CAE"; // smart account address , created by calling createAccount method of AccountFactory ( deployed at 0x9406Cc6185a346906296840746125a0E44976454 ) passing RECEIVER_ADDRESS as address and 1 as salt value
const nonce = '1'; // used salt's value as 1 at the time of smart account creation . that's why I kept it same .
const callGasLimit = '500000';
const verificationGasLimit = '200000';
const preVerificationGas = '50000';
const maxFeePerGas = '1000000000'; // adjust the value according to your needs
const maxPriorityFeePerGas = '100000000'; // adjust the value according to your needs
const account = new ethers.utils.Interface(accountABI); // ethers code
const calldata = account.encodeFunctionData('execute',[RECEIVER_ADDR, amount, "0x"]);
// calldata : 0xb61d27f600000000000000000000000053c242cc21d129155acc5fac321abdfe83c35af700000000000000000000000000000000000000000000000000038d7ea4c6800000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
    
// getUserOpHash function is taken from StackUp's UserOp library . Reference : https://github.com/stackup-wallet/userop.js/blob/main/src/context.ts
const getUserOpHash = () => {
            const packed = ethers.utils.defaultAbiCoder.encode(
              [
                "address",
                "uint256",
                "bytes32",
                "bytes32",
                "uint256",
                "uint256",
                "uint256",
                "uint256",
                "uint256",
                "bytes32",
              ],
              [
                sender,
                nonce,
                ethers.utils.keccak256('0x'),             ethers.utils.keccak256('0xb61d27f600000000000000000000000053c242cc21d129155acc5fac321abdfe83c35af700000000000000000000000000000000000000000000000000038d7ea4c6800000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000'),
                callGasLimit,
                verificationGasLimit,
                preVerificationGas,
                maxFeePerGas,
                maxPriorityFeePerGas,
                ethers.utils.keccak256('0x'),
              ]
            );
        
            const enc = ethers.utils.defaultAbiCoder.encode(
              ["bytes32", "address", "uint256"],
              [ethers.utils.keccak256(packed), EntryPoint_Addr, 80001]
            );
        
            return ethers.utils.keccak256(enc);
         }

         const userOpHash = getUserOpHash();
        //  userOpHash value : 0x1a23a91638f4a6c594c64b1b17bb930f9505c244b7a9cbc7065213bfccc71ba9

        // Arraified the userOpHash . Reference : https://github.com/stackup-wallet/userop.js/blob/main/src/preset/middleware/signature.ts
        
        const arraifiedHash =  ethers.utils.arrayify(userOpHash);
        console.log("arraified Hash :",arraifiedHash);
        const provider = new ethers.providers.JsonRpcProvider("https://polygon-mumbai.infura.io/v3/infurakey"); 
        const wallet = new ethers.Wallet('myprivatekey', provider);
        const signer = wallet.provider.getSigner(wallet.address);
        const serializeObj = JSON.stringify(arraifiedHash);   // **error suspect 1**
        const signature = signer.signMessage(serializeObj);

        const options = {
          method: "POST",
          url: "https://api.stackup.sh/v1/node/stackupkey",
          headers: {
            accept: "application/json",
            "content-type": "application/json",
          },
          data: {
            jsonrpc: "2.0",
            id: 1,
            method: "eth_sendUserOperation",
            params: [
              {
                sender: "0x1e87a1Eca600313aE1388D04e71ea473AD468CAE",
                nonce: "0x0",
                initCode: '0x',
                callData: "0xb61d27f600000000000000000000000053c242cc21d129155acc5fac321abdfe83c35af700000000000000000000000000000000000000000000000000038d7ea4c6800000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
                callGasLimit: "500000",
                verificationGasLimit: "200000",
                preVerificationGas: "50000",
                maxFeePerGas: "1000000000",
                maxPriorityFeePerGas: "100000000",
                paymasterAndData: "0x",
                signature:signature
              },
              "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
            ],
          },
        }; 
        await axios
          .request(options)
          .then(function (response) {
            console.log(response.data);
          })
          .catch(function (error) {
            console.error(error);
          });
});


Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions