Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ASR upgrade script #163

Merged
merged 5 commits into from
Jan 17, 2025
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

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

// Scripts
import {DeployUtils} from "scripts/libraries/DeployUtils.sol";

// Libraries
import {GameType, Hash, OutputRoot} from "src/dispute/lib/Types.sol";
// Contracts
import {StorageSetter} from "src/universal/StorageSetter.sol";

// Interfaces
import {IAnchorStateRegistry} from "interfaces/dispute/IAnchorStateRegistry.sol";
import {IDisputeGameFactory} from "interfaces/dispute/IDisputeGameFactory.sol";
import {IAnchorStateRegistry} from "interfaces/dispute/IAnchorStateRegistry.sol";
import {IProxyAdmin} from "interfaces/universal/IProxyAdmin.sol";
import {ISuperchainConfig} from "interfaces/L1/ISuperchainConfig.sol";

/// @title UpgradeAnchorStateRegistry
contract UpgradeAnchorStateRegistry is Script {
function run(
address _disputeGameFactoryProxy,
address _opChainProxyAdmin,
address _anchorStateRegistryProxy,
address _superchainConfig,
address _storageSetter,
uint32 _type,
uint256 _l2BlockNumber,
bytes32 _outputRoot
) public {
console.log("_disputeGameFactoryProxy: %s", _disputeGameFactoryProxy);
console.log("_opChainProxyAdmin: %s", _opChainProxyAdmin);
console.log("_anchorStateRegistryProxy: %s", _anchorStateRegistryProxy);
console.log("_superchainConfig: %s", _superchainConfig);
console.log("_storageSetter: %s", _storageSetter);
console.log("_type: %s", _type);
console.log("_l2BlockNumber: %s", _l2BlockNumber);
console.log("_outputRoot: %s", bytes32ToHex(_outputRoot));

vm.startBroadcast();
upgradeAnchorStateRegistryImpl(
IDisputeGameFactory(_disputeGameFactoryProxy),
IProxyAdmin(_opChainProxyAdmin),
IAnchorStateRegistry(_anchorStateRegistryProxy),
ISuperchainConfig(_superchainConfig),
_storageSetter,
GameType.wrap(_type),
_l2BlockNumber,
Hash.wrap(_outputRoot)
);
vm.stopBroadcast();
checkOutput(
IAnchorStateRegistry(_anchorStateRegistryProxy),
GameType.wrap(_type),
_l2BlockNumber,
Hash.wrap(_outputRoot)
);
dajuguan marked this conversation as resolved.
Show resolved Hide resolved
}

function upgradeAnchorStateRegistryImpl(
IDisputeGameFactory _disputeGameFactoryProxy,
IProxyAdmin _opChainProxyAdmin,
IAnchorStateRegistry _anchorStateRegistryProxy,
ISuperchainConfig _superchainConfig,
address _storageSetter,
GameType _type,
uint256 _l2BlockNumber,
Hash _outputRoot
) internal {
address anchorStateRegistryImpl = DeployUtils.create1({
_name: "AnchorStateRegistry",
_args: abi.encode(_disputeGameFactoryProxy)
});

if (_storageSetter == address(0)) {
_storageSetter = DeployUtils.create1({
_name: "StorageSetter",
_args: ""
});
}

bytes memory data;
data = encodeStorageSetterZeroOutInitializedSlot();
blockchaindevsh marked this conversation as resolved.
Show resolved Hide resolved
upgradeAndCall(
dajuguan marked this conversation as resolved.
Show resolved Hide resolved
_opChainProxyAdmin,
address(_anchorStateRegistryProxy),
_storageSetter,
data
);
data = encodeAnchorStateRegistryInitializer(
_type,
_l2BlockNumber,
_outputRoot,
_superchainConfig
);
upgradeAndCall(
_opChainProxyAdmin,
address(_anchorStateRegistryProxy),
anchorStateRegistryImpl,
data
);
}

function encodeStorageSetterZeroOutInitializedSlot()
internal
pure
returns (bytes memory)
{
return
abi.encodeWithSelector(
bytes4(keccak256("setBytes32(bytes32,bytes32)")),
0,
0
);
}

function encodeAnchorStateRegistryInitializer(
GameType _type,
uint256 _l2BlockNumber,
Hash _outputRoot,
ISuperchainConfig _superchainConfig
) internal view virtual returns (bytes memory) {
IAnchorStateRegistry.StartingAnchorRoot[]
memory startingAnchorRoots = new IAnchorStateRegistry.StartingAnchorRoot[](
1
);
startingAnchorRoots[0] = IAnchorStateRegistry.StartingAnchorRoot({
gameType: _type,
outputRoot: OutputRoot({
root: _outputRoot,
l2BlockNumber: _l2BlockNumber
})
});
return
abi.encodeWithSelector(
IAnchorStateRegistry.initialize.selector,
startingAnchorRoots,
_superchainConfig
);
}

/// @notice Makes an external call to the target to initialize the proxy with the specified data.
/// First performs safety checks to ensure the target, implementation, and proxy admin are valid.
function upgradeAndCall(
IProxyAdmin _proxyAdmin,
address _target,
address _implementation,
bytes memory _data
) internal {
DeployUtils.assertValidContractAddress(address(_proxyAdmin));
DeployUtils.assertValidContractAddress(_target);
DeployUtils.assertValidContractAddress(_implementation);

_proxyAdmin.upgradeAndCall(
payable(address(_target)),
_implementation,
_data
);
}

function checkOutput(
IAnchorStateRegistry _anchorStateRegistryProxy,
GameType _type,
uint256 _l2BlockNumber,
Hash _outputRoot
) public view {
(Hash root, uint256 l2BlockNumber) = IAnchorStateRegistry(
_anchorStateRegistryProxy
).anchors(_type);
require(
Hash.unwrap(root) == Hash.unwrap(_outputRoot),
"UpgradeAnchorStateRegistryOutput: root mismatch"
);
require(
l2BlockNumber == _l2BlockNumber,
"UpgradeAnchorStateRegistryOutput: l2BlockNumber mismatch"
);
}

function bytes32ToHex(bytes32 data) internal pure returns (string memory) {
bytes memory result = new bytes(64);
for (uint256 i = 0; i < 32; i++) {
uint8 byteValue = uint8(data[i]);
result[i * 2] = toHexChar(byteValue / 16);
result[i * 2 + 1] = toHexChar(byteValue % 16);
}
return string(result);
}

function toHexChar(uint8 b) internal pure returns (bytes1) {
return b < 10 ? bytes1(b + 0x30) : bytes1(b + 0x57);
}
}