Git Product home page Git Product logo

alto's People

Contributors

0xmonkeyy avatar alvrs avatar github-actions[bot] avatar hilliamt avatar kristofgazso avatar mouseless-eth avatar nikmel2803 avatar pavlovdog avatar plusminushalf avatar shuoer86 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

alto's Issues

Argument --max-gas-per-bundle doesn't affect anything

Describe the bug
Hello there

Right now I'm working on a tool, that could activate a huge amount of smart accounts derived from one deployer address. Basically I'm sending all of them without waiting for the transaction to be minted and then waiting for the userOp statuses to become included into . But I faced an issue, where I have a lot of userOps in the state non_submited, which means that they are in mempool waiting to be included in the bundle. And they do but only like 4-5 userOps at a time.

So I started researching how to increase a bandwidth and found those flags: max-gas-per-bundle and mempool-max-parallel-ops. After increasing default values of it -- nothing happened. And I tried to reduce it to the ridiculously low value of 5 which I assumed will make bundler to not include any transaction to the bundle. But nothing happened again, I had the same 4-5 userOps at a time.

So is there any problem with this argument, or an issue with the bandwidth is in something else?

To Reproduce
Try to send a lot of transactions to the bundler and then wait for them to be mined.

The way I used to start bundler:

node src/lib/cli/alto.js run "--port" "3000" "--network-name" "mainnet" "--entrypoints" "0x" "--executor-private-keys" "0x" "--utility-private-key" "0x" "--min-executor-balance" "1000000000000000000" "--rpc-url" "http://eth_node:8545" "--log-level" "info" "--safe-mode" "false" "--max-gas-per-bundle" "5" "--mempool-max-parallel-ops" "50"

Expected behavior
With a increase of max-gas-per-bundle argument, amount of time for the processing of all userOps should be decreased

Environment:

  • Bundler Image: ghcr.io/pimlicolabs/alto:v1.2.0
  • Ethereum Node Image: ghcr.io/foundry-rs/foundry:nightly-156cb1396b7076c6f9cb56f3719f8c90f7f52064

Refilling wallet throws an error and causes process to exit

Describe the bug

The process exits when refilling the wallet due to a "replacement transaction underpriced" error.

Expected behavior

Regardless of any transaction failures, the bundler shouldn't shut down.

Screenshots

{"level":30,"time":1697786179976,"pid":1061950,"hostname":"PublicSale","module":"executor","tx":"0xd5f39c3dd30e7275bc1e811df91070db9b2baaab4d03bb3ab2a4daffa1bb6499","executor":"0x072a207D1Ec56D4A60FdBaD6e72B605c6CAD60C2","missingBalance":"0x670aeafb69165bb40","msg":"refilled wallet"}
/home/testnet/endurance/aa/alto-priv/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/viem/dist/cjs/utils/errors/getTransactionError.js:11
    return new transaction_js_1.TransactionExecutionError(cause, {
           ^

TransactionExecutionError: Missing or invalid parameters.
Double check you have provided the correct parameters.

URL: http://**********:3334/
Request body: {"method":"eth_sendRawTransaction","params":["0x02f8788501823cf7e88202cd830f4248830f424882520894f1b4a63eaedce2283e33f2a6ed52005ea385ea15890670aeaf0994e6d34080c080a0bba113532b5b3c16796a8d329c8d708e2624d6596725d6a718ca721d83942266a05cd6b3f72fb70144e961b5a7936f4f6627f23edc66243fe1ec43ad0b2fa08a37"]}
 
Request Arguments:
  from:                  0xA949e80F95F27f64C7b7cE33711A43304c6aAAc4
  to:                    0xF1B4a63EAedcE2283e33f2a6ed52005eA385ea15
  value:                 118.800084076140614464 ETH
  maxFeePerGas:          0.001000008 gwei
  maxPriorityFeePerGas:  0.001000008 gwei

Details: replacement transaction underpriced
Version: [email protected]
    at getTransactionError (/home/testnet/endurance/aa/alto-priv/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/viem/dist/cjs/utils/errors/getTransactionError.js:11:12)
    at sendTransaction (/home/testnet/endurance/aa/alto-priv/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/viem/dist/cjs/actions/wallet/sendTransaction.js:77:64)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async SenderManager.validateAndRefillWallets (/home/testnet/endurance/aa/alto-priv/packages/executor/lib/senderManager.js:108:32)
    at async Timeout._onTimeout (/home/testnet/endurance/aa/alto-priv/packages/cli/lib/handler.js:227:9) {
  details: 'replacement transaction underpriced',
  docsPath: undefined,
  metaMessages: [
    'URL: http://**********:3334/',
    'Request body: {"method":"eth_sendRawTransaction","params":["0x02f8788501823cf7e88202cd830f4248830f424882520894f1b4a63eaedce2283e33f2a6ed52005ea385ea15890670aeaf0994e6d34080c080a0bba113532b5b3c16796a8d329c8d708e2624d6596725d6a718ca721d83942266a05cd6b3f72fb70144e961b5a7936f4f6627f23edc66243fe1ec43ad0b2fa08a37"]}',
    ' ',
    'Request Arguments:',
    '  from:                  0xA949e80F95F27f64C7b7cE33711A43304c6aAAc4\n' +
      '  to:                    0xF1B4a63EAedcE2283e33f2a6ed52005eA385ea15\n' +
      '  value:                 118.800084076140614464 ETH\n' +
      '  maxFeePerGas:          0.001000008 gwei\n' +
      '  maxPriorityFeePerGas:  0.001000008 gwei'
  ],
  shortMessage: 'Missing or invalid parameters.\n' +
    'Double check you have provided the correct parameters.',
  version: '[email protected]',
  cause: InvalidInputRpcError: Missing or invalid parameters.
  Double check you have provided the correct parameters.
  
  URL: http://**********:3334/
  Request body: {"method":"eth_sendRawTransaction","params":["0x02f8788501823cf7e88202cd830f4248830f424882520894f1b4a63eaedce2283e33f2a6ed52005ea385ea15890670aeaf0994e6d34080c080a0bba113532b5b3c16796a8d329c8d708e2624d6596725d6a718ca721d83942266a05cd6b3f72fb70144e961b5a7936f4f6627f23edc66243fe1ec43ad0b2fa08a37"]}
  
  Details: replacement transaction underpriced
  Version: [email protected]
      at delay.count.count (/home/testnet/endurance/aa/alto-priv/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/viem/dist/cjs/utils/buildRequest.js:46:27)
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
      at async attemptRetry (/home/testnet/endurance/aa/alto-priv/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/viem/dist/cjs/utils/promise/withRetry.js:15:30) {
    details: 'replacement transaction underpriced',
    docsPath: undefined,
    metaMessages: [
      'URL: http://**********:3334/',
      'Request body: {"method":"eth_sendRawTransaction","params":["0x02f8788501823cf7e88202cd830f4248830f424882520894f1b4a63eaedce2283e33f2a6ed52005ea385ea15890670aeaf0994e6d34080c080a0bba113532b5b3c16796a8d329c8d708e2624d6596725d6a718ca721d83942266a05cd6b3f72fb70144e961b5a7936f4f6627f23edc66243fe1ec43ad0b2fa08a37"]}'
    ],
    shortMessage: 'Missing or invalid parameters.\n' +
      'Double check you have provided the correct parameters.',
    version: '[email protected]',
    cause: RpcRequestError: RPC Request failed.
    
    URL: http://**********:3334/
    Request body: {"method":"eth_sendRawTransaction","params":["0x02f8788501823cf7e88202cd830f4248830f424882520894f1b4a63eaedce2283e33f2a6ed52005ea385ea15890670aeaf0994e6d34080c080a0bba113532b5b3c16796a8d329c8d708e2624d6596725d6a718ca721d83942266a05cd6b3f72fb70144e961b5a7936f4f6627f23edc66243fe1ec43ad0b2fa08a37"]}
    
    Details: replacement transaction underpriced
    Version: [email protected]
        at request (/home/testnet/endurance/aa/alto-priv/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/viem/dist/cjs/clients/transports/http.js:40:27)
        at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
        at async delay.count.count (/home/testnet/endurance/aa/alto-priv/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/viem/dist/cjs/utils/buildRequest.js:30:20)
        at async attemptRetry (/home/testnet/endurance/aa/alto-priv/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/viem/dist/cjs/utils/promise/withRetry.js:15:30) {
      details: 'replacement transaction underpriced',
      docsPath: undefined,
      metaMessages: [
        'URL: http://**********:3334/',
        'Request body: {"method":"eth_sendRawTransaction","params":["0x02f8788501823cf7e88202cd830f4248830f424882520894f1b4a63eaedce2283e33f2a6ed52005ea385ea15890670aeaf0994e6d34080c080a0bba113532b5b3c16796a8d329c8d708e2624d6596725d6a718ca721d83942266a05cd6b3f72fb70144e961b5a7936f4f6627f23edc66243fe1ec43ad0b2fa08a37"]}'
      ],
      shortMessage: 'RPC Request failed.',
      version: '[email protected]',
      cause: { code: -32000, message: 'replacement transaction underpriced' },
      code: -32000
    },
    code: -32000
  }
}

Node.js v20.1.0
 ELIFECYCLE  Command failed with exit code 1.

Desktop (please complete the following information):

  • Versio: latest

Safe Account with custom ERC1271 owner contract may bypass EIP7562 storage validation rules

Describe the bug

So far, according to EIP-7562, arbitrary storage access is forbidden unless some requirements are met. One of this is that read-only storage in non-entity contracts is allowed only if the entity is staked:

If the entity (paymaster, factory) is staked, then it is also allowed:
...

  • [STO-033] Read-only access to any storage in non-entity contract.

The issue (not sure if a bug or a feature) is that I've been playing with the idea of using ERC-1271 to set smart contract owners of smart contract wallets and I'm not sure whether the bundler allows for bypassing the storage validation rules.

Particularly, I've been using the ERC4337 module for Safe, which supports isValidSignature through their checkSignatures method that eventually checks the contract signature. This way I've been using a custom smart contract signer similar to the following:

contract P256Identity is IERC1271 {
    using P256 for bytes32;

    // bytes4(keccak256("isValidSignature(bytes,bytes)")
    bytes4 internal constant EIP1271_MAGIC_VALUE = 0x20c13b0b;

    struct PublicKey {
        bytes32 qx;
        bytes32 qy;
    }

    PublicKey publicKey;

    constructor(bytes32 qx, bytes32 qy) {
        publicKey = PublicKey(qx, qy);
    }

    function isValidSignature(
        bytes32 digest,
        bytes memory signature
    ) external view returns (bytes4) {
        return
            _verifyP256Identity(digest, signature)
                ? EIP1271_MAGIC_VALUE
                : bytes4(0);
    }

    function _verifyP256Identity(
        bytes32 digest,
        bytes memory signature
    ) internal view returns (bool) {
        PublicKey memory pubKey = publicKey();

        (uint256 r, uint256 s) = _splitSignature(signature);

        if (normalize) {
            digest = sha256(abi.encode(digest));
        }

        return digest.verify(digest, r, s, pubKey.qx, pubKey.qy);
    }
    function _splitSignature(
        bytes memory signature
    ) private pure returns (uint256 r, uint256 s) {
        r = uint256(bytes32(signature[00:31]));
        s = uint256(bytes32(signature[32:63]));
    }
}

After testing it out a couple of times (here's a test tx in Arbitrum) it's been working fine so far but I can't reason why.

The rationale of the validation rules is that it shouldn't be possible to create spam UserOperations (i.e. that fail due to a storage change), although that's impossible for this tiny contract (because storage can't be changed) then it should be possible to craft an operation that does change storage between the validation and execution.

To Reproduce

Reproducing the transaction I shared is quite difficult as it requires a custom off-chain signer, but here's the execution diagram according to the test tx I'm sharing: https://sepolia.arbiscan.io/tx/0x924257e84890082d39daeb9c34bd5839a559b13be06a93cb7597f6a58f59c6d5

sequenceDiagram
    EntryPoint ->> SafeWallet1.4.1: validateUserOp()
    SafeWallet1.4.1 ->> P256Identity: isValidSignature()
    P256Identity -->> P256Identity: sload public key slots
    Note right of P256Identity: Aren't validation rules violated here?
    P256Identity ->> SafeWallet1.4.1: success
    SafeWallet1.4.1 ->> EntryPoint: success
Loading

Expected behavior

Not sure whether it should be possible in the first place.

Additional Context

Seems like the corresponding rules is enabled:

} else if (writes[slot] === undefined) {
// [STO-033]: staked entity have read-only access to any storage in non-entity contract.

Add mempool persistence logic using Redis

NOTE: Lower priority

Currently we don't persist incoming UserOperations in a mempool, and send them straight to be included on-chain. This is not a big problem right now because there isn't enough volume on-chain to justify waiting for multiple UserOperations until submission for inclusion, but this is required to be compliant with the spec.

Let's create a persistent mempool using Redis with ioredis

[Help] Unable to estimateUserOperationGas

Hi, very appreciate this great work.
However, I am trying to use alto on a local testnet and could not make estimateUserOperation json-rpc work. The error message is: Cannot decode zero data ("0x") with ABI parameters..

I investigated the code of alto and found that alto seems to call callExecute function in EntryPoint address during simulateHandleOp:

const targetCallData = encodeFunctionData({
abi: ExecuteSimulatorAbi,
functionName: "callExecute",
args: [userOperation.sender, userOperation.callData, 2_000_000n]
})
userOperation.callGasLimit = 0n
const error = await simulateHandleOp(userOperation, entryPoint, publicClient, true, entryPoint, targetCallData)

I don't think there is a function called callExecute in the entrypoint. Then I notice there is a special parameter in the RPC parameters called finalParam, which seems to instruct the RPC backend to replace the bytecode of entrypoint to a given ExecuteSimulator code.

const finalParam = replacedEntryPoint
? {
[userOperation.sender]: {
balance: toHex(100000_000000000000000000n)
},
[entryPoint]: {
code: ExecuteSimulatorDeployedBytecode
}
}
: {
[userOperation.sender]: {
balance: toHex(100000_000000000000000000n)
}
}
try {
await publicClient.request({
method: "eth_call",
params: [
// @ts-ignore
{
to: entryPoint,
data: encodeFunctionData({
abi: EntryPointAbi,
functionName: "simulateHandleOp",
args: [userOperation, targetAddress, targetCallData]
}),
gas: toHex(20_000_000)
},
// @ts-ignore
"latest",
// @ts-ignore
finalParam
]
})
} catch (e) {

Is this contract bytecode replacement feature in the Ethereum JSON-RPC standard? Or are you using a customized Ethereum node to handle such RPCs? How can I make this work on a local testnet (e.g., anvil)?

Fix arbitrum gas calculation

Arbitrum calculates gas usage differently than other chains, as explained here. Currently we just hardcode a gas usage multiple, but we should precisely calculate the actual gas limit to use based on Arbitrum's formula.

Custom EVM Support

Hello guys,

Is there any guide on how to deploy this bundler in custom EVM networks?

Add `pimlico_getUserOperationGasPrice` endpoint

Currently, most wallets call eth_gasPrice to get a reasonable value for gas price for their user operations. However, in order for the bundler to be profitable, it needs to bundle User Operations with a gas price that is higher than the gas price of the transaction bundling the ops.

Instead of asking wallets to guess a good gas price to use, it would be better to expose an api that they can use to get a good value for what will be (statistically) acceptable for our bundler, including an overhead that gives the bundler some wiggle room in case gas prices increase.

This API endpoint could return a safeLow, standard, and fast gas prices, likely perhaps ranging from 10-20% on top of the normal gas prices the bundler would typically use (depending on network conditions and the speed chosen by the user: safeLow, standard, or fast).

Useful example from polygon/mumbai: https://wiki.polygon.technology/docs/tools/faucets/polygon-gas-station/

Might be good to standardize this endpoint over time and move it into the eth_ namespace so it's not pimlico specific.

Alto Bundler local run - Issue/Instruction updates

Describe the bug
Detailed steps to Run bundler with command line arguments
current instruction in readme guide doesn't mention about passing command line args (yargs)

it gives

./alto

this runs in to error:

> [email protected] start /Users/kanth/Documents/defi/account-abstraction/pimlico/alto
> node packages/cli/lib/alto.js run

 ✖ Missing required arguments: entryPoint, signerPrivateKeys, utilityPrivateKey, minBalance, rpcUrl

Suggestion

  1. For local run need steps to deploy entryPoint on geth node / hardhat node

It would be nice to have instructions:

  1. run geth node
  2. deploy essential contracts on geth/local node
  3. capture the privateKeys of local node which can be signerPrivateKey

@plusminushalf

Gas limit estimation is broken by [email protected]

Description

We are running Alto in a container locally alongside geth node as an infra for our AA tests. After switching to newer versions of go-ethereum, we have noticed that Alto is failing to estimate the callGasLimit properly.

To Reproduce

Steps to reproduce the behavior:

  1. Start up geth locally
  2. Deploy infra contracts (EntryPoint, SW, SW Factory etc)
  3. Start Alto locally, supplying the EntryPoint and other necessary info
  4. All eth_estimateUserOperationGas calls result in callGasLimit estimated to 9000, which leads to OOG errors in userop execution.

Expected behavior

Alto estimates callGasLimit correctly, so that userop is executed successfuly.

Versions

  • OS: macOS v14.1.2
  • Alto: v1.0.1, with balanceOverride = false
  • Go-ethereum: 1.13.14
  • Geth node: without eth_call overrides support

Reason

We have found that a magic number 9000 is used when estimated callGasLimit is lower than 9000. Given our geth and Alto settings, Alto uses viem to call EntryPoint.simulateHandleOp, which does NOT set gasPrice, feePerGas and priorityFeePerGas to eth_call call.

[email protected] introduced a change to block.basefee logic in the vm in the eth_call, eth_estimateGas etc. contexts: if gasPrice is not specified, then block.basefee returns 0. This is very important for the Alto Bundler, because its gas estimation depends on EntryPoint.simulateHandleOp, which uses block.basefee.

Currently, without specifying gasPrice when calling EntryPoint.simulateHandleOp, it returns paid equal to gasUsed * maxPriorityFeePerGas (without adding block.baseFee), which results in callGasLimit calculated to ~-1500000.

Fix

As specified in the go-ethereum PR, specifying gasPrice in eth_call is sufficient. Indeed, after changing

const errorResult = await entryPointContract.simulate
    .simulateHandleOp(
        [
            userOperation,
            "0x0000000000000000000000000000000000000000",
            "0x"
        ],
        {
            account: this.utilityWallet
        }
    )

in packages/rpc/src/validation/validator.ts to

const errorResult = await entryPointContract.simulate
    .simulateHandleOp(
        [
            userOperation,
            "0x0000000000000000000000000000000000000000",
            "0x"
        ],
        {
            account: this.utilityWallet,
            gasPrice: userOperation.maxFeePerGas,
            feePerGas: userOperation.maxFeePerGas,
            priorityFeePerGas: userOperation.maxPriorityFeePerGas,
        }
    )

Alto's gas limit estimation works as expected.

We hope you can incorporate this fix, as we use Alto heavily in our workflow.

Running Alto in Prod

Hello,

I would like to ask if it's advisable to run Alto in production using the unsafe mode, I'm asking because we have been trying to get Alto to work by sending mint operation using the lightAccount but the bundler seems to revert it only works in unsafe mode is there something I'm doing wrong?

e.g. callData

  const callData = await lightAccount.encodeCallData({
    to: deployments.TestToken,
    data: encodeFunctionData({
      abi: ERC20_ABI,
      args: [
        lightAccount.address,
        new BigNumber(2).multipliedBy(10 ** 18).toFixed(0),
      ],
      functionName: "mint",
    }),
    value: 0n,
  });

Then we use a paymaster
the estimateUserOperationGas endpoint manages to estimate gas but when we send the user operation we get issues
the bundler errors out with a response

{"message":"Cannot read properties of undefined (reading 'slice')"}

Rewrite config options to use dot notation

Currently all the options use names like lokiHost, lokiUsername, lokiPassword, signerPrivateKeys, utilityPrivateKey, maxSigners, etc.

Would be much cleaner to namespace them using dot notation for the configs where it makes sense, so something like loki.host, loki.username, loki.password, signer.privateKeys, signer.utilityKey, signer.maxSigners, etc.

The current config options are mostly written under packages/cli/src

Remove @account-abstraction/utils dependency

Using the @account-abstraction npm packages in packages/utils/src/validation.ts means having to import all of ethers.js as well even though we only needed that package for one the packUserOp function.

Let's remove that dependency, and reimplement packUserOp natively using viem

Unable to run test:spec

[email protected] test:spec
./test/run-spec-tests.sh
====================================================================
====== alto-launcher.sh
====================================================================
./test/run-spec-tests.sh: line 35: /Users/fallenangel/pimlico/alto/spec-tests/alto-launcher.sh: No such file or directory

OS: macOS

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.