Understanding Hardhat Upgradable Smart Contracts(part 1)
Table of contents
Hardhat is a development environment that is popular among developers working on Ethereum-based projects. It is an open-source tool that provides a suite of utilities to streamline the development process and make it easier to write, test, and deploy smart contracts.
One of the key features of Hardhat is its support for upgradable smart contracts. Upgradable smart contracts are a powerful tool for developers, as they allow them to fix bugs, add features, and make other improvements to deployed smart contracts without having to redeploy the entire contract from scratch. This can save time, reduce costs, and minimize the risks associated with redeploying smart contracts.
Upgradable smart contracts
Upgradable smart contracts are made possible through the use of proxy contracts. A proxy contract acts as an intermediary between the user and the implementation contract, allowing the implementation contract to be upgraded while the proxy contract remains unchanged.
When a user interacts with an upgradable smart contract, the proxy contract forwards the call to the implementation contract. If the implementation contract has been upgraded, the proxy contract will forward the call to the new implementation contract. This allows developers to make changes to the implementation contract without having to update the proxy contract or redeploy the entire smart contract.
Types of upgrades
There are several types of upgrades that can be made to upgradeable smart contracts, including:
Bug Fixes: Developers can fix bugs in the implementation contract without having to redeploy the entire smart contract.
Feature Upgrades: Developers can add new features to the implementation contract without having to redeploy the entire smart contract.
Security Upgrades: Developers can make security upgrades to the implementation contract without having to redeploy the entire smart contract.
Examples (code in Solidity)
Here is an example of an upgradable smart contract using Hardhat and Solidity:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract MyContract is Initializable, UUPSUpgradeable {
uint256 public value;
function initialize(uint256 _value) public initializer {
value = _value;
}
function increment() public {
value++;
}
function _authorizeUpgrade(address) internal override {}
}
In this example, the MyContract
contract inherits from the UUPSUpgradeable
contract, which provides support for upgradable smart contracts. The initialize
function is used to set the initial value of the value
variable. The increment
function is used to increment the value of the value
variable by one. The _authorizeUpgrade
function is used to control who can upgrade the smart contract.
To upgrade the smart contract, a new implementation contract is created with the desired changes. The new implementation contract is then registered with the proxy contract using the upgradeTo
function. Here is an example of upgrading the MyContract
contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract MyContractV2 is UUPSUpgradeable {
uint256 public value;
function decrement() public {
value--;
}
function _authorizeUpgrade(address) internal override {}
}
In this example, a new implementation contract called MyContractV2
is created with a new function called decrement
. To upgrade the MyContract
contract to use the new implementation contract, the upgradeTo
the function is called:
MyContract contract = MyContract(payable(proxyAddress));
MyContractV2 newImplementation = new MyContractV2();
Subscribe to my newsletter
Read articles from Muhindo Galien directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Muhindo Galien
Muhindo Galien
I am a Software Engineer with a strong focus on full-stack web3 dev #open_to_work