Skip to content
Draft
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
216 changes: 216 additions & 0 deletions src/components/StorageSavingsExplorer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
'use client'

import * as React from 'react'
import { Container } from './Container'

type Scenario = {
id: string
label: string
description: string
earnLabel: string
earnBefore: number
earnAfter: number
reuseLabel: string
reuseBefore: number
reuseAfter: number
}

const SCENARIOS: Scenario[] = [
{
id: 'cancel',
label: 'Order is canceled',
description:
'The maker cancels an eligible order, then returns later to place another eligible order.',
earnLabel: 'Cancel bid, earn reusable savings',
earnBefore: 304_741,
earnAfter: 361_184,
reuseLabel: 'Same maker reuses savings after cancel',
reuseBefore: 2_075_413,
reuseAfter: 868_756,
},
{
id: 'full-fill',
label: 'Order is fully filled',
description:
'An eligible order is fully filled, then the same maker returns later with another eligible order.',
earnLabel: 'Full fill, earn reusable savings',
earnBefore: 384_497,
earnAfter: 436_040,
reuseLabel: 'Same maker reuses savings after full fill',
reuseBefore: 1_828_213,
reuseAfter: 621_456,
},
]

const numberFormat = new Intl.NumberFormat('en-US')
const percentFormat = new Intl.NumberFormat('en-US', {
maximumFractionDigits: 1,
})

function formatGas(value: number) {
return `${numberFormat.format(value)} gas`
}

function formatSignedGas(value: number) {
const sign = value > 0 ? '+' : value < 0 ? '-' : ''
return `${sign}${formatGas(Math.abs(value))}`
}

function formatPercent(value: number) {
const sign = value > 0 ? '+' : value < 0 ? '-' : ''
return `${sign}${percentFormat.format(Math.abs(value))}%`
}

function changePercent(before: number, after: number) {
return ((after - before) / before) * 100
}

export function StorageSavingsExplorer() {
const [scenarioId, setScenarioId] = React.useState(SCENARIOS[0].id)
const [repeatOrders, setRepeatOrders] = React.useState(1)
const scenario = SCENARIOS.find((item) => item.id === scenarioId) ?? SCENARIOS[0]

const earningCost = scenario.earnAfter - scenario.earnBefore
const reuseSavings = scenario.reuseBefore - scenario.reuseAfter
const beforeTotal = scenario.earnBefore + scenario.reuseBefore * repeatOrders
const afterTotal = scenario.earnAfter + scenario.reuseAfter * repeatOrders
const netSavings = beforeTotal - afterTotal
const netPercent = changePercent(beforeTotal, afterTotal)
const breaksEven = reuseSavings > earningCost
const updateRepeatOrders = (value: number) => {
setRepeatOrders(Math.min(10, Math.max(1, value)))
}

return (
<Container
headerLeft={
<h4 className="font-normal text-[14px] text-gray12 leading-none">
Storage savings explorer
</h4>
}
footer={
<span>
Uses the merged DEX benchmark in{' '}
<a href="https://github.com/tempoxyz/tempo/pull/5903">tempoxyz/tempo#5903</a>. These
numbers are for the StablecoinDEX benchmark only.
</span>
}
>
<div className="space-y-5">
<div className="space-y-2">
<p className="m-0 text-gray11 text-sm">
Pick the lifecycle that earns a storage saving, then choose how many later eligible
orders the same maker places.
</p>

<fieldset className="grid gap-2 md:grid-cols-2">
<legend className="sr-only">Storage lifecycle</legend>
{SCENARIOS.map((item) => {
const active = item.id === scenario.id
return (
<button
key={item.id}
type="button"
aria-pressed={active}
onClick={() => setScenarioId(item.id)}
className={`rounded-md border px-3 py-2 text-left text-sm transition-colors ${
active
? 'border-accent bg-accent/10 text-gray12'
: 'border-gray5 bg-gray1 text-gray11 hover:border-gray8 hover:text-gray12'
}`}
>
<span className="block font-medium">{item.label}</span>
<span className="mt-1 block text-[13px] leading-5">{item.description}</span>
</button>
)
})}
</fieldset>
</div>

<div className="space-y-2 text-sm">
<div className="flex items-center justify-between gap-3 text-gray11">
<span id="repeat-orders-label">Later eligible orders by the same maker</span>
<span className="flex items-center gap-2">
<button
type="button"
aria-label="Decrease later eligible orders"
disabled={repeatOrders === 1}
onClick={() => updateRepeatOrders(repeatOrders - 1)}
className="grid h-7 w-7 place-items-center rounded-md border border-gray5 text-gray12 disabled:cursor-not-allowed disabled:opacity-40"
>
-
</button>
<strong className="min-w-5 text-center text-gray12">{repeatOrders}</strong>
<button
type="button"
aria-label="Increase later eligible orders"
disabled={repeatOrders === 10}
onClick={() => updateRepeatOrders(repeatOrders + 1)}
className="grid h-7 w-7 place-items-center rounded-md border border-gray5 text-gray12 disabled:cursor-not-allowed disabled:opacity-40"
>
+
</button>
</span>
</div>
<input
type="range"
min="1"
max="10"
value={repeatOrders}
aria-labelledby="repeat-orders-label"
onChange={(event) => updateRepeatOrders(Number(event.currentTarget.value))}
onInput={(event) => updateRepeatOrders(Number(event.currentTarget.value))}
className="w-full accent-gray12"
/>
</div>

<div className="grid gap-4 md:grid-cols-[1fr_1.1fr]">
<div className="space-y-3">
<h5 className="m-0 font-medium text-[14px] text-gray12">Benchmark impact</h5>

<div className="grid grid-cols-[1fr_auto] gap-x-4 gap-y-2 text-sm">
<span className="text-gray11">{scenario.earnLabel}</span>
<span className="text-right text-gray12">
{formatSignedGas(earningCost)} (
{formatPercent(changePercent(scenario.earnBefore, scenario.earnAfter))})
</span>
<span className="text-gray11">{scenario.reuseLabel}</span>
<span className="text-right text-gray12">
-{formatGas(reuseSavings)} (
{formatPercent(changePercent(scenario.reuseBefore, scenario.reuseAfter))})
</span>
<span className="text-gray11">Net over this lifecycle</span>
<span className="text-right font-medium text-gray12">
-{formatGas(netSavings)} ({formatPercent(netPercent)})
</span>
</div>
</div>

<div className="space-y-3">
<h5 className="m-0 font-medium text-[14px] text-gray12">Who should get the saving?</h5>

<ol className="m-0 grid list-decimal gap-2 pl-5 text-gray11 text-sm">
<li>Alice clears eligible order storage and earns reusable savings.</li>
<li>Bob places an order later, but does not spend Alice's savings.</li>
<li>Alice returns and can use the savings she earned.</li>
</ol>
</div>
</div>

<div className="border-gray4 border-t pt-4 text-gray11 text-sm">
{breaksEven ? (
<p className="m-0">
In this benchmark, one later eligible order is enough to outweigh the extra gas paid
when the DEX records who earned the reusable savings.
</p>
) : (
<p className="m-0">
This lifecycle needs more repeat usage before the reusable savings outweigh the
upfront accounting cost.
</p>
)}
</div>
</div>
</Container>
)
}
4 changes: 4 additions & 0 deletions src/pages/guide/issuance/distribute-rewards.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import { Cards, Card } from 'vocs'

