Skip to content

feat(tempo): funding requirements - #5125

Open
jxom wants to merge 112 commits into
mainfrom
jxom/tempo-funding-v1
Open

jxom wants to merge 112 commits into
mainfrom
jxom/tempo-funding-v1

Conversation

@jxom

@jxom jxom commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Adds support for TIP-1120 requireFunds.

import { parseUnits } from 'viem'
import { Addresses } from 'viem/tempo'

await client.token.transferSync({
  token: Addresses.pathUsd,
  to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
  amount: parseUnits('10', 6),
  requireFunds: true, // Source funds required for execution from user balances.
})

@vercel

vercel Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
viem Ready Ready Preview Sep 29, 2026 4:32pm UTC

Request Review

@changeset-bot

changeset-bot Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e1ca10e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
viem Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@socket-security

socket-security Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedviem@​2.56.3 ⏵ 2.56.89710010097100

View full report

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e0e879649

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +195 to +198
return {
rootAddress: result.rootAddress,
keyAuthorization: KeyAuthorization.fromRpc(result.keyAuthorization),
hash: undefined,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate the wallet authorization matches the requested key

For a JSON-RPC account with an explicit accessKey, this accepts any well-formed authorization returned by wallet_authorizeAccessKey after checking only rootAddress. If a wallet returns an authorization for a different key, the action reports success even though the caller does not control the authorized key and the supplied key remains unusable; compare the decoded authorization address and key type with the explicitly requested access key before returning it.

Useful? React with 👍 / 👎.

The operation hash returned by the first coordinated approval. Pass it instead of the initial
authorization fields when adding another owner approval.

### fundingPolicy (optional)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Move fundingPolicy before hash

Move this newly added fundingPolicy parameter section before hash; placing it afterward makes the option-bag documentation nonalphabetical. Repository guidance requires required and optional properties in hand-written parameter documentation to share one alphabetical order.

AGENTS.md reference: AGENTS.md:L114-L119

Useful? React with 👍 / 👎.

Comment on lines +364 to +367
if (policy === undefined || policy === 0n)
throw new RpcResponse.InvalidParamsError({
message: 'The access key has no funding policy.',
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Infer empty requirements before requiring a policy

When an access key without a funding policy sends requireFunds: true for a transaction that inference would resolve to an empty array, such as a read-only balanceOf call or a call that only credits the sender, this policy check rejects the request before inference runs. No funding source executes for an empty requirement set, and the same plugin explicitly supports empty inferred results for owner transactions, so defer the missing-policy error until inference has produced at least one requirement.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5a35413261

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tempo/Selectors.ts
@@ -311,6 +320,26 @@ export const zoneVerifier = {
} as const satisfies FunctionSelectors<typeof Abis.zoneVerifier, 'verify'> &

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Move funding selector blocks into alphabetical order

Move fundingDiscovery before fundingPolicy and place both before fundingSource; appending these new exported selector blocks near the end leaves the module's public declarations nonalphabetical, contrary to the repository's required export ordering.

AGENTS.md reference: AGENTS.md:L91-L94

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d49de0756d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

* @returns The policy creation event.
*/
export function extractEvent(logs: Log[]) {
const [log] = parseEventLogs({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Select the requested policy creation event

When createPolicySync is submitted by an uninstalled access key whose keyAuthorization contains an inline funding policy, installing that key creates a policy and emits PolicyCreated before the explicit createPolicy call emits its event. Selecting the first matching log therefore returns the inline policy's ID, hash, and rules instead of the policy requested by this action; select the final event or otherwise match the requested creation.

Useful? React with 👍 / 👎.

Comment on lines +3605 to +3606
log.address.toLowerCase() === address.toLowerCase() &&
(log.args.to?.toLowerCase() === parameters.to.toLowerCase() ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match transfers to resolved virtual recipients

When transferSync sends a TIP-20 to a registered virtual address, the protocol credits the resolved master wallet directly, so the emitted Transfer.to is the master address rather than parameters.to. This new recipient equality check filters out the successful transfer and causes the sync action to throw Transfer event not found after the transaction has already been mined; resolve virtual recipients before matching or retain a fallback that identifies the final requested-token transfer.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 95e29c13f1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +584 to +585
if (result.tx)
relay.result = { ...result, tx: { ...result.tx, requireFunds } }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the raw fill envelope consistent with restored funding

When downstream eth_fillTransaction returns altered funding requirements, this repairs only result.tx; the public fill response's raw envelope remains serialized from the downstream requirements. Callers that sign or forward raw can therefore act on different sources or amounts than the validated transaction shown to post-fill hooks and returned as transaction. The fresh evidence in this revision is that the new restoration explicitly updates only tx; validate and regenerate or discard raw at the same time.

Useful? React with 👍 / 👎.


## Recipes

### Set Up a Client

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the standalone client-setup recipe

The Recipes section now begins with a standalone Set Up a Client task, but repository guidance explicitly forbids repeating client setup as its own recipe and instead requires a prerequisite line plus the shared viem.config.ts include. Replace this recipe with that prerequisite/config pattern before the funding tasks.

AGENTS.md reference: AGENTS.md:L366-L370

Useful? React with 👍 / 👎.

@@ -0,0 +1,10 @@
---
"viem": minor

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Mark the authorize return change as breaking

This changes the established local accessKey.authorize result from a transaction-hash string to an object, so existing consumers that pass, compare, or store the returned hash break after upgrading. Because viem is currently 2.x and this is an unconditional public return-shape change, publishing it as a minor release understates the compatibility impact; mark the changeset as major.

AGENTS.md reference: AGENTS.md:L238-L238

Useful? React with 👍 / 👎.

Comment on lines +245 to +246
})()
if (requirements) return requirements

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor code overrides before using calldata inference

When eth_call or eth_estimateGas supplies a state override that replaces a TIP-20 target's code, this shortcut still decodes the calldata as the standard TIP-20 implementation and returns before simulation applies the override. A transfer-shaped call whose replacement code performs no debit, debits another token, or reverts therefore receives incorrect funding requirements. Skip the calldata shortcut for overridden target code so inference observes the requested state.

AGENTS.md reference: AGENTS.md:L98-L98

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 97cc382060

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tempo/Formatters.ts Outdated
Comment on lines +179 to +180
...(requirement.amount === undefined && defaults
? { amount: Hex.fromNumber(defaults.amount) }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Match the token before applying the default amount

When a single transfer, burn, or swap supplies a partial requirement such as requireFunds: [{ token: someOtherToken }], getDefaults describes the call's token, but this branch copies only its amount while retaining the explicitly different token. The requirement then appears complete, so the relay can acquire the unrelated token and spend source assets instead of rejecting the mismatch; apply the amount default only when the supplied token matches defaults.token.

Useful? React with 👍 / 👎.


## Parameters

### admins

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add focused examples for the policy parameters

The new admins parameter section, and the adjacent rules section, stop after their type and prose without the required minimal ts twoslash examples showing each option in realistic use with // [!code focus]. Add a focused parameter-reference snippet to each heading.

AGENTS.md reference: AGENTS.md:L329-L335

Useful? React with 👍 / 👎.

Comment thread src/tempo/internal/funding.ts Outdated
Comment on lines +311 to +314
const [available, required, token_] = AbiError.decode(
insufficientBalance,
data,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Translate malformed shortfall reverts before decoding

When an arbitrary called contract reverts with bytes that begin with the InsufficientBalance selector but do not contain its complete ABI payload, this unconditional decode throws an ABI codec error. An eth_fillTransaction request can therefore turn a crafted execution revert into an internal RPC failure instead of the existing funding-inference invalid-parameters response; catch decoding failures and route them through the normal inference error path.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6548c16ec6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tempo/chainConfig.ts
Comment on lines +336 to +340
...(filled.feeToken ? { feeToken: filled.feeToken } : {}),
gas: filled.gas,
maxFeePerGas: filled.maxFeePerGas,
maxPriorityFeePerGas: filled.maxPriorityFeePerGas ?? 0n,
nonce: filled.nonce,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve explicit fee fields across funding fills

When unresolved funding is filled through a remote relay, these assignments unconditionally replace caller-supplied feeToken, gas limits, fee caps, and nonce with values returned by that relay. A sender-paid request that omits only requireFunds.sources, for example, can therefore be made to sign with a different fee token or materially different fee parameters; validate explicitly supplied transaction fields and use the filled values only for fields the caller omitted.

Useful? React with 👍 / 👎.

? FundingPolicy.encode(parameters.defaultRules)
: undefined)
if (rules !== undefined && rules !== null) {
const decoded = FundingPolicy.decode(rules as Hex)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject malformed policy-rule bytes as invalid parameters

When an access-key fill supplies a hex-valid but non-ABI policyRules value such as 0x1234, the requirement parser can retain it as opaque bytes and this decode then throws an uncaught ABI codec error. A malformed public relay request is consequently reported as an internal failure instead of the invalid-parameters response used for malformed rule registration and other requirement fields; catch decoding failures here and translate them to RpcResponse.InvalidParamsError.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e1ca10e57f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

message:
'The funding access key is not installed; supply `keyAuthorization`.',
})
const expiry = installed ? metadata.expiry : authorization?.expiry

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor renewed authorization for an expired installed key

When an access key remains installed but its stored positive expiry has passed, a request can include a newly signed, unexpired keyAuthorization; the preparation path explicitly attaches such pending authorizations when installed metadata is no longer active. This ternary nevertheless always selects the stale metadata expiry whenever the key IDs match, so every funding fill rejects the renewal as expired before the transaction can reinstall the key. Use the supplied authorization's expiry and policy when the installed record is expired.

Useful? React with 👍 / 👎.

Comment on lines +164 to +168
fundingPolicy:
fundingPolicy === true
? true
: FundingPolicy.toRpc(fundingPolicy),
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Register inline wallet policy rules with the relay

When a JSON-RPC account authorizes an inline fundingPolicy, this branch only forwards the rules to the wallet; unlike the local preparation path, it never calls registerPolicyRules. If the wallet installs the key without executing a funded transaction through the same relay, the chain retains only the rules hash while the relay store remains empty, so subsequent automatic funding for the installed key fails with Funding policy rules are not in the store. Register the inline rules with the funding handler before requesting wallet authorization.

Useful? React with 👍 / 👎.

Comment thread src/tempo/Addresses.ts
Comment on lines +15 to +16
export const alphaUsd = '0x20c0000000000000000000000000000000000001'
export const betaUsd = '0x20c0000000000000000000000000000000000002'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Document the new public funding addresses

The newly public alphaUsd, betaUsd, dexFundingSource, fundingDiscovery, fundingPolicy, thetaUsd, and tip20Funder constants are exposed through the public Addresses namespace without TSDoc, leaving the generated API surface without descriptions or network scope for these protocol addresses. Add TSDoc to each new constant.

AGENTS.md reference: AGENTS.md:L121-L121

Useful? React with 👍 / 👎.

This branch was successfully deployed

1 active deployment
Preview — e1ca10e5 Deployed Sep 29, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant