From ece613683d2969c766476692ce2f3f6c3d74c783 Mon Sep 17 00:00:00 2001 From: stubbsta Date: Wed, 13 Aug 2025 13:50:40 +0200 Subject: [PATCH] Add UUPSUPgradeable to TST --- script/DeployTokenWithProxy.s.sol | 40 ++++++++++--------------------- test/TestStableToken.sol | 23 ++++++++++++++---- test/TestStableToken.t.sol | 16 ++++++++++--- test/WakuRlnV2.t.sol | 9 +++++-- 4 files changed, 50 insertions(+), 38 deletions(-) diff --git a/script/DeployTokenWithProxy.s.sol b/script/DeployTokenWithProxy.s.sol index 0ade85e..f20d67c 100644 --- a/script/DeployTokenWithProxy.s.sol +++ b/script/DeployTokenWithProxy.s.sol @@ -3,37 +3,21 @@ pragma solidity >=0.8.19 <0.9.0; import { BaseScript } from "./Base.s.sol"; import { TestStableToken } from "../test/TestStableToken.sol"; -import { - TransparentUpgradeableProxy, - ITransparentUpgradeableProxy -} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract DeployTokenWithProxy is BaseScript { - function run() public broadcast returns (address proxy, address implementation, address admin) { - // Deploy the initial implementation - implementation = address(new TestStableToken()); - - // Deploy proxy admin - admin = address(new ProxyAdmin()); - - // Encode the transferOwnership call as initialization data - bytes memory initData = abi.encodeWithSignature("transferOwnership(address)", broadcaster); - - // Deploy the proxy with initialization data to set ownership - proxy = address(new TransparentUpgradeableProxy(implementation, admin, initData)); - - return (proxy, implementation, admin); + function run() public broadcast returns (address) { + return address(deploy()); } -} -contract UpdateTokenImplementation is BaseScript { - function run(address proxyAddress, address proxyAdminAddress, address newImplementation) public broadcast { - // Upgrade via ProxyAdmin using the provided implementation address - ProxyAdmin(proxyAdminAddress).upgradeAndCall( - ITransparentUpgradeableProxy(proxyAddress), - newImplementation, - "" - ); + function deploy() public returns (ERC1967Proxy) { + // Deploy the initial implementation + address implementation = address(new TestStableToken()); + + // Encode the initialize call + bytes memory data = abi.encodeCall(TestStableToken.initialize, ()); + + // Deploy the proxy with initialization data + return new ERC1967Proxy(implementation, data); } } \ No newline at end of file diff --git a/test/TestStableToken.sol b/test/TestStableToken.sol index f1b257d..d84a6bc 100644 --- a/test/TestStableToken.sol +++ b/test/TestStableToken.sol @@ -2,15 +2,17 @@ pragma solidity >=0.8.19 <0.9.0; import { BaseScript } from "../script/Base.s.sol"; -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { ERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; +import { ERC20PermitUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; error AccountNotMinter(); error AccountAlreadyMinter(); error AccountNotInMinterList(); -contract TestStableToken is ERC20, ERC20Permit, Ownable { +contract TestStableToken is Initializable, ERC20Upgradeable, ERC20PermitUpgradeable, OwnableUpgradeable, UUPSUpgradeable { mapping(address => bool) public isMinter; event MinterAdded(address indexed account); @@ -21,7 +23,18 @@ contract TestStableToken is ERC20, ERC20Permit, Ownable { _; } - constructor() ERC20("TestStableToken", "TST") ERC20Permit("TestStableToken") Ownable() { } + constructor() { + _disableInitializers(); + } + + function initialize() public initializer { + __ERC20_init("TestStableToken", "TST"); + __ERC20Permit_init("TestStableToken"); + __Ownable_init(); + __UUPSUpgradeable_init(); + } + + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} function addMinter(address account) external onlyOwner { if (isMinter[account]) revert AccountAlreadyMinter(); diff --git a/test/TestStableToken.t.sol b/test/TestStableToken.t.sol index 2fde09a..0a07280 100644 --- a/test/TestStableToken.t.sol +++ b/test/TestStableToken.t.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.19 <0.9.0; import { Test } from "forge-std/Test.sol"; import { TestStableToken, AccountNotMinter, AccountAlreadyMinter, AccountNotInMinterList } from "./TestStableToken.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract TestStableTokenTest is Test { TestStableToken internal token; @@ -12,7 +13,16 @@ contract TestStableTokenTest is Test { address internal nonMinter; function setUp() public { - token = new TestStableToken(); + // Deploy implementation + TestStableToken implementation = new TestStableToken(); + + // Deploy proxy with initialization + bytes memory data = abi.encodeCall(TestStableToken.initialize, ()); + ERC1967Proxy proxy = new ERC1967Proxy(address(implementation), data); + + // Wrap proxy in TestStableToken interface + token = TestStableToken(address(proxy)); + owner = address(this); user1 = vm.addr(1); user2 = vm.addr(2); @@ -46,7 +56,7 @@ contract TestStableTokenTest is Test { function test__NonOwnerCannotAddMinterRole() external { vm.prank(user1); - vm.expectRevert("Ownable: caller is not the owner"); + vm.expectRevert(); token.addMinter(user1); } @@ -54,7 +64,7 @@ contract TestStableTokenTest is Test { token.addMinter(user1); vm.prank(user1); - vm.expectRevert("Ownable: caller is not the owner"); + vm.expectRevert(); token.removeMinter(user1); } diff --git a/test/WakuRlnV2.t.sol b/test/WakuRlnV2.t.sol index ce02e79..ddbc1a7 100644 --- a/test/WakuRlnV2.t.sol +++ b/test/WakuRlnV2.t.sol @@ -23,14 +23,19 @@ contract WakuRlnV2Test is Test { uint256[] internal noIdCommitmentsToErase = new uint256[](0); function setUp() public virtual { - token = new TestStableToken(); + // Deploy TestStableToken through proxy with initialization + TestStableToken implementation = new TestStableToken(); + bytes memory data = abi.encodeCall(TestStableToken.initialize, ()); + ERC1967Proxy tokenProxy = new ERC1967Proxy(address(implementation), data); + token = TestStableToken(address(tokenProxy)); + IPriceCalculator priceCalculator = (new DeployPriceCalculator()).deploy(address(token)); WakuRlnV2 wakuRlnV2 = (new DeployWakuRlnV2()).deploy(); ERC1967Proxy proxy = (new DeployProxy()).deploy(address(priceCalculator), address(wakuRlnV2)); w = WakuRlnV2(address(proxy)); - // TestStableTokening a large number of tokens to not have to worry about + // Minting a large number of tokens to not have to worry about // Not having enough balance token.mint(address(this), 100_000_000 ether); }