Check existing issues
Describe the bug
Problem
type="hash" verification in tempo.charge() checks that Transfer.from === receipt.from via assertTransferLogs. This fails when a third party (bridge solver, payment processor) delivers funds on behalf of the payer.
Code: src/tempo/server/Charge.ts — assertTransferLogs
if (!TempoAddress.isEqual(log.args.from, parameters.sender)) return false
// where sender = receipt.from
Proof
Verified against a real Relay bridge fill on Base (BaseScan):
receipt.from: 0x728f51950ff096dc03a48f5e83f45ac8bb75f500 (caller EOA)
Transfer.from: 0xf70da97812cb96acdf810712aa562db8dfa3dbef (Relay Solver)
Match? false → verification fails
The solver holds the tokens and is the from in the ERC-20 Transfer event, but a different EOA submits the transaction. This pattern is standard across bridge protocols — the authorized caller and the token source are different addresses.
Use Case
Cross-chain MPP payments: an agent pays on chain A, a bridge solver delivers to the service on chain B. The service's mppx verification needs to accept the fill transaction as valid payment.
This applies to any bridge (Relay, Across, Stargate, etc.), payment processor, or custodial service that delivers funds on behalf of a payer.
Suggested Direction
A credential type that verifies the transfer landed on-chain (correct token, recipient, amount) without requiring Transfer.from === receipt.from. All other security layers (HMAC challenge binding, expiry, replay protection) remain unchanged.
Happy to discuss the approach and contribute a PR.
Package Version
0.5.3
Check existing issues
Describe the bug
Problem
type="hash"verification intempo.charge()checks thatTransfer.from === receipt.fromviaassertTransferLogs. This fails when a third party (bridge solver, payment processor) delivers funds on behalf of the payer.Code:
src/tempo/server/Charge.ts—assertTransferLogsProof
Verified against a real Relay bridge fill on Base (BaseScan):
The solver holds the tokens and is the
fromin the ERC-20 Transfer event, but a different EOA submits the transaction. This pattern is standard across bridge protocols — the authorized caller and the token source are different addresses.Use Case
Cross-chain MPP payments: an agent pays on chain A, a bridge solver delivers to the service on chain B. The service's mppx verification needs to accept the fill transaction as valid payment.
This applies to any bridge (Relay, Across, Stargate, etc.), payment processor, or custodial service that delivers funds on behalf of a payer.
Suggested Direction
A credential type that verifies the transfer landed on-chain (correct token, recipient, amount) without requiring
Transfer.from === receipt.from. All other security layers (HMAC challenge binding, expiry, replay protection) remain unchanged.Happy to discuss the approach and contribute a PR.
Package Version
0.5.3