Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions content/BPIP-12.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,18 @@ A new entry point is added alongside the existing `executeMetaTransaction`.

```solidity
/**
* @notice Executes a metatransaction with a queue of per-transfer token-pull authorizations.
* @notice Same as `executeMetaTransaction`, but additionally accepts a
* token-transfer authorization queue that funds-pulling functions
* can consume in lieu of an ERC-20 allowance.
*
* Each entry in _tokenTransferAuthorization is consumed in order by transferFundsIn calls
* made during execution of _functionSignature. An empty-bytes entry ("0x") is a
* fallback marker that causes that transfer slot to fall back to safeTransferFrom
* (requires a prior on-chain approve). Entries beyond the number of transferFundsIn
* calls are ignored; the queue is cleared from transient storage at transaction end.
* Each entry in `_tokenTransferAuthorization` is consumed in order by
* transferFundsIn calls made during execution of `_functionSignature`. Entries
* beyond the number of transferFundsIn calls are ignored; the queue is cleared
* from transient storage at transaction end. Each element is one of:
* - empty bytes ("0x") — fall back to safeTransferFrom for this slot
* (shortcut for (TokenTransferAuthorizationStrategy.None, "")).
* - `abi.encode(BosonTypes.TokenTransferAuthorizationStrategy strategy, bytes data)`
* — strategy-specific payload described in the table below.
*
* Emits MetaTransactionExecuted event if successful.
*
Expand All @@ -64,32 +69,27 @@ A new entry point is added alongside the existing `executeMetaTransaction`.
* - A Permit2 permitTransferFrom call fails
*
* @param _userAddress - the address of the user on whose behalf the transaction is being executed
* @param _functionName - the name of the function to be executed
* @param _functionSignature - the encoded function call to execute
* @param _nonce - nonce of the transaction, used to prevent replay attacks
* @param _sigR - r part of the metatransaction signer's signature
* @param _sigS - s part of the metatransaction signer's signature
* @param _sigV - v part of the metatransaction signer's signature
* @param _tokenTransferAuthorization - ABI-encoded queue of (TokenTransferAuthorizationStrategy, bytes) pairs,
* one per transferFundsIn call in execution order. Each non-empty entry is
* abi.encode(TokenTransferAuthorizationStrategy strategy, bytes data) where data
* holds the strategy-specific fields described below.
* @param _signature - meta transaction signature (ECDSA concatenated r,s,v for EOAs; ERC-1271 for contracts)
* @param _tokenTransferAuthorization - queue of per-transfer authorization entries (see above)
*/
function executeMetaTransactionWithTokenTransferAuthorization(
address _userAddress,
string memory _functionName,
bytes calldata _functionSignature,
bytes32 _nonce,
bytes32 _sigR,
bytes32 _sigS,
uint8 _sigV,
uint256 _nonce,
bytes calldata _signature,
bytes[] calldata _tokenTransferAuthorization
) external payable;
) external payable returns (bytes memory);
```

#### Per-strategy entry payload (`data` field)

