Skip to content
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

Potential risk of unlimited UserOP gas fee #10

Open
Gooong opened this issue May 18, 2023 · 4 comments
Open

Potential risk of unlimited UserOP gas fee #10

Gooong opened this issue May 18, 2023 · 4 comments

Comments

@Gooong
Copy link

Gooong commented May 18, 2023

Hi,

There is not limit on the gas fee of one UserOP. A malicious user can compose an UserOP with very high preVerificationGas or maxPriorityFeePerGas, making the gas fee high enough to drain all the eth of the Paymaster. Note in this case the malicious user can bundle this UserOP with his own bundler, so that the profit is returned to himself. This means malicious user only lose the actual gas fee (which is low) of executing the UserOP.

This can be expolited for below purpose:

  1. Attack Paymaster to make it unavailable: Drain all the eth from paymaster in a low cost.
  2. Swap ERC20 token to eth in a favorable price: The token price is read from Oracle and is updated in postOp. It's possible that the price deviates from the actual price in extreme cases. The malicious user can compose an UserOP with high gas fee, use TokenPaymaster and bundle it with his own bundler. In this case the malicious user pay ERC20 token and get eth in a favorable price.
@kristofgazso
Copy link
Contributor

Thank you for writing this issue!

We considered this potential scenario when designing the paymaster. The cached ETH price + markup being higher than the actual ETH price is known requirement for the paymaster to not be exploitable. In fact, the main function of the price markup for us is actually to put this buffer between the real and the cached prices, giving us (or anyone else using the paymaster) a leeway to update the price before the price decreases enough.

We will be running automatic bots that update the price when too low so as to avoid the cached price going below the real price more than the price markup can make up for. In case of very high price variance, we are also able to temporarily increase the price markup of the paymaster to give a larger buffer (up to a harcoded limit of 20%). This is a further way to protect against this threat.

Attacking the paymaster to drain it implies paying the price markup to the paymaster owner, which is a large extra cost that we will in the future likely be maintaining the paymaster with >$10,000 of tokens, and will be running automatic bots to swap the tokens back to native tokens if they get too low. Assuming $10,000 of tokens is the target amount, draining the paymaster would cost the attacker $1000 (assuming a price markup of 10%), which we could refill immediately, likely in the next block or two.

Also this attack does not scale, because if we realize this is a common occurrence we can fill the paymaster up with even more native tokens, letting us arbitrarily increase the cost of disabling it for a block. Even with only $10,000 of native tokens being targeted, assuming we can refill the tokens every block, that is 86400 / 12 = 7200 times the attacker has to waste $1000 of tokens -> $7,200,000 cost to attack the paymaster per day. And again, we can decide to arbitrarily increase the amount of tokens to maintain in the paymaster, so if we, for example, targeted $100,000, then the cost to attack per day would rise to $72,000,000.

@Gooong
Copy link
Author

Gooong commented May 19, 2023

Thanks for the reply! The priceMarkup is a good design to avoid most attack in normal circumstances!

Still, in extreme cases if the eth price goes up to 30%, it will need to perfrom at least one OP to get the price from Oracle (assume the Oracle's price is already up-to-date). Then automatic bots need to act and bundle a safe OP before the malicious user. This is hard because malicious user is profiltable to arbitrage to bundle his own OP.

However, the exteme case seldom happens and the loss is acceptable. Attack won't happen in most of the cases. The priceMarkup and fetch price in _postOP is good design!

If there is future upgrade, I suggest to limit the gas fee of each OP (for example, to 0.1 eth), which makes it less profitable to perform attack.

@leekt
Copy link
Contributor

leekt commented May 19, 2023

Still, in extreme cases if the eth price goes up to 30%, it will need to perfrom at least one OP to get the price from Oracle (assume the Oracle's price is already up-to-date). Then automatic bots need to act and bundle a safe OP before the malicious user. This is hard because malicious user is profiltable to arbitrage to bundle his own OP.

In extreme cases, our update bot will call updatePrice() which does not require an UserOp and can be called directly through EOA,

If there is future upgrade, I suggest to limit the gas fee of each OP (for example, to 0.1 eth), which makes it less profitable to perform attack.

I'm not sure about this cause if this DoS scenario happens, even if gas cap per userOp is set to 0.1eth, DoS can still happen if attacker runs multiple userOps in same bundle?

@Gooong
Copy link
Author

Gooong commented May 19, 2023

Oh, yes, I ignored updatePrice(), which can also be arbitraged.

I'm not sure about this cause if this DoS scenario happens, even if gas cap per userOp is set to 0.1eth, DoS can still happen if attacker runs multiple userOps in same bundle?

Yes, DoS can still happen. The price is only updated after executing the bundle. This is used to increase attack cost because attacker need to bundle more userOps and will lose more gas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants