Skip to content
This repository has been archived by the owner on Jan 11, 2024. It is now read-only.

Contract upgrade tooling: makefile + documentation #293

Merged
merged 19 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ OUTPUT ?= .out
deploy-ipc:
./ops/deploy.sh $(NETWORK)

deploy-subnet-registry:
./ops/deploy-subnet-registry.sh $(NETWORK)

deploy-subnet:
./ops/deploy-subnet.sh $(NETWORK)

upgrade-gw-diamond:
./ops/upgrade-gw-diamond.sh $(NETWORK)

Expand Down
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,48 @@ To deploy the contracts in some other network configured in the Hardhat config y
make deploy-ipc NETWORK=<network-name>
```

# Upgrading IPC Solidity Contracts

This repository's contracts use the Diamond pattern for upgradability, allowing new features to be added or issues to be corrected without a full redeployment. The upgrade process is automated and includes bytecode verification to ensure the integrity of the changes.

## Automated Upgrade and Bytecode Verification

When you run an upgrade command, the repository's scripts handle several tasks:

1. **Bytecode Verification**: The scripts fetch the bytecode of the currently deployed contracts on an FEVM-powered IPC network using the details stored in local JSON files in the root directory of the git repository. They compare this with the bytecode generated after applying the intended changes on a temporary Ganache network.

2. **Conditional Upgrades**: If the bytecode verification process detects changes that align with the intended upgrades, the `make` command conditionally triggers other scripts to perform the actual upgrade on the network.

## Upgrade Commands

To upgrade a contract, you may use the following commands. The NETWORK parameter is optional; if not specified, the scripts will default to "auto":

- **Gateway Diamond Upgrade**:

```bash
make upgrade-gw-diamond [NETWORK=<network-name>]
```

- **Subnet Actor Diamond Upgrade**:

```bash
make upgrade-sa-diamond [NETWORK=<network-name>]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can a subnet actor be upgraded if it wasn't initially deployed using hardhat but the ipc-cli? This would mean that the deployment assets are not available for deployment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know enough about ipc-cli to answer this question.. does ipc-cli end up calling hardhat?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately not, it makes a transaction to the registry to trigger the deployment of a new subnet actor. Is there a way to artificially generate a desployment.json to help with the upgrade? We may need to come up with a way to allow updates from subnets deployed from the registry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I understand better how this code works and what needs to happen for this to work from doing the internal audit. I think that there's a reasonable way through this where we need to add code in ./src/subnetregistry/RegisterSubnetFacet.sol that includes the diamond cut facets and then we will just need to exapnd the facets on the subnet registry to manage the upgrades. we'll need some sort of management for the equivalent of deployment.json but that might not be so bad and it might make sense to store some of these data items on chain in the registry. One last concern is that we may end up with a system that has too many subnets to upgrade in a single block so we should have a fallback there to paginate and may need to think about whether we need to do this upgrade change in a transaction where contracts are paused during the upgarde if it spans multiple txs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now tracking here: consensus-shipyard/ipc#497

```

- **Subnet Registry Diamond Upgrade**:
```bash
make upgrade-sr-diamond [NETWORK=<network-name>]
```

After running any of these commands, the scripts will provide transaction details for verification. Check the transaction on the appropriate block explorer to confirm the upgrade's success.

## Important Notes

- The upgrade commands are intended for use by authorized personnel with a deep understanding of the contracts' functionality.
- Ensure that your local repository is up to date with the latest contract code and JSON files before initiating an upgrade.
- Backup all contract data and thoroughly test any new code in a controlled environment prior to an upgrade.
- Monitor the output of the upgrade process carefully for transaction details and to verify its successful completion.

## Branching Strategy

### Production branch
Expand Down
33 changes: 5 additions & 28 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { HardhatUserConfig, task } from 'hardhat/config'
import '@typechain/hardhat'
import 'hardhat-storage-layout-changes'

import '@nomicfoundation/hardhat-foundry'
import '@nomiclabs/hardhat-ethers'
import 'hardhat-deploy'
import 'hardhat-contract-sizer'

import '@typechain/hardhat'
import dotenv from 'dotenv'
import fs from 'fs'
import 'hardhat-contract-sizer'
import 'hardhat-deploy'
import 'hardhat-storage-layout-changes'
import { HardhatUserConfig, task } from 'hardhat/config'
import { HardhatRuntimeEnvironment } from 'hardhat/types'

dotenv.config()
Expand Down Expand Up @@ -193,27 +191,6 @@ task(
},
)

task(
'deploy-subnet',
snissn marked this conversation as resolved.
Show resolved Hide resolved
'Builds and deploys the SubnetActor contract on the selected network',
async (args, hre: HardhatRuntimeEnvironment) => {
const network = hre.network.name

const deployments = await getDeployments(network)
const { deploy } = await lazyImport('./scripts/deploy-subnet')

// remove unused lib
delete deployments.libs['StorableMsgHelper']

const subnetDeployment = await deploy(
deployments.Gateway,
deployments.libs,
)

await saveDeployments(network, subnetDeployment)
},
)

task(
'deploy-gw-diamond-and-facets',
'Builds and deploys Gateway Actor diamond and its facets',
Expand Down
19 changes: 19 additions & 0 deletions ops/deploy-subnet-registry.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash
# Upgrades IPC Gateway Diamond Facets on an EVM-compatible subnet using hardhat
set -e

if [ $# -ne 1 ]
then
echo "Expected a single argument with the name of the network to deploy (localnet, calibrationnet, mainnet)"
exit 1
fi

NETWORK=$1

if [ "$NETWORK" = "auto" ]; then
echo "[*] Automatically getting chainID for network"
source ops/chain-id.sh
fi


npx hardhat deploy-subnet-registry --network ${NETWORK}
20 changes: 20 additions & 0 deletions ops/deploy-subnet.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash
# Upgrades IPC Gateway Diamond Facets on an EVM-compatible subnet using hardhat
set -e

if [ $# -ne 1 ]
then
echo "Expected a single argument with the name of the network to deploy (localnet, calibrationnet, mainnet)"
exit 1
fi

NETWORK=$1

if [ "$NETWORK" = "auto" ]; then
echo "[*] Automatically getting chainID for network"
source ops/chain-id.sh
fi


npx hardhat deploy-sa-diamond-and-facets --network ${NETWORK}

2 changes: 1 addition & 1 deletion scripts/deploy-registry.template.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ethers } from 'hardhat'
import { deployContractWithDeployer, getTransactionFees } from './util'
import { ethers } from 'hardhat'

const { getSelectors, FacetCutAction } = require('./js/diamond.js')

Expand Down
2 changes: 1 addition & 1 deletion scripts/deploy-sa-diamond.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import hre, { ethers } from 'hardhat'
import { deployContractWithDeployer, getTransactionFees } from './util'
import hre, { ethers } from 'hardhat'

const { getSelectors, FacetCutAction } = require('./js/diamond.js')

Expand Down
62 changes: 0 additions & 62 deletions scripts/deploy-subnet.ts

This file was deleted.

3 changes: 2 additions & 1 deletion scripts/util.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
import { providers, Wallet, ContractFactory, Contract } from 'ethers'
import { Contract, ethers } from 'hardhat'
import ganache from 'ganache'
import { ethers } from 'hardhat'
import * as linker from 'solc/linker'

const { getSelectors, FacetCutAction } = require('./js/diamond.js')
const fs = require('fs')

Expand Down
Loading