Skip to content
Merged
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
8 changes: 8 additions & 0 deletions .changeset/dry-sage-robinhood-beta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@artblocks/abx-sdk': patch
'@artblocks/abx-cli': patch
---

Enable Robinhood Chain production as beta after canonical deployment, paired-testnet qualification,
and managed-service validation. Surface the same real-funds warning and testnet-first gate used for
other production beta networks.
16 changes: 11 additions & 5 deletions .claude/skills/abx/reference/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,21 @@ output bug without repeating the secret.
## Select the chain explicitly through the environment

Read the full `chains` array from `abx capabilities --json`. Base Sepolia is the default; Sepolia is
also supported. Robinhood Chain Testnet is experimental, Base production is beta, and Robinhood
Chain and Ethereum are disabled. There is deliberately no
also supported. Robinhood Chain Testnet is experimental, production deployments on Base and
Robinhood Chain are beta, and Ethereum is disabled. There is deliberately no
`--chain` flag because silently ignoring a wrong-chain request could spend on the wrong network.

Choose a production chain by intended collector base, then measured cost. Base fits projects aimed at
Base users; Robinhood Chain fits projects intentionally aimed at that network. Run the exact flow on
the paired testnet and compare the CLI dry-run gas report before deciding. Large onchain payloads
amplify transaction cost on either network, so weigh onchain permanence against Arweave, IPFS, or
cloud custody rather than assuming one chain makes storage cheap.

Before any transaction on an `experimental` or `beta` network, name the network and support level,
explain what the transaction or transaction group will do, and state the relevant contract,
configuration, and real-funds risks. Base beta is prerelease software without an independent
third-party audit; bugs, misconfiguration, and nondeterministic agent behavior may cause permanent
loss. Link to the open source, use-at-your-own-risk implementation at
configuration, and real-funds risks. Production beta support is prerelease software without an
independent third-party audit; bugs, misconfiguration, and nondeterministic agent behavior may cause
permanent loss. Link to the open source, use-at-your-own-risk implementation at
https://github.com/ArtBlocks/abx. Qualify the same flow on the paired testnet before production.

Use per-chain RPC variables when operating more than one chain. `abx doctor` checks chain identity,
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ the Solidity contracts, TypeScript SDK, command-line interface, reference servic
public documentation.

ABX tooling is prerelease software. Base Sepolia and Sepolia are supported, Robinhood Chain Testnet
is experimental, and Base production is beta. Robinhood Chain and Ethereum come later.
is experimental, and production deployments on Base and Robinhood Chain are beta. Ethereum comes
later.

## Quickstart

Expand All @@ -28,11 +29,12 @@ The complete user guide, protocol reference, deployment addresses, and API docum
| Environment | Available | Next |
| --- | --- | --- |
| Testnet | Base Sepolia (default), Sepolia, Robinhood Chain Testnet (experimental) | — |
| Production | Base (beta) | Robinhood Chain, Ethereum |
| Production | Base, Robinhood Chain (beta) | Ethereum |

Base beta transactions use real ETH and irreversible state; prove the same flow on Base Sepolia
first. Experimental networks are for deliberate qualification. For live support status, risks, and canonical
contract addresses, see [Networks and deployments](https://docs.abx.io/docs/reference/deployments).
Production beta transactions use real funds and create irreversible state; prove the same flow on the
paired testnet first. Experimental networks are for deliberate qualification. For live support
status, risks, and canonical contract addresses, see
[Networks and deployments](https://docs.abx.io/docs/reference/deployments).
The machine-readable sources of truth are
[`chain-support.json`](packages/sdk/src/chain-support.json) and
[`deployments.ts`](packages/sdk/src/deployments.ts).
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ function assertKnownChainEnv(): void {
process.stderr.write(
`\n\u001b[31m\u2717\u001b[0m ABX_CHAIN="${key}" is not a recognized chain. Selectable: ${KNOWN_CHAIN_KEYS.join(', ')}.\n` +
(mainnetish
? ` Base is available as beta with ABX_CHAIN=base. Other production networks remain disabled.\n` +
? ` Base and Robinhood Chain are available as beta with ABX_CHAIN=base or ABX_CHAIN=robinhood. Ethereum remains disabled.\n` +
` Prove the same flow on the paired testnet before using real funds.\n\n`
: ` Unset it to use the default (${DEFAULT_CHAIN_KEY}), or set one of the above.\n\n`),
);
Expand Down
39 changes: 18 additions & 21 deletions packages/cli/test/chain-from-dotenv.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,27 +78,7 @@ test('an unknown chain in .env is REFUSED, not silently ignored', () => {
}
});
assert.match(out, /is not a recognized chain/);
assert.match(out, /Base is available as beta/, 'a mainnet-ish alias gets the current production explanation');
});

