[Whitelisted Caller] HyperFX fee refund for two Base users

Refund 18.277 USDC and 40,023.228375 cNGN of protocol fees from the Base IntentGateway to the two accounts they were taken from. One paid the placement fee on three orders that never filled; the other had the protocol keep its 60% surplus share on a fill.

What This Does

The whitelisted call is a Utility.batchAll of two IntentsCoprocessor.sweepDust calls against StateMachine::Evm(8453). It is atomic: both apply or neither does. Nothing else rides along in this batch.

1. Fees taken on three orders that never filled

0x2009c64589dFB42bc26bf9E29bb61F28a79275aA placed three same chain orders on Base on 2026-09-05, USDC in and cNGN out, each with a deadline about 56 blocks out. All three expired without a fill and were refunded from escrow.

The gateway takes protocolFeeBps off the input at placement, before any fill happens, and Base is configured at 5 bps. Cancelling returns the escrow, which is already net of that fee, so the fee stays with the protocol even though nothing was swapped.

Order Gross in (USDC) Fee taken (USDC) Outcome
0x9be5c5e8… 22,194.000000 11.097000 Never filled, 22,182.903000 refunded
0xdd3a86dd… 12,183.000000 6.091500 Never filled, 12,176.908500 refunded
0xee2fda0e… 2,177.000000 1.088500 Never filled, 2,175.911500 refunded
Total 36,554.000000 18.277000

Every fee figure is the gateway's own DustCollected(address,uint256) log in the placement transaction, topic 0x51eb5aa877b3d80e186f9a323c6dce052491963271d09ee40615d0bb182359d5, and each is exactly 5 bps of the gross input to the last unit. Every refund is an EscrowRefunded log returning the full escrow.

2. The protocol's surplus share on one fill

0x8d11E9AA67863d555332207F7F5eC296b63aD066 placed order nonce 799 on 2026-09-07 at Base block 51,001,709, escrowing 97,451.25 USDC for a minimum of 133,344,055.869375 cNGN. It filled at block 51,001,726 in 0x0eb1a814….

The filler paid in more cNGN than the minimum, and the gateway split the difference on surplus_share_bps, which reads 6000 on Base.

cNGN
Gross output the filler paid in 133,410,761.250000
Order minimum 133,344,055.869375
Surplus 66,705.380625
To the user, 40% 26,682.152250
To the protocol, 60% 40,023.228375

The protocol's share went to the gateway as a cNGN DustCollected in the same transaction. This order filled, so the 48.75 USDC placement fee on its input stays with the protocol and is not part of this refund.

At the rate this order implies, about 1,368 cNGN per USDC, the two legs together are roughly $48.

Decoded Call

Utility.batchAll(calls), pallet index 4, call index 2, with two entries:

# Call Arguments
0 IntentsCoprocessor.sweepDust (94/4) Evm(8453), beneficiary 0x2009c64589dFB42bc26bf9E29bb61F28a79275aA, outputs [{ USDC, 11097000 }, { USDC, 6091500 }, { USDC, 1088500 }]
1 IntentsCoprocessor.sweepDust (94/4) Evm(8453), beneficiary 0x8d11E9AA67863d555332207F7F5eC296b63aD066, outputs [{ cNGN, 40023228375 }]

USDC is 0x833589fCd6EDb6E08f4c7C32D4f71b54bdA02913 and cNGN is 0x46C85152bFe9f96829aA94755D9f915F9B10EF5F, both 6 decimals, both left padded to H256.

Call 0 lists three outputs rather than one summed entry because _sweepDust loops over outputs and does one safeTransfer and one DustSwept per entry. Three transfers, same total, and each line maps to one of that user's three orders.

What Lands on Base

Each call builds an ISMP post request addressed to the registered gateway 0xAe041F7B0CB581876832830baeB6a2Aa2a3C9716, with timeout: 0 and fee: 0, carrying a one-byte RequestKind::SweepDust discriminator followed by abi.encode(SweepDust).

Request from call 0, 321 bytes:

0x03
  0000000000000000000000000000000000000000000000000000000000000020   offset to the struct
  0000000000000000000000002009c64589dfb42bc26bf9e29bb61f28a79275aa   beneficiary
  0000000000000000000000000000000000000000000000000000000000000040   offset to outputs
  0000000000000000000000000000000000000000000000000000000000000003   outputs.length
  000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913   token, USDC
  0000000000000000000000000000000000000000000000000000000000a953a8   amount, 11.097 USDC
  000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913   token, USDC
  00000000000000000000000000000000000000000000000000000000005cf2ec   amount, 6.0915 USDC
  000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913   token, USDC
  0000000000000000000000000000000000000000000000000000000000109bf4   amount, 1.0885 USDC

Request from call 1, 193 bytes:

0x03
  0000000000000000000000000000000000000000000000000000000000000020   offset to the struct
  0000000000000000000000008d11e9aa67863d555332207f7f5ec296b63ad066   beneficiary
  0000000000000000000000000000000000000000000000000000000000000040   offset to outputs
  0000000000000000000000000000000000000000000000000000000000000001   outputs.length
  00000000000000000000000046c85152bfe9f96829aa94755d9f915f9b10ef5f   token, cNGN
  000000000000000000000000000000000000000000000000000000095191ffd7   amount, 40,023.228375 cNGN

The leading offset word is there because abi.decode(body[1:], (SweepDust)) on the gateway expects abi.encode of a single dynamic struct.

ExtrinsicIntents.onAccept requires keccak256(request.source) == keccak256(host.hyperbridge()) for this request kind. host.hyperbridge() on Base returns POLKADOT-3367, which is what Nexus dispatches as, so the check passes. The gateway then runs safeTransfer(token, beneficiary, amount) per output and emits DustSwept for each.

The two requests are independent once they leave Nexus. Atomicity is on the Nexus side only. On Base they can be relayed and executed at different times.

Edited
Reply
Up
Share
Status
Decision1d
Confirmation
1hr
Attempts
1
Tally
100%Aye
50.0%Threshold
0%Nay
Aye
≈349.48MBRIDGE
Nay
0BRIDGE
  • 5.00%
  • 0.0%

    Threshold

  • 0.0%
Support
57.4%
≈349.48MBRIDGE
Issuance
≈609.11MBRIDGE
Votes
Nested
Flattened
Actions
Check how referenda works here.
Call
Metadata
Timeline6
Votes Bubble
Curves
Statistics
Comments

Status
Decision1d
Confirmation
1hr
Attempts
1
Tally
100%Aye
50.0%Threshold
0%Nay
Aye
≈349.48MBRIDGE
Nay
0BRIDGE
  • 5.00%
  • 0.0%

    Threshold

  • 0.0%
Support
57.4%
≈349.48MBRIDGE
Issuance
≈609.11MBRIDGE
Votes
Nested
Flattened
Actions
Check how referenda works here.