Skip to content

Commit 5d3397d

Browse files
committed
add proxy test
1 parent 788c56b commit 5d3397d

File tree

10 files changed

+536
-13
lines changed

10 files changed

+536
-13
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,6 @@ lib
7474
## yarn cache
7575
**/.yarn/cache
7676
**/.yarn/install-state.gz
77+
78+
## openzeppelin cache
79+
**/.openzeppelin/

e2e-tests/e2e-hardhat/contracts/Echo.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pragma solidity =0.8.9;
1+
pragma solidity =0.8.20;
22

33
contract Echo{
44
string public echo;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
pragma solidity =0.8.20;
2+
3+
import "hardhat/console.sol";
4+
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5+
6+
contract Greeter is Initializable {
7+
string private greeting;
8+
9+
function initialize(string memory _greeting) public initializer {
10+
console.log("Deploying a Greeter with greeting:", _greeting);
11+
greeting = _greeting;
12+
}
13+
14+
function greet() public view returns (string memory) {
15+
return greeting;
16+
}
17+
18+
function setGreeting(string memory _greeting) public {
19+
console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);
20+
greeting = _greeting;
21+
}
22+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
pragma solidity =0.8.20;
2+
3+
import "hardhat/console.sol";
4+
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5+
import "./Greeter.sol";
6+
7+
contract GreeterV2 is Greeter {
8+
string private greeting;
9+
10+
function setGreetingV2(string memory _greeting) public {
11+
string memory newGreeting = string(abi.encodePacked(_greeting, " - V2"));
12+
console.log("<V2> Changing greeting from '%s' to '%s'", greeting, newGreeting);
13+
setGreeting(newGreeting);
14+
}
15+
}

e2e-tests/e2e-hardhat/contracts/HelloWorld.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pragma solidity =0.8.9;
1+
pragma solidity =0.8.20;
22

33
contract HelloWorld{
44
string public helloWorld = 'Hello World!';

e2e-tests/e2e-hardhat/contracts/Token.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pragma solidity =0.8.9;
1+
pragma solidity =0.8.20;
22

33
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
44

e2e-tests/e2e-hardhat/hardhat.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import '@nomicfoundation/hardhat-toolbox';
2+
import '@openzeppelin/hardhat-upgrades';
23
import { HardhatUserConfig } from 'hardhat/config';
34

45
const config: HardhatUserConfig = {
5-
solidity: '0.8.9',
6+
solidity: '0.8.20',
67
networks: {
78
acalaFork: {
89
chainId: 787,

e2e-tests/e2e-hardhat/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"scripts": {
88
"build": "hardhat compile",
99
"lint": "eslint .",
10-
"clean": "rm -rf artifacts/ cache/ typechain-types/",
10+
"clean": "rm -rf artifacts/ cache/ typechain-types/ .openzeppelin/",
1111
"test": "hardhat test",
1212
"test:acalaFork": "hardhat test --network acalaFork"
1313
},
@@ -18,6 +18,8 @@
1818
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
1919
"@nomicfoundation/hardhat-verify": "^2.0.0",
2020
"@openzeppelin/contracts": "^4.9.0",
21+
"@openzeppelin/contracts-upgradeable": "5.0.1",
22+
"@openzeppelin/hardhat-upgrades": "3.0.0",
2123
"@typechain/ethers-v6": "^0.5.0",
2224
"@typechain/hardhat": "^9.0.0",
2325
"@types/chai": "^4.2.0",
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { ethers, upgrades } from 'hardhat';
2+
import { expect } from 'chai';
3+
import { getImplementationAddress } from '@openzeppelin/upgrades-core';
4+
5+
import { Greeter, GreeterV2, GreeterV2__factory, Greeter__factory } from '../typechain-types';
6+
7+
describe('UpgradeableGreeter contract', () => {
8+
let greeterFactory: Greeter__factory;
9+
let greeterV2Factory: GreeterV2__factory;
10+
let instance: Greeter;
11+
let instanceV2: GreeterV2;
12+
let proxyAddr: string;
13+
let implAddrV1: string;
14+
15+
const msg0 = 'Hello, Goku!';
16+
const msg1 = 'Hello, Kakarot!';
17+
const msg2 = 'Hello, Vegeta!';
18+
19+
before(async () => {
20+
console.log('deploying greater V1 and proxy ..');
21+
greeterFactory = await ethers.getContractFactory('Greeter');
22+
instance = await upgrades.deployProxy(greeterFactory, [msg0]) as unknown as Greeter;
23+
await instance.waitForDeployment();
24+
25+
proxyAddr = await instance.getAddress();
26+
implAddrV1 = await getImplementationAddress(ethers.provider, proxyAddr);
27+
console.log('proxy with greeter v1 deployed at', proxyAddr);
28+
console.log('implementation address', implAddrV1);
29+
});
30+
31+
describe('Deployment', () => {
32+
it('should return the greeting set at deployment', async () => {
33+
expect(await instance.greet()).to.equal(msg0);
34+
});
35+
36+
it('should return a new greeting when one is set', async () => {
37+
await (await instance.setGreeting(msg1)).wait();
38+
expect(await instance.greet()).to.equal(msg1);
39+
});
40+
});
41+
42+
describe('Upgrade', () => {
43+
before(async () => {
44+
console.log('upgrading to greeter V2 ...');
45+
greeterV2Factory = await ethers.getContractFactory('GreeterV2');
46+
instanceV2 = await upgrades.upgradeProxy(await instance.getAddress(), greeterV2Factory) as unknown as GreeterV2;
47+
48+
let implAddrV2 = await getImplementationAddress(ethers.provider, proxyAddr);
49+
while (implAddrV2 === implAddrV1) {
50+
// there is no better way to check if the upgrade is done?
51+
console.log('still waiting for upgrade confirmation ...');
52+
await new Promise(resolve => setTimeout(resolve, 1000));
53+
implAddrV2 = await getImplementationAddress(ethers.provider, proxyAddr);
54+
}
55+
console.log('proxy with greeter V2 upgraded at', await instanceV2.getAddress());
56+
console.log('implementation address V2: ', implAddrV2);
57+
});
58+
59+
it('should maintain the greeting after the upgrade', async () => {
60+
expect(await instanceV2.greet()).to.equal(msg1);
61+
});
62+
63+
it('should maintain the original method', async () => {
64+
await (await instanceV2.setGreeting(msg2)).wait();
65+
expect(await instanceV2.greet()).to.equal(msg2);
66+
});
67+
68+
it('should add a new method', async () => {
69+
await (await instanceV2.setGreetingV2(msg2)).wait();
70+
expect(await instanceV2.greet()).to.equal(`${msg2} - V2`);
71+
});
72+
});
73+
});

0 commit comments

Comments
 (0)