feat: establish UUPS bank V1

This commit is contained in:
golem
2026-08-17 16:54:31 -06:00
parent 1f4175ba72
commit 0664eb4688
4 changed files with 192 additions and 5 deletions
+94
View File
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.35;
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {BankV1} from "../src/BankV1.sol";
import {BankTestBase} from "./helpers/BankTestBase.sol";
contract BankV1AdminTest is BankTestBase {
bytes32 private constant ERC1967_IMPLEMENTATION_SLOT =
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
function testProxyStartsWithConfiguredAdministrationAndEmptyAccounting() public view {
assertEq(address(bank.asset()), address(token));
assertEq(bank.owner(), owner);
assertFalse(bank.paused());
assertEq(bank.balanceOf(alice), 0);
assertEq(bank.totalLiabilities(), 0);
assertEq(bank.contractVersion(), 1);
}
function testInitializationChecksZeroAssetBeforeZeroOwner() public {
vm.expectRevert(abi.encodeWithSelector(BankV1.InvalidAsset.selector, address(0)));
new ERC1967Proxy(implementation, abi.encodeCall(BankV1.initialize, (address(0), address(0))));
}
function testInitializationRejectsZeroOwner() public {
vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableInvalidOwner.selector, address(0)));
new ERC1967Proxy(implementation, abi.encodeCall(BankV1.initialize, (address(token), address(0))));
}
function testProxyCannotBeInitializedTwice() public {
vm.expectRevert(Initializable.InvalidInitialization.selector);
bank.initialize(address(token), owner);
}
function testImplementationCannotBeInitialized() public {
vm.expectRevert(Initializable.InvalidInitialization.selector);
BankV1(implementation).initialize(address(token), owner);
}
function testOwnerCanPauseAndUnpause() public {
vm.prank(owner);
bank.pause();
assertTrue(bank.paused());
vm.prank(owner);
bank.unpause();
assertFalse(bank.paused());
}
function testNonOwnerCannotPause() public {
vm.prank(stranger);
vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableUnauthorizedAccount.selector, stranger));
bank.pause();
}
function testNonOwnerCannotUnpause() public {
vm.prank(owner);
bank.pause();
vm.prank(stranger);
vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableUnauthorizedAccount.selector, stranger));
bank.unpause();
}
function testViewsRemainAvailableWhilePaused() public {
vm.prank(owner);
bank.pause();
assertEq(address(bank.asset()), address(token));
assertEq(bank.balanceOf(alice), 0);
assertEq(bank.totalLiabilities(), 0);
assertEq(bank.contractVersion(), 1);
}
function testNonOwnerCannotAuthorizeUpgrade() public {
vm.prank(stranger);
vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableUnauthorizedAccount.selector, stranger));
bank.upgradeToAndCall(implementation, "");
}
function testImplementationExposesERC1967ProxiableUUID() public view {
assertEq(BankV1(implementation).proxiableUUID(), ERC1967_IMPLEMENTATION_SLOT);
}
function testProxyRejectsProxiableUUIDCall() public {
vm.expectRevert(UUPSUpgradeable.UUPSUnauthorizedCallContext.selector);
bank.proxiableUUID();
}
}
+33
View File
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.35;
import {Test} from "forge-std/Test.sol";
import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {BankV1} from "../../src/BankV1.sol";
import {MockUSDC} from "../../src/MockUSDC.sol";
abstract contract BankTestBase is Test {
address internal owner;
address internal alice;
address internal bob;
address internal stranger;
MockUSDC internal token;
address internal proxy;
address internal implementation;
BankV1 internal bank;
function setUp() public virtual {
owner = makeAddr("owner");
alice = makeAddr("alice");
bob = makeAddr("bob");
stranger = makeAddr("stranger");
token = new MockUSDC(owner);
proxy =
Upgrades.deployUUPSProxy("BankV1.sol:BankV1", abi.encodeCall(BankV1.initialize, (address(token), owner)));
bank = BankV1(proxy);
implementation = Upgrades.getImplementationAddress(proxy);
}
}