# Distribute Rewards

:::warning[Rewards deprecation planned]
This change is planned for testnet on June 30, 2026 and mainnet on July 6, 2026. After activation, new Tempo Token Rewards opt-ins and distributions become no-ops. Already-accrued rewards remain claimable through the existing `claimRewards()` flow. See the [network upgrade overview](/protocol/upgrades/t7) for the full timeline and scope.
:::

Distribute rewards to token holders using TIP-20's built-in reward distribution mechanism. Rewards allow parties to incentivize holders of a token by distributing tokens proportionally based on their balance.

Rewards can be distributed by anyone on any TIP-20 token, and claimed by any holder who has opted in. This guide covers both the reward distributor and token holder use cases. While the demo below uses a token you create, the same principles apply to any token.
Expand Down
8 changes: 4 additions & 4 deletions src/pages/guide/node/network-upgrades.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ For detailed release notes and binaries, see the [Changelog](/changelog).

| | |
|---|---|
| **Scope** | Lower fees for work that is expected to expire; lower the base fee when gas is below the target threshold; remove TIP-20 rewards |
| **TIPs** | [TIP-1060: Gas Credits Primitive](https://tips.sh/1060), [TIP-1064: Gas Credits for DEX](https://tips.sh/1064), [TIP-1066: Gas Credits for MPP](https://tips.sh/1066), [TIP-1067: Dynamic Base Fee](https://tips.sh/1067-1), [TIP-1075: Remove TIP-20 Rewards](https://github.com/tempoxyz/tempo/pull/5380) |
| **Details** | [T7 network upgrade](/protocol/upgrades/t7) |
| **Scope** | Reusable storage savings; user-attributed DEX storage savings; dynamic base fee; Tempo Token Rewards cleanup |
| **References** | [Storage credits proposal](https://github.com/tempoxyz/tempo/pull/4016), [DEX maker credit proposal](https://github.com/tempoxyz/tempo/pull/4082), [Dynamic base fee proposal](https://github.com/tempoxyz/tempo/pull/5153), [Rewards deprecation proposal](https://github.com/tempoxyz/tempo/pull/5380) |
| **Details** | [Network upgrade overview](/protocol/upgrades/t7) |
| **Release** | TBD |
| **Testnet** | Planned: June 30, 2026 |
| **Mainnet** | Planned: July 6, 2026 |
| **Priority** | TBD |

T7 is planned but does not have a release yet. Node operator upgrade guidance will be added when the T7-compatible release is available.
T7 is planned for testnet on June 30, 2026 and mainnet on July 6, 2026. Node operator upgrade guidance will be added when the T7-compatible release is available.

---

Expand Down
4 changes: 4 additions & 0 deletions src/pages/guide/stablecoin-dex/providing-liquidity.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ Add liquidity for a token pair by placing orders on the Stablecoin DEX. You can

In this guide you will learn how to place buy and sell orders to provide liquidity on the Stablecoin DEX orderbook.

:::info[Planned storage savings for active makers]
After the T7 network upgrade, active makers may pay less gas when they cancel or fully fill eligible orders and later place new eligible orders. See [Pass Storage Savings to Users](/guide/t7-storage-credits) for the DEX benchmark and allocation pattern.
:::

## Demo

<Demo.Container name="Place an Order" footerVariant="source" src="tempoxyz/examples/tree/main/examples/exchange">
Expand Down
Loading
Loading