diff --git a/src/pages/docs/guide/bridge-bungee.mdx b/src/pages/docs/guide/bridge-bungee.mdx
index fe3bae07..287a097d 100644
--- a/src/pages/docs/guide/bridge-bungee.mdx
+++ b/src/pages/docs/guide/bridge-bungee.mdx
@@ -7,6 +7,8 @@ description: Bridge tokens to and from Tempo using Bungee. Covers Bungee Link, d
[Bungee](https://www.bungee.exchange/) is a cross-chain routing protocol built by the [SOCKET](https://docs.socket.tech/) team. For Tempo, the recommended integration path is Bungee Deposit: request a quote, execute the returned source-chain transaction, and track the request until Bungee delivers funds on the destination chain.
+If you are bringing an existing ERC-20 to Tempo, first decide whether to preserve it as the canonical asset behind a bridge adapter or migrate issuance to native TIP-20. See [Migrate an ERC-20 to TIP-20](/docs/guide/issuance/migrate-erc20-to-tip20).
+
Tempo's Bungee chain ID is **`4217`**.
## How Bungee Deposit works
diff --git a/src/pages/docs/guide/bridge-layerzero.mdx b/src/pages/docs/guide/bridge-layerzero.mdx
index 2d4a1ad1..931f25f9 100644
--- a/src/pages/docs/guide/bridge-layerzero.mdx
+++ b/src/pages/docs/guide/bridge-layerzero.mdx
@@ -14,6 +14,8 @@ There are two flavors of OFT on Tempo:
Both use the same underlying LayerZero endpoint on Tempo.
+If you are bringing an existing ERC-20 to Tempo, first decide whether to preserve it as the canonical asset behind a bridge adapter or migrate issuance to native TIP-20. See [Migrate an ERC-20 to TIP-20](/docs/guide/issuance/migrate-erc20-to-tip20).
+
## USDC.e and native USDC
USDC.e is the bridged representation of USDC on Tempo. It is backed 1:1 by native USDC in Stargate liquidity infrastructure.
diff --git a/src/pages/docs/guide/bridge-relay.mdx b/src/pages/docs/guide/bridge-relay.mdx
index 5437ef2b..fd45e788 100644
--- a/src/pages/docs/guide/bridge-relay.mdx
+++ b/src/pages/docs/guide/bridge-relay.mdx
@@ -7,6 +7,8 @@ description: Bridge tokens to and from Tempo using Relay. Includes supported tok
[Relay](https://relay.link/) is a cross-chain payments network powered by a solver that fills bridge requests instantly. Users deposit on the source chain and receive funds on the destination chain within seconds - no lock-and-mint or messaging protocol required.
+If you are bringing an existing ERC-20 to Tempo, first decide whether to preserve it as the canonical asset behind a bridge adapter or migrate issuance to native TIP-20. See [Migrate an ERC-20 to TIP-20](/docs/guide/issuance/migrate-erc20-to-tip20).
+
Tempo's Relay chain ID is **`4217`**.
## Contracts on Tempo
diff --git a/src/pages/docs/guide/issuance/index.mdx b/src/pages/docs/guide/issuance/index.mdx
index 81fdd681..00268237 100644
--- a/src/pages/docs/guide/issuance/index.mdx
+++ b/src/pages/docs/guide/issuance/index.mdx
@@ -19,6 +19,13 @@ Create and manage your own stablecoin on Tempo. Launch the token first, then con
title="Create a Stablecoin"
/>
+
+
>Registry: Create or select policy
+ end
+
+ Note over Issuer,Token: One-time token deployment
+ Issuer->>Factory: createToken(name, symbol, currency, quoteToken, admin, salt, logoURI)
+ Factory-->>Token: Create native TIP-20 token
+ Factory->>Token: Grant DEFAULT_ADMIN_ROLE to Admin
+
+ opt Compliance required
+ Note over Admin,Token: Attach the prepared policy before token operations
+ Admin->>Token: changeTransferPolicyId(policyId)
+ end
+
+ Note over Admin,Operator: One-time or occasional role setup
+ Admin->>Token: grantRole(ISSUER_ROLE, Operator)
+ Admin->>Token: grantRole(PAUSE_ROLE, pause wallet)
+ Admin->>Token: grantRole(UNPAUSE_ROLE, unpause wallet)
+
+ opt Compliance required
+ Note over PolicyAdmin,Registry: Ongoing compliance maintenance
+ PolicyAdmin->>Registry: Add, remove, allow, or block wallets
+ end
+
+ Note over Operator,Vault: Ongoing issuance operations
+ Operator->>Token: mint(Vault, amount)
+ Token->>Token: Check ISSUER_ROLE, pause state, and supply cap
+ Token->>Registry: Authorize Vault as mint recipient
+ Token-->>Vault: TIP-20 balance increases`} />
+
+`TIP20Factory.createToken` does not accept a policy ID. If compliance is required, prepare the policy first, deploy the token, and attach the policy before minting or transferring. A new TIP-20 otherwise starts on the always-allow policy.
+
+## 3. Complete the implementation checklist
+
+Before production deployment, confirm:
+
+- TIP-20 token is deployed through `TIP20Factory`.
+- Token name, symbol, currency, quote token, and logo are correct.
+- Admin address is controlled by the issuer or approved operator.
+- `ISSUER_ROLE` is granted only to the intended issuer wallet, manager, or bridge adapter.
+- Native role queries use `hasRole(account, role)`, and each role's administrator is confirmed with `getRoleAdmin(role)`.
+- `PAUSE_ROLE` and `UNPAUSE_ROLE` are assigned.
+- Supply cap is set deliberately. Every TIP-20 starts at `type(uint128).max`; prefer the lowest practical cap and increase it as issuance grows.
+- Transfer policy is configured if compliance is required.
+- If using a compound policy, sender, recipient, and mint-recipient checks are tested independently.
+- Existing ERC-20 supply is burned, locked, or reconciled if this is a migration or bridge.
+- Decimal conversion is tested.
+- Mint and burn flows are tested.
+- Mint tests cover the supply cap, paused state, and TIP-403 mint-recipient authorization.
+- Pause tests confirm that transfers, minting, normal burns, and `burnBlocked` are blocked while role and configuration administration remain available.
+- Transfer and transferFrom are tested.
+- Custody and treasury wallets are funded and labeled.
+- Tokenlist and explorer metadata are ready.
+- The issuer has an operational runbook for role changes, pausing, minting, burning, and reconciliation.
+
+### Review mutable and immutable settings
+
+| Setting | Initial value | Can it change? |
+|---|---|---|
+| Token address | Deterministically derived from factory caller and salt | No |
+| Name and symbol | Set at creation | No |
+| Decimals | `6` | No |
+| Currency | Set at creation | No |
+| Supply cap | `type(uint128).max` | Yes, but not below current total supply |
+| Quote token | Set at creation | Yes, through the staged quote-token update flow |
+| Transfer policy | Always-allow policy (`1`) | Yes, by the TIP-20 admin |
+| Logo URI | Set or left empty at creation | Yes, by the TIP-20 admin |
+| Roles and role administrators | Admin receives `DEFAULT_ADMIN_ROLE` | Yes |
+| Pause state | Unpaused | Yes, through `PAUSE_ROLE` and `UNPAUSE_ROLE` |
+
+### Choose the currency by unit-price behavior
+
+Set `currency` to the asset or unit of account that **one token unit is designed to remain approximately 1:1 with**. The deciding question is how the price of one token unit behaves, not whether the token generates yield.
+
+| Token behavior | Example | `currency` |
+|---|---|---|
+| USD stablecoin that remains near $1 | USDC | `USD` |
+| Rebasing USD yield token whose balance grows while each unit remains near $1 | Rebasing USD yield token | `USD` |
+| Wrapped token that remains 1:1 with BTC | WBTC or cbBTC | `BTC` |
+| Accumulating token whose balance stays fixed while its redemption value rises | PRIME or cbETH | Its own asset identifier, such as `PRIME` or `cbETH` |
+| Non-rebasing wrapper around a rebasing asset | Wrapped yield token | Its own asset identifier, unless one wrapper unit remains near 1:1 with the underlying denomination |
+
+Do not set `currency = USD` merely because an accumulating token is USD-backed or reports its value in USD. Classifying a TIP-20 as USD makes it eligible for infrastructure designed for near-par USD assets:
+
+- The [Fee AMM](/docs/protocol/fees/spec-fee-amm) converts between a user's fee token and a validator's preferred fee token at fixed near-par rates. If one token unit is worth more than $1, that conversion would misprice it.
+- The [Stablecoin DEX](/docs/protocol/exchange) is market-priced, but it is designed for USD-classified pairs and currently limits orders to a ±2% range around parity. An accumulating token can move outside that range as its redemption value grows.
+
+Because `currency` is immutable, confirm the token's unit-price behavior before deployment. See [Currency Declaration](/docs/protocol/tip20/overview#currency-declaration) for the full selection rules.
+
+## 4. Inspect the current ERC-20
+
+Before deploying on Tempo, identify the current token architecture.
+
+| Item | What to check |
+|---|---|
+| Token address | Current ERC-20 or proxy address |
+| Implementation | Proxy implementation, if upgradeable |
+| Metadata | `name`, `symbol`, `decimals` |
+| Supply | `totalSupply`, current holder or treasury vault |
+| Roles | Admin, minter, burner, pauser, upgrader |
+| Mint flow | Who can create supply and through what contract |
+| Burn flow | Who can destroy supply and whether `burnFrom` is used |
+| Pause flow | Who can pause and unpause |
+| Compliance | Allowlist, blocklist, sanctions, KYC, transfer hooks |
+| Bridge | Source adapter, destination adapter, replay protection |
+| Oracle | NAV, FX, redemption price, or yield calculation |
+
+## 5. Map OpenZeppelin patterns to TIP-20
+
+Map by capability, not by contract name.
+
+| OpenZeppelin pattern | Common behavior | Tempo mapping |
+|---|---|---|
+| `ERC20` / `ERC20Upgradeable` | Core transfer and allowance surface | Native TIP-20 transfer and allowance surface |
+| `IERC20Metadata` | `name`, `symbol`, `decimals` | Set name, symbol, and currency at TIP-20 creation |
+| `AccessControl` | Role-based permissions | TIP-20 native roles |
+| `Pausable` | Pause state and pause checks | `PAUSE_ROLE` and `UNPAUSE_ROLE` |
+| `ERC20Burnable` | `burn` and often `burnFrom` | An `ISSUER_ROLE` holder can burn only its own TIP-20 balance; TIP-20 does not expose `burnFrom` |
+| `ERC20Wrapper` | Deposit underlying ERC-20, mint wrapped ERC-20 | Use an external adapter that mints TIP-20 |
+| Proxy upgrade pattern | Upgradeable implementation and storage | Not portable to TIP-20 |
+
+## 6. Map roles
+
+| Current role or control | Tempo role |
+|---|---|
+| `DEFAULT_ADMIN_ROLE` or owner | TIP-20 `DEFAULT_ADMIN_ROLE` for role and configuration administration; grant `ISSUER_ROLE` separately for minting |
+| `MINTER_ROLE` | `ISSUER_ROLE` |
+| `BURNER_ROLE` | `ISSUER_ROLE` for normal burns |
+| `PAUSER_ROLE` | `PAUSE_ROLE` plus `UNPAUSE_ROLE` |
+| Compliance admin | TIP-403 simple-policy admin |
+| Bridge operator | Bridge adapter with `ISSUER_ROLE`; enforce limits in the adapter |
+| Lifecycle manager | Manager contract with `ISSUER_ROLE`; enforce limits in the manager |
+
+Important: `Pausable` does not define who can pause. That authority usually comes from `AccessControl`, `Ownable`, or a custom manager. On TIP-20, pause and unpause are separate permissions.
+
+`ISSUER_ROLE` is not natively scoped by amount, destination, or operation. If an issuer needs those limits, its wallet, manager, or adapter must enforce them before calling TIP-20.
+
+## 7. Handle decimals
+
+OpenZeppelin ERC-20 tokens commonly use 18 decimals unless overridden. TIP-20 uses 6 decimals.
+
+Before migration or integration:
+
+- Define the conversion rule.
+- Decide how to handle dust.
+- Update bridge and migration scripts.
+- Update reporting and accounting.
+- Confirm wallet and explorer display.
+- Test mint, burn, transfer, and reconciliation in smallest units.
+
+Example:
+
+```text
+1.000000 TIP-20 unit = 1 token
+1 TIP-20 token = 1,000,000 base units
+```
+
+## 8. Move custom logic outside the token
+
+TIP-20 is native. Do not port custom ERC-20 methods into the token.
+
+| Current custom logic | Tempo location |
+|---|---|
+| Transfer hooks | TIP-403 policy, maintained by an issuer compliance sync service |
+| Allowlist or blocklist | TIP-403 simple or compound policy |
+| Sanctions checks | TIP-403 policy, maintained by an issuer compliance sync service |
+| Subscription flow | Lifecycle manager |
+| Redemption flow | Lifecycle manager |
+| Fee logic | Lifecycle manager |
+| Rate limits | Lifecycle manager |
+| Oracle pricing | External oracle or manager-facing oracle |
+| Bridge accounting | Bridge adapter |
+
+## 9. Map compliance hooks to TIP-403
+
+Many issuer ERC-20s enforce compliance inside token transfer hooks such as `_beforeTokenTransfer` or `_update`.
+
+Common checks include:
+
+- allowlisted sender
+- allowlisted recipient
+- blocked sender or recipient
+- sanctions screening
+- KYC or identity registry membership
+- transfer-agent or operator eligibility
+
+On Tempo, keep the token native and move transfer eligibility into TIP-403 policy.
+
+A TIP-20 token points to one `transferPolicyId`. Do not model compliance as attaching both an allowlist policy and a blocklist policy directly to the token. Use a simple whitelist or blacklist when the same rule applies to transfer senders, transfer recipients, and mint recipients. Use a compound policy when those three rules need to differ.
+
+### Simple vs compound policies
+
+| Policy type | Use when |
+|---|---|
+| Simple whitelist | The same allowlist applies to transfer-sender, transfer-recipient, and mint-recipient checks |
+| Simple blacklist | The same blocklist applies to transfer-sender, transfer-recipient, and mint-recipient checks |
+| Compound policy | Sender, recipient, and mint-recipient rules need to differ |
+
+For simple whitelist or blacklist policies, the flow is shorter: create the simple policy, update its wallet entries, and set the token's `transferPolicyId` to that simple policy ID. Use a compound policy only when sender, recipient, and mint-recipient rules need to differ.
+
+A compound policy references three simple policies:
+
+| Compound policy component | Used for |
+|---|---|
+| `senderPolicyId` | Transfer senders and blocked-account burn eligibility |
+| `recipientPolicyId` | Transfer recipients |
+| `mintRecipientPolicyId` | Mint recipients |
+
+For compound policies, the TIP-20 admin attaches the compound policy initially:
+
+```text
+TIP20.changeTransferPolicyId(compoundPolicyId)
+```
+
+The TIP-20 admin can later change `transferPolicyId` to another policy. Day to day, the issuer updates the underlying simple policies as wallets become allowed, blocked, or ineligible.
+
+### Separate policy and token responsibilities
+
+Each TIP-403 simple policy has one admin address. A compliance sync service must operate through that address; the service is not a parallel native authority.
+
+| Responsibility | Owner |
+|---|---|
+| Select which policy the token uses | TIP-20 admin |
+| Maintain allowlist, blocklist, KYC, or sanctions entries | Simple-policy admin address, which may be operated by a compliance sync service |
+| Mint and burn normal supply | Issuer wallet, lifecycle manager, or bridge adapter with `ISSUER_ROLE` |
+| Pause or unpause token operations | `PAUSE_ROLE` / `UNPAUSE_ROLE` holders |
+
+### Follow the compliance flow
+
+>Registry: Create sender policy
+ Updater->>Registry: Create recipient policy
+ Updater->>Registry: Create mint recipient policy
+ Updater->>Registry: Create compound policy(senderPolicyId, recipientPolicyId, mintRecipientPolicyId)
+
+ Note over Admin,Token: One-time policy attachment
+ Admin->>Token: changeTransferPolicyId(compoundPolicyId)
+
+ Note over Compliance,Registry: Ongoing compliance maintenance
+ Compliance->>Updater: Wallet eligibility changes
+ Updater->>Registry: Update simple policy entries
+
+ Note over Sender,Recipient: Ongoing transfer checks
+ Sender->>Token: transfer(Recipient, amount)
+ Token->>Registry: Check senderPolicyId for Sender
+ Token->>Registry: Check recipientPolicyId for Recipient
+ Registry-->>Token: allow or reject
+ Token-->>Recipient: Balance increases if allowed
+
+ Note over Issuer,Recipient: Ongoing mint checks
+ Issuer->>Token: mint(Recipient, amount)
+ Token->>Token: Check ISSUER_ROLE, not paused, and totalSupply + amount <= supplyCap
+ Token->>Registry: Check mintRecipientPolicyId for Recipient
+ Registry-->>Token: allow or reject`} />
+
+Minting succeeds only when the caller holds `ISSUER_ROLE`, the token is not paused, the resulting supply does not exceed the supply cap, and TIP-403 authorizes the mint recipient.
+
+The recipient can also configure an account-level receive policy, which the issuer does not control. If that policy blocks a transfer or mint, the call succeeds but delivery is redirected to `ReceivePolicyGuard` as a claimable receipt. Issuers should monitor this outcome when reconciling mints and transfers. See [Receive policies](/docs/protocol/tip403/receive-policies).
+
+### Map ERC-20 compliance patterns
+
+| Current ERC-20 compliance pattern | Tempo mapping |
+|---|---|
+| `_beforeTokenTransfer` allowlist check | Simple whitelist or compound policy component |
+| `_update` allowlist check | Simple whitelist or compound policy component |
+| Blocklist check | Simple blacklist or compound policy component |
+| Sanctions-list contract | Simple blacklist maintained by issuer compliance sync service |
+| Identity or KYC registry | Simple whitelist maintained by issuer compliance sync service |
+| Different sender and recipient rules | Compound policy |
+| Mint recipient eligibility | Compound policy `mintRecipientPolicyId` |
+| Operator or spender compliance | Lifecycle manager or bridge adapter check |
+| Compliance admin | TIP-403 simple-policy admin |
+
+## 10. Avoid incompatible ERC-20 assumptions
+
+- Do not deploy a custom ERC-20 when the target is native TIP-20.
+- Do not assume proxy storage or upgrade logic carries over.
+- Do not grant issuer permissions to broad operational wallets without a reason.
+- Use TIP-20's native role-query methods; do not assume OpenZeppelin argument ordering.
+- Do not ignore 18-to-6 decimal conversion.
+- Do not put compliance or subscription logic inside the token.
+
+## 11. Consult the operational reference
+
+### Query and administer native roles
+
+TIP-20 exposes native methods for querying and administering roles:
+
+```solidity
+hasRole(address account, bytes32 role)
+getRoleAdmin(bytes32 role)
+setRoleAdmin(bytes32 role, bytes32 adminRole)
+```
+
+Unlike OpenZeppelin's `hasRole(role, account)`, TIP-20's `hasRole` takes the account first: `hasRole(account, role)`.
+
+`DEFAULT_ADMIN_ROLE` is `bytes32(0)`. Multiple accounts may hold it. It governs role and token administration, but it does not itself permit minting; an account or contract must hold `ISSUER_ROLE` to mint.
+
+Initially, every role is governed by `DEFAULT_ADMIN_ROLE`. `setRoleAdmin(role, adminRole)` can later change which role is authorized to grant and revoke that role. Use `getRoleAdmin(role)` to inspect the current relationship before changing role assignments.
+
+### Apply pause semantics
+
+Since the T3 upgrade, a paused TIP-20 blocks:
+
+- transfers
+- minting
+- normal burns
+- `burnBlocked`
+
+Administration remains available while paused.
+
+`transferFeePreTx` and `transferFeePostTx` are system-only entrypoints used by Tempo protocol precompiles, not issuer-callable operations. As a protocol invariant, `transferFeePreTx` respects pause while `transferFeePostTx` remains available so fee settlement can complete.
+
+## Related references
+
+- [OpenZeppelin ERC-20 contracts](https://docs.openzeppelin.com/contracts/5.x/api/token/erc20)
+- [OpenZeppelin access control](https://docs.openzeppelin.com/contracts/5.x/access-control)
+- [TIP-20 tokens specification](/docs/protocol/tip20/spec)
\ No newline at end of file
diff --git a/src/pages/docs/quickstart/integrate-tempo.mdx b/src/pages/docs/quickstart/integrate-tempo.mdx
index 4a1f6c2a..c387d6e9 100644
--- a/src/pages/docs/quickstart/integrate-tempo.mdx
+++ b/src/pages/docs/quickstart/integrate-tempo.mdx
@@ -67,6 +67,12 @@ Tempo is EVM-compatible and targets the **Osaka** EVM hard fork. Most Ethereum t
## Bridges and Ecosystem
+