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,99 @@
|
||||
### Task 3: Establish the V1 proxy, initialization, views, and administration
|
||||
|
||||
**Files:**
|
||||
- Create: `src/BankV1.sol`
|
||||
- Create: `test/helpers/BankTestBase.sol`
|
||||
- Create: `test/BankV1Admin.t.sol`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces `initialize(address,address)`, `asset()`, `balanceOf(address)`, `totalLiabilities()`, `contractVersion()`, `pause()`, `unpause()`, and owner-authorized UUPS upgrades.
|
||||
- Consumes `MockUSDC` and OpenZeppelin `Upgrades.deployUUPSProxy`.
|
||||
- Freezes V1 application storage as `_asset`, `_balances`, `_totalLiabilities`, then `uint256[47] __gap`.
|
||||
|
||||
- [ ] Create `BankTestBase.sol` with deterministic `owner`, `alice`, `bob`, and `stranger` addresses from `makeAddr`; deploy `MockUSDC`; deploy the proxy with:
|
||||
|
||||
```solidity
|
||||
proxy = Upgrades.deployUUPSProxy(
|
||||
"BankV1.sol:BankV1",
|
||||
abi.encodeCall(BankV1.initialize, (address(token), owner))
|
||||
);
|
||||
bank = BankV1(proxy);
|
||||
```
|
||||
|
||||
All bank calls in tests target `proxy`; retain `implementation = Upgrades.getImplementationAddress(proxy)` only for assertions.
|
||||
|
||||
- [ ] Write failing admin tests for:
|
||||
|
||||
- initialized asset, owner, unpaused state, zero liabilities, and version `1`;
|
||||
- initialization with zero asset;
|
||||
- initialization with zero owner through `OwnableInvalidOwner`;
|
||||
- proxy double initialization;
|
||||
- direct implementation initialization;
|
||||
- only owner can pause/unpause;
|
||||
- views still work while paused;
|
||||
- `_authorizeUpgrade` rejects a non-owner through `upgradeToAndCall`;
|
||||
- implementation `proxiableUUID()` is available directly while the proxy-context call reverts.
|
||||
|
||||
- [ ] Run the focused suite and observe red:
|
||||
|
||||
```bash
|
||||
npm_config_offline=true forge test --match-path test/BankV1Admin.t.sol -vvv --force
|
||||
```
|
||||
|
||||
Expected red: `BankV1` is missing.
|
||||
|
||||
- [ ] Implement the minimum V1 skeleton with these imports and inheritance order:
|
||||
|
||||
```solidity
|
||||
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
|
||||
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
|
||||
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
||||
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
|
||||
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
|
||||
|
||||
contract BankV1 is
|
||||
Initializable,
|
||||
UUPSUpgradeable,
|
||||
OwnableUpgradeable,
|
||||
PausableUpgradeable,
|
||||
ReentrancyGuard
|
||||
{
|
||||
IERC20 internal _asset;
|
||||
mapping(address account => uint256 balance) internal _balances;
|
||||
uint256 internal _totalLiabilities;
|
||||
uint256[47] private __gap;
|
||||
}
|
||||
```
|
||||
|
||||
Use `error InvalidAsset(address asset);`. The initializer checks the asset before calling only `__Ownable_init(initialOwner)` and `__Pausable_init()`. `Initializable`, `UUPSUpgradeable`, and `ReentrancyGuard` are stateless/shared in pinned OpenZeppelin 5.6.1 and have no initializer calls.
|
||||
|
||||
- [ ] Add the only permitted validator annotation and no other bypass:
|
||||
|
||||
```solidity
|
||||
/// @custom:oz-upgrades-unsafe-allow constructor
|
||||
constructor() {
|
||||
_disableInitializers();
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] Add `pause`/`unpause` with `onlyOwner`, simple views, `contractVersion() public pure virtual returns (uint256)`, and `_authorizeUpgrade(address) internal override onlyOwner {}`. Do not add deposits or withdrawals yet.
|
||||
|
||||
- [ ] Run green verification and inspect storage:
|
||||
|
||||
```bash
|
||||
forge fmt
|
||||
npm_config_offline=true forge test --match-path test/BankV1Admin.t.sol -vvv --force
|
||||
forge inspect BankV1 storage-layout
|
||||
```
|
||||
|
||||
Expected: tests pass and the application fields appear in the frozen order. OpenZeppelin namespaced/stateless internals must not be mistaken for permission to reorder application fields.
|
||||
|
||||
- [ ] Commit:
|
||||
|
||||
```bash
|
||||
git add src/BankV1.sol test/helpers/BankTestBase.sol test/BankV1Admin.t.sol
|
||||
git commit -m "feat: establish UUPS bank V1"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user