Bundle Requirements

Transaction Requirements for Solver Operations

  1. Gas Parameters for userOpHash Generation

    • Legacy Transactions:

      • gasPrice: Must match the opportunity-creating transaction.

    • Type 2 (EIP-1559) Transactions:

      • maxFeePerGas and maxPriorityFeePerGas: Must match the opportunity-creating transaction.

    • Implementation:

      • Ensure meta transactions (EIP-712) use gas parameters identical to the opportunity-creating transaction to accurately generate userOpHash.

  2. userOpHash Generation

    • Purpose: Identifies the opportunity transaction in the PFL-Auction context

    • Procedure:

      • Call the PFL-Auction dAppControl contract with the matched gas parameters.

      • The transaction type influences the gas parameters used but does not need separate handling.

  3. Solver Operation Handling

    • Behavior:

      • Does not differentiate between legacy and Type 2 transactions.

      • Relies solely on the correctly generated userOpHash for processing.

    • Implications:

      • No adjustments needed within the solver for different transaction types.

Please follow Bundle Format guide for more detailed guide for Solver Operation

The Example below show how to obtain the correct userOpHash to be passed as reference ot the targeted opportunity transaction.

import { Contract, Interface, JsonRpcProvider, keccak256, parseEther, TypedDataDomain, Wallet } from "ethers";


const provider = new JsonRpcProvider("https://polygon.llamarpc.com");

const dappControlAddr = "0x3e23e4282FcE0cF42DCd0E9bdf39056434E65C1F"; // current dappControl address (review docs)
const PFLControlAbi = [
  {
    "inputs": [
      { "internalType": "bytes32", "name": "oppTxHash", "type": "bytes32" },
      { "internalType": "uint256", "name": "oppTxMaxFeePerGas", "type": "uint256" },
      { "internalType": "uint256", "name": "oppTxMaxPriorityFeePerGas", "type": "uint256" },
      { "internalType": "address", "name": "fastLaneSigner", "type": "address" }
    ],
    "name": "getBackrunUserOpHash",
    "outputs": [{ "internalType": "bytes32", "name": "userOpHash", "type": "bytes32" }],
    "stateMutability": "view",
    "type": "function"
  },
];
const dappControl = new Contract(dappControlAddr, PFLControlAbi, provider);


async function main() {
  const feeData = await provider.getFeeData();

  const opportunityRawTx = "0x000"; //binary string of opportunity tx
  const isLegacyTx = isLegacy(opportunityRawTx);
  
  //match opportunity tx transaction type
  const maxFeePerGas = isLegacyTx ? feeData.gasPrice: feeData.maxFeePerGas;
  const maxPriorityFeePerGas = isLegacyTx ? feeData.gasPrice : feeData.maxPriorityFeePerGas,
   
  // Get the userOpHash for the opportunity tx calling the PFL dappControl contract
  //NOTE: we need to use the same transaction type as the opportunity tx
  const userOpHash = await dappControl.getBackrunUserOpHash(
      keccak256(opportunityRawTx),
      maxFeePerGas,
      maxPriorityFeePerGas,
      dAppOpSignerAddr
  );
  
  // additional code for generation of the solver operation and bidSubmission
  
}

main().catch(console.error);

Last updated