Skip to content

Commit

Permalink
2436 deployment scripts for lightclientarbitrum upgrade scripts light…
Browse files Browse the repository at this point in the history
…client (#2449)

* Add LightClientArbitrum

* fix typos

* contract-bindings

* adding foundry script for deploying the light client arb and removing the updateStateHistory from Lightclient during the initialization step as precompiles cannot be called during a forge script deployment

* old broadcasts

* statehistory is not updated in the initialization steps because precompiles cannot be called during a forge script deploy

* remove disable initializer

* remove test, not sure of test aim

---------

Co-authored-by: Sneh Koul <snehkoul1999@gmail.com>
  • Loading branch information
alysiahuggins and Sneh1999 authored Jan 15, 2025
1 parent ea5d100 commit 6e1dc58
Show file tree
Hide file tree
Showing 15 changed files with 3,676 additions and 23 deletions.
1 change: 1 addition & 0 deletions .env.contracts.example
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export FEE_CONTRACT_ADDRESS=
# The etherscan API key is needed to verify contracts on etherscan.
export ETHERSCAN_API_KEY=
export SOLC_VERSION=
export ARBISCAN_API_KEY=

# foundry scripts
export DEPLOYER_PRIVATE_KEY= #include the 0x prefix
Expand Down
4 changes: 0 additions & 4 deletions .vscode/ltex.dictionary.en-US.txt

This file was deleted.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contract-bindings/artifacts/LightClientMock_bytecode.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contract-bindings/artifacts/LightClient_bytecode.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions contract-bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod erc1967_proxy;
pub mod fee_contract;
pub mod i_plonk_verifier;
pub mod light_client;
pub mod light_client_arbitrum;
pub mod light_client_mock;
pub mod light_client_state_update_vk;
pub mod light_client_state_update_vk_mock;
Expand Down
3,238 changes: 3,238 additions & 0 deletions contract-bindings/src/light_client_arbitrum.rs

Large diffs are not rendered by default.

263 changes: 263 additions & 0 deletions contracts/broadcast/LightClientArb.s.sol/421614/run-latest.json

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions contracts/broadcast/PlonkVerifier.s.sol/421614/run-latest.json

Large diffs are not rendered by default.

85 changes: 85 additions & 0 deletions contracts/script/LightClientArb.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import { Script } from "forge-std/Script.sol";
import { LightClientArbitrum } from "../src/LightClientArbitrum.sol";
import { LightClient as LC } from "../src/LightClient.sol";
import { Upgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol";

contract DeployLightClientArbitrum is Script {
// Deployment Errors
error SetPermissionedProverFailed();
error OwnerTransferFailed();
error RetentionPeriodIsNotSetCorrectly();
error InitialStateIsNotSetCorrectly();

function run(uint32 numInitValidators, uint32 stateHistoryRetentionPeriod, address owner)
public
returns (
address proxyAddress,
address implementationAddress,
LC.LightClientState memory lightClientState
)
{
address deployer;

string memory ledgerCommand = vm.envString("USE_HARDWARE_WALLET");
if (keccak256(bytes(ledgerCommand)) == keccak256(bytes("true"))) {
deployer = vm.envAddress("DEPLOYER_HARDWARE_WALLET_ADDRESS");
} else {
// get the deployer info from the environment
string memory seedPhrase = vm.envString("DEPLOYER_MNEMONIC");
uint32 seedPhraseOffset = uint32(vm.envUint("DEPLOYER_MNEMONIC_OFFSET"));
(deployer,) = deriveRememberKey(seedPhrase, seedPhraseOffset);
}

vm.startBroadcast(deployer);

string[] memory cmds = new string[](3);
cmds[0] = "diff-test";
cmds[1] = "mock-genesis";
cmds[2] = vm.toString(uint256(numInitValidators));

bytes memory result = vm.ffi(cmds);
(LC.LightClientState memory state, LC.StakeTableState memory stakeState) =
abi.decode(result, (LC.LightClientState, LC.StakeTableState));

proxyAddress = Upgrades.deployUUPSProxy(
"LightClientArbitrum.sol:LightClientArbitrum",
abi.encodeCall(
LC.initialize, (state, stakeState, stateHistoryRetentionPeriod, deployer)
)
);

LightClientArbitrum lightClientArbitrumProxy = LightClientArbitrum(proxyAddress);

// Currently, the light client is in prover mode so set the permissioned prover
address permissionedProver = vm.envAddress("PERMISSIONED_PROVER_ADDRESS");
lightClientArbitrumProxy.setPermissionedProver(permissionedProver);

// transfer ownership to the multisig
lightClientArbitrumProxy.transferOwnership(owner);

// verify post deployment details
if (lightClientArbitrumProxy.permissionedProver() != permissionedProver) {
revert SetPermissionedProverFailed();
}
if (lightClientArbitrumProxy.owner() != owner) revert OwnerTransferFailed();
if (lightClientArbitrumProxy.stateHistoryRetentionPeriod() != stateHistoryRetentionPeriod) {
revert RetentionPeriodIsNotSetCorrectly();
}
if (lightClientArbitrumProxy.stateHistoryFirstIndex() != 0) {
revert InitialStateIsNotSetCorrectly();
}
if (lightClientArbitrumProxy.getStateHistoryCount() != 0) {
revert InitialStateIsNotSetCorrectly();
}

// Get the implementation address
implementationAddress = Upgrades.getImplementationAddress(proxyAddress);

vm.stopBroadcast();

return (proxyAddress, implementationAddress, state);
}
}
2 changes: 1 addition & 1 deletion contracts/script/PlonkVerifier.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ pragma solidity ^0.8.20;
import { Script } from "forge-std/Script.sol";

import { Options, Upgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol";

/// @notice Deploys an upgradeable Plonk Verifier Contract using the OpenZeppelin Upgrades plugin.
/// @dev The Upgrades library has a deployImplementation function which is used here

contract DeployPlonkVerifierScript is Script {
string public contractName = "PlonkVerifier.sol";

Expand Down
19 changes: 19 additions & 0 deletions contracts/script/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,3 +368,22 @@ This error occurs when build_info is set to true in the foundry.toml configurati
foundry profile is set to default when running commands like `just gen-bindings`.
Solution: `export FOUNDRY_PROFILE=default`
## Deploy LightClientArbitrum
Additional Pre-requisites:
- an API key from arbiscan to verify the contract.
```bash
source .env.contracts && \
forge clean && \
forge script contracts/script/LightClientArb.s.sol:DeployLightClientArbitrum $NUM_INIT_VALIDATORS $STATE_HISTORY_RETENTION_PERIOD $SAFE_MULTISIG_ADDRESS \
--sig 'run(uint32, uint32, address)' \
--ffi \
--rpc-url $RPC_URL \
--libraries contracts/src/libraries/PlonkVerifier.sol:PlonkVerifier:$PLONK_VERIFIER_ADDRESS \
--build-info true \
--verify --etherscan-api-key $ARBISCAN_API_KEY \
--broadcast
```
2 changes: 0 additions & 2 deletions contracts/src/LightClient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,6 @@ contract LightClient is Initializable, OwnableUpgradeable, UUPSUpgradeable {
finalizedState = _genesis;

stateHistoryRetentionPeriod = _stateHistoryRetentionPeriod;

updateStateHistory(uint64(currentBlockNumber()), uint64(block.timestamp), _genesis);
}

// === State Modifying APIs ===
Expand Down
23 changes: 10 additions & 13 deletions contracts/test/LightClient.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,9 @@ contract LightClient_StateUpdatesTest is LightClientCommonTest {
lc.newFinalizedState(states[i], proofs[i]);
}

// assert that the size of the state history is equal to the retention period
assertEq(lc.getStateHistoryCount(), numDays);

// the number of elements are equal to the max state history so the first index would
// be 0
assertEq(lc.stateHistoryFirstIndex(), 0);
Expand All @@ -708,14 +711,18 @@ contract LightClient_StateUpdatesTest is LightClientCommonTest {
vm.prank(permissionedProver);
vm.expectEmit(true, true, true, true);
emit LC.NewState(states[i].viewNum, states[i].blockHeight, states[i].blockCommRoot);
vm.warp(initialBlockTimestamp + ((i + 1) * 1 days)); // increase the timestamp for each
vm.warp((numDays + 3) * 1 days); // increase the timestamp
lc.newFinalizedState(states[i], proofs[i]);
i++;

// the duration between the updates are more than stateHistoryRetentionPeriod, so the first
// index should be one
assertEq(lc.stateHistoryFirstIndex(), 1);

// assert that the first state commitment is zero as it would have been deleted
(, uint256 blocktimestamp,,) = lc.stateHistoryCommitments(0);
assertEq(blocktimestamp, 0);

// continue updating the state
for (uint256 j = i; j < states.length; j++) {
vm.warp(initialBlockTimestamp + ((j + 1) * 1 days)); // increase the timestamp for each
Expand Down Expand Up @@ -822,8 +829,8 @@ contract LightClient_StateUpdatesTest is LightClientCommonTest {
}

function test_revertWhenBlockNumberTooHigh() public {
//assert that there is a state history
assertGt(lc.getStateHistoryCount(), 0);
// assert that there isn't a state history when the light client is first initialized
assertEq(lc.getStateHistoryCount(), 0);

vm.expectRevert(LC.InsufficientSnapshotHistory.selector);
lc.lagOverEscapeHatchThreshold(block.number + 10, 5); // No updates exist in history
Expand Down Expand Up @@ -1072,14 +1079,4 @@ contract LightClient_HotShotCommUpdatesTest is LightClientCommonTest {
assertEqBN254(hotShotBlockComm, blockComm);
assertEq(hotShotBlockHeight, blockHeight);
}

function test_revertWhenGetHotShotCommitmentInvalidHeight() public {
// Get the highest HotShot blockheight recorded
uint256 numCommitments = lc.getStateHistoryCount();
(,, uint64 blockHeight,) = lc.stateHistoryCommitments(numCommitments - 1);
// Expect revert when attempting to retrieve a block height higher than the highest one
// recorded
vm.expectRevert(LC.InvalidHotShotBlockForCommitmentCheck.selector);
lc.getHotShotCommitment(blockHeight + 1);
}
}
3 changes: 2 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ build-docker-images:
scripts/build-docker-images-native

# generate rust bindings for contracts
REGEXP := "^LightClient$|^LightClientStateUpdateVK$|^FeeContract$|PlonkVerifier$|^ERC1967Proxy$|^LightClientMock$|^LightClientStateUpdateVKMock$|^PlonkVerifier2$|^PermissionedStakeTable$"
REGEXP := "^LightClient$|^LightClientArbitrum$|^LightClientStateUpdateVK$|^FeeContract$|PlonkVerifier$|^ERC1967Proxy$|^LightClientMock$|^LightClientStateUpdateVKMock$|^PlonkVerifier2$|^PermissionedStakeTable$"
gen-bindings:
forge bind --contracts ./contracts/src/ --crate-name contract-bindings --bindings-path contract-bindings --select "{{REGEXP}}" --overwrite --force

Expand All @@ -111,6 +111,7 @@ gen-bindings:
# date, without needed to recompile the contracts.
mkdir -p contract-bindings/artifacts
jq '.bytecode.object' < contracts/out/LightClient.sol/LightClient.json > contract-bindings/artifacts/LightClient_bytecode.json
jq '.bytecode.object' < contracts/out/LightClientArbitrum.sol/LightClientArbitrum.json > contract-bindings/artifacts/LightClientArbitrum_bytecode.json
jq '.bytecode.object' < contracts/out/LightClientMock.sol/LightClientMock.json > contract-bindings/artifacts/LightClientMock_bytecode.json

cargo fmt --all
Expand Down

0 comments on commit 6e1dc58

Please sign in to comment.