This project, hosted at GitHub - upgradableContract, demonstrates the deployment and interaction of upgradeable smart contracts using Hardhat and ethers.js. It includes JavaScript scripts for deploying and interacting with both the original and upgraded versions of a contract. The project leverages OpenZeppelin's upgradeable libraries to ensure the contracts can be improved over time while retaining their state and addresses.
upgradableContract/
├── contracts/
│ ├── MyContract.sol
│ └── MyContractV2.sol
├── scripts/
│ ├── deployProxy.js
│ ├── upgradeProxy.js
│ └── scripts.js
├── test/
│ └── myContractTest.js
├── dpTABI.json
├── upTABI.json
├── hardhat.config.js
└── README.md
- Node.js: Ensure you have Node.js installed.
- Hardhat: A development environment for Ethereum smart contracts.
- Ethers.js: A library for interacting with the Ethereum blockchain.
- OpenZeppelin Upgrades Plugin: For deploying upgradeable contracts.
-
Clone the repository:
git clone https://github.com/faridrafati/upgradableContract.git cd upgradableContract -
Install dependencies:
npm install
-
Configure environment variables: Create a
.envfile in the root directory and add:HOLESKY_URL="YOUR_RPC_URL" PRIVATE_KEY_HOLESKY="YOUR_PRIVATE_KEY" HOLESKY_CONTRACT_ADDRESS="ADDRESS_OF_DEPLOYED_ORIGINAL_CONTRACT" HOLESKY_UPDATEDC_ADDRESS="ADDRESS_OF_DEPLOYED_UPGRADED_CONTRACT"
Ensure hardhat.config.js is set up to use your environment and network:
require("@nomiclabs/hardhat-ethers");
require("@openzeppelin/hardhat-upgrades");
module.exports = {
solidity: "0.8.4",
networks: {
holesky: {
url: process.env.HOLESKY_URL,
accounts: [process.env.PRIVATE_KEY_HOLESKY],
},
},
};Deploys the initial version of the contract:
const { ethers, upgrades } = require("hardhat");
async function main() {
const Contract = await ethers.getContractFactory("MyContract");
console.log("Deploying MyContract...");
const instance = await upgrades.deployProxy(Contract, [42], {
initializer: "initialize",
});
console.log("MyContract deployed to:", instance.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error("Error deploying the contract:", error);
process.exit(1);
});Deploys the upgraded version:
const { ethers, upgrades } = require("hardhat");
async function main() {
const ContractV2 = await ethers.getContractFactory("MyContractV2");
console.log("Upgrading to MyContractV2...");
const instance = await upgrades.upgradeProxy(process.env.HOLESKY_CONTRACT_ADDRESS, ContractV2);
console.log("Contract upgraded to MyContractV2 at:", instance.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error("Error upgrading the contract:", error);
process.exit(1);
});Interacts with the deployed contracts:
const { ethers } = require("ethers");
const fs = require("fs").promises;
async function loadContract(abiFilePath, contractAddress, providerUrl, privateKey) {
const abi = JSON.parse(await fs.readFile(abiFilePath, "utf8"));
const provider = new ethers.JsonRpcProvider(providerUrl);
const wallet = new ethers.Wallet(privateKey, provider);
return new ethers.Contract(contractAddress, abi, wallet);
}
async function main() {
try {
const deployedToken = await loadContract("dpTABI.json", process.env.HOLESKY_CONTRACT_ADDRESS, process.env.HOLESKY_URL, process.env.PRIVATE_KEY_HOLESKY);
console.log("Deployed Contract Address:", deployedToken.target);
let value = await deployedToken.myValue();
console.log("Original myValue:", ethers.BigNumber.isBigNumber(value) ? ethers.utils.formatUnits(value, 0) : value.toString());
const upgradedToken = await loadContract("upTABI.json", process.env.HOLESKY_UPDATEDC_ADDRESS, process.env.HOLESKY_URL, process.env.PRIVATE_KEY_HOLESKY);
console.log("Upgraded Contract Address:", upgradedToken.target);
value = await upgradedToken.myValue();
console.log("Upgraded myValue:", ethers.BigNumber.isBigNumber(value) ? ethers.utils.formatUnits(value, 0) : value.toString());
const tx = await upgradedToken.setNewValue("Hello");
await tx.wait();
console.log("Updated newValue:", await upgradedToken.newValue());
} catch (error) {
console.error("Error during contract interaction:", error);
}
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error("Unexpected error:", error);
process.exit(1);
});-
Deploy the original contract:
npx hardhat run scripts/deployProxy.js --network holesky
-
Upgrade the contract:
npx hardhat run scripts/upgradeProxy.js --network holesky
-
Interact with the contracts:
node scripts/scripts.js
This project is licensed under the MIT License.