We have prepared a set of scripts to deploy all contracts in one click. Otherwise, you can look into and customize each contract as you like.
we reference to OPStack 's version of v1.9.4
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"AddressManager": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>"
}
Without this artifact file, the next deployment scripts can not be run.
Note: This script is not completed yet. It is for one layer only. Check our final script for full deployment.
forge script script/000_DeployAllScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeploySafeProxyScript} from "@scripts/101_DeploySafeProxyScript.s.sol";
import {Script} from "@redprint-forge-std/Script.sol";
import {SetupOpAltDAScript} from "@scripts/300_SetupOpAltDAScript.s.sol";
import {SetupSuperchainScript} from "@scripts/200_SetupSuperchain.s.sol";
contract DeployAllScript is Script {
function run() public {
DeploySafeProxyScript safeDeployments = new DeploySafeProxyScript();
//1) set up Safe Multisig
safeDeployments.deploy();
SetupSuperchainScript superchainSetups = new SetupSuperchainScript();
superchainSetups.run();
SetupOpAltDAScript opAltDASetups = new SetupOpAltDAScript();
opAltDASetups.run();
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployAndInitializeDataAvailabilityChallengeScript} from "@scripts/301B_DeployAndInitializeDataAvailabilityChallengeScript.s.sol";
import {DeployDataAvailabilityChallengeProxyScript} from "@scripts/301A_DeployDataAvailabilityChallengeProxyScript.s.sol";
import {IDeployer, getDeployer} from "@redprint-deploy/deployer/DeployScript.sol";
import {Script} from "@redprint-forge-std/Script.sol";
import {console} from "@redprint-forge-std/console.sol";
contract SetupOpAltDAScript is Script {
IDeployer deployerProcedue;
function run() public {
deployerProcedue = getDeployer();
deployerProcedue.setAutoSave(true);
console.log("Setup Op Alt DA ... ");
DeployDataAvailabilityChallengeProxyScript dataAvailabilityChallengeProxyDeployments = new DeployDataAvailabilityChallengeProxyScript();
DeployAndInitializeDataAvailabilityChallengeScript dataAvailabilityChallengeDeployments = new DeployAndInitializeDataAvailabilityChallengeScript();
dataAvailabilityChallengeProxyDeployments.deploy();
dataAvailabilityChallengeDeployments.deploy();
dataAvailabilityChallengeDeployments.initialize();
console.log("DataAvailabilityChallengeProxy at: ", deployerProcedue.getAddress("DataAvailabilityChallengeProxy"));
console.log("DataAvailabilityChallenge at: ", deployerProcedue.getAddress("DataAvailabilityChallenge"));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"AddressManager": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
"DataAvailabilityChallenge": "<ADDRESS_11>" // optional
}
click on ✕ button to close
3.1A : Deploy DataAvailabilityChallengeProxy Contract
forge script script/301A_DeployDataAvailabilityChallengeProxyScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Constants} from "@redprint-core/libraries/Constants.sol";
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/4/packages/contracts-bedrock/src/universal/Proxy.sol
contract Proxy {
/**
* @notice An event that is emitted each time the implementation is changed. This event is part
* of the EIP-1967 specification.
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation);
/**
* @notice An event that is emitted each time the owner is upgraded. This event is part of the
* EIP-1967 specification.
*
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin);
modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
constructor(address _admin) {
_changeAdmin(_admin);
}
receive() external payable {
// Proxy call by default.
_doProxyCall();
}
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
function upgradeTo(address _implementation)
public
virtual
returns (proxyCallIfNotAdmin)
{
_setImplementation(_implementation);
}
function upgradeToAndCall(address _implementation, bytes calldata _data)
public
payable virtual proxyCallIfNotAdmin
returns (bytes memory)
{
_setImplementation(_implementation);
(bool success, bytes memory returndata) = _implementation.delegatecall(_data);
require(success, "Proxy: delegatecall to new implementation contract failed");
return returndata;
}
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin);
}
function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin();
}
function implementation()
public
virtual proxyCallIfNotAdmin
returns (address)
{
return _getImplementation();
}
function _setImplementation(address _implementation) internal {
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
sstore(proxyImplementation, _implementation)
}
emit Upgraded(_implementation);
}
function _changeAdmin(address _admin) internal {
address previous = _getAdmin();
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
sstore(proxyOwner, _admin)
}
emit AdminChanged(previous, _admin);
}
function _doProxyCall() internal {
address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) { revert(0x0, returndatasize()) }
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
function _getImplementation() internal view returns (address) {
address impl;
bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS;
assembly {
impl := sload(proxyImplementation)
}
return impl;
}
function _getAdmin() internal view returns (address) {
address owner;
bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS;
assembly {
owner := sload(proxyOwner)
}
return owner;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DeployScript} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, IDeployer} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {Proxy} from "@redprint-core/universal/Proxy.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployDataAvailabilityChallengeProxyScript is DeployScript {
using DeployerFunctions for IDeployer ;
function deploy() external returns (Proxy) {
address proxyOwner = deployer.mustGetAddress("ProxyAdmin");
return Proxy(deployer.deploy_ERC1967Proxy("DataAvailabilityChallengeProxy", proxyOwner));
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"AddressManager": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional
}
click on ✕ button to close
3.1B : Deploy and Initialize DataAvailabilityChallenge Contract
forge script script/301B_DeployAndInitializeDataAvailabilityChallengeScript.s.sol --trezor --sender <DEPLOYER_ADDRESS> --rpc-url <RPC_URL> --broadcast
--mnemonic-derivation-paths "m/44'/60'/0'/0/0"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {ISemver} from "@redprint-core/universal/interfaces/ISemver.sol";
import {OwnableUpgradeable} from "@redprint-openzeppelin-upgradeable/access/OwnableUpgradeable.sol";
import {SafeCall} from "@redprint-core/libraries/SafeCall.sol";
/// @dev An enum representing the status of a DA challenge.
enum ChallengeStatus {
Uninitialized,
Active,
Resolved,
Expired
}
/// @dev An enum representing known commitment types.
enum CommitmentType {
Keccak256
}
/// @dev A struct representing a single DA challenge.
/// @custom:field status The status of the challenge.
/// @custom:field challenger The address that initiated the challenge.
/// @custom:field startBlock The block number at which the challenge was initiated.
struct Challenge {
address challenger;
uint256 lockedBond;
uint256 startBlock;
uint256 resolvedBlock;
}
/// @notice Compute the expected commitment for a given blob of data.
/// @param _data The blob of data to compute a commitment for.
/// @return The commitment for the given blob of data.
function computeCommitmentKeccak256(bytes memory _data) pure returns (bytes memory) {
return bytes.concat(bytes1(uint8(CommitmentType.Keccak256)), keccak256(_data));
}
/// @custom:security-contact Consult full code at https://github.com/ethereum-optimism/optimism/blob/v1.9.4/packages/contracts-bedrock/src/L1/DataAvailabilityChallenge.sol
contract DataAvailabilityChallenge is OwnableUpgradeable {
/// @notice Error for when the provided resolver refund percentage exceeds 100%.
error InvalidResolverRefundPercentage(uint256 invalidResolverRefundPercentage);
/// @notice Error for when the challenger's bond is too low.
error BondTooLow(uint256 balance, uint256 required);
/// @notice Error for when attempting to challenge a commitment that already has a challenge.
error ChallengeExists();
/// @notice Error for when attempting to resolve a challenge that is not active.
error ChallengeNotActive();
/// @notice Error for when attempting to unlock a bond from a challenge that is not expired.
error ChallengeNotExpired();
/// @notice Error for when attempting to challenge a commitment that is not in the challenge window.
error ChallengeWindowNotOpen();
/// @notice Error for when the provided input data doesn't match the commitment.
error InvalidInputData(bytes providedDataCommitment, bytes expectedCommitment);
/// @notice Error for when the call to withdraw a bond failed.
error WithdrawalFailed();
/// @notice Error for when a the type of a given commitment is unknown
error UnknownCommitmentType(uint8 commitmentType);
/// @notice Error for when the commitment length does not match the commitment type
error InvalidCommitmentLength(uint8 commitmentType, uint256 expectedLength, uint256 actualLength);
/// @notice An event that is emitted when the status of a challenge changes.
/// @param challengedCommitment The commitment that is being challenged.
/// @param challengedBlockNumber The block number at which the commitment was made.
/// @param status The new status of the challenge.
event ChallengeStatusChanged(
uint256 indexed challengedBlockNumber, bytes challengedCommitment, ChallengeStatus status
);
/// @notice An event that is emitted when the bond size required to initiate a challenge changes.
event RequiredBondSizeChanged(uint256 challengeWindow);
/// @notice An event that is emitted when the percentage of the resolving cost to be refunded to the resolver
/// changes.
event ResolverRefundPercentageChanged(uint256 resolverRefundPercentage);
/// @notice An event that is emitted when a user's bond balance changes.
event BalanceChanged(address account, uint256 balance);
/// @notice Semantic version.
/// @custom:semver 1.0.1-beta.2
string public constant version = "1.0.1-beta.2";
/// @notice The fixed cost of resolving a challenge.
/// @dev The value is estimated by measuring the cost of resolving with 'bytes(0)'
uint256 public constant fixedResolutionCost = 72925;
/// @notice The variable cost of resolving a callenge per byte scaled by the variableResolutionCostPrecision.
/// @dev upper limit; The value is estimated by measuring the cost of resolving with variable size data where each
/// byte is non-zero.
uint256 public constant variableResolutionCost = 16640;
/// @dev The precision of the variable resolution cost.
uint256 public constant variableResolutionCostPrecision = 1000;
/// @notice The block interval during which a commitment can be challenged.
uint256 public challengeWindow;
/// @notice The block interval during which a challenge can be resolved.
uint256 public resolveWindow;
/// @notice The amount required to post a challenge.
uint256 public bondSize;
/// @notice The percentage of the resolving cost to be refunded to the resolver.
/// @dev There are no decimals, ie a value of 50 corresponds to 50%.
uint256 public resolverRefundPercentage;
/// @notice A mapping from addresses to their bond balance in the contract.
mapping(address => uint256) public balances;
/// @notice A mapping from challenged block numbers to challenged commitments to challenges.
mapping(uint256 => mapping(bytes => Challenge)) internal challenges;
constructor() OwnableUpgradeable() {
initialize({
_owner: address(0xdEaD),
_challengeWindow: 0,
_resolveWindow: 0,
_bondSize: 0,
_resolverRefundPercentage: 0
});
}
receive() external payable {
deposit();
}
function initialize(address _owner, uint256 _challengeWindow, uint256 _resolveWindow, uint256 _bondSize, uint256 _resolverRefundPercentage)
public
initializer
{
__Ownable_init();
challengeWindow = _challengeWindow;
resolveWindow = _resolveWindow;
setBondSize(_bondSize);
setResolverRefundPercentage(_resolverRefundPercentage);
_transferOwnership(_owner);
}
function setBondSize(uint256 _bondSize) public onlyOwner {
bondSize = _bondSize;
emit RequiredBondSizeChanged(_bondSize);
}
function setResolverRefundPercentage(uint256 _resolverRefundPercentage)
public
onlyOwner
{
if (_resolverRefundPercentage > 100) {
revert InvalidResolverRefundPercentage(_resolverRefundPercentage);
}
resolverRefundPercentage = _resolverRefundPercentage;
}
function deposit() public payable {
balances[msg.sender] += msg.value;
emit BalanceChanged(msg.sender, balances[msg.sender]);
}
function withdraw() external {
// get caller's balance
uint256 balance = balances[msg.sender];
// set caller's balance to 0
balances[msg.sender] = 0;
emit BalanceChanged(msg.sender, 0);
// send caller's balance to caller
bool success = SafeCall.send(msg.sender, gasleft(), balance);
if (!success) {
revert WithdrawalFailed();
}
}
function _isInChallengeWindow(uint256 _challengedBlockNumber)
internal
view
returns (bool)
{
return (block.number >= _challengedBlockNumber && block.number <= _challengedBlockNumber + challengeWindow);
}
function _isInResolveWindow(uint256 _challengeStartBlockNumber)
internal
view
returns (bool)
{
return block.number <= _challengeStartBlockNumber + resolveWindow;
}
function getChallenge(uint256 _challengedBlockNumber, bytes calldata _challengedCommitment)
public
view
returns (Challenge memory)
{
return challenges[_challengedBlockNumber][_challengedCommitment];
}
function getChallengeStatus(uint256 _challengedBlockNumber, bytes calldata _challengedCommitment)
public
view
returns (ChallengeStatus)
{
Challenge memory _challenge = challenges[_challengedBlockNumber][_challengedCommitment];
// if the address is 0, the challenge is uninitialized
if (_challenge.challenger == address(0)) return ChallengeStatus.Uninitialized;
// if the challenge has a resolved block, it is resolved
if (_challenge.resolvedBlock != 0) return ChallengeStatus.Resolved;
// if the challenge's start block is in the resolve window, it is active
if (_isInResolveWindow(_challenge.startBlock)) return ChallengeStatus.Active;
// if the challenge's start block is not in the resolve window, it is expired
return ChallengeStatus.Expired;
}
function _getCommitmentType(bytes calldata _commitment)
internal
pure
returns (uint8)
{
return uint8(bytes1(_commitment));
}
function validateCommitment(bytes calldata _commitment) public pure {
uint8 commitmentType = _getCommitmentType(_commitment);
if (commitmentType == uint8(CommitmentType.Keccak256)) {
if (_commitment.length != 33) {
revert InvalidCommitmentLength(uint8(CommitmentType.Keccak256), 33, _commitment.length);
}
return;
}
revert UnknownCommitmentType(commitmentType);
}
function challenge(uint256 _challengedBlockNumber, bytes calldata _challengedCommitment)
external payable
{
// require the commitment type to be known
validateCommitment(_challengedCommitment);
// deposit value sent with the transaction as bond
deposit();
// require the caller to have a bond
if (balances[msg.sender] < bondSize) {
revert BondTooLow(balances[msg.sender], bondSize);
}
// require the challenge status to be uninitialized
if (getChallengeStatus(_challengedBlockNumber, _challengedCommitment) != ChallengeStatus.Uninitialized) {
revert ChallengeExists();
}
// require the current block to be in the challenge window
if (!_isInChallengeWindow(_challengedBlockNumber)) {
revert ChallengeWindowNotOpen();
}
// reduce the caller's balance
balances[msg.sender] -= bondSize;
// store the challenger's address, bond size, and start block of the challenge
challenges[_challengedBlockNumber][_challengedCommitment] =
Challenge({ challenger: msg.sender, lockedBond: bondSize, startBlock: block.number, resolvedBlock: 0 });
// emit an event to notify that the challenge status is now active
emit ChallengeStatusChanged(_challengedBlockNumber, _challengedCommitment, ChallengeStatus.Active);
}
function resolve(uint256 _challengedBlockNumber, bytes calldata _challengedCommitment, bytes calldata _resolveData)
external
{
// require the commitment type to be known
validateCommitment(_challengedCommitment);
// require the challenge to be active (started, not resolved, and resolve window still open)
if (getChallengeStatus(_challengedBlockNumber, _challengedCommitment) != ChallengeStatus.Active) {
revert ChallengeNotActive();
}
// compute the commitment corresponding to the given resolveData
uint8 commitmentType = _getCommitmentType(_challengedCommitment);
bytes memory computedCommitment;
if (commitmentType == uint8(CommitmentType.Keccak256)) {
computedCommitment = computeCommitmentKeccak256(_resolveData);
}
// require the provided input data to correspond to the challenged commitment
if (keccak256(computedCommitment) != keccak256(_challengedCommitment)) {
revert InvalidInputData(computedCommitment, _challengedCommitment);
}
// store the block number at which the challenge was resolved
Challenge storage activeChallenge = challenges[_challengedBlockNumber][_challengedCommitment];
activeChallenge.resolvedBlock = block.number;
// emit an event to notify that the challenge status is now resolved
emit ChallengeStatusChanged(_challengedBlockNumber, _challengedCommitment, ChallengeStatus.Resolved);
// distribute the bond among challenger, resolver and address(0)
_distributeBond(activeChallenge, _resolveData.length, msg.sender);
}
function _distributeBond(Challenge storage _resolvedChallenge, uint256 _preImageLength, address _resolver)
internal
{
uint256 lockedBond = _resolvedChallenge.lockedBond;
address challenger = _resolvedChallenge.challenger;
// approximate the cost of resolving a challenge with the provided pre-image size
uint256 resolutionCost = (
fixedResolutionCost + _preImageLength * variableResolutionCost / variableResolutionCostPrecision
) * block.basefee;
// refund bond exceeding the resolution cost to the challenger
if (lockedBond > resolutionCost) {
balances[challenger] += lockedBond - resolutionCost;
lockedBond = resolutionCost;
emit BalanceChanged(challenger, balances[challenger]);
}
// refund a percentage of the resolution cost to the resolver (but not more than the locked bond)
uint256 resolverRefund = resolutionCost * resolverRefundPercentage / 100;
if (resolverRefund > lockedBond) {
resolverRefund = lockedBond;
}
if (resolverRefund > 0) {
balances[_resolver] += resolverRefund;
lockedBond -= resolverRefund;
emit BalanceChanged(_resolver, balances[_resolver]);
}
// burn the remaining bond
if (lockedBond > 0) {
payable(address(0)).transfer(lockedBond);
}
_resolvedChallenge.lockedBond = 0;
}
function unlockBond(uint256 _challengedBlockNumber, bytes calldata _challengedCommitment)
external
{
// require the challenge to be active (started, not resolved, and in the resolve window)
if (getChallengeStatus(_challengedBlockNumber, _challengedCommitment) != ChallengeStatus.Expired) {
revert ChallengeNotExpired();
}
// Unlock the bond associated with the challenge
Challenge storage expiredChallenge = challenges[_challengedBlockNumber][_challengedCommitment];
balances[expiredChallenge.challenger] += expiredChallenge.lockedBond;
expiredChallenge.lockedBond = 0;
// Emit balance update event
emit BalanceChanged(expiredChallenge.challenger, balances[expiredChallenge.challenger]);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {DataAvailabilityChallenge} from "@redprint-core/L1/DataAvailabilityChallenge.sol";
import {DeployConfig} from "@redprint-deploy/deployer/DeployConfig.s.sol";
import {DeployScript, IDeployer} from "@redprint-deploy/deployer/DeployScript.sol";
import {DeployerFunctions, DeployOptions} from "@redprint-deploy/deployer/DeployerFunctions.sol";
import {SafeScript} from "@redprint-deploy/safe-management/SafeScript.sol";
import {Vm, VmSafe} from "@redprint-forge-std/Vm.sol";
import {console} from "@redprint-forge-std/console.sol";
/// @custom:security-contact Consult full internal deploy script at https://github.com/Ratimon/redprint-forge
contract DeployAndInitializeDataAvailabilityChallengeScript is DeployScript, SafeScript {
using DeployerFunctions for IDeployer ;
DataAvailabilityChallenge dataAvailabilityChallenge;
string mnemonic = vm.envString("MNEMONIC");
uint256 ownerPrivateKey = vm.deriveKey(mnemonic, "m/44'/60'/0'/0/", 1);
address owner = vm.envOr("DEPLOYER_ADDRESS", vm.addr(ownerPrivateKey));
function deploy() external returns (DataAvailabilityChallenge) {
bytes32 _salt = DeployScript.implSalt();
DeployOptions memory options = DeployOptions({salt:_salt});
dataAvailabilityChallenge = deployer.deploy_DataAvailabilityChallenge("DataAvailabilityChallenge", options);
return dataAvailabilityChallenge;
}
function initialize() external {
(VmSafe.CallerMode mode ,address msgSender, ) = vm.readCallers();
if(mode != VmSafe.CallerMode.Broadcast && msgSender != owner) {
console.log("Pranking owner ...");
vm.startPrank(owner);
initializeDataAvailabilityChallenge();
vm.stopPrank();
} else {
console.log("Broadcasting ...");
vm.startBroadcast(owner);
initializeDataAvailabilityChallenge();
console.log("DataAvailabilityChallenge setted to : %s", address(dataAvailabilityChallenge));
vm.stopBroadcast();
}
}
function initializeDataAvailabilityChallenge() public {
console.log("Upgrading and initializing DataAvailabilityChallenge proxy");
address proxyAdmin = deployer.mustGetAddress("ProxyAdmin");
address safe = deployer.mustGetAddress("SystemOwnerSafe");
address dataAvailabilityChallengeProxy = deployer.mustGetAddress("DataAvailabilityChallengeProxy");
DeployConfig cfg = deployer.getConfig();
address finalSystemOwner = cfg.finalSystemOwner();
uint256 daChallengeWindow = cfg.daChallengeWindow();
uint256 daResolveWindow = cfg.daResolveWindow();
uint256 daBondSize = cfg.daBondSize();
uint256 daResolverRefundPercentage = cfg.daResolverRefundPercentage();
_upgradeAndCallViaSafe({
_proxyAdmin: proxyAdmin,
_safe: safe,
_owner: owner,
_proxy: payable(dataAvailabilityChallengeProxy),
_implementation: address(dataAvailabilityChallenge),
_innerCallData: abi.encodeCall(
DataAvailabilityChallenge.initialize,
(finalSystemOwner, daChallengeWindow, daResolveWindow, daBondSize, daResolverRefundPercentage)
)
});
DataAvailabilityChallenge dac = DataAvailabilityChallenge(payable(dataAvailabilityChallengeProxy));
string memory version = dac.version();
console.log("DataAvailabilityChallenge version: %s", version);
require(dac.owner() == finalSystemOwner);
require(dac.challengeWindow() == daChallengeWindow);
require(dac.resolveWindow() == daResolveWindow);
require(dac.bondSize() == daBondSize);
require(dac.resolverRefundPercentage() == daResolverRefundPercentage);
}
}
After running the deploy script, the address deployed is saved at deployments/31337/.save.json. Otherwise, as specified in .env.<network>.local.
Your saved address will be different.
You can change DEPLOYMENT_OUTFILE=deployments/31337/.save.json to reflect yours!
{
"SafeProxyFactory": "<ADDRESS_1>",
"SafeSingleton": "<ADDRESS_2>",
"SystemOwnerSafe": "<ADDRESS_3>",
"AddressManager": "<ADDRESS_4>",
"ProxyAdmin": "<ADDRESS_5>",
"SuperchainConfigProxy": "<ADDRESS_6>",
"SuperchainConfig": "<ADDRESS_7>",
"ProtocolVersionsProxy": "<ADDRESS_8>",
"ProtocolVersions": "<ADDRESS_9>",
"DataAvailabilityChallengeProxy": "<ADDRESS_10>", // optional,
"DataAvailabilityChallenge": "<ADDRESS_11>" // optional
}
click on ✕ button to close