Skip to content

Commit

Permalink
add comments to the upgradeable proxy example
Browse files Browse the repository at this point in the history
  • Loading branch information
zoeyTM committed Dec 18, 2023
1 parent 4580d25 commit 3a054cb
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 73 deletions.
20 changes: 0 additions & 20 deletions examples/upgradeable/contracts/Box.sol

This file was deleted.

9 changes: 9 additions & 0 deletions examples/upgradeable/contracts/Demo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

// A contrived example of a contract that can be upgraded
contract Demo {
function version() public pure returns (string memory) {
return "1.0.0";
}
}
9 changes: 9 additions & 0 deletions examples/upgradeable/contracts/DemoV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

// A contrived example of a contract that can be upgraded
contract DemoV2 {
function version() public pure returns (string memory) {
return "2.0.0";
}
}
2 changes: 2 additions & 0 deletions examples/upgradeable/contracts/Proxies.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

// We import these here to force Hardhat to compile them.
// This ensures that their artifacts are available for Hardhat Ignition to use.
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
24 changes: 0 additions & 24 deletions examples/upgradeable/contracts/UpgradedBox.sol

This file was deleted.

49 changes: 43 additions & 6 deletions examples/upgradeable/ignition/modules/ProxyModule.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,85 @@
// ./ignition/LockModule.js
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");

/**
* This is the first module that will be run. It deploys the proxy and the
* proxy admin, and returns them so that they can be used by other modules.
*/
const proxyModule = buildModule("ProxyModule", (m) => {
// This address is the owner of the ProxyAdmin contract,
// so it will be the only account that can upgrade the proxy when needed.
const proxyAdminOwner = m.getAccount(0);

const box = m.contract("Box");
// This is our contract that will be proxied.
// We will upgrade this contract with a new version later.
const demo = m.contract("Demo");

// The TransparentUpgradeableProxy contract creates the ProxyAdmin within its constructor.
// To read more about how this proxy is implemented, you can view the source code and comments here:
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.1/contracts/proxy/transparent/TransparentUpgradeableProxy.sol
const proxy = m.contract("TransparentUpgradeableProxy", [
box,
demo,
proxyAdminOwner,
"0x",
]);

// We need to get the address of the ProxyAdmin contrac that was created by the TransparentUpgradeableProxy
// so that we can use it to upgrade the proxy later.
const proxyAdminAddress = m.readEventArgument(
proxy,
"AdminChanged",
"newAdmin"
);

// Here we use m.contractAt(...) to create a contract instance for the ProxyAdmin that we can interact with.
const proxyAdmin = m.contractAt("ProxyAdmin", proxyAdminAddress);

// Return the proxy and proxy admin so that they can be used by other modules.
return { proxyAdmin, proxy };
});

/**
* This is the second module that will be run. It upgrades the proxy to a new
* version of the Demo contract.
*/
const upgradeModule = buildModule("UpgradeModule", (m) => {
// Make sure we're account that owns the ProxyAdmin contract.
const proxyAdminOwner = m.getAccount(0);

// Get the proxy and proxy admin from the previous module.
const { proxyAdmin, proxy } = m.useModule(proxyModule);

const upgradedBox = m.contract("UpgradedBox");
// This is the new version of the Demo contract that we want to upgrade to.
const demoV2 = m.contract("DemoV2");

m.call(proxyAdmin, "upgradeAndCall", [proxy, upgradedBox, "0x"], {
// Upgrade the proxy to the new version of the Demo contract.
// This function also accepts a data parameter, which can be used to call a function,
// but we don't need it here so we pass an empty hex string ("0x").
m.call(proxyAdmin, "upgradeAndCall", [proxy, demoV2, "0x"], {
from: proxyAdminOwner,
});

// Return the proxy and proxy admin so that they can be used by other modules.
return { proxyAdmin, proxy };
});

/**
* This is the third and final module that will be run.
*
* It takes the proxy from the previous module and uses it to create a local contract instance
* for the DemoV2 contract. This allows us to interact with the DemoV2 contract via the proxy.
*/
const interactableModule = buildModule("InteractableModule", (m) => {
// Get the proxy from the previous module.
const { proxy } = m.useModule(upgradeModule);

const box = m.contractAt("UpgradedBox", proxy);
// Create a local contract instance for the DemoV2 contract.
// This line tells Hardhat Ignition to treat the contract at the proxy address as an DemoV2 contract.
// This allows us to call functions on the DemoV2 contract via the proxy.
const demo = m.contractAt("DemoV2", proxy);

return { box };
// Return the contract instance so that it can be used by other modules or in tests.
return { demo };
});

module.exports = interactableModule;
23 changes: 0 additions & 23 deletions examples/upgradeable/test/BoxProxy.js

This file was deleted.

24 changes: 24 additions & 0 deletions examples/upgradeable/test/ProxyDemo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const {
loadFixture,
} = require("@nomicfoundation/hardhat-toolbox/network-helpers");
const { expect } = require("chai");

const ProxyModule = require("../ignition/modules/ProxyModule");

describe("Demo Proxy", function () {
async function deployFixture() {
const [owner, otherAccount] = await ethers.getSigners();

const { demo } = await ignition.deploy(ProxyModule);

return { demo, owner, otherAccount };
}

describe("Upgrading", function () {
it("Should have upgraded the proxy to DemoV2", async function () {
const { demo, otherAccount } = await loadFixture(deployFixture);

expect(await demo.connect(otherAccount).version()).to.equal("2.0.0");
});
});
});

0 comments on commit 3a054cb

Please sign in to comment.