Add UUPSUPgradeable to TST

This commit is contained in:
stubbsta 2025-08-13 13:50:40 +02:00
parent 7c45fa5c83
commit ece613683d
No known key found for this signature in database
4 changed files with 50 additions and 38 deletions

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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);
}