| Strategy | `data` encoding |
|----------|-----------------|
| `ERC3009` | `abi.encode(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)` |
| `ERC3009` | `abi.encode(uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s)` |
| `EIP2612` | `abi.encode(uint256 deadline, uint8 v, bytes32 r, bytes32 s)` |
| `Permit2` | `abi.encode(uint256 nonce, uint256 deadline, bytes signature)` |
| `None` / `"0x"` | empty — falls back to `safeTransferFrom` |
Expand All @@ -116,7 +116,7 @@ A new internal library manages the queue in transient storage (EIP-1153 / Cancun
- **Transient storage** — the queue is stored with `tstore` / `tload`, so it is automatically cleared at the end of each transaction with no explicit cleanup required.
- **ERC-7201-style slot masking** — the last byte of each entry's base slot is zeroed, giving every entry a 256-sub-slot range that cannot overlap with any other entry for typical ERC-3009 payloads (which use 7 sub-slots).
- **`discardNext()`** — advances the queue head by one without performing any work. Called by `transferFundsIn` for zero-amount transfers and by `createOfferAndCommit` when `useDepositedFunds=true` bypasses the creator pull.
- **`consumeForTransfer(token, from, amount)`** — pops the next entry, decodes the `(strategy, data)` envelope, and dispatches to the appropriate per-strategy helper. Returns `false` for `None` / empty-bytes entries, causing the caller to fall through to `safeTransferFrom`.
- **`consumeForTransfer(token, from, to, amount)`** — pops the next entry, decodes the `(strategy, data)` envelope, and dispatches to the appropriate per-strategy helper. Returns `false` for `None` / empty-bytes entries, causing the caller to fall through to `safeTransferFrom`.

### EIP-2612 diversion guard

Expand Down
8 changes: 4 additions & 4 deletions content/BPIP-13.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ Combining commit and redeem into a single transaction is safe because the commit

To share the internal commit and redeem logic across the new orchestration methods without duplicating code or exceeding the 24 KB facet size limit, two new abstract base contracts are introduced:

- **ExchangeRedeemBase** — contains `redeemVoucherInternal`, `burnVoucher`, `transferTwins`, and `updateNFTRanges`. `ExchangeHandlerFacet` inherits it and overrides `_computeBurnTokenId` to retain pre-2.2.0 voucher token-id compatibility.
- **ExchangeRedeemBase** — contains `redeemVoucherInternal`, `burnVoucher`, `transferTwins`, and `updateNFTRanges`. Voucher token-id backward compatibility with pre-2.2.0 exchanges is handled directly inside `burnVoucher` using an immutable versioning threshold (`EXCHANGE_ID_2_2_0`): for exchange ids at or above the threshold the token id is `exchangeId | (offerId << 128)`; older ids are passed through unchanged.
- **ExchangeCommitBase** — contains `commitToOfferInternal`, `verifyOffer`, `authorizeCommit`, `holdsThreshold`/`holdsSpecificToken`, `validateConditionRange`, `handleDRFeeCollection`, and `addSellerParametersToBuyerOffer`. `ExchangeCommitFacet` now inherits it instead of implementing these directly.

`OrchestrationHandlerFacet2` inherits both bases and the three new methods delegate to the shared internals.
Expand All @@ -158,12 +158,12 @@ This proposal does not break backward compatibility. All existing methods contin
## Implementation
* Introduce `ExchangeRedeemBase` with the internal redeem logic extracted from `ExchangeHandlerFacet`.
* Introduce `ExchangeCommitBase` with the internal commit logic extracted from `ExchangeCommitFacet`.
* `ExchangeHandlerFacet` inherits `ExchangeRedeemBase` and overrides `_computeBurnTokenId` for backward-compatible voucher token-id handling.
* `ExchangeHandlerFacet` inherits `ExchangeRedeemBase`. Backward-compatible voucher token-id handling is implemented directly in `ExchangeRedeemBase.burnVoucher` via `EXCHANGE_ID_2_2_0` — no override is needed.
* `ExchangeCommitFacet` inherits `ExchangeCommitBase`.
* `OrchestrationHandlerFacet2` inherits both `ExchangeCommitBase` and `ExchangeRedeemBase` and adds the three new public methods.
* Each new method:
1. Validates and processes the commit step using shared internals (including offer validation, condition check, fund encumbrance).
2. Immediately calls `redeemVoucherInternal` with the same exchange, transferring any twins to `_msgSender()`.
1. Validates and processes the commit step using shared internals (including offer validation, condition check, fund encumbrance). The commit is called with `_skipVoucher = true`, so no NFT is minted and `voucherCount` is not incremented.
2. Immediately calls `redeemVoucherInternal(_exchangeId, _skipVoucher: true)`, which skips the burn call and buyer-ownership check (no voucher NFT was ever issued), and transfers any twins to `_msgSender()`.
* Add `OfferCreatorMustBeSeller` to `BosonErrors.sol`.


Expand Down