diff --git a/.gas-snapshot b/.gas-snapshot index f309fb6a..a6f2bd62 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1 +1,4 @@ +NitroContracts2Point1Point2UpgradeActionTest:testShouldRevertOnEth() (gas: 61684) +NitroContracts2Point1Point2UpgradeActionTest:testShouldRevertOnV2() (gas: 65683) +NitroContracts2Point1Point2UpgradeActionTest:testShouldUpgradeAndSetDecimals() (gas: 91928) UpgradeArbOSVersionAtTimestampActionTest:test_1() (gas: 165) \ No newline at end of file diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 19bf0d0a..5c06776c 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -20,7 +20,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - run: yarn minimal-install - run: yarn audit:ci diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 49892d4b..cdb99f4f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,7 +20,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - run: yarn && yarn build - run: yarn lint diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index b82f6e50..7929f1dd 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -25,7 +25,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - run: yarn - run: cp .env.example .env && yarn test:e2e @@ -52,7 +52,7 @@ jobs: # - name: Install Foundry # uses: foundry-rs/foundry-toolchain@v1 # with: - # version: nightly + # version: stable # - run: yarn # - run: cp .env.example .env && yarn test:e2e @@ -80,7 +80,7 @@ jobs: # - name: Install Foundry # uses: foundry-rs/foundry-toolchain@v1 # with: - # version: nightly + # version: stable # - run: yarn # - run: cp .env.example .env && yarn test:e2e diff --git a/.github/workflows/test-fork.yml b/.github/workflows/test-fork.yml index d7a09dea..aef7dc1a 100644 --- a/.github/workflows/test-fork.yml +++ b/.github/workflows/test-fork.yml @@ -20,7 +20,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - run: yarn minimal-install - run: ETH_FORK_URL=${{ secrets.ETH_FORK_URL }} ARB_FORK_URL=${{ secrets.ARB_FORK_URL }} yarn test:fork diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cb1cf56e..1274f006 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - run: yarn minimal-install - run: yarn test:unit @@ -35,7 +35,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - run: yarn minimal-install - run: yarn test:sizes @@ -50,7 +50,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - run: yarn minimal-install - run: yarn test:gas-check @@ -65,7 +65,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - run: yarn minimal-install - run: yarn test:sigs @@ -80,7 +80,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - run: yarn minimal-install - run: yarn test:storage diff --git a/README.md b/README.md index 6a9f3c82..d5123ec9 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,18 @@ _This section is also referenced in the documentation on ["How to upgrade ArbOS For ArbOS upgrades, a common pre-requisite is to deploy new Nitro contracts to the parent chain of your Orbit chain before scheduling the ArbOS upgrade. These contracts include the rollup logic, fraud proof contracts, and interfaces for interacting with Nitro precompiles. The scripts and instructions in this repository are meant for Orbit chain owners to upgrade the aforementioned contracts, set the new WASM module root, and then schedule the ArbOS upgrade. +### Nitro contracts 2.1.2 + +The [`nitro-contracts 2.1.2` upgrade guide](scripts/foundry/contract-upgrades/2.1.2) will patch the `ERC20Bridge` with a storage layout fix. + +This upgrade is only required if: + +1. The chain has a custom native token; AND +1. The chain was originally deployed before `v2.0.0`; AND +1. The chain wishes to upgrade to `v3.0.0` + +Do not perform this upgrade if the above requirements aren't met. + ### Nitro contracts 2.1.0 (for [ArbOS 32 Bianca](https://docs.arbitrum.io/run-arbitrum-node/arbos-releases/arbos32)) The [`nitro-contracts 2.1.0` upgrade action](scripts/foundry/contract-upgrades/2.1.0) will deploy `nitro-contracts v2.1.0` contracts to your Orbit's parent chain. Note that this action will only work for chains with `nitro-contracts v1.2.1` or `nitro-contracts v1.3.0`. diff --git a/contracts/parent-chain/contract-upgrades/NitroContracts2Point1Point2UpgradeAction.sol b/contracts/parent-chain/contract-upgrades/NitroContracts2Point1Point2UpgradeAction.sol new file mode 100644 index 00000000..c09f5156 --- /dev/null +++ b/contracts/parent-chain/contract-upgrades/NitroContracts2Point1Point2UpgradeAction.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.16; + +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; + +interface IERC20Bridge { + function nativeToken() external view returns (address); +} + +interface IERC20Bridge_v2 { + function nativeTokenDecimals() external view returns (uint8); +} + +interface IERC20Bridge_v2_patch { + function postUpgradeInit() external; +} + +/** + * @title NitroContracts2Point1Point2UpgradeAction + * @notice Upgrade the bridge to ERC20Bridge v2.1.2 and force it to set nativeTokenDecimals to 18. + * Will revert if the bridge is not an ERC20Bridge. + * Will revert if ERC20Bridge is not v1.x.x + */ +contract NitroContracts2Point1Point2UpgradeAction { + address public immutable newBridgeImpl; + + constructor(address _newBridgeImpl) { + require( + Address.isContract(_newBridgeImpl), + "NitroContracts2Point1Point2UpgradeAction: _newBridgeImpl is not a contract" + ); + + newBridgeImpl = _newBridgeImpl; + } + + function perform(address bridge, ProxyAdmin proxyAdmin) external { + // ensure the bridge is an ERC20Bridge + try IERC20Bridge(bridge).nativeToken() returns (address) {} + catch { + // nativeToken() reverted, so it's not an ERC20Bridge + revert("NitroContracts2Point1Point2UpgradeAction: bridge is not an ERC20Bridge"); + } + + // ensure the bridge is v1.x.x + try IERC20Bridge_v2(address(bridge)).nativeTokenDecimals() returns (uint8) { + // nativeTokenDecimals() didn't revert, so it must be v2.x.x + revert("NitroContracts2Point1Point2UpgradeAction: bridge is not v1.x.x"); + } catch {} + + // upgrade to the new implementation and call forceEighteenDecimalsPatch + proxyAdmin.upgradeAndCall({ + proxy: TransparentUpgradeableProxy(payable((bridge))), + implementation: newBridgeImpl, + data: abi.encodeCall(IERC20Bridge_v2_patch.postUpgradeInit, ()) + }); + + // ensure decimals were set to 18 + require(IERC20Bridge_v2((bridge)).nativeTokenDecimals() == 18, "decimals not set to 18"); + } +} diff --git a/foundry.toml b/foundry.toml index f5e41c07..3117eb62 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,5 +6,5 @@ test = 'test' cache_path = 'cache_forge' solc_version = '0.8.16' optimizer_runs = 2000 -fs_permissions = [{ access = "read", path = "node_modules/@arbitrum/"}, { access = "read", path = "node_modules/@openzeppelin/"},{ access = "read-write", path = "./scripts/foundry"}] +fs_permissions = [{ access = "read", path = "node_modules/@offchainlabs/"},{ access = "read", path = "node_modules/@arbitrum/"}, { access = "read", path = "node_modules/@openzeppelin/"},{ access = "read-write", path = "./scripts/foundry"}] script = 'scripts' diff --git a/package.json b/package.json index f225d7fd..51b2ef62 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@arbitrum/nitro-contracts-1.2.1": "npm:@arbitrum/nitro-contracts@1.2.1", "@arbitrum/nitro-contracts-1.3.0": "npm:@arbitrum/nitro-contracts@1.3.0", "@arbitrum/nitro-contracts-2.1.0": "npm:@arbitrum/nitro-contracts@2.1.0", + "@arbitrum/nitro-contracts-2.1.2": "npm:@arbitrum/nitro-contracts@2.1.2", "@arbitrum/token-bridge-1.2.2": "npm:@arbitrum/token-bridge-contracts@1.2.2", "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", "@nomicfoundation/hardhat-ethers": "^3.0.0", diff --git a/scripts/foundry/contract-upgrades/2.1.0/README.md b/scripts/foundry/contract-upgrades/2.1.0/README.md index eafe344a..99c055f5 100644 --- a/scripts/foundry/contract-upgrades/2.1.0/README.md +++ b/scripts/foundry/contract-upgrades/2.1.0/README.md @@ -44,7 +44,7 @@ Also, expectation is that rollup being upgraded currently uses official ArbOS20 ## How to use it -1. Setup .env according to the example files, make sure you have everything correctly defined. The script will do some sanity checks but not everything can be checked. The .env file must be in project root for recent foundary versions. +1. Setup .env according to the example files, make sure you have everything correctly defined. The script will do some sanity checks but not everything can be checked. The .env file must be in project root for recent foundry versions. > [!CAUTION] > The .env file must be in project root. diff --git a/scripts/foundry/contract-upgrades/2.1.2/.env.sample b/scripts/foundry/contract-upgrades/2.1.2/.env.sample new file mode 100644 index 00000000..eba03a66 --- /dev/null +++ b/scripts/foundry/contract-upgrades/2.1.2/.env.sample @@ -0,0 +1,6 @@ +## These env vars are used for ExecuteNitroContracts2Point1Point2UpgradeScript + +UPGRADE_ACTION_ADDRESS= +INBOX_ADDRESS= +PROXY_ADMIN_ADDRESS= +PARENT_UPGRADE_EXECUTOR_ADDRESS= \ No newline at end of file diff --git a/scripts/foundry/contract-upgrades/2.1.2/DeployNitroContracts2Point1Point2UpgradeAction.s.sol b/scripts/foundry/contract-upgrades/2.1.2/DeployNitroContracts2Point1Point2UpgradeAction.s.sol new file mode 100644 index 00000000..d71c81be --- /dev/null +++ b/scripts/foundry/contract-upgrades/2.1.2/DeployNitroContracts2Point1Point2UpgradeAction.s.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.16; + +import {DeploymentHelpersScript} from "../../helper/DeploymentHelpers.s.sol"; +import {NitroContracts2Point1Point2UpgradeAction} from + "../../../../contracts/parent-chain/contract-upgrades/NitroContracts2Point1Point2UpgradeAction.sol"; + +/** + * @title DeployNitroContracts2Point1Point2UpgradeActionScript + * @notice This script deploys the ERC20Bridge contract and NitroContracts2Point1Point2UpgradeAction contract. + */ +contract DeployNitroContracts2Point1Point2UpgradeActionScript is DeploymentHelpersScript { + function run() public { + vm.startBroadcast(); + + // deploy new ERC20Bridge contract from v2.1.2 + address newBridgeImpl = deployBytecodeFromJSON( + "/node_modules/@arbitrum/nitro-contracts-2.1.2/build/contracts/src/bridge/ERC20Bridge.sol/ERC20Bridge.json" + ); + + // deploy upgrade action + new NitroContracts2Point1Point2UpgradeAction(newBridgeImpl); + + vm.stopBroadcast(); + } +} diff --git a/scripts/foundry/contract-upgrades/2.1.2/ExecuteNitroContracts2Point1Point2Upgrade.s.sol b/scripts/foundry/contract-upgrades/2.1.2/ExecuteNitroContracts2Point1Point2Upgrade.s.sol new file mode 100644 index 00000000..2643b5f5 --- /dev/null +++ b/scripts/foundry/contract-upgrades/2.1.2/ExecuteNitroContracts2Point1Point2Upgrade.s.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.16; + +import "forge-std/Script.sol"; +import { + NitroContracts2Point1Point2UpgradeAction, + ProxyAdmin +} from "../../../../contracts/parent-chain/contract-upgrades/NitroContracts2Point1Point2UpgradeAction.sol"; +import {IInboxBase} from "@arbitrum/nitro-contracts-1.2.1/src/bridge/IInboxBase.sol"; +import {IERC20Bridge} from "@arbitrum/nitro-contracts-2.1.2/src/bridge/IERC20Bridge.sol"; +import {IUpgradeExecutor} from "@offchainlabs/upgrade-executor/src/IUpgradeExecutor.sol"; + +/** + * @title ExecuteNitroContracts1Point2Point1UpgradeScript + * @notice This script executes nitro contracts 2.1.2 upgrade through UpgradeExecutor + */ +contract ExecuteNitroContracts2Point1Point2UpgradeScript is Script { + function run() public { + NitroContracts2Point1Point2UpgradeAction upgradeAction = + NitroContracts2Point1Point2UpgradeAction(vm.envAddress("UPGRADE_ACTION_ADDRESS")); + + IInboxBase inbox = IInboxBase(vm.envAddress("INBOX_ADDRESS")); + + address bridge = address(inbox.bridge()); + + // prepare upgrade calldata + ProxyAdmin proxyAdmin = ProxyAdmin(vm.envAddress("PROXY_ADMIN_ADDRESS")); + bytes memory upgradeCalldata = + abi.encodeCall(NitroContracts2Point1Point2UpgradeAction.perform, (bridge, proxyAdmin)); + + // execute the upgrade + // action checks prerequisites, and script will fail if the action reverts + IUpgradeExecutor executor = IUpgradeExecutor(vm.envAddress("PARENT_UPGRADE_EXECUTOR_ADDRESS")); + vm.startBroadcast(); + executor.execute(address(upgradeAction), upgradeCalldata); + vm.stopBroadcast(); + + // sanity check, full checks are done on-chain by the upgrade action + require(IERC20Bridge(bridge).nativeTokenDecimals() == 18, "Unexpected native token decimals"); + } +} diff --git a/scripts/foundry/contract-upgrades/2.1.2/README.md b/scripts/foundry/contract-upgrades/2.1.2/README.md new file mode 100644 index 00000000..16b04a6c --- /dev/null +++ b/scripts/foundry/contract-upgrades/2.1.2/README.md @@ -0,0 +1,87 @@ +# Nitro contracts 2.1.2 upgrade + +> [!CAUTION] +> This is a patch version and is only necessary for custom fee token chains with an `ERC20Bridge` contract below version `< v2.0.0`. +> +> If your chain uses the parent chain's native asset for fees, or your `ERC20Bridge` is already at `v2.0.0` or above, do not perform this upgrade. +> +> The rest of this document assumes the chain satisfies the above. + +These scripts deploy and execute the `NitroContracts2Point1Point2UpgradeAction` contract which allows Orbit chains to upgrade to [2.1.2 release](https://github.com/OffchainLabs/nitro-contracts/releases/tag/v2.1.2). Predeployed instances of the upgrade action exist on the chains listed in the following section. + +Upgrading to `v2.1.2` is REQUIRED before upgrading to `v3.0.0`. Upgrading to `v2.1.0` is REQUIRED before upgrading to `v2.1.2`. + +`NitroContracts2Point1Point2UpgradeAction` will perform the following action: + +1. Upgrade the `ERC20Bridge` contract to `v2.1.2` +1. Force `nativeTokenDecimals` to 18 + +It is assumed that the native token has 18 decimals, since this was a requirement for deploying a custom fee token chain prior to `v2.0.0`. + +## Requirements + +This upgrade only support upgrading from the following [nitro-contract release](https://github.com/OffchainLabs/nitro-contracts/releases): + +- Inbox: v1.1.0 - v1.3.0 inclusive +- Outbox: v1.1.0 - v1.3.0 inclusive +- SequencerInbox: v1.2.1 - v2.1.0 inclusive +- Bridge: v1.1.0 - v1.3.0 inclusive +- RollupProxy: v1.1.0 - v2.1.0 inclusive +- RollupAdminLogic: v2.1.0 +- RollupUserLogic: v2.1.0 +- ChallengeManager: v2.1.0 + +Please refer to the top [README](/README.md#check-version-and-upgrade-path) `Check Version and Upgrade Path` on how to determine your current nitro contracts version. + +## Deployed instances + +### Mainnets +- L1 Mainnet: 0x78Ee30C74B3Ce1aeB38163Db3E7d769d9735542F +- L2 Arb1: 0x7D42F098e79DE006CFAB475cFD50BdF2310d7ae8 +- L2 Nova: 0xEb35A5E1B0FdBa925880A539Eac661907d43Ee07 +- L2 Base: 0x9d924ffE6D66ca0727657734a615CC9730925c49 + +### Testnets +- L1 Sepolia: 0xA8a3869A55Baf88f20B81bdbf54eDaC532b98369 +- L1 Holesky: 0x619a0B831d61b90a8585CE9B25077021f1fFa925 +- L2 ArbSepolia: 0x76A35A0c721A6bf53982f5a00ccb3AaDb184aD8E +- L2 BaseSepolia: 0xA5b663B60502ef6bFFe3e003A43d3E79AFB1aC1c + +## How to use it + +1. Setup .env according to the example files, make sure you have everything correctly defined. The .env file must be in project root for recent foundry versions. + +> [!CAUTION] +> The .env file must be in project root. + +2. (Skip this step if you can use the deployed instances of action contract) + `DeployNitroContracts2Point1Point2UpgradeActionScript.s.sol` script deploys templates, and upgrade action itself. It can be executed in this directory like this: + +```bash +forge script --sender $DEPLOYER --rpc-url $PARENT_CHAIN_RPC --broadcast --slow DeployNitroContracts2Point1Point2UpgradeActionScript -vvv --verify --skip-simulation +# use --account XXX / --private-key XXX / --interactive / --ledger to set the account to send the transaction from +``` + +As a result, all templates and upgrade action are deployed. Note the last deployed address - that's the upgrade action. + +3. `ExecuteNitroContracts2Point1Point2Upgrade.s.sol` script uses previously deployed upgrade action to execute the upgrade. It makes following assumptions - L1UpgradeExecutor is the rollup owner, and there is an EOA which has executor rights on the L1UpgradeExecutor. Proceed with upgrade using the owner account (the one with executor rights on L1UpgradeExecutor): + +```bash +forge script --sender $EXECUTOR --rpc-url $PARENT_CHAIN_RPC --broadcast ExecuteNitroContracts2Point1Point2UpgradeScript -vvv +# use --account XXX / --private-key XXX / --interactive / --ledger to set the account to send the transaction from +``` + +If you have a multisig as executor, you can still run the above command without broadcasting to get the payload for the multisig transaction. + +4. That's it, upgrade has been performed. You can make sure it has successfully executed by checking the native token decimals. + +```bash +# should return 18 +cast call --rpc-url $PARENT_CHAIN_RPC $BRIDGE "nativeTokenDecimals()(uint8)" +``` + +## FAQ + +### Q: intrinsic gas too low when running foundry script + +A: try to add -g 1000 to the command diff --git a/scripts/orbit-versioner/orbitVersioner.ts b/scripts/orbit-versioner/orbitVersioner.ts index ee713568..09b55282 100644 --- a/scripts/orbit-versioner/orbitVersioner.ts +++ b/scripts/orbit-versioner/orbitVersioner.ts @@ -21,6 +21,7 @@ interface BridgeHashes { Outbox: string[] SequencerInbox: string[] Bridge: string[] + RollupEventInbox: string[] } interface MetadataHashesByNativeToken { eth: BridgeHashes @@ -65,14 +66,10 @@ async function main() { const bridge = IBridge__factory.connect(bridgeAddress, provider) const seqInboxAddress = await bridge.sequencerInbox() const rollupAddress = await bridge.rollup() - const outboxAddress = await IRollupCore__factory.connect( - rollupAddress, - provider - ).outbox() - const challengeManagerAddress = await IRollupCore__factory.connect( - rollupAddress, - provider - ).challengeManager() + const rollup = IRollupCore__factory.connect(rollupAddress, provider) + const outboxAddress = await rollup.outbox() + const challengeManagerAddress = await rollup.challengeManager() + const rollupEventInboxAddress = await rollup.rollupEventInbox() // get metadata hashes const metadataHashes: { [key: string]: string } = { @@ -92,6 +89,10 @@ async function main() { await _getLogicAddress(bridgeAddress, provider), provider ), + RollupEventInbox: await _getMetadataHash( + await _getLogicAddress(rollupEventInboxAddress, provider), + provider + ), RollupProxy: await _getMetadataHash(rollupAddress, provider), RollupAdminLogic: await _getMetadataHash( await _getLogicAddress(rollupAddress, provider), @@ -115,10 +116,15 @@ async function main() { console.log('\nMetadataHashes of deployed contracts:', metadataHashes, '\n') } + let isFeeTokenChain = false const versions: { [key: string]: string | null } = {} // get and print version per bridge contract Object.keys(metadataHashes).forEach(key => { - versions[key] = _getVersionOfDeployedContract(metadataHashes[key]) + const { version, isErc20 } = _getVersionOfDeployedContract( + metadataHashes[key] + ) + versions[key] = version + if (isErc20) isFeeTokenChain = true console.log( `Version of deployed ${key}: ${versions[key] ? versions[key] : 'unknown'}` ) @@ -126,13 +132,25 @@ async function main() { // TODO: make this more generic to support other other upgrade paths in the future // TODO: also check osp - _checkForPossibleUpgrades(versions) + _checkForPossibleUpgrades(versions, isFeeTokenChain) } -function _checkForPossibleUpgrades(currentVersions: { - [key: string]: string | null -}) { +function _checkForPossibleUpgrades( + currentVersions: { + [key: string]: string | null + }, + isFeeTokenChain: boolean +) { const targetVersionsDescending = [ + // DISABLING BOLD UPGRADE FOR NOW + // { + // version: 'v3.0.0', + // actionName: 'BOLD UpgradeAction', + // }, + { + version: 'v2.1.2', + actionName: 'NitroContracts2Point1Point2UpgradeAction', + }, { version: 'v2.1.0', actionName: 'NitroContracts2Point1Point0UpgradeAction', @@ -144,7 +162,13 @@ function _checkForPossibleUpgrades(currentVersions: { ] for (const target of targetVersionsDescending) { - if (_canBeUpgradedToTargetVersion(target.version, currentVersions)) { + if ( + _canBeUpgradedToTargetVersion( + target.version, + currentVersions, + isFeeTokenChain + ) + ) { console.log( `This deployment can be upgraded to ${target.version} using ${target.actionName}` ) @@ -159,44 +183,100 @@ function _canBeUpgradedToTargetVersion( targetVersion: string, currentVersions: { [key: string]: string | null - } + }, + isFeeTokenChain: boolean ): boolean { console.log('\nChecking if deployment can be upgraded to', targetVersion) let supportedSourceVersionsPerContract: { [key: string]: string[] } = {} - if (targetVersion === 'v2.1.0') { + // DISABLING BOLD UPGRADE FOR NOW + // if (targetVersion === 'v3.0.0') { + // // v3.0.0 will upgrade bridge, inbox, rollupEventInbox, outbox, sequencerInbox, rollup logics, challengeManager + // supportedSourceVersionsPerContract = { + // Inbox: [ + // 'v1.1.0', + // 'v1.1.1', + // 'v1.2.0', + // 'v1.2.1', + // 'v1.3.0', + // 'v2.0.0', + // 'v2.1.0', + // ], + // Outbox: ['any'], + // Bridge: [ + // 'v1.1.0', + // 'v1.1.1', + // 'v1.2.0', + // 'v1.2.1', + // 'v1.3.0', + // 'v2.0.0', + // 'v2.1.0', + // ], + // RollupEventInbox: ['any'], + // RollupProxy: ['any'], + // RollupAdminLogic: ['v2.0.0', 'v2.1.0'], + // RollupUserLogic: ['v2.0.0', 'v2.1.0'], + // ChallengeManager: ['v2.0.0', 'v2.1.0'], + // SequencerInbox: ['v1.2.1', 'v1.3.0', 'v2.0.0', 'v2.1.0'], + // } + // if (isFeeTokenChain) { + // // cannot upgrade erc20 orbit chains from v1 to v3 right now due to a storage diff + // supportedSourceVersionsPerContract.Bridge = ['v2.0.0', 'v2.1.0', 'v2.1.2'] + // // TODO: remove this later, but the script does not custom fee token chain yet + // supportedSourceVersionsPerContract.Bridge = [] + // } + // } else + if (targetVersion === 'v2.1.2') { + // v2.1.2 will upgrade the ERC20Bridge contract to set decimals in storage + // v2.1.2 is only required for custom fee token chains + // only necessary if ERC20Bridge is < v2.0.0 + // must have performed v2.1.0 upgrade first + if (!isFeeTokenChain) { + supportedSourceVersionsPerContract = { + Inbox: [], + Outbox: [], + Bridge: [], + RollupEventInbox: [], + RollupProxy: [], + RollupAdminLogic: [], + RollupUserLogic: [], + ChallengeManager: [], + SequencerInbox: [], + } + } else { + supportedSourceVersionsPerContract = { + Inbox: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1', 'v1.3.0'], + Outbox: ['any'], + Bridge: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1', 'v1.3.0'], + RollupEventInbox: ['any'], + RollupProxy: ['any'], + RollupAdminLogic: ['v2.1.0'], + RollupUserLogic: ['v2.1.0'], + ChallengeManager: ['v2.1.0'], + SequencerInbox: ['v1.2.1', 'v1.3.0', 'v2.0.0', 'v2.1.0'], + } + } + } else if (targetVersion === 'v2.1.0') { + // v2.1.0 will upgrade rollup logics and challenge manager supportedSourceVersionsPerContract = { Inbox: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1', 'v1.3.0'], - Outbox: [ - 'v1.1.0', - 'v1.1.1', - 'v1.2.0', - 'v1.2.1', - 'v1.3.0', - 'v2.0.0', - 'v2.1.0', - ], + Outbox: ['any'], Bridge: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1', 'v1.3.0'], - RollupProxy: [ - 'v1.1.0', - 'v1.1.1', - 'v1.2.0', - 'v1.2.1', - 'v1.3.0', - 'v2.0.0', - 'v2.1.0', - ], + RollupEventInbox: ['any'], + RollupProxy: ['any'], RollupAdminLogic: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1', 'v1.3.0'], RollupUserLogic: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1', 'v1.3.0'], ChallengeManager: ['v1.2.1', 'v1.3.0'], SequencerInbox: ['v1.2.1', 'v1.3.0', 'v2.0.0', 'v2.1.0'], } } else if (targetVersion === 'v1.2.1') { + // v1.2.1 will upgrade sequencer inbox and challenge manager supportedSourceVersionsPerContract = { Inbox: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1'], - Outbox: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1'], + Outbox: ['any'], Bridge: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1'], - RollupProxy: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1'], + RollupEventInbox: ['any'], + RollupProxy: ['any'], RollupAdminLogic: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1'], RollupUserLogic: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1'], ChallengeManager: ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1'], @@ -211,6 +291,9 @@ function _canBeUpgradedToTargetVersion( for (const [contract, supportedSourceVersions] of Object.entries( supportedSourceVersionsPerContract )) { + if (supportedSourceVersions.includes('any')) { + continue + } if (!supportedSourceVersions.includes(currentVersions[contract]!)) { // found contract that can't be upgraded to target version console.log('Cannot upgrade', contract, 'to', targetVersion) @@ -221,7 +304,10 @@ function _canBeUpgradedToTargetVersion( return true } -function _getVersionOfDeployedContract(metadataHash: string): string | null { +function _getVersionOfDeployedContract(metadataHash: string): { + version: string | null + isErc20: boolean +} { for (const [version] of Object.entries(referentMetadataHashes)) { // check if given hash matches any of the referent hashes for specific version const versionHashes = referentMetadataHashes[version] @@ -234,11 +320,16 @@ function _getVersionOfDeployedContract(metadataHash: string): string | null { ...versionHashes.ChallengeManager, ] + const erc20Hashes = [...Object.values(versionHashes.erc20).flat()] + if (allHashes.includes(metadataHash)) { - return version + if (erc20Hashes.includes(metadataHash)) { + return { version, isErc20: true } + } + return { version, isErc20: false } } } - return null + return { version: null, isErc20: false } } async function _getMetadataHash( diff --git a/scripts/orbit-versioner/referentMetadataHashes.json b/scripts/orbit-versioner/referentMetadataHashes.json index 0bb73044..cc9b1b9f 100644 --- a/scripts/orbit-versioner/referentMetadataHashes.json +++ b/scripts/orbit-versioner/referentMetadataHashes.json @@ -1,4 +1,66 @@ { + "v2.1.2": { + "eth": { + "Inbox": [ + "1220628e60c87e41de8e6a81e185b46d287cde8c08a6428c975b93f51625154e", + "122091702e735e50f68dac5823e925b473ebcc2fb5f7a3e16423a6b66ae3e41f" + ], + "Outbox": [ + "1220d72bec3b88f0c24d7071c836c8b7bae617bfcb4ba8257b31d08513327c3e", + "1220a71c0b2b1bb378b4e87b3d74997da580d1aeddfa0020bf7828e35ac6e461" + ], + "SequencerInbox": [ + "1220808ebb88e683cd824929d0402cad1483444601cb2684e3cfaaaeed19ac57", + "12200b70d39c8af70cc4bbc2b5720d07462c71f7284b1e45497748c5118bb338" + ], + "Bridge": [ + "122064054196f2755fb5f47e6097337338d1e194d98c5954455caa8b7baf8e5d", + "12206c38d558afd13c030589dace1d3b4f8d157625dfc5f1ee771258bbf86c5d" + ], + "RollupEventInbox": [ + "12207d19a28e7f0e10a9b2eb981ce3da9fceb0fe3e7644296a1bb96e3c96cbc8", + "122083a34bbde14e9dec4a2f310a86f137fe593f771ab544d81c02bf11b957c6" + ] + }, + "erc20": { + "Inbox": [ + "1220554d1f2e24c9e4d69b248f0dd3a38201a778c4de8dfdeb6c9603141cf39c", + "1220b619f34ba272ec72ca2035fc421c7dd2bc6f98ff5f8a9cdeda227076bac5" + ], + "Outbox": [ + "1220b6f57428af8be2dd64e9c538a09dc180519aae4ba146ec1c30d632f1d2b5", + "122065c63281532ea50f5bde466e32959b8197898044c1677fa59f725f274ff2" + ], + "SequencerInbox": [ + "1220808ebb88e683cd824929d0402cad1483444601cb2684e3cfaaaeed19ac57", + "12200b70d39c8af70cc4bbc2b5720d07462c71f7284b1e45497748c5118bb338" + ], + "Bridge": [ + "1220e960459b981dbc4d07204a7a2305085824f5a8787332d5649a5b64b1c098", + "122015780c5a69efd79a90adc3c14919c8a776c3acdc3575261bf44f3d54f2b6" + ], + "RollupEventInbox": [ + "12207d19a28e7f0e10a9b2eb981ce3da9fceb0fe3e7644296a1bb96e3c96cbc8", + "122083a34bbde14e9dec4a2f310a86f137fe593f771ab544d81c02bf11b957c6" + ] + }, + "RollupProxy": [ + "1220bab353bebd2841fa52caf85916c15589ea2750f92da55e48857dc5190a73", + "1220039b2791e4013e004cd51e37e19e1137184e0a7f5dec2621e721140c54ba" + ], + "RollupAdminLogic": [ + "1220234108252d432aa9102cd74587054f02d4911560a43b4cada21493e410a8", + "1220839876227496412329143261f9aee68b0488c8443af858067961fa782617" + ], + "RollupUserLogic": [ + "1220e522aeb65ca50fd75e371d71357f5aaf5d6bfc0a68fe6939eab69d97030e", + "12209d2c30d4500f07983f4c3ae838cdc93cdf73f3daf90d4dbd3288f072b2d1" + ], + "ChallengeManager": [ + "12203d3c8fc40e3acb1cd932cf29519fe01da37b3e32a8670a81760f4ecf9497", + "1220a10b85e7c0f109a0a569ed2fe7e8603230eaa7d5df62f1531f548fe0eff8" + ] + }, "v2.1.0": { "eth": { "Inbox": [ @@ -16,7 +78,8 @@ "Bridge": [ "12206c38d558afd13c030589dace1d3b4f8d157625dfc5f1ee771258bbf86c5d", "12202046bd5adb858c77c93e2b65a31b8f11b3f381d5055793f137e085421542" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": [ @@ -34,7 +97,8 @@ "Bridge": [ "122091f2b3a26837eb7f6ae1ee1395e00da6a57a8923d02f716ccaebf4348167", "12202b5d5c431949e42cc0f94ae888b71651bdbd6aad7d357822e0b769a9310d" - ] + ], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "1220039b2791e4013e004cd51e37e19e1137184e0a7f5dec2621e721140c54ba", @@ -70,7 +134,8 @@ "Bridge": [ "1220506ed7ef8395a03cfb43943c618809bd281b51ea77ecd261aed28bb30a8d", "12201a9f67fb3c7f5bfec02931dc84a6854b5cb012b0746f1476e2c0a03cdafb" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": [ @@ -88,7 +153,8 @@ "Bridge": [ "12203ff1e011449147ed6c37be48c3ee711841c26d4edb6eec8f48144eac53c7", "12200597a9ae76302c33df923d6ed948d9378de1e91f0c351cf3b1c0410fad28" - ] + ], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "1220c1a242275798d8f2e0b3a59eea6aea18c580869c70ad2fbf232f106e4ce5", @@ -124,7 +190,8 @@ "Bridge": [ "1220ba7a1cededf660a42a7377a73bb0d14a4397581fcbb24bebdd45d63810c2", "1220cf8a2df9168c7d5af713d037a7a686dc8face22911e8979f91a80e8c1560" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": [ @@ -142,7 +209,8 @@ "Bridge": [ "1220f587e602015bef05909a3dc4d3f302450c6b00ea429653353e9c6a202972", "12204de6c5de92ad43eb67bffc52cab35d3bfe43bdbe1c92a87b47c52c4219fe" - ] + ], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "12201b31c429a0e4c8b02c3e9ecc213345054112368bf2c3821ae941dd87167c", @@ -178,7 +246,8 @@ "Bridge": [ "1220ba7a1cededf660a42a7377a73bb0d14a4397581fcbb24bebdd45d63810c2", "1220c3c76b4863c78b535187aa58b9b008b260271e5be20b6319095c61fa1f62" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": [ @@ -196,7 +265,8 @@ "Bridge": [ "1220f587e602015bef05909a3dc4d3f302450c6b00ea429653353e9c6a202972", "12202ba4687d78116ae8629782b0ccc8e70f30db90127cc1ee45a07dadbab544" - ] + ], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "12201f644f13efd6c7b8c4ef216106f36b132e19c811eeb8cee47de7e96b69d5", @@ -232,7 +302,8 @@ "Bridge": [ "1220fc415098f1984b6eb0036bf74d4c58c8f2aecced4f9aa23bc8f1ec40a763", "12202c5ff330f1a94e5bb5b2e35bdc74b9b974d83de9f9705f82ed0f23e74816" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": [ @@ -250,7 +321,8 @@ "Bridge": [ "1220608c64e88e11ca7c69079c15d6e7a635d96c8c450b764d917d39c39d927a", "12200feb0990fb1e40d8b046a8996b213f9ee17c5e9a707d81f49b65d1fb9403" - ] + ], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "122050d53014317e8cdb5c3e4f6737c818a3257250f410e29949414733539236", @@ -286,7 +358,8 @@ "Bridge": [ "122036229552e25569ee81b36ff0079ed482a0f5114c34695a273717057e68b7", "12203cb53c06e3d38f5055af396f234d714307935d59ca28459db5226efad4d0" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": [ @@ -304,7 +377,8 @@ "Bridge": [ "1220acaca6cc8d40714063ec21646cf3fb554ba0394dc105b80d1c758ae649ee", "1220611c0f41c29b817325b2d56fbd2d81ce85b6458fab21ed9f950ad47db5dd" - ] + ], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "122045d1669737d3f66bbfc5cb21688cdbc2decfc09897811ac43760f60bfdc1", @@ -340,7 +414,8 @@ "Bridge": [ "122036229552e25569ee81b36ff0079ed482a0f5114c34695a273717057e68b7", "12203cb53c06e3d38f5055af396f234d714307935d59ca28459db5226efad4d0" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": [ @@ -358,7 +433,8 @@ "Bridge": [ "1220acaca6cc8d40714063ec21646cf3fb554ba0394dc105b80d1c758ae649ee", "1220611c0f41c29b817325b2d56fbd2d81ce85b6458fab21ed9f950ad47db5dd" - ] + ], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "122045d1669737d3f66bbfc5cb21688cdbc2decfc09897811ac43760f60bfdc1", @@ -390,13 +466,15 @@ ], "Bridge": [ "12201fc2f62f301cacfe134a078470b95e8ac19b8ac3be1ae1c76208c3da5e45" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": ["n/a"], "Outbox": ["n/a"], "SequencerInbox": ["n/a"], - "Bridge": ["n/a"] + "Bridge": ["n/a"], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "122060f5deee0a99bbc2c2d0731e05f3c9710ab8e2c75e0cbc20f8935a93229d" @@ -424,13 +502,15 @@ ], "Bridge": [ "1220a48ff3a66ec9a49bf00ab4d639b5f224664d4cf9ee281ee5feb2111c43bf" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": ["n/a"], "Outbox": ["n/a"], "SequencerInbox": ["n/a"], - "Bridge": ["n/a"] + "Bridge": ["n/a"], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "122060f5deee0a99bbc2c2d0731e05f3c9710ab8e2c75e0cbc20f8935a93229d" @@ -458,13 +538,15 @@ ], "Bridge": [ "1220a866b4912045c6c37c22a163c767d0d623c89bec19b9daba7e0208beee06" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": ["n/a"], "Outbox": ["n/a"], "SequencerInbox": ["n/a"], - "Bridge": ["n/a"] + "Bridge": ["n/a"], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "12202ed603dc21970c25521fb1c7854b938f777a8157233615740ea445d17d08" @@ -492,13 +574,15 @@ ], "Bridge": [ "1220711f146678e425a300d270a5f9c04973e720a2571efa5f0ec557c81e750c" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": ["n/a"], "Outbox": ["n/a"], "SequencerInbox": ["n/a"], - "Bridge": ["n/a"] + "Bridge": ["n/a"], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "1220aeae77513137259801b7ab6793936907a0e6897fd62899007329b9a2e33f" @@ -526,13 +610,15 @@ ], "Bridge": [ "12208d5132810e8d5b98491e43f5a09f382935a7c32e395c98416ee408e6742b" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": ["n/a"], "Outbox": ["n/a"], "SequencerInbox": ["n/a"], - "Bridge": ["n/a"] + "Bridge": ["n/a"], + "RollupEventInbox": ["n/a"] }, "RollupProxy": [ "1220c810c2a8b0f7c41e29d1351996102968a231fa74a467bdcbba66c06a4c0e" @@ -560,13 +646,15 @@ ], "Bridge": [ "122058d67ed2766b0236b5d54528534f6bf055a580c8cb1694f76b78ad2dd6b3" - ] + ], + "RollupEventInbox": ["n/a"] }, "erc20": { "Inbox": ["n/a"], "Outbox": ["n/a"], "SequencerInbox": ["n/a"], - "Bridge": ["n/a"] + "Bridge": ["n/a"], + "RollupEventInbox": ["n/a"] }, "RollupProxy": ["n/a"], "RollupAdminLogic": [ diff --git a/test/signatures/AddWasmCacheManagerAction b/test/signatures/AddWasmCacheManagerAction index d60470db..99103b94 100644 --- a/test/signatures/AddWasmCacheManagerAction +++ b/test/signatures/AddWasmCacheManagerAction @@ -1,5 +1,11 @@ -{ - "perform()": "b147f40c", - "targetArbOSVersion()": "fcb528a2", - "wasmCachemanager()": "b6763099" -} + +╭----------------------+------------╮ +| Method | Identifier | ++===================================+ +| perform() | b147f40c | +|----------------------+------------| +| targetArbOSVersion() | fcb528a2 | +|----------------------+------------| +| wasmCachemanager() | b6763099 | +╰----------------------+------------╯ + diff --git a/test/signatures/EnableFastConfirmAction b/test/signatures/EnableFastConfirmAction index a47b3e4a..10a5a175 100644 --- a/test/signatures/EnableFastConfirmAction +++ b/test/signatures/EnableFastConfirmAction @@ -1,6 +1,13 @@ -{ - "GNOSIS_COMPATIBILITY_FALLBACK_HANDLER()": "e9f250c1", - "GNOSIS_SAFE_1_3_0()": "acbd7fb4", - "GNOSIS_SAFE_PROXY_FACTORY()": "97ce5a2b", - "perform(address,address[],uint256,uint256)": "6214cbd9" -} + +╭--------------------------------------------+------------╮ +| Method | Identifier | ++=========================================================+ +| GNOSIS_COMPATIBILITY_FALLBACK_HANDLER() | e9f250c1 | +|--------------------------------------------+------------| +| GNOSIS_SAFE_1_3_0() | acbd7fb4 | +|--------------------------------------------+------------| +| GNOSIS_SAFE_PROXY_FACTORY() | 97ce5a2b | +|--------------------------------------------+------------| +| perform(address,address[],uint256,uint256) | 6214cbd9 | +╰--------------------------------------------+------------╯ + diff --git a/test/signatures/NitroContracts1Point2Point1UpgradeAction b/test/signatures/NitroContracts1Point2Point1UpgradeAction index c0ce1ae3..431521a3 100644 --- a/test/signatures/NitroContracts1Point2Point1UpgradeAction +++ b/test/signatures/NitroContracts1Point2Point1UpgradeAction @@ -1,7 +1,15 @@ -{ - "newChallengeManagerImpl()": "924ef096", - "newOsp()": "5c4bb63c", - "newSequencerInboxImpl()": "d268538a", - "newWasmModuleRoot()": "6741148c", - "perform(address,address)": "857d1ab7" -} + +╭---------------------------+------------╮ +| Method | Identifier | ++========================================+ +| newChallengeManagerImpl() | 924ef096 | +|---------------------------+------------| +| newOsp() | 5c4bb63c | +|---------------------------+------------| +| newSequencerInboxImpl() | d268538a | +|---------------------------+------------| +| newWasmModuleRoot() | 6741148c | +|---------------------------+------------| +| perform(address,address) | 857d1ab7 | +╰---------------------------+------------╯ + diff --git a/test/signatures/NitroContracts2Point1Point0UpgradeAction b/test/signatures/NitroContracts2Point1Point0UpgradeAction index cc15fe34..8d9f8bcc 100644 --- a/test/signatures/NitroContracts2Point1Point0UpgradeAction +++ b/test/signatures/NitroContracts2Point1Point0UpgradeAction @@ -1,10 +1,21 @@ -{ - "condOsp()": "acdf78b9", - "condRoot()": "828545a7", - "newChallengeManagerImpl()": "924ef096", - "newRollupAdminLogic()": "719c1d83", - "newRollupUserLogic()": "98ab2129", - "newWasmModuleRoot()": "6741148c", - "osp()": "f26a62c6", - "perform(address,address)": "857d1ab7" -} + +╭---------------------------+------------╮ +| Method | Identifier | ++========================================+ +| condOsp() | acdf78b9 | +|---------------------------+------------| +| condRoot() | 828545a7 | +|---------------------------+------------| +| newChallengeManagerImpl() | 924ef096 | +|---------------------------+------------| +| newRollupAdminLogic() | 719c1d83 | +|---------------------------+------------| +| newRollupUserLogic() | 98ab2129 | +|---------------------------+------------| +| newWasmModuleRoot() | 6741148c | +|---------------------------+------------| +| osp() | f26a62c6 | +|---------------------------+------------| +| perform(address,address) | 857d1ab7 | +╰---------------------------+------------╯ + diff --git a/test/signatures/NitroContracts2Point1Point2UpgradeAction b/test/signatures/NitroContracts2Point1Point2UpgradeAction new file mode 100644 index 00000000..b4427520 --- /dev/null +++ b/test/signatures/NitroContracts2Point1Point2UpgradeAction @@ -0,0 +1,9 @@ + +╭--------------------------+------------╮ +| Method | Identifier | ++=======================================+ +| newBridgeImpl() | 28b07406 | +|--------------------------+------------| +| perform(address,address) | 857d1ab7 | +╰--------------------------+------------╯ + diff --git a/test/signatures/SetSequencerInboxMaxTimeVariationAction b/test/signatures/SetSequencerInboxMaxTimeVariationAction index 109f1edf..6445d04a 100644 --- a/test/signatures/SetSequencerInboxMaxTimeVariationAction +++ b/test/signatures/SetSequencerInboxMaxTimeVariationAction @@ -1,7 +1,15 @@ -{ - "delayBlocks()": "ad9c0c2e", - "delaySeconds()": "b752a7d1", - "futureBlocks()": "4f359a37", - "futureSeconds()": "2f1ec5e9", - "perform(address)": "b38ed43b" -} + +╭------------------+------------╮ +| Method | Identifier | ++===============================+ +| delayBlocks() | ad9c0c2e | +|------------------+------------| +| delaySeconds() | b752a7d1 | +|------------------+------------| +| futureBlocks() | 4f359a37 | +|------------------+------------| +| futureSeconds() | 2f1ec5e9 | +|------------------+------------| +| perform(address) | b38ed43b | +╰------------------+------------╯ + diff --git a/test/signatures/UpgradeArbOSVersionAtTimestampAction b/test/signatures/UpgradeArbOSVersionAtTimestampAction index fc6cfce5..e18cbf5e 100644 --- a/test/signatures/UpgradeArbOSVersionAtTimestampAction +++ b/test/signatures/UpgradeArbOSVersionAtTimestampAction @@ -1,5 +1,11 @@ -{ - "newArbOSVersion()": "0959267e", - "perform()": "b147f40c", - "upgradeTimestamp()": "921bd6f0" -} + +╭--------------------+------------╮ +| Method | Identifier | ++=================================+ +| newArbOSVersion() | 0959267e | +|--------------------+------------| +| perform() | b147f40c | +|--------------------+------------| +| upgradeTimestamp() | 921bd6f0 | +╰--------------------+------------╯ + diff --git a/test/storage/NitroContracts2Point1Point2UpgradeAction b/test/storage/NitroContracts2Point1Point2UpgradeAction new file mode 100644 index 00000000..1ec5dc07 --- /dev/null +++ b/test/storage/NitroContracts2Point1Point2UpgradeAction @@ -0,0 +1,6 @@ + +╭------+------+------+--------+-------+----------╮ +| Name | Type | Slot | Offset | Bytes | Contract | ++================================================+ +╰------+------+------+--------+-------+----------╯ + diff --git a/test/unit/NitroContracts2Point1Point2UpgradeAction.t.sol b/test/unit/NitroContracts2Point1Point2UpgradeAction.t.sol new file mode 100644 index 00000000..6dc14082 --- /dev/null +++ b/test/unit/NitroContracts2Point1Point2UpgradeAction.t.sol @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.16; + +import "forge-std/Test.sol"; + +import {Bridge, IOwnable} from "@arbitrum/nitro-contracts-2.1.2/src/bridge/Bridge.sol"; +import { + ERC20Bridge as ERC20Bridge_2_1_2, + IOwnable as IOwnable_2_1_2 +} from "@arbitrum/nitro-contracts-2.1.2/src/bridge/ERC20Bridge.sol"; +import { + ERC20Bridge as ERC20Bridge_2_1_0, + IOwnable as IOwnable_2_1_0 +} from "@arbitrum/nitro-contracts-2.1.0/src/bridge/ERC20Bridge.sol"; +import { + ERC20Bridge as ERC20Bridge_1_3_0, + IOwnable as IOwnable_1_3_0 +} from "@arbitrum/nitro-contracts-1.3.0/src/bridge/ERC20Bridge.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {NitroContracts2Point1Point2UpgradeAction} from + "../../contracts/parent-chain/contract-upgrades/NitroContracts2Point1Point2UpgradeAction.sol"; +import {IUpgradeExecutor} from "@offchainlabs/upgrade-executor/src/IUpgradeExecutor.sol"; +import {DeploymentHelpersScript} from "../../scripts/foundry/helper/DeploymentHelpers.s.sol"; + +interface IUpgradeExecutorExtended is IUpgradeExecutor { + function initialize(address admin, address[] memory executors) external; +} + +contract FakeToken { + uint256 public decimals = 18; +} + +contract NitroContracts2Point1Point2UpgradeActionTest is Test, DeploymentHelpersScript { + IUpgradeExecutorExtended upgradeExecutor; + + address fakeToken; + + ProxyAdmin proxyAdmin; + + ERC20Bridge_2_1_2 newBridgeImpl; + + address ethBridge; + address erc20Bridge_2_1_0; + address erc20Bridge_1_3_0; + + NitroContracts2Point1Point2UpgradeAction action; + + address fakeRollup = 0x822F75d77182fa8Fc17232E511d3A2abf98c7907; + + function setUp() public { + // deploy a proxy admin + proxyAdmin = new ProxyAdmin(); + + // deploy an upgrade executor + address[] memory execs = new address[](1); + execs[0] = address(this); + upgradeExecutor = IUpgradeExecutorExtended( + address( + new TransparentUpgradeableProxy( + deployBytecodeFromJSON( + "/node_modules/@offchainlabs/upgrade-executor/build/contracts/src/UpgradeExecutor.sol/UpgradeExecutor.json" + ), + address(proxyAdmin), + "" + ) + ) + ); + upgradeExecutor.initialize(address(this), execs); + + proxyAdmin.transferOwnership(address(upgradeExecutor)); + + // deploy a fake token + fakeToken = address(new FakeToken()); + + // deploy ERC20Bridge v2.1.2 implementation + newBridgeImpl = new ERC20Bridge_2_1_2(); + + // deploy an ETH Bridge + ethBridge = address(new TransparentUpgradeableProxy(address(new Bridge()), address(proxyAdmin), "")); + Bridge(ethBridge).initialize(IOwnable(fakeRollup)); // pretend the test contract is the rollup + + // deploy an ERC20Bridge on v2.1.0 + erc20Bridge_2_1_0 = + address(new TransparentUpgradeableProxy(address(new ERC20Bridge_2_1_0()), address(proxyAdmin), "")); + ERC20Bridge_2_1_0(erc20Bridge_2_1_0).initialize(IOwnable_2_1_0(fakeRollup), fakeToken); + + // deploy an ERC20Bridge on v1.3.0 + erc20Bridge_1_3_0 = + address(new TransparentUpgradeableProxy(address(new ERC20Bridge_1_3_0()), address(proxyAdmin), "")); + ERC20Bridge_1_3_0(erc20Bridge_1_3_0).initialize(IOwnable_1_3_0(fakeRollup), fakeToken); + + // deploy the upgrade action + action = new NitroContracts2Point1Point2UpgradeAction(address(newBridgeImpl)); + } + + function testShouldRevertOnEth() public { + vm.expectRevert("NitroContracts2Point1Point2UpgradeAction: bridge is not an ERC20Bridge"); + upgradeExecutor.execute(address(action), abi.encodeCall(action.perform, (ethBridge, proxyAdmin))); + } + + function testShouldRevertOnV2() public { + vm.expectRevert("NitroContracts2Point1Point2UpgradeAction: bridge is not v1.x.x"); + upgradeExecutor.execute(address(action), abi.encodeCall(action.perform, (erc20Bridge_2_1_0, proxyAdmin))); + } + + function testShouldUpgradeAndSetDecimals() public { + upgradeExecutor.execute(address(action), abi.encodeCall(action.perform, (erc20Bridge_1_3_0, proxyAdmin))); + + assertEq( + proxyAdmin.getProxyImplementation(TransparentUpgradeableProxy(payable(erc20Bridge_1_3_0))), + address(newBridgeImpl) + ); + assertEq(ERC20Bridge_2_1_2(address(erc20Bridge_1_3_0)).nativeTokenDecimals(), 18); + } +} diff --git a/test/unit/test-unit.bash b/test/unit/test-unit.bash index 03887ba6..01ea5059 100755 --- a/test/unit/test-unit.bash +++ b/test/unit/test-unit.bash @@ -14,7 +14,7 @@ fi foundryFiles=$(ls ./test/unit/**/*.t.sol 2>/dev/null) if [ -n "$foundryFiles" ]; then - forge test --match-path "test/unit/*.t.sol" + forge test --match-path "test/unit/*.t.sol" -vvv code=$? fi diff --git a/test/util/forge-inspect.bash b/test/util/forge-inspect.bash index a4640ead..cce5fd58 100755 --- a/test/util/forge-inspect.bash +++ b/test/util/forge-inspect.bash @@ -18,12 +18,12 @@ for contractName in $contracts; do # if the file doesn't exist, create it if [ ! -f "$outputDir/$contractName" ]; then - forge inspect "$contractName" "$inspectType" --pretty > "$outputDir/$contractName" + forge inspect "$contractName" "$inspectType" > "$outputDir/$contractName" CHANGED=1 # if the file does exist, compare it else mv "$outputDir/$contractName" "$outputDir/$contractName-old" - forge inspect "$contractName" "$inspectType" --pretty > "$outputDir/$contractName" + forge inspect "$contractName" "$inspectType" > "$outputDir/$contractName" diff "$outputDir/$contractName-old" "$outputDir/$contractName" if [[ $? != "0" ]]; then CHANGED=1 diff --git a/yarn.lock b/yarn.lock index 61489f8f..33b2e028 100644 --- a/yarn.lock +++ b/yarn.lock @@ -43,6 +43,17 @@ patch-package "^6.4.7" solady "0.0.182" +"@arbitrum/nitro-contracts-2.1.2@npm:@arbitrum/nitro-contracts@2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@arbitrum/nitro-contracts/-/nitro-contracts-2.1.2.tgz#ee06cdaa55941850c9921e5d0542379234047071" + integrity sha512-kOAep2l///8xBP9fUj843pxoCBiCWH7zL+Qc0pRy3llbE7s4TNI54tiycjuobbYT9geJ01tFvCLWF+pSe+q7DA== + dependencies: + "@offchainlabs/upgrade-executor" "1.1.0-beta.0" + "@openzeppelin/contracts" "4.5.0" + "@openzeppelin/contracts-upgradeable" "4.5.2" + patch-package "^6.4.7" + solady "0.0.182" + "@arbitrum/nitro-contracts@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@arbitrum/nitro-contracts/-/nitro-contracts-1.1.1.tgz#2d8a2f9ab757bb7654562aebe435bff833c4b98d" @@ -2659,8 +2670,43 @@ ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.4: ethereum-cryptography "^0.1.3" rlp "^2.2.4" -"ethers-v5@npm:ethers@^5.7.2", ethers@^5.7.1, ethers@^5.7.2: - name ethers-v5 +"ethers-v5@npm:ethers@^5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" + "@ethersproject/abstract-signer" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/base64" "5.7.0" + "@ethersproject/basex" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/bytes" "5.7.0" + "@ethersproject/constants" "5.7.0" + "@ethersproject/contracts" "5.7.0" + "@ethersproject/hash" "5.7.0" + "@ethersproject/hdnode" "5.7.0" + "@ethersproject/json-wallets" "5.7.0" + "@ethersproject/keccak256" "5.7.0" + "@ethersproject/logger" "5.7.0" + "@ethersproject/networks" "5.7.1" + "@ethersproject/pbkdf2" "5.7.0" + "@ethersproject/properties" "5.7.0" + "@ethersproject/providers" "5.7.2" + "@ethersproject/random" "5.7.0" + "@ethersproject/rlp" "5.7.0" + "@ethersproject/sha2" "5.7.0" + "@ethersproject/signing-key" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@ethersproject/strings" "5.7.0" + "@ethersproject/transactions" "5.7.0" + "@ethersproject/units" "5.7.0" + "@ethersproject/wallet" "5.7.0" + "@ethersproject/web" "5.7.1" + "@ethersproject/wordlists" "5.7.0" + +ethers@^5.7.1, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==