---
id: TIP-1111
title: Configurable Account Access Keys
description: Lets configurable accounts grant access keys and act as access keys for other accounts.
authors: Tanishk Goyal (@legion2002), Jake Moxey (@jxom)
status: Draft
related: TIP-1107, TIP-1113, TIP-1011, TIP-1049, TIP-1137
protocolVersion: T14
---

# TIP-1111: Configurable Account Access Keys

## Abstract

This TIP lets configurable accounts grant access keys, so routine payments don't need a quorum. A configurable account can also hold a grant on another account, so a team multisig can spend from a treasury with its own owners approving.

AccountKeychain enforces every grant's expiry, limits and scopes as today. Only the account that holds the funds can create or revoke its grants, through its own key or its current quorum. Owner updates and migration keep existing grants, so ending one needs an explicit revocation.

## Motivation

Access keys ([TIP-1011](./tip-1011.md)) let an account authorize a secondary key. AccountKeychain records the grant with an expiry, per-token spending limits that can reset each period, and optional call scopes. The key then signs transactions inside a keychain envelope, and the transactions run as the account within those limits. A transaction can also carry a `key_authorization` field that creates a grant the same transaction can use. Today both sides of a grant are ordinary single-key accounts. This TIP extends the AccountKeychain so that configurable accounts can both grant access keys and receive them. 

As an example: suppose Acme's treasury is a 3-of-5 [configurable account](./tip-1107.md). Its employee Dana pays supplier invoices every day, and three executive signatures per invoice is too slow. Acme wants to give Dana's passkey up to 500 OUSD a day. Acme's operations team is a 2-of-3 configurable account, and Acme wants the team to spend from the treasury, with any two members approving. With this TIP, the treasury can grant appropriately scoped/ limited access keys to Dana and the operations team.

---

# Specification

## Overview

