Repository navigation
🐛 Apply max fee overhead to privacy pool fee - #72
Merged
Merged
Conversation
Pool fee was added raw on top of the multiplied gas fee, leaving no headroom for STRK/token price drift between build and execute. With a non-STRK pool_fee_token (e.g. USDC), this caused POOL_FEE_TOO_LOW (167) on paymaster_executeTransaction. Fold pool fee into the total before applying the max_fee_multiplier, and apply the same overhead to the sponsored-mode fee_action_amount.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This was referenced Apr 23, 2026
florian-bellotti
added a commit
that referenced
this pull request
Apr 24, 2026
PR #72 applied `max_fee_multiplier` (~3x) to the pool fee, which caused users to approve triple the amount they actually owed and hit "Insufficient ERC20 balance" on execute. The pool fee is a fixed amount in STRK read from the pool, so it does not need the large safety multiplier that guards against gas-fee volatility — only a small overhead to cover STRK / gas-token price drift between build and execute. Use `compute_paid_fee_in_strk` (~1.1x via `provider_fee_overhead`) for the pool portion; keep `compute_max_fee_in_strk` on the gas portion.
florian-bellotti
added a commit
that referenced
this pull request
Apr 24, 2026
PR #72 applied `max_fee_multiplier` (~3x) to the pool fee, which caused users to approve triple the amount they actually owed and hit "Insufficient ERC20 balance" on execute. The pool fee is a fixed amount in STRK read from the pool, so it does not need the large safety multiplier that guards against gas-fee volatility — only a small overhead to cover STRK / gas-token price drift between build and execute. Use `compute_paid_fee_in_strk` (~1.1x via `provider_fee_overhead`) for the pool portion; keep `compute_max_fee_in_strk` on the gas portion.
florian-bellotti
added a commit
that referenced
this pull request
Apr 24, 2026
PR #72 applied `max_fee_multiplier` (~3x) to the pool fee, which caused users to approve triple the amount they actually owed and hit "Insufficient ERC20 balance" on execute. The pool fee is a fixed amount in STRK read from the pool, so it does not need the large safety multiplier that guards against gas-fee volatility — only a small overhead to cover STRK / gas-token price drift between build and execute. Use `compute_paid_fee_in_strk` (~1.1x via `provider_fee_overhead`) for the pool portion; keep `compute_max_fee_in_strk` on the gas portion.
florian-bellotti
added a commit
that referenced
this pull request
Apr 24, 2026
* Approve privacy pool to pull STRK fee in forwarder The last call of a private batch targets a privacy pool whose `apply_actions` collects its fee via `transferFrom(forwarder, fee_collector, fee)` on STRK, independent of the user's gas token. Without an allowance, that transfer reverts on the ERC20 check. - Add `IPrivacyPool` dispatcher (`get_fee_amount`) and a 10_000 STRK safety cap. - Hardcode the canonical STRK address on Starknet; `approve_pool_fee` always approves the pool on STRK, never on the user's gas token. - Wire the helper into `execute_private` and `execute_private_sponsored`. - Add a minimal `MockPrivacyPool` and tests covering the fee-limit guard. * Apply only provider overhead to the privacy pool fee PR #72 applied `max_fee_multiplier` (~3x) to the pool fee, which caused users to approve triple the amount they actually owed and hit "Insufficient ERC20 balance" on execute. The pool fee is a fixed amount in STRK read from the pool, so it does not need the large safety multiplier that guards against gas-fee volatility — only a small overhead to cover STRK / gas-token price drift between build and execute. Use `compute_paid_fee_in_strk` (~1.1x via `provider_fee_overhead`) for the pool portion; keep `compute_max_fee_in_strk` on the gas portion. * Pre-fund forwarder with STRK from relayer for privacy pool fee The privacy pool collects its fee via `transferFrom(forwarder, fee_collector, fee)` in STRK. When the user pays in a non-STRK gas token (USDC, etc.), the forwarder has no STRK balance for the pool to pull, so `apply_actions` reverts. The relayer already holds STRK (refilled by the gas-tank → relayers rebalancing), so we prepend a `strk.transfer(forwarder, pool_fee_amount)` call before the forwarder call in both private and private-sponsored flows. The relayer is reimbursed when the forwarder forwards the user's gas-token payment to the gas tank, closing the loop via the existing rebalancing. Only emitted when `privacy_pool_fee_amount > 0`, so non-pool-fee transactions are unchanged.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
POOL_FEE_TOO_LOW(167) onpaymaster_executeTransactionforapply_actioninsponsored_privatemode whenpool_fee_tokenis not STRK (reproduced with USDC on mainnet).max_fee_multiplierwas applied only to the gas portion; the privacy pool fee was added raw. With a non-STRK fee token, STRK↔token price drift between build and execute left the user-approved pool-fee transfer short of the executor's re-computed amount.pool_fee_amountinto the total before applyingcompute_max_fee_in_strk, and apply the same overhead to the sponsored-modefee_action_amount.Test plan
cargo build -p paymaster-executioncargo clippy -p paymaster-execution(no new warnings)cargo test -p paymaster-execution(all tests pass)apply_actiontx insponsored_privatewithpool_fee_token = USDCand confirm noPOOL_FEE_TOO_LOWpool_fee_token = STRK