docs: track superpowers working documents in git
The uups-bank-demo wave's SDD records (ledger, six task briefs and reports, review diffs) and the brainstorm design mockups were git-ignored, so they existed only on one sandbox VM and reached no remote — this repo had no remote at all until now. Removes `.superpowers/` from .gitignore and the `*` .gitignore the superpowers plugin writes inside .superpowers/sdd/; the second blocks the directory even with the first removed. Excluded as ephemeral local-server state, and now ignored by name: .last-port, .last-token (a 64-char session token for a brainstorm server on a port that is long gone), and the per-session state/ directories. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fnwzj6McD6kSkXwjUKFKxe
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user