Skip to content

Commit

Permalink
modified scripts required for upgrading the LC without OPZ defender
Browse files Browse the repository at this point in the history
  • Loading branch information
alysiahuggins committed Jul 12, 2024
1 parent 3deae0e commit 9e46a1c
Show file tree
Hide file tree
Showing 11 changed files with 770 additions and 4 deletions.
153 changes: 153 additions & 0 deletions contracts/broadcast/LightClient.s.sol/11155111/run-1720726496.json

Large diffs are not rendered by default.

153 changes: 153 additions & 0 deletions contracts/broadcast/LightClient.s.sol/11155111/run-latest.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

131 changes: 131 additions & 0 deletions contracts/broadcast/UpgradeLightClient.s.sol/11155111/run-latest.json

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions contracts/script/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ file is used.
1. Select the approval process created in Step 2
1. Be sure to save `DEFENDER_SECRET` ("Team Secret key") and `DEFENDER_KEY` ("Team API Key"), that is shown at the
end of this step, into the `.env` file. The keys won't be available later at a later point.
4. In the home folder of this repo, you're in a nix shell: Enter `nix-shell` in the terminal
5. If the contracts have never been compiled run, `forge build`

## Deployments

Expand Down Expand Up @@ -194,12 +196,15 @@ forge script contracts/script/LightClient.s.sol:DeployLightClientContractScript
--broadcast --legacy
```

To Upgrade
To Upgrade (assuming it's the same LightClient.sol file being used (pre-mainnet))
```bash
forge script contracts/script/UpgradeLightClient.s.sol:UpgradeLightClientScript $offset $mostRecentlyDeployedProxy \
forge script contracts/script/UpgradeSameLightClient.s.sol:UpgradeLightClientScript $mnemonicOffset $mostRecentlyDeployedProxy \
--sig 'run(uint32, address)' \
--ffi \
--rpc-url https://ethereum-sepolia.publicnode.com \
--broadcast --legacy
```
Note: the `$mnemonicOffset` should be zero by default if address referenced by the `$MNEMONIC` in the `.env` is the
first address in that wallet. Otherwise, please specify the correct `$mnemonicOffset`
41 changes: 41 additions & 0 deletions contracts/script/UpgradeLightClientToV2.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { Script } from "forge-std/Script.sol";

import { LightClientV2 as LCV2 } from "../test/LightClientV2.sol";
import { LightClient as LC } from "../src/LightClient.sol";

contract UpgradeLightClientScript is Script {
/// @notice runs the upgrade
/// @param mostRecentlyDeployedProxy address of deployed proxy
/// @return address of the proxy
/// TODO get the most recent deployment from the devops tooling
function run(uint32 seedPhraseOffset, address mostRecentlyDeployedProxy)
external
returns (address)
{
string memory seedPhrase = vm.envString("MNEMONIC");
(address admin,) = deriveRememberKey(seedPhrase, seedPhraseOffset);
vm.startBroadcast(admin);
address proxy = upgradeLightClient(mostRecentlyDeployedProxy, address(new LCV2()));
return proxy;
}

/// @notice upgrades the light client contract by calling the upgrade function the
/// implementation contract via
/// the proxy
/// @param proxyAddress address of proxy
/// @param newLightClient address of new implementation
/// @return address of the proxy
function upgradeLightClient(address proxyAddress, address newLightClient)
public
returns (address)
{
LC proxy = LC(proxyAddress); //make the function call on the previous implementation
proxy.upgradeToAndCall(newLightClient, ""); //proxy address now points to the new
// implementation
vm.stopBroadcast();
return address(proxy);
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"multisig": "0xc56fA6505d10bF322e01327e22479DE78C3Bf1cE",
"newContractName": "LightClient.sol",
"proposalId": "8d347333-7e10-417e-96fd-a2b785115c58",
"proxyAddress": "0xbC781a2BCcdac8F65EF10EA85D765CA240D1789b",
"responseUrl": "https://app.safe.global/transactions/tx?safe=sep:0xc56fA6505d10bF322e01327e22479DE78C3Bf1cE&id=0xad6fe9ec8b6275b81e3a894fb87408fb77e9ad0020e40506aa189024fe28fae8",
"salt": 13
}
88 changes: 88 additions & 0 deletions contracts/test/LightClientUpgradeSameContract.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;

import { Test } /*, console2*/ from "forge-std/Test.sol";
import { LightClient as LCV1 } from "../src/LightClient.sol";
import { LightClient as LCV2 } from "../src/LightClient.sol";
import { DeployLightClientContractScript } from "../script/LightClient.s.sol";
import { UpgradeLightClientScript } from "../script/UpgradeSameLightClient.s.sol";

contract LightClientUpgradeSameContractTest is Test {
LCV1 public lcV1Proxy;
LCV2 public lcV2Proxy;

DeployLightClientContractScript public deployer = new DeployLightClientContractScript();
UpgradeLightClientScript public upgrader = new UpgradeLightClientScript();

LCV1.LightClientState public stateV1;

address public admin;
address public proxy;

// deploy the first implementation with its proxy
function setUp() public {
(proxy, admin, stateV1) = deployer.run(10, 5);
lcV1Proxy = LCV1(proxy);
}

function testCorrectInitialization() public view {
assert(lcV1Proxy.blocksPerEpoch() == 10);
assert(lcV1Proxy.currentEpoch() == 0);

assertEq(abi.encode(lcV1Proxy.getGenesisState()), abi.encode(stateV1));

assertEq(abi.encode(lcV1Proxy.getFinalizedState()), abi.encode(stateV1));

bytes32 stakeTableComm = lcV1Proxy.computeStakeTableComm(stateV1);
assertEq(lcV1Proxy.votingStakeTableCommitment(), stakeTableComm);
assertEq(lcV1Proxy.frozenStakeTableCommitment(), stakeTableComm);
assertEq(lcV1Proxy.votingThreshold(), stateV1.threshold);
assertEq(lcV1Proxy.frozenThreshold(), stateV1.threshold);
}

// that the data remains the same after upgrading the implementation
function testUpgradeSameData() public {
// Upgrade LightClient and check that the genesis state is not changed and that the new
// field
// of the upgraded contract is set to 0
lcV2Proxy = LCV2(upgrader.run(0, proxy));

assertEq(lcV2Proxy.blocksPerEpoch(), 10);
assertEq(lcV2Proxy.currentEpoch(), 0);

LCV2.LightClientState memory expectedLightClientState = LCV2.LightClientState(
stateV1.viewNum,
stateV1.blockHeight,
stateV1.blockCommRoot,
stateV1.feeLedgerComm,
stateV1.stakeTableBlsKeyComm,
stateV1.stakeTableSchnorrKeyComm,
stateV1.stakeTableAmountComm,
stateV1.threshold
);

assertEq(abi.encode(lcV2Proxy.getFinalizedState()), abi.encode(expectedLightClientState));
}

// check that the proxy address remains the same
function testUpgradesSameProxyAddress() public {
(uint8 major, uint8 minor, uint8 patch) = lcV1Proxy.getVersion();
assertEq(major, 1);
assertEq(minor, 0);
assertEq(patch, 0);

//upgrade box
lcV2Proxy = LCV2(upgrader.run(0, proxy));
assertEq(address(lcV2Proxy), address(lcV1Proxy));
}

function testMaliciousUpgradeFails() public {
address attacker = makeAddr("attacker");

//attempted upgrade as attacker will revert
vm.prank(attacker);
vm.expectRevert();
lcV2Proxy = LCV2(upgrader.run(0, address(proxy)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { Test } /*, console2*/ from "forge-std/Test.sol";
import { LightClient as LCV1 } from "../src/LightClient.sol";
import { LightClientV2 as LCV2 } from "../test/LightClientV2.sol";
import { DeployLightClientContractScript } from "../script/LightClient.s.sol";
import { UpgradeLightClientScript } from "../script/UpgradeLightClient.s.sol";
import { UpgradeLightClientScript } from "../script/UpgradeLightClientToV2.s.sol";

contract LightClientUpgradeTest is Test {
contract LightClientUpgradeToV2Test is Test {
LCV1 public lcV1Proxy;
LCV2 public lcV2Proxy;

Expand Down

0 comments on commit 9e46a1c

Please sign in to comment.