Summary
Several issues (#1893, #2140) touch on how the AggLayer bridging flow deals with the faucet registry. Let's use this issue as a consolidated place to align on how the faucet registry should be stored and what responsibilities it has.
The main question is: what data lives in the bridge’s registry vs. in the faucet’s own storage, an, as a result, who is responsible for amount and address conversion?
Background
- The
AggLayer bridge maintains a registry of AggLayer faucets and rejects bridge operations for unregistered ones.
- I think we have consensus on storing a map
faucet_registry in the AggLayerBridge. The mapping would look like:
faucet_registry: FAUCET_ACCOUNT_ID -> VALUE
- Conversion between Miden asset amounts and native (L1) token amounts requires:
- identifying the native token (e.g. ERC20 address), and
- applying a token-specific scaling factor.
Proposed storage in AggLayerBridge:
faucet_registry map
The registry is the authoritative allowlist. Whether it is also the authoritative source of conversion parameters is the core decision to be made.
- Key:
FAUCET_ACCOUNT_ID
- Value: either:
- an
EMPTY_WORD (i.e. membership-only registry), or
- a packed word containing conversion metadata.
If the value is non-empty, the suggested layout is:
native_token_address (20 bytes, could be packed into 3 Felts)
scale (u8)
Option A - Store conversion data in the bridge registry
faucet_registry stores:
- native token address
- scale
- Conversion logic lives in
AggLayerBridge.
- Faucets do not need to store conversion metadata themselves.
Pros
- Bridge can compute
[NATIVE_AMOUNT, NATIVE_IDENTIFIER] locally
- No FPI call needed
- Single conversion implementation used by bridge logic
- Faucet storage stays minimal
Cons
- The address format we use in Merkle hashing is stored as 5x
u32 (=20 bytes). We could store a packed version, but that requires extra format conversion logic.
- High coupling between the bridge and faucets
- Less extensible & customizable
Option B - Store conversion data in the faucet
faucet_registry is membership-only (EMPTY_WORD).
- Each faucet stores:
- native token address
- scale
- Bridge obtains the final conversion results via an FPI call to the faucet.
Option B.2 - Obtain conversion info via FPI, convert locally
- Bridge obtains only the "conversion info" (i.e.
scale) but does the conversion locally. This is a bit of a hybrid with an unclear split of responsibilities so I think it's the least optimal choice, but flagging it here for completeness.
Pros
- Conversion logic and parameters live with the asset-specific contract (if we ever have assets with non-uniform conversion)
- Bridge stays simpler
- Faucets are more flexible
Cons
- Requires FPI calls during bridging
- Conversion logic likely duplicated in each faucet
Conclusion
My personal preference is for Option B, with the main benefit being the de-coupling of the bridge and faucet logic.
Summary
Several issues (#1893, #2140) touch on how the
AggLayerbridging flow deals with the faucet registry. Let's use this issue as a consolidated place to align on how the faucet registry should be stored and what responsibilities it has.The main question is: what data lives in the bridge’s registry vs. in the faucet’s own storage, an, as a result, who is responsible for amount and address conversion?
Background
AggLayerbridge maintains a registry of AggLayer faucets and rejects bridge operations for unregistered ones.faucet_registryin theAggLayerBridge. The mapping would look like:faucet_registry: FAUCET_ACCOUNT_ID -> VALUEProposed storage in
AggLayerBridge:faucet_registrymapThe registry is the authoritative allowlist. Whether it is also the authoritative source of conversion parameters is the core decision to be made.
FAUCET_ACCOUNT_IDEMPTY_WORD(i.e. membership-only registry), orIf the value is non-empty, the suggested layout is:
native_token_address(20 bytes, could be packed into 3Felts)scale(u8)Option A - Store conversion data in the bridge registry
faucet_registrystores:AggLayerBridge.Pros
[NATIVE_AMOUNT, NATIVE_IDENTIFIER]locallyCons
u32(=20 bytes). We could store a packed version, but that requires extra format conversion logic.Option B - Store conversion data in the faucet
faucet_registryis membership-only (EMPTY_WORD).Option B.2 - Obtain conversion info via FPI, convert locally
scale) but does the conversion locally. This is a bit of a hybrid with an unclear split of responsibilities so I think it's the least optimal choice, but flagging it here for completeness.Pros
Cons
Conclusion
My personal preference is for Option B, with the main benefit being the de-coupling of the bridge and faucet logic.