**Terms.** These add to the terms in [TIP-1107](./tip-1107.md#overview).

| Term | Meaning |
|---|---|
| Commitment | The 32-byte hash of a configurable account's current configuration, stored in its account leaf. Zero means the account isn't configurable or isn't registered yet. |
| Version | The configuration's counter. Each owner update increases it by one, so approvals signed for an earlier version stop working. |
| `configurable_account_digest(inner_digest, account, version)` | What each owner signs: `keccak256("tempo:configurable-account:signature" \|\| inner_digest \|\| account \|\| uint64(version))`. |
| `V` | The gas for checking one configurable-account signature: its calldata, configuration hashing and approval signature checks ([TIP-1107 Gas](./tip-1107.md#gas)). |
| Parent | The account that holds the funds. |
| Delegate | The key or configurable account that receives access. |
| Grant | The AccountKeychain record of the delegate's permissions on that parent. |
| Admin access key | A key granted under TIP-1049 before T14 that spends without limits. [TIP-1137](https://github.com/tempoxyz/tempo/pull/8204) activates with this TIP at T14, so no admin key can be created from then on. |

The parent can also be either kind of account.

**Lifecycle.**

1. **Grant to Dana.** Three of Acme's owners sign a `key_authorization` giving Dana's passkey 500 OUSD per 24 hours.
2. **Dana pays.** Dana signs an invoice payment inside a keychain envelope. The protocol checks her signature and her limit, then runs the payment as Acme. No owner signs.
3. **Grant to the team.** Acme's quorum grants the operations team account 2,000 OUSD a day. The grant records the team account's address as its key ID, with the new configurable-account key type.
4. **The team pays.** Two of the operations team's three owners sign. Their configurable-account signature goes inside the keychain envelope. The protocol checks the team's quorum against the team's commitment, then the grant's limit, then runs the payment as Acme.
5. **The team changes members.** The operations team updates its owners. Acme's grant now follows the team's new quorum, with the same limit and the same spending counter. Acme signs nothing.
6. **Acme changes owners.** Dana's and the operations team's grants keep working. If Acme wants to cut someone off, its quorum revokes that grant.

Steps 5 and 6 are worth emphasizing: Owner updates never touch grants in either direction. That makes planned rotation painless, but recovery from a compromise has to revoke grants explicitly.

## Mechanics

### Who can grant and revoke

Only the parent's direct authority creates, changes or revokes its grants. For an ordinary parent that is its key, subject to TIP-1113's retirement check. For a configurable parent it is its current quorum. This applies to the inline `key_authorization` field and to AccountKeychain's direct authorization calls. Both accept configurable parents from T14. Access-key transactions cannot manage grants.

### Grant format

- A grant to a configurable delegate MUST use key type `ConfigurableAccount = 3` and store the delegate's address as `key_id`.
- A configurable delegate MUST NOT have code or EIP-7702 delegation other than TIP-1107's [account code marker](./tip-1107.md#account-code), and MUST NOT be the parent itself.
- The `key_authorization` signature is either an ordinary signature (`TempoSignature::Primitive`), in its existing encoding, or a configurable-account signature (`TempoSignature::ConfigurableAccount`). An access-key (`Keychain`) signature MUST be rejected.
- A configurable parent's quorum signs `configurable_account_digest(key_authorization.signature_hash(), parent_account, version)`, and the signature MUST name the parent.
- An unregistered configurable parent is registered when it signs a grant (TIP-1107 Registration).
- Existing expiry, replay, permission and witness-burning checks apply. A burned authorization witness can't be reused.

### Using a grant

The delegate signs inside the existing keychain envelope:

```text
0x04 || parent_account || delegate_signature
inner_digest = keccak256(0x04 || tx.signature_hash() || parent_account)
```

- An ordinary delegate signs `inner_digest`.
- A configurable delegate's quorum signs `configurable_account_digest(inner_digest, delegate_account, delegate_version)`.

At the transaction's position in the block, the protocol requires:

1. The signing key ID matches the grant.
2. For an ordinary signature, its type matches the grant's stored type, and TIP-1113's retirement check passes on the key ID.
3. If the key ID has a nonzero commitment, only a configurable-account signature from its current quorum is accepted, whatever type the grant stores. This is how a migrated delegate keeps its grants.
4. The grant's expiry, limits and scopes allow the transaction.

The transaction then runs as the parent, and the parent's owners don't sign. A configurable delegate's access keys can't sign on its behalf, and a keychain envelope can't be nested inside another. Otherwise delegation could chain without limit, and verification work per transaction would no longer be bounded. An unregistered configurable delegate is registered before calls run.

### Grant and use in one transaction

A transaction can create a grant with `key_authorization` and use it immediately. The grant signature and the outer signature are checked independently, and both must pass. A configurable parent with code or delegation, other than the account code marker, makes the transaction invalid.

### Owner updates, migration and revocation

- **A parent's owner update or migration** keeps every grant, with its permissions, expiry, limits, spending counters and revocation state.
- **A configurable delegate's owner update** moves use of the grant to its new quorum and changes nothing else. Signatures under the old configuration stop working.
- **Revocation** is per grant, by the parent's direct authority.

### Delegates that migrate

When a delegate migrates under TIP-1113, its existing grants keep their permissions, expiry, limits, counters and revocation state. Only its current quorum can use them (rule 3 under Using a grant). Its retired original key can't.

### Failure and rollback

| Outcome | What persists | Next step |
|---|---|---|
| Grant signature or outer signature invalid | Nothing. The transaction is invalid. | Fix the approval against the current configuration and grant state. |
| Included, calls revert or halt | Registrations, their events and the inline `key_authorization` persist. Grants made through precompile calls roll back with the other call changes. Normal fee and nonce rules apply. | Check which grants exist before retrying, because a burned witness can't be reused. |

Expiry, permissions, spending accounting and revocation otherwise follow TIP-1011.

### Bounded work and gas

Signatures are counted before any is checked:

- Each quorum uses at most eight signatures.
- A transaction has at most two quorums, one for a grant and one for its own signature, so at most sixteen signatures.
- An optional secp256k1 fee-payer signature adds one more.

Gas:

- Each configurable-account signature costs TIP-1107's `V` in place of that role's ordinary signature cost.
- Ordinary intrinsic gas already includes 3,000 for one base signature. That 3,000 is subtracted once, for the outer signature only, not for signed key authorizations.
- Existing keychain processing and policy charges still apply.
- Each additional delegate account costs a normal account access.
- Each unregistered signer adds TIP-1107's registration cost, including its event's log cost, once per account.
- Intrinsic gas and fee affordability are checked before any cryptography.
- There is no configuration storage-read charge.

### On-chain keychain helpers

- From T14, TIP-1049's `verifyKeychain` accepts an inner `0x05` signature from a configurable delegate. It checks the delegate's quorum against the delegate's current state as TIP-1107's `verifyConfigurableAccount` does, including an unregistered delegate's derived address, without registering it. The quorum signs `configurable_account_digest(keccak256(0x04 || digest || account), delegate_account, delegate_version)`, as for `inner_digest` under [Using a grant](#using-a-grant), so an approval names the parent. It then validates the grant under the delegate's address with key type `ConfigurableAccount`. A failed state check returns `false`; invalid approvals revert with `InvalidSignature()`.
- This path charges what `verifyConfigurableAccount` charges for the delegate's signature (TIP-1107's `V` without the 3,000 subtraction, including the address derivation for an unregistered delegate, and no registration cost), plus the existing keychain grant lookup. From T14, TIP-1020's calldata limit doesn't apply to `verifyKeychain`, so a delegate signature larger than a primitive one is accepted; TIP-1107's signature size limits still apply.
- From T14, `verifyKeychain` and `verifyKeychainAdmin` return `false` when the inner signature's type differs from the grant's stored type, except that a configurable signature uses a primitive grant whose key ID has a nonzero commitment. Before T14 they don't compare types.
- `verifyKeychainAdmin` accepts only the account's own key, subject to TIP-1113's retirement check, as [TIP-1137](https://github.com/tempoxyz/tempo/pull/8204) specifies. An inner `0x05` signature reverts with `InvalidFormat()`, as does one in `verifyKeychain` before T14.

## Interfaces

AccountKeychain adds `ConfigurableAccount = 3` to its key-type enum. Values 0, 1 and 2 MUST NOT change. Before T14, key type 3 and configurable-account key authorizations MUST be rejected, including during historical replay.

# Compatibility

| Integration | What changes |
|---|---|
| Wallets | Show the parent, the delegate, the permissions and who must sign. After a delegate's owner update or migration, track its current configuration. |
| Contracts reading `getKey` | `getKey` can now return 3. Solidity callers compiled with an enum limited to 0–2 revert when decoding it. A migrated delegate may still show its earlier ordinary type. |
| Contracts using keychain helpers | `verifyKeychain` accepts configurable delegates from T14. `verifyKeychainAdmin` rejects them. |
| Recovery tooling | List every active grant, including pre-T14 grants and admin access keys, and offer per-grant revocation. Don't present an owner update as revoking anything. |
| Transaction pools | Revalidate when a delegate's commitment changes, a grant is revoked, or the chain reorganises. |

# Threat Model

This threat model covers who can use a grant and who can change it. TIP-1107 covers owners, wallets and infrastructure.

Some risks are accepted by the design. Grants survive owner updates and migration, so recovery must revoke them explicitly. Grant events don't record which key authorised a grant, so cleanup relies on transaction history.

The most consequential attack is a compromised delegate that survives the parent's recovery. If Dana's key leaks and Acme only rotates its owners, Dana's grant keeps spending up to its limit until the quorum revokes it.

| Actor | Capability and trust | Boundary check and failure consequence |
|---|---|---|
| Parent's key or quorum | Controls grants on the parent. Trusted to choose delegates and limits. | The [direct-authority check](#who-can-grant-and-revoke). If compromised, it can create unwanted grants or revoke legitimate ones. |
| Delegate | Uses its grant. Trusted to stay within it. | AccountKeychain checks the grant's key ID, signature, limits, scopes and expiry. A compromised delegate spends up to its limit until revoked. |
| Configurable delegate's owners | Decide who uses the grant. Trusted to rotate responsibly. | The delegate's current commitment. A rotation hands the grant to new owners without the parent's approval, with limits and counters unchanged. |
| Admin access key | Spends without limit. Trusted with nothing else. | [TIP-1137](https://github.com/tempoxyz/tempo/pull/8204) removes its key management. If compromised, it drains the parent until revoked. |
| Wallet | Shows the parent what it grants. Trusted to show grants accurately. | The signature binds the real grant. A misleading wallet gets the parent to approve broader access than intended. |

# Invariants

## Managing grants

- For every grant created, changed or revoked, the authorising signature is the parent's own key or its current quorum, never an access-key signature.
- For every grant, its permissions include no power to manage keys or update the parent's owners.
- For every grant to a configurable delegate, the key type is `ConfigurableAccount = 3`, the key ID is the delegate's address, and the delegate is not the parent and has no code or EIP-7702 delegation other than the account code marker.
- For every block before T14, key type 3 and configurable-account key authorizations are rejected, and key-type values 0, 1 and 2 keep their meaning.

## Using grants

- For every valid access-key transaction, the delegate's signature is the only approval required, and the parent's owners don't sign.
- For every valid access-key transaction from a configurable delegate, the approvals come from the quorum whose configuration matches the delegate's commitment at that transaction's position in the block.
- For every key ID with a nonzero commitment, only a configurable-account signature from its current quorum uses the grant, whatever key type the grant stores.
- For every keychain envelope, the delegate signature is not itself a keychain envelope.
- For every transaction, at most sixteen owner signatures are checked across the grant and outer signatures, plus at most one secp256k1 fee-payer signature.
- For every call to `verifyKeychain` from T14 with a configurable-account inner signature, it returns `true` only when the delegate's quorum matches the delegate's current commitment, or its derived address when unregistered, its approvals sign over `keccak256(0x04 || digest || account)`, and the delegate holds an active grant on the account that accepts the signature.
- For every call to `verifyKeychainAdmin` with a configurable-account inner signature, and every such call to `verifyKeychain` before T14, the call reverts with `InvalidFormat()`.

## Owner updates and registration

- For every owner update or migration of the parent, and every owner update of a configurable delegate, each affected grant's permissions, expiry, limits, spending counters and revocation state are unchanged.
- For every included transaction, each configurable parent signing a grant and each configurable delegate using one has a nonzero commitment afterwards, whether the calls succeeded, reverted or halted.
