-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1b78dc8
commit 5c03f4f
Showing
17 changed files
with
437 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ out/ | |
!/broadcast | ||
/broadcast/*/31337/ | ||
/broadcast/**/dry-run/ | ||
/broadcast/ | ||
|
||
# Docs | ||
docs/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] | ||
path = lib/openzeppelin-contracts | ||
url = https://github.com/openzeppelin/openzeppelin-contracts | ||
[submodule "lib/openzeppelin-contracts-upgradeable"] | ||
path = lib/openzeppelin-contracts-upgradeable | ||
url = https://github.com/openzeppelin/openzeppelin-contracts-upgradeable | ||
[submodule "lib/foundry-devops"] | ||
path = lib/foundry-devops | ||
url = https://github.com/chainaccelorg/foundry-devops |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
# Foundry UUPS Upgradeable Contracts | ||
|
||
This is a section of the Cyfrin Foundry Solidity Course. | ||
|
||
*This is for demo purposes only. Upgradeable contracts are a menance and in general should be avoided for | ||
|
||
|
||
- [Foundry UUPS Upgradeable Contracts](#foundry-uups-upgradeable-contracts) | ||
- [Getting Started](#getting-started) | ||
- [Requirements](#requirements) | ||
- [Quickstart](#quickstart) | ||
- [Optional Gitpod](#optional-gitpod) | ||
- [Usage](#usage) | ||
- [Start a local node](#start-a-local-node) | ||
- [Deploy](#deploy) | ||
- [Deploy - Other Network](#deploy---other-network) | ||
- [Testing](#testing) | ||
- [Test Coverage](#test-coverage) | ||
- [Deployment to a testnet or mainnet](#deployment-to-a-testnet-or-mainnet) | ||
- [Estimate gas](#estimate-gas) | ||
- [Formatting](#formatting) | ||
- [Thank you!](#thank-you) | ||
|
||
# Getting Started | ||
|
||
## Requirements | ||
|
||
- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) | ||
- You'll know you did it right if you can run `git --version` and you see a response like `git version x.x.x` | ||
- [foundry](https://getfoundry.sh/) | ||
- You'll know you did it right if you can run `forge --version` and you see a response like `forge 0.2.0 (816e00b 2023-03-16T00:05:26.396218Z)` | ||
|
||
## Quickstart | ||
|
||
``` | ||
git clone https://github.com/PatrickAlphaC/foundry-upgrades-f23 | ||
cd foundry-upgrades-f23 | ||
forge build | ||
``` | ||
|
||
### Optional Gitpod | ||
|
||
If you can't or don't want to run and install locally, you can work with this repo in Gitpod. If you do this, you can skip the `clone this repo` part. | ||
|
||
[](https://gitpod.io/#github.com/PatrickAlphaC/foundry-upgrades-f23) | ||
|
||
# Usage | ||
|
||
## Start a local node | ||
|
||
``` | ||
make anvil | ||
``` | ||
|
||
## Deploy | ||
|
||
This will default to your local node. You need to have it running in another terminal in order for it to deploy. | ||
|
||
``` | ||
make deploy | ||
``` | ||
|
||
## Deploy - Other Network | ||
|
||
[See below](#deployment-to-a-testnet-or-mainnet) | ||
|
||
## Testing | ||
|
||
``` | ||
forge test | ||
``` | ||
|
||
### Test Coverage | ||
|
||
``` | ||
forge coverage | ||
``` | ||
|
||
and for coverage based testing: | ||
|
||
``` | ||
forge coverage --report debug | ||
``` | ||
|
||
|
||
# Deployment to a testnet or mainnet | ||
|
||
1. Setup environment variables | ||
|
||
You'll want to set your `SEPOLIA_RPC_URL` and `PRIVATE_KEY` as environment variables. You can add them to a `.env` file, similar to what you see in `.env.example`. | ||
|
||
- `PRIVATE_KEY`: The private key of your account (like from [metamask](https://metamask.io/)). **NOTE:** FOR DEVELOPMENT, PLEASE USE A KEY THAT DOESN'T HAVE ANY REAL FUNDS ASSOCIATED WITH IT. | ||
- You can [learn how to export it here](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key). | ||
- `SEPOLIA_RPC_URL`: This is url of the goerli testnet node you're working with. You can get setup with one for free from [Alchemy](https://alchemy.com/?a=673c802981) | ||
|
||
Optionally, add your `ETHERSCAN_API_KEY` if you want to verify your contract on [Etherscan](https://etherscan.io/). | ||
|
||
1. Get testnet ETH | ||
|
||
Head over to [faucets.chain.link](https://faucets.chain.link/) and get some tesnet ETH. You should see the ETH show up in your metamask. | ||
|
||
2. Deploy | ||
|
||
``` | ||
make deploy ARGS="--network sepolia" | ||
``` | ||
|
||
|
||
## Estimate gas | ||
|
||
You can estimate how much gas things cost by running: | ||
|
||
``` | ||
forge snapshot | ||
``` | ||
|
||
And you'll see and output file called `.gas-snapshot` | ||
|
||
|
||
# Formatting | ||
|
||
|
||
To run code formatting: | ||
``` | ||
forge fmt | ||
``` | ||
|
||
|
||
# Thank you! | ||
|
||
If you appreciated this, feel free to follow me or donate! | ||
|
||
ETH/Polygon/Avalanche/etc Address: 0x9680201d9c93d65a3603d2088d125e955c73BD65 | ||
|
||
[](https://twitter.com/PatrickAlphaC) | ||
[](https://www.youtube.com/channel/UCn-3f8tw_E1jZvhuHatROwA) | ||
[](https://www.linkedin.com/in/patrickalphac/) | ||
[](https://medium.com/@patrick.collins_58673/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule foundry-devops
added at
d4a3bb
Submodule openzeppelin-contracts
added at
0a25c1
Submodule openzeppelin-contracts-upgradeable
added at
58fa0f
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {BoxV1} from "../src/BoxV1.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) { | ||
BoxV1 box = new BoxV1(); | ||
ERC1967Proxy proxy = new ERC1967Proxy(address(box), ""); | ||
return address(proxy); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {BoxV1} from "../src/BoxV1.sol"; | ||
import {BoxV2} from "../src/BoxV2.sol"; | ||
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; | ||
import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol"; | ||
|
||
contract UpgradeBox is Script { | ||
function run() external returns (address) { | ||
address mostRecentlyDeployedProxy = DevOpsTools | ||
.get_most_recent_deployment("ERC1967Proxy", block.chainid); | ||
|
||
vm.startBroadcast(); | ||
BoxV2 newBox = new BoxV2(); | ||
vm.stopBroadcast(); | ||
address proxy = upgradeBox(mostRecentlyDeployedProxy, address(newBox)); | ||
return proxy; | ||
} | ||
|
||
function upgradeBox( | ||
address proxyAddress, | ||
address newBox | ||
) public returns (address) { | ||
vm.startBroadcast(); | ||
BoxV1 proxy = BoxV1(payable(proxyAddress)); | ||
proxy.upgradeTo(address(newBox)); | ||
vm.stopBroadcast(); | ||
return address(proxy); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
|
||
import "@openzeppelin/contracts-upgradeable@4.8.3/access/OwnableUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable@4.8.3/proxy/utils/Initializable.sol"; | ||
import "@openzeppelin/contracts-upgradeable@4.8.3/proxy/utils/UUPSUpgradeable.sol"; | ||
|
||
contract BoxV1 is Initializable, OwnableUpgradeable, UUPSUpgradeable { | ||
uint256 internal value; | ||
|
||
/// @custom:oz-upgrades-unsafe-allow constructor | ||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
function initialize() public initializer { | ||
__Ownable_init(); | ||
__UUPSUpgradeable_init(); | ||
} | ||
|
||
function getValue() public view returns (uint256) { | ||
return value; | ||
} | ||
|
||
function version() public pure returns (uint256) { | ||
return 1; | ||
} | ||
|
||
function _authorizeUpgrade( | ||
address newImplementation | ||
) internal override onlyOwner {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
|
||
import "@openzeppelin/contracts-upgradeable@4.8.3/access/OwnableUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable@4.8.3/proxy/utils/Initializable.sol"; | ||
import "@openzeppelin/contracts-upgradeable@4.8.3/proxy/utils/UUPSUpgradeable.sol"; | ||
|
||
contract BoxV2 is Initializable, OwnableUpgradeable, UUPSUpgradeable { | ||
uint256 internal value; | ||
|
||
/// @custom:oz-upgrades-unsafe-allow constructor | ||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
function initialize() public initializer { | ||
__Ownable_init(); | ||
__UUPSUpgradeable_init(); | ||
} | ||
|
||
function setValue(uint256 newValue) public { | ||
value = newValue; | ||
} | ||
|
||
function getValue() public view returns (uint256) { | ||
return value; | ||
} | ||
|
||
function version() public pure returns (uint256) { | ||
return 2; | ||
} | ||
|
||
function _authorizeUpgrade( | ||
address newImplementation | ||
) internal override onlyOwner {} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
// Be sure to check out solidity-by-example | ||
// https://solidity-by-example.org/delegatecall | ||
|
||
pragma solidity ^0.8.19; | ||
|
||
// NOTE: Deploy this contract first | ||
contract B { | ||
// NOTE: storage layout must be the same as contract A | ||
uint256 public num; | ||
address public sender; | ||
uint256 public value; | ||
|
||
function setVars(uint256 _num) public payable { | ||
num = _num; | ||
sender = msg.sender; | ||
value = msg.value; | ||
} | ||
} | ||
|
||
contract A { | ||
uint256 public num; | ||
address public sender; | ||
uint256 public value; | ||
|
||
function setVars(address _contract, uint256 _num) public payable { | ||
// A's storage is set, B is not modified. | ||
// (bool success, bytes memory data) = _contract.delegatecall( | ||
(bool success, ) = _contract.delegatecall( | ||
abi.encodeWithSignature("setVars(uint256)", _num) | ||
); | ||
if (!success) { | ||
revert("delegatecall failed"); | ||
} | ||
} | ||
} |
Oops, something went wrong.