Skip to content

Commit

Permalink
UUPS upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
mpuj99 committed Jul 25, 2024
1 parent b701862 commit d0b9770
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 57 deletions.
9 changes: 9 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/openzeppelin-contracts-upgradeable"]
path = lib/openzeppelin-contracts-upgradeable
url = https://github.com/openzeppelin/openzeppelin-contracts-upgradeable
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/openzeppelin/openzeppelin-contracts
[submodule "lib/foundry-devops"]
path = lib/foundry-devops
url = https://github.com/cyfrin/foundry-devops
3 changes: 3 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ src = "src"
out = "out"
libs = ["lib"]


remappings = ["openzeppelin/contracts-upgradeable=lib/openzeppelin-contracts-upgradeable/contracts", "@openzeppelin/contracts=lib/openzeppelin-contracts/contracts"]

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
1 change: 1 addition & 0 deletions lib/foundry-devops
Submodule foundry-devops added at df9f90
1 change: 1 addition & 0 deletions lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at dbb610
1 change: 1 addition & 0 deletions lib/openzeppelin-contracts-upgradeable
19 changes: 0 additions & 19 deletions script/Counter.s.sol

This file was deleted.

23 changes: 23 additions & 0 deletions script/DeployBox.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {BoxV1} from "../src/BoxV1.sol";
import {Script} from "forge-std/Script.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";



contract DeployBox is Script {
function run() external returns (address) {
address proxy = deployBox();
return proxy;
}

function deployBox() public returns(address) {
vm.startBroadcast();
BoxV1 box = new BoxV1(); // implementation (Logic)
ERC1967Proxy proxy = new ERC1967Proxy(address(box), "");
vm.stopBroadcast();
return address(proxy);
}
}
34 changes: 34 additions & 0 deletions script/UpgradeBox.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {BoxV1} from "../src/BoxV1.sol";
import {BoxV2} from "../src/BoxV2.sol";
import {Script} from "forge-std/Script.sol";
import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol";



contract UpgradeBox is Script {
function run() external returns (address) {
address mostRecentlyDeployed = DevOpsTools.get_most_recent_deployment("ERC1967Proxy", block.chainid);

vm.startBroadcast();
BoxV2 newBox = new BoxV2();
vm.stopBroadcast();
address proxy = upgradeBox(address(mostRecentlyDeployed), address(newBox));
return proxy;


}


function upgradeBox(address proxyAddress, address newBox) public returns (address) {
vm.startBroadcast();
// We use teh proxy address already deployed to put it into type BoxV1 to then (in the line below) upgrade the contract to BoxV2, because we doing a UUPS upgrade,
// the upgrade functions are in the implementation, so we need the type BoxV1 to call te upgrades.
BoxV1 proxy = BoxV1(proxyAddress);
proxy.upgradeToAndCall(address(newBox), ""); // proxy contract now points to this new address
vm.stopBroadcast();
return address(proxy);
}
}
31 changes: 31 additions & 0 deletions src/BoxV1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract BoxV1 is Initializable, UUPSUpgradeable, OwnableUpgradeable{
uint256 internal number;

// We don't use the constructor, we could not put te constructor in it but this is more vervose to make sure anything is initializing
constructor() {
_disableInitializers();
}

function initialize() public initializer {
__Ownable_init(msg.sender); // sets the owner = msg.sender
__UUPSUpgradeable_init(); // best practice
}

function getNumber() external view returns (uint256) {
return number;
}

function version() external pure returns (uint256) {
return 1;
}


function _authorizeUpgrade(address newImplementation) internal override {}
}
25 changes: 25 additions & 0 deletions src/BoxV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

contract BoxV2 is UUPSUpgradeable {
uint256 internal number;


function setNumber(uint256 _number) external {
number = _number;
}

function getNumber() external view returns (uint256) {
return number;
}

function version() external pure returns (uint256) {
return 2;
}

function _authorizeUpgrade(address newImplementation) internal override {}


}
14 changes: 0 additions & 14 deletions src/Counter.sol

This file was deleted.

24 changes: 0 additions & 24 deletions test/Counter.t.sol

This file was deleted.

49 changes: 49 additions & 0 deletions test/DeployAndUpgradeTest.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {Test} from "forge-std/Test.sol";
import {DeployBox} from "../script/DeployBox.s.sol";
import {UpgradeBox} from "../script/UpgradeBox.s.sol";
import {BoxV1} from "../src/BoxV1.sol";
import {BoxV2} from "../src/BoxV2.sol";




contract DeployAndUpgradeTest is Test {
DeployBox public deployer;
UpgradeBox public upgrader;
address public OWNER = makeAddr("owner");
address public proxy;

function setUp() public {
deployer = new DeployBox();
upgrader = new UpgradeBox();
proxy = deployer.run(); // Right now is the proxy of BoxV1

}


function testProxyStartsAsBoxV1() public view {
uint256 expectedValue = 1;
assertEq(expectedValue, BoxV1(proxy).version());

}

function testProxyRevertsIfSetNumberInBoxV1() public {
vm.expectRevert();
BoxV2(proxy).setNumber(7);
}

function testUpgrades() public {
BoxV2 newBox = new BoxV2();

upgrader.upgradeBox(proxy, address(newBox));

uint256 expectedValue = 2;
assertEq(expectedValue, BoxV2(proxy).version());

BoxV2(proxy).setNumber(7);
assertEq(7, BoxV2(proxy).getNumber());
}
}

0 comments on commit d0b9770

Please sign in to comment.