test('a recognized but disabled production chain is REFUSED with its registry status', () => {
const out = withDotEnv('ABX_CHAIN=robinhood\n', (dir) => {
try {
execFileSync('node', ['--import', 'tsx', `${CLI_SRC}/main.ts`, 'doctor'], {
cwd: dir,
encoding: 'utf8',
env: {...process.env, ABX_CHAIN: undefined, ABX_NO_UPDATE_CHECK: '1'} as NodeJS.ProcessEnv,
timeout: 60_000,
});
return '';
} catch (e) {
const err = e as {stdout?: string; stderr?: string};
return (err.stdout ?? '') + (err.stderr ?? '');
}
});
assert.match(out, /ABX_CHAIN="robinhood" is recognized but disabled/);
assert.match(out, /chain 4663, production/);
assert.match(out, /paired robinhood-testnet network/);
assert.match(out, /Base and Robinhood Chain are available as beta/, 'a mainnet-ish alias gets the current production explanation');
});

test('Base is selectable but every substantive invocation prints the production-beta warning', () => {
Expand All @@ -117,6 +97,23 @@ test('Base is selectable but every substantive invocation prints the production-
assert.equal(capabilities.chains.find((chain) => chain.key === 'base')?.supportLevel, 'beta');
});

test('Robinhood Chain is selectable but every substantive invocation prints the production-beta warning', () => {
const result = withDotEnv('ABX_CHAIN=robinhood\n', (dir) =>
spawnSync('node', ['--import', 'tsx', `${CLI_SRC}/main.ts`, 'capabilities', '--json'], {
cwd: dir,
encoding: 'utf8',
env: {...process.env, ABX_CHAIN: undefined, ABX_NO_UPDATE_CHECK: '1'} as NodeJS.ProcessEnv,
timeout: 60_000,
}),
);
assert.equal(result.status, 0, result.stderr);
assert.match(result.stderr, /Robinhood Chain production beta \(chain 4663\)/);
assert.match(result.stderr, /Real funds and irreversible state are at risk/);
assert.match(result.stderr, /Prove the flow on robinhood-testnet/);
const capabilities = JSON.parse(result.stdout) as {chains: Array<{key: string; supportLevel: string}>};
assert.equal(capabilities.chains.find((chain) => chain.key === 'robinhood')?.supportLevel, 'beta');
});

test('Robinhood Chain Testnet is selectable but every substantive invocation prints the experimental warning', () => {
const result = withDotEnv('ABX_CHAIN=robinhood-testnet\n', (dir) =>
spawnSync('node', ['--import', 'tsx', `${CLI_SRC}/main.ts`, 'capabilities', '--json'], {
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/src/chain-support.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"environment": "production",
"pairedChain": "robinhood-testnet",
"contractStatus": "deployed",
"supportLevel": "disabled"
"supportLevel": "beta"
},
{
"key": "ethereum",
Expand Down
9 changes: 5 additions & 4 deletions packages/sdk/src/deployments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,11 @@ export const DEPLOYMENTS: Record<number, ChainDeployment> = {
...CANONICAL,
generator: '0x4F74De4835B51414a4DA83527589aEDc41A26FaE',
},
// Robinhood Chain (production candidate). Contracts were deployed from this release on
// 2026-09-17 and have exact-match source records on Sourcify. The network remains disabled until
// the separate services and low-value acceptance gates pass. No canonical dependency registry
// exists, so the generator fallback is address(0). SSTORE2 asset pointers:
// Robinhood Chain (production beta). Contracts were deployed from this release on
// 2026-09-17 and have exact-match source records on Sourcify. Beta enablement followed paired-testnet
// qualification and managed-service validation; low-value production acceptance follows under the
// beta warning. No canonical dependency registry exists, so the generator fallback is address(0).
// SSTORE2 asset pointers:
// abxJsPointer 0xbeD5a9dec0c94fF39F7874df979eBdC3Adab568D,
// gunzipScriptPointer 0x686CE62bdE8FE4Fc3de70c8fC65b574A05a23D52.
4663: {
Expand Down
14 changes: 8 additions & 6 deletions packages/sdk/test/chains.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,15 @@ test('chain registry separates recognized networks from selectable networks', ()
'robinhood',
'ethereum',
]);
assert.deepEqual(KNOWN_CHAIN_KEYS, ['base-sepolia', 'sepolia', 'robinhood-testnet', 'base']);
assert.equal(CHAIN_SUPPORT.filter(isChainSelectable).length, 4);
assert.deepEqual(KNOWN_CHAIN_KEYS, ['base-sepolia', 'sepolia', 'robinhood-testnet', 'base', 'robinhood']);
assert.equal(CHAIN_SUPPORT.filter(isChainSelectable).length, 5);
assert.equal(chainSupportByKey('robinhood-testnet')?.contractStatus, 'deployed');
assert.equal(chainSupportByKey('robinhood-testnet')?.supportLevel, 'experimental');
assert.equal(chainSupportByKey('base')?.contractStatus, 'deployed');
assert.equal(chainSupportByKey('base')?.supportLevel, 'beta');
assert.equal(chainSupportByKey('robinhood')?.contractStatus, 'deployed');
assert.equal(chainSupportByKey('robinhood')?.supportLevel, 'disabled');
for (const key of ['robinhood', 'ethereum']) {
assert.equal(chainSupportByKey(key)?.supportLevel, 'disabled');
}
assert.equal(chainSupportByKey('robinhood')?.supportLevel, 'beta');
assert.equal(chainSupportByKey('ethereum')?.supportLevel, 'disabled');
});

test('registry ids agree with viem chain metadata, including disabled production networks', () => {
Expand All @@ -50,6 +48,10 @@ test('Base has a keyless default RPC for beta access', () => {
assert.deepEqual(resolveRpcUrls('base'), ['https://mainnet.base.org']);
});

test('Robinhood Chain has a keyless default RPC for beta access', () => {
assert.deepEqual(resolveRpcUrls('robinhood'), ['https://rpc.mainnet.chain.robinhood.com']);
});

test('redactRpcUrlsInText removes credential-bearing configured endpoints from upstream errors', () => {
const rpc = 'https://rpc.example/v2/super-secret-api-key?tenant=private';
const input = `HTTP request failed at ${rpc}\nURL: ${rpc}`;
Expand Down
18 changes: 11 additions & 7 deletions site/content/docs/reference/deployments.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@ title: "Networks and deployments"
description: "ABX network support and canonical contract addresses."
---

Start on Base Sepolia. Sepolia is supported, Robinhood Chain Testnet is experimental, and Base
production is beta after the same flow has passed on its testnet pair.
Start on Base Sepolia. Sepolia is supported, Robinhood Chain Testnet is experimental, and production
deployments on Base and Robinhood Chain are beta after the same flow has passed on the paired testnet.

**Base beta:** transactions use real ETH and create irreversible state. ABX is prerelease software,
has not had an independent third-party audit, and may fail through software bugs, configuration
mistakes, or nondeterministic agent behavior. Review the network, signer, complete transaction group,
value, and locks before sending. Use at your own risk.
**Production beta:** transactions use real funds and create irreversible state. ABX is prerelease
software, has not had an independent third-party audit, and may fail through software bugs,
configuration mistakes, or nondeterministic agent behavior. Review the network, signer, complete
transaction group, value, and locks before sending. Use at your own risk.

Choose by audience first, then measured cost: use Base for projects aimed at Base users and Robinhood
Chain for projects aimed at that network. Run the same dry run on the paired testnet before deciding.
Large onchain payloads increase transaction cost on either network, so decide byte custody separately.

| Network | Chain ID | Support | Canonical contracts |
| --- | ---: | --- | --- |
| Base Sepolia | `84532` | supported · default | deployed |
| Sepolia | `11155111` | supported | deployed |
| Robinhood Chain Testnet | `46630` | experimental | deployed |
| Base | `8453` | beta | deployed |
| Robinhood Chain | `4663` | disabled | deployed |
| Robinhood Chain | `4663` | beta | deployed |
| Ethereum | `1` | disabled | not deployed |

“Experimental” means deliberate testnet qualification. “Beta” means production use is enabled with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Edition sales are priced per token ID. See [Sales](/docs/using-abx/guides/sales#

Read the dry-run summary and confirm:

- the network reported by the dry run and, for Base beta, the matching Base Sepolia proof
- the network reported by the dry run and, for a production beta, the matching paired-testnet proof
- project shape and token standard
- owner, royalties, burnability, and transfer restrictions
- media custody and metadata route
Expand Down
4 changes: 2 additions & 2 deletions site/content/docs/using-abx/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {QUICKSTART_PROMPT} from '@/lib/quickstart';
- A browser wallet with Base Sepolia test ETH

Start on Base Sepolia, the default. Sepolia is supported, and Robinhood Chain Testnet is available
for experimental qualification. Base production is beta: use it only after the same flow passes on
Base Sepolia and after reviewing
for experimental qualification. Production deployments on Base and Robinhood Chain are beta: use
either only after the same flow passes on its paired testnet and after reviewing
the network, signer, transaction group, value, and irreversible choices. You do not need a private
key: the agent can open your browser wallet for approval, or use a dedicated environment key for
deliberate automation.
Expand Down
Loading