Skip to content

core-sdk: support fallback / empty entries in token-transfer-authorization queues (BPIP-12) #1032

Description

@levalleux-ludo

Summary

@bosonprotocol/core-sdk's erc20.handler.encodeTransferAuthorizationEntry and
metaTx.handler.executeMetaTransactionWithTokenTransferAuthorization cannot
express empty / fallback entries (0x) inside a token-transfer-authorization
queue. The on-chain
MetaTransactionsHandlerFacet.executeMetaTransactionWithTokenTransferAuthorization

  • TokenTransferAuthorizationLib.loadQueue accept 0x as a shortcut for "no
    auth — fall back to ERC-20 allowance", and several commit-time flows
    require at least one empty leading slot. The SDK gap forces downstream
    consumers to bypass the handler and hand-roll the queue + outer calldata.

Where the gap is

In packages/contracts-sdk/src/erc20/handler.ts (and the corresponding
meta-tx/handler.ts), the public type is:

export type UnsignedTransferAuthorization =
  | { strategy: "ERC3009"; data: { ... } }
  | { strategy: "EIP2612"; data: { ... } }
  | { strategy: "Permit2";  data: { ... } }
  | { strategy: "DAIPermit"; data: { ... } };

encodeTransferAuthorizationEntry is an exhaustive switch over these four
strategies — every element of transferAuthorizations: TransferAuthorization[]
must carry a strategy id + signature. There is no representation for
bytes("") (the empty entry the on-chain queue accepts as a placeholder).

metaTx.handler.executeMetaTransactionWithTokenTransferAuthorization then
maps the input array via .map(encodeTransferAuthorizationEntry) and passes
the result to the meta-tx handler's executeMetaTransactionWithTokenTransferAuthorization(..., bytes[]) ABI member — so the same restriction applies end-to-end.

Why it matters (BPIP-12 / commit-time flows)

The protocol's commit-time meta-transactions
(createOfferAndCommit, createOfferCommitAndRedeem) emit multiple
transferFundsIn calls in sequence — one for the zero-amount seller
deposit, one for the buyer's price. TokenTransferAuthorizationLib.loadQueue
consumes one queue entry per transferFundsIn site via discardNext(). For
these flows the queue must have a leading empty entry so the zero-amount
seller-deposit transferFundsIn advances past 0x (no auth needed for a
zero-value pull) and the buyer's strategy-typed auth lands on the next slot.

Today, downstream consumers that want to drive BPIP-12 meta-txes have to:

  • Hand-roll the outer envelope ABI (or import it from @bosonprotocol/common's
    IBosonMetaTransactionsHandlerABI),
  • Hand-roll the per-entry abi.encode(uint8 strategy, bytes data) layout,
  • Hand-pin the on-chain TokenTransferAuthorizationStrategy enum values
    (ERC3009=1, EIP2612=2, Permit2=3, DAIPermit=4),
  • And manage the leading-empty-slot insertion themselves.

That's exactly what the SDK is supposed to encapsulate. The current shape
forces a separate code path for every consumer that needs the empty-slot
queue.

Proposed change

Add an explicit fallback variant, called "None".

export type UnsignedTransferAuthorization =
  | { strategy: "None" }
  | { strategy: "ERC3009"; data: { ... } }
  | { strategy: "EIP2612"; data: { ... } }
  | { strategy: "Permit2";  data: { ... } }
  | { strategy: "DAIPermit"; data: { ... } };

encodeTransferAuthorizationEntry returns "0x" for the "None" case.
No signature fields required. Cleanly typed; callers can build queues
declaratively.

metaTx.handler.executeMetaTransactionWithTokenTransferAuthorization
should accept the same shape transparently.

Reference

  • On-chain semantics: boson-protocol-contracts
    TokenTransferAuthorizationLib.loadQueue / discardNext / consumeForTransfer.
  • On-chain enum: BosonTypes.TokenTransferAuthorizationStrategy (None=0,
    ERC3009=1, EIP2612=2, Permit2=3, DAIPermit=4).
  • Downstream motivation: the @bosonprotocol/x402-facilitator package in
    bosonprotocol/x402B currently
    ships typescript/packages/facilitator/src/internal/build-bpip12-calldata.ts
    as a local workaround. Closing this issue would let us delete that helper
    and route the BPIP-12 commit path through
    metaTx.handler.executeMetaTransactionWithTokenTransferAuthorization({ returnTxInfo: true }).

Acceptance

  • UnsignedTransferAuthorization (or the queue array shape) can express an
    empty / fallback entry without consumers reaching into ABI primitives.
  • A test that round-trips a queue like
    [fallback, erc3009Auth] through
    executeMetaTransactionWithTokenTransferAuthorization and asserts the
    encoded bytes[] matches the protocol's expectation ([ "0x", <strategy-typed entry> ]).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions