# Task 3 Report: V1 proxy, initialization, views, and administration ## Status Complete. BankV1 now provides the initialized UUPS proxy shell, frozen V1 application storage, administrative pause controls, read-only accounting views, version reporting, and owner-gated upgrade authorization. The final implementation uses OpenZeppelin 5.6.1 `ReentrancyGuardTransient`, as explicitly selected by the user after the pinned validator incompatibility investigation described below. ## Implementation - Added `BankV1` with inheritance in the required order: `Initializable`, `UUPSUpgradeable`, `OwnableUpgradeable`, `PausableUpgradeable`, then the approved constructor-free `ReentrancyGuardTransient`. - Kept the V1 application fields in the frozen order: `_asset`, `_balances`, `_totalLiabilities`, then `uint256[47] __gap`. - Disabled initialization on the implementation constructor with the sole validator annotation `@custom:oz-upgrades-unsafe-allow constructor`. - Added `initialize(address,address)`, checking the asset before invoking only `__Ownable_init(initialOwner)` and `__Pausable_init()`. - Added owner-only `pause()` and `unpause()`. - Added `asset()`, `balanceOf(address)`, `totalLiabilities()`, and virtual pure `contractVersion()` returning literal `1`. - Added owner-gated `_authorizeUpgrade(address)`. - Added a reusable proxy fixture with deterministic `owner`, `alice`, `bob`, and `stranger` addresses, a `MockUSDC`, `Upgrades.deployUUPSProxy`, proxy-bound `bank`, and implementation address retained only for assertions. - Added 12 behavior tests covering successful initialization, validation order, disabled/double initialization, ownership and pause administration, paused views, upgrade authorization, and direct-versus-proxy UUPS context. - Updated the implementation plan's global, Task 3, scanner, and source-guard references to record the explicitly approved transient-guard design and restore the single ordinary constructor annotation. ## Files - `src/BankV1.sol` — V1 UUPS implementation shell. - `test/helpers/BankTestBase.sol` — reusable proxy deployment fixture. - `test/BankV1Admin.t.sol` — initialization, administration, views, and UUPS-context tests. - `docs/superpowers/plans/2026-08-17-uups-bank-demo.md` — narrowly authorized compatibility/design update. - `.superpowers/sdd/2026-08-17-uups-bank-demo/task-3-report.md` — this ignored task report; not part of the commit. ## TDD RED evidence The required tool binaries were placed on `PATH` in a separate persistent-shell setup. The literal RED command was then issued exactly as briefed: ```bash npm_config_offline=true forge test --match-path test/BankV1Admin.t.sol -vvv --force ``` Relevant output: ```text Compiler run failed: Error (6275): Source "src/BankV1.sol" not found: File not found. --> test/BankV1Admin.t.sol:9:1 Error (6275): Source "src/BankV1.sol" not found: File not found. --> test/helpers/BankTestBase.sol:7:1 Error: Compilation failed ``` This was the expected RED: the tests and fixture referenced the required production API before `BankV1` existed, and failed specifically because the feature was missing. ## Validator incompatibility investigation and rulings The first literal GREEN attempt used the brief's original non-upgradeable `ReentrancyGuard` and sole local `@custom:oz-upgrades-unsafe-allow constructor`. Solidity compiled, but Foundry Upgrades validation rejected the inherited dependency: ```text Upgrade safety validation failed: lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol:58: Contract `ReentrancyGuard` has a constructor ``` Investigation established: - Pinned OpenZeppelin Contracts is 5.6.1 and marks `ReentrancyGuard` `@custom:stateless`, but that guard still has a constructor that initializes its namespaced guard slot. - Pinned upgrades-core is 1.46.0 and contains no support for the `@custom:stateless` annotation. - upgrades-core aggregates constructor errors from inherited contracts. The first user ruling approved replacing the local annotation with `@custom:oz-upgrades-unsafe-allow-reachable constructor`. The exact change was made and the literal focused command rerun, but validation failed identically. Source-level tracing then established that upgrades-core 1.46.0 uses `skipCheckReachable` only for opcode traversal (`delegatecall`/`selfdestruct`); `getConstructorErrors` checks annotations lexically on each constructor node, so an annotation on `BankV1` cannot suppress an inherited constructor finding. No `Options.unsafeAllow`, exclude, skip, `UnsafeUpgrades`, dependency edit, or other workaround was applied. After that evidence, the user's final ruling selected OpenZeppelin 5.6.1 `ReentrancyGuardTransient` and restored the ordinary sole constructor annotation. This guard has no constructor or persistent application storage and is appropriate for this project's explicitly Cancun-targeted Anvil and Base Sepolia networks, where EIP-1153 is available. One subsequent test-harness issue was also corrected: `vm.expectRevert` placed before `Upgrades.deployUUPSProxy` intercepted the library's preliminary implementation deployment. The invalid-initializer tests now construct a real `ERC1967Proxy` against the already validated implementation, making the next external operation the intended initializer delegatecall and preserving exact custom-error assertions. ## GREEN and verification evidence The brief's literal GREEN sequence was run in the same shell after the separate PATH setup: ```bash forge fmt npm_config_offline=true forge test --match-path test/BankV1Admin.t.sol -vvv --force forge inspect BankV1 storage-layout ``` Final focused result: ```text Ran 12 tests for test/BankV1Admin.t.sol:BankV1AdminTest Suite result: ok. 12 passed; 0 failed; 0 skipped ``` Storage inspection result: ```text _asset IERC20 slot 0 offset 0 _balances mapping(address => uint256) slot 1 offset 0 _totalLiabilities uint256 slot 2 offset 0 __gap uint256[47] slot 3 offset 0 (1504 bytes) ``` The final full validation-bearing suite was run offline: ```bash npm_config_offline=true forge test -vvv --force ``` Result: ```text Ran 2 test suites: 19 tests passed, 0 failed, 0 skipped ``` Both focused and full commands compiled successfully with only two existing dependency warnings in `openzeppelin-foundry-upgrades` about functions whose mutability could be `pure`; no project warning or error was emitted. ## Storage and upgrade safety notes - Application storage is exactly `_asset` at slot 0, `_balances` at slot 1, `_totalLiabilities` at slot 2, and the 47-word gap beginning at slot 3. Later versions must not reorder, remove, or change the type of these fields. - OpenZeppelin ownership and pause state use ERC-7201 namespaced storage. UUPS, Initializable, and the approved transient reentrancy guard do not consume ordinary application slots; this does not permit reordering the frozen application fields. - Every ordinary bank call in the fixture and tests targets `BankV1(proxy)`. The implementation address is used only to assert disabled initialization and direct `proxiableUUID()` behavior, as required. - `proxiableUUID()` returns the literal ERC-1967 implementation slot on the implementation and rejects proxy-context calls with `UUPSUnauthorizedCallContext`. - `_authorizeUpgrade` is covered through the public proxy `upgradeToAndCall` boundary and rejects a non-owner with `OwnableUnauthorizedAccount`. - The transient guard restricts supported execution environments to EIP-1153-capable networks. That is an explicit design constraint, not a hidden fallback. ## Self-review - Reviewed all four committed diffs and ran `git diff --check`; no whitespace errors were found. - Confirmed the fixture uses the exact `Upgrades.deployUUPSProxy("BankV1.sol:BankV1", abi.encodeCall(...))` form and binds all application behavior to the proxy. - Confirmed only one source validator annotation exists and no `unsafeSkip`, `UnsafeUpgrades`, Options `unsafeAllow`, exclude, reachable annotation, or dependency edit exists in Task 3 code/tests. - Strengthened the zero-asset test to pass both zero asset and zero owner, so it proves the mandated asset-check ordering; a mutation that invokes ownable initialization first now fails that test. - Mentally checked realistic mutations: wrong/missing asset assignment, wrong version, missing owner initialization, missing pause authorization/state change, pausing views, enabled reinitialization, implementation initialization, missing upgrade authorization, or broken UUPS call context each fail at least one test. - No deposit or withdrawal behavior was added. ## Concerns - `ReentrancyGuardTransient` requires EIP-1153/Cancun. The approved project targets (Anvil with `evm_version = "cancun"` and Base Sepolia) satisfy this, but deploying this implementation on a pre-Cancun EVM is unsupported. - Existing dependency-only compiler mutability warnings remain; they do not originate from Task 3 files.