6.8 KiB
UUPS Bank V1 → V2 Demo
Educational demo — mock token — never use real funds.
This repository is a local-first upgradeability lesson. It deploys a six-decimal mock ERC-20 and a V1 custody ledger behind an ERC-1967 proxy, upgrades the proxy to V2 without losing state, performs a customer-to-customer ledger transfer, and presents the result in a read-only operations console.
Trust boundary: MockUSDC has no value. These contracts are educational and unaudited; real deposits must never be sent here. The owner can pause customer actions and install arbitrary future logic. UUPS mistakes can corrupt state or permanently brick upgradeability. A real custody product requires professional audits, operational key controls, multisig or timelocked governance, incident procedures, legal advice, and jurisdiction-specific compliance work.
Prerequisites
Use a Linux-like Bash environment with Git, GNU Make, curl, Foundry 1.7.1 (forge, anvil, and cast), Node 24.18.0, and npm 11.17.0. The exact package graph is committed in the lockfiles. Installation documentation: Git, Foundry, Node, npm, Bash, Make, and curl.
make setup
make doctor
make setup initializes recursive Git submodules and installs both pinned npm dependency trees. make doctor is read-only: it verifies versions, dependencies, writable runtime locations, and that local ports 8545 and 5173 are available.
Ten-minute local quick start
This complete path is local. It needs no Base Sepolia service, browser wallet, faucet, explorer, public RPC, keystore, secret, or real funds.
In the first terminal:
make demo-local
The command performs a scoped reset, starts deterministic Anvil at http://127.0.0.1:8545, deploys and seeds V1, checks its exact state, exports public artifacts, and starts the console at http://127.0.0.1:5173/. It remains attached so Ctrl-C safely stops only the recorded project process groups.
In a second terminal:
DEMO_EXPECTED_STAGE=v1 make check-state
make upgrade-v2
make demo-transfer
DEMO_EXPECTED_STAGE=v2 make check-state
curl --fail http://127.0.0.1:5173/
Act 1 proves Alice has 900 mUSDC, Bob has 500 mUSDC, liabilities and reserves are both 1,400 mUSDC, and version is 1. The upgrade keeps the proxy, owner, asset, pause state, customer balances, liabilities, reserves, surplus, and deployment block unchanged while changing the implementation and version to 2. The internal 250 mUSDC transfer then leaves Alice with 650 mUSDC and Bob with 750 mUSDC; liabilities and reserves remain 1,400 mUSDC, and the console decodes BalanceTransferred without an ERC-20 reserve transfer.
Stop the attached first terminal with Ctrl-C, then remove only reproducible local state:
make reset-local
Architecture and guarantees
Foundry scripts are the state-changing control plane; the browser has no connector, signer, transaction client, or write control. MockUSDC holds no value. An ERC-1967 proxy keeps the bank address and storage stable while delegating calls to BankV1 or BankV2. The proxy holds token reserves and the internal ledger records liabilities. Confirmed public manifests and generated ABIs connect that system to the React/Vite console through viem and wagmi.
OpenZeppelin supplies the UUPS and access-control primitives plus storage/upgrade validation. Foundry supplies compilation, tests, scripts, and the local chain. The project supplies the application logic, tests, manifests, lifecycle tooling, and UI. Passing those checks does not make the demo audited, decentralized, or suitable for custody.
Command reference
make doctor— check prerequisites, dependencies, runtime locations, configuration, and local ports without changing chain state.make setup— initialize pinned submodules and npm dependencies.make demo-local— run the attached local V1 experience.make verify— run Solidity format/build/unit/fuzz/invariant/upgrade gates, artifact and shell-safety tests, the project scanner, and web lint/type/tests/build.make check-state— print and validate the selected stage; useDEMO_EXPECTED_STAGE=v1orv2for the exact local acts.make upgrade-v2— validate and perform the owner-authorized local V1-to-V2 upgrade, finalize its manifest, and refresh exported artifacts.make demo-transfer— perform Alice's local250 mUSDCinternal transfer to Bob and validate Act 3.make reset-local— validate recorded process identity, stop only owned groups, and remove only known local artifacts.make deploy-v1andmake seed-v1— run the lower-level guarded V1 deployment and deterministic Act 1 setup used bymake demo-local.make sync-artifacts,make sync-artifacts-check,make sync-abis, andmake publish-web-manifest— regenerate or validate the ABI bridge and publish only the confirmed active manifest.make test-finalize-manifest— exercise manifest finalization in isolation.make select-anvilandmake select-base-sepolia— explicitly select and republish an existing confirmed manifest.make archive-base-manifest— safely archive the Base canonical manifest before an intentional redeployment.make deploy-base-sepolia,make upgrade-base-sepolia, andmake transfer-base-sepolia— explicit optional-testnet commands with chain, actor, account, and RPC guards.
Optional Base Sepolia encore
The local lesson above is complete without a wallet, faucet, explorer, or public RPC. The optional Base Sepolia encore is separate and runs only after the local V1→V2 demo and make verify succeed. It uses a named encrypted Foundry keystore through --account and the same public address through --sender; no supported command accepts a raw private key or mnemonic.
Copy .env.example to .env and fill only its public configuration. BASE_SEPOLIA_RPC_URL is the terminal endpoint and may be credentialed; BASE_SEPOLIA_PUBLIC_RPC_URL is intentionally public and is the only RPC serialized for the browser. Foundry requests the keystore password interactively, and that password never belongs in .env.
Use make archive-base-manifest before an intentional Base redeployment. It moves only the Base canonical manifest to a timestamped sibling while preserving the active browser fallback and Anvil state. See the presenter runbook for the exact optional onboarding, funding boundary, execution sequence, and recovery rules.
Continue with the learning guide or rehearse from the presenter runbook.