Skip to content

Commit 28c5a5d

Browse files
committed
add upgradable test to the token
1 parent 662522b commit 28c5a5d

File tree

3 files changed

+63
-16
lines changed

3 files changed

+63
-16
lines changed

contracts/XXXTokenV2.sol

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.24;
3+
4+
import "./XXXToken.sol";
5+
6+
/**
7+
* @title XXXTokenV2
8+
* @dev This is a demonstration contract for testing the upgradeability of XXXToken.
9+
* It serves as a simple example of how to implement contract upgrades using the UUPS pattern.
10+
*
11+
* Key features:
12+
* - Inherits all functionality from XXXToken
13+
* - Adds a version number to demonstrate upgrade success
14+
* - Uses reinitializer to safely initialize new state variables
15+
*
16+
* This contract is primarily used for testing purposes to verify that:
17+
* 1. The upgrade process works correctly
18+
* 2. All existing functionality is preserved
19+
* 3. New functionality can be added safely
20+
*
21+
* @custom:oz-upgrades-validate-as-initializer
22+
*/
23+
contract XXXTokenV2 is XXXToken {
24+
/// @notice The version number of this contract implementation
25+
uint256 public version;
26+
27+
/**
28+
* @dev Initializes the V2 contract with a version number.
29+
* This function is called after the upgrade to set up the new state variables.
30+
* The reinitializer modifier ensures this can only be called once after the upgrade.
31+
*/
32+
function initializeV2() public reinitializer(2) {
33+
version = 2;
34+
}
35+
}

test/TokenVault.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ describe("TokenVault", function () {
4141
const ALLOCATOR_ROLE = ethers.keccak256(ethers.toUtf8Bytes("ALLOCATOR_ROLE"));
4242
const AIRDROP_ROLE = ethers.keccak256(ethers.toUtf8Bytes("AIRDROP_ROLE"));
4343
const UPGRADER_ROLE = ethers.keccak256(ethers.toUtf8Bytes("UPGRADER_ROLE"));
44+
const DEFAULT_ADMIN_ROLE = "0x0000000000000000000000000000000000000000000000000000000000000000";
4445

4546
// Grant MINTER_ROLE to the vault contract
4647
await token.grantRole(MINTER_ROLE, await vault.getAddress());
4748

4849
// Grant all other roles to the owner
50+
await vault.grantRole(DEFAULT_ADMIN_ROLE, owner.address);
4951
await vault.grantRole(ALLOCATOR_ROLE, owner.address);
5052
await vault.grantRole(AIRDROP_ROLE, owner.address);
5153
await vault.grantRole(UPGRADER_ROLE, owner.address);

test/XXXToken.test.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers";
55
import { Contract } from "ethers";
66

77
// Import the contract type
8-
import { XXXToken } from "../typechain-types";
8+
import { XXXToken, XXXTokenV2 } from "../typechain-types";
99

1010
describe("XXXToken", function () {
1111
// Test roles
@@ -157,19 +157,29 @@ describe("XXXToken", function () {
157157
});
158158
});
159159

160-
// describe("Upgrading", function () {
161-
// it("Should allow upgrader to upgrade the contract", async function () {
162-
// const XXXTokenV2 = await ethers.getContractFactory("XXXTokenV2");
163-
// await expect(
164-
// token.connect(upgrader).upgradeTo(await XXXTokenV2.getAddress())
165-
// ).to.not.be.reverted;
166-
// });
167-
168-
// it("Should not allow non-upgrader to upgrade the contract", async function () {
169-
// const XXXTokenV2 = await ethers.getContractFactory("XXXTokenV2");
170-
// await expect(
171-
// token.connect(user1).upgradeTo(await XXXTokenV2.getAddress())
172-
// ).to.be.revertedWithCustomError(token, "AccessControlUnauthorizedAccount");
173-
// });
174-
// });
160+
describe("Upgrading", function () {
161+
it("Should allow upgrader to upgrade the contract", async function () {
162+
const XXXTokenV2Factory = await ethers.getContractFactory("XXXTokenV2");
163+
const upgraded = await upgrades.upgradeProxy(await token.getAddress(), XXXTokenV2Factory) as unknown as XXXTokenV2;
164+
await upgraded.initializeV2();
165+
expect(await upgraded.version()).to.equal(2);
166+
});
167+
168+
it("Should not allow initializing V2 twice", async function () {
169+
const XXXTokenV2Factory = await ethers.getContractFactory("XXXTokenV2");
170+
const upgraded = await upgrades.upgradeProxy(await token.getAddress(), XXXTokenV2Factory) as unknown as XXXTokenV2;
171+
await upgraded.initializeV2();
172+
173+
await expect(
174+
upgraded.initializeV2()
175+
).to.be.revertedWithCustomError(upgraded, "InvalidInitialization");
176+
});
177+
178+
it("Should not allow non-upgrader to upgrade the contract", async function () {
179+
const XXXTokenV2Factory = await ethers.getContractFactory("XXXTokenV2");
180+
await expect(
181+
upgrades.upgradeProxy(await token.getAddress(), XXXTokenV2Factory.connect(user1))
182+
).to.be.revertedWithCustomError(token, "AccessControlUnauthorizedAccount");
183+
});
184+
});
175185
});

0 commit comments

Comments
 (0)