Skip to content
Merged
Show file tree
Hide file tree
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
13 changes: 13 additions & 0 deletions .github/workflows/docker-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,16 @@ jobs:
file: docker/Dockerfile.gen-configs
tags: |
${{ env.REPOSITORY }}:gen-configs-${{ github.sha }}

- name: Build verify image
id: build_verify_image
env:
REPOSITORY: scrolltech/scroll-stack-contracts
uses: docker/build-push-action@v3
with:
platforms: linux/amd64,linux/arm64
push: true
context: .
file: docker/Dockerfile.verify
tags: |
${{ env.REPOSITORY }}:verify-${{ github.sha }}
2 changes: 1 addition & 1 deletion docker/Dockerfile.deploy
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ RUN curl -L https://foundry.paradigm.xyz | bash
ENV PATH="/root/.foundry/bin:${PATH}"

# Run foundryup to update Foundry
RUN foundryup -v nightly-56dbd20c7179570c53b6c17ff34daa7273a4ddae
RUN foundryup -v nightly-fdd321bac95f0935529164a88faf99d4d5cfa321

# copy dependencies
COPY ./lib /contracts/lib
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.gen-configs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ RUN curl -L https://foundry.paradigm.xyz | bash
ENV PATH="/root/.foundry/bin:${PATH}"

# Run foundryup to update Foundry
RUN foundryup -v nightly-56dbd20c7179570c53b6c17ff34daa7273a4ddae
RUN foundryup -v nightly-fdd321bac95f0935529164a88faf99d4d5cfa321

# copy dependencies
COPY ./lib /contracts/lib
Expand Down
45 changes: 45 additions & 0 deletions docker/Dockerfile.verify
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Use the latest node Debian slim base image
# This makes installing yarn dep much easier
FROM node:20-bookworm-slim

# Switch to bash shell
SHELL ["/bin/bash", "-c"]

WORKDIR /root

# Install dependencies
RUN apt update
RUN apt install --yes curl bash coreutils git jq ca-certificates

# Download and run the Foundry installation script
RUN curl -L https://foundry.paradigm.xyz | bash

# Set the environment variables to ensure Foundry tools are in the PATH
ENV PATH="/root/.foundry/bin:${PATH}"

# Run foundryup to update Foundry
RUN foundryup -v nightly-fdd321bac95f0935529164a88faf99d4d5cfa321

# copy dependencies
COPY ./lib /contracts/lib
COPY ./node_modules/@openzeppelin /contracts/node_modules/@openzeppelin
COPY ./node_modules/hardhat /contracts/node_modules/hardhat

# copy configurations
COPY foundry.toml /contracts/foundry.toml
COPY remappings.txt /contracts/remappings.txt

# copy source code
COPY ./src /contracts/src
COPY ./scripts /contracts/scripts

# compile contracts
ENV FOUNDRY_EVM_VERSION="cancun"
ENV FOUNDRY_BYTECODE_HASH="none"

WORKDIR /contracts
RUN forge build

COPY ./docker/scripts/verify.sh /contracts/docker/scripts/verify.sh

ENTRYPOINT ["/bin/bash", "/contracts/docker/scripts/verify.sh"]
10 changes: 10 additions & 0 deletions docker/config-example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ L2_WHITELIST = "0x5300000000000000000000000000000000000003"
L2_WETH = "0x5300000000000000000000000000000000000004"
L2_TX_FEE_VAULT = "0x5300000000000000000000000000000000000005"

[contracts.verify]

VERIFIER_TYPE_L1 = "blockscout"
VERIFIER_TYPE_L2 = "blockscout"
EXPLORER_URI_L1 = "http://l1-explorer.scrollsdk"
EXPLORER_URI_L2 = "http://blockscout.scrollsdk"
RPC_URI_L1 = "http://l1-devnet.scrollsdk"
RPC_URI_L2 = "http://l2-rpc.scrollsdk"
EXPLORER_API_KEY_L1 = ""
EXPLORER_API_KEY_L2 = ""

[coordinator]

Expand Down
150 changes: 150 additions & 0 deletions docker/scripts/verify.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#!/bin/sh

# extract values from config file
config_file="./volume/config.toml"
CHAIN_ID_L1=$(grep -E "^CHAIN_ID_L1 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2-)
CHAIN_ID_L2=$(grep -E "^CHAIN_ID_L2 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2-)
RPC_URI_L1=$(grep -E "^RPC_URI_L1 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
RPC_URI_L2=$(grep -E "^RPC_URI_L2 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
VERIFIER_TYPE_L1=$(grep -E "^VERIFIER_TYPE_L1 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
VERIFIER_TYPE_L2=$(grep -E "^VERIFIER_TYPE_L2 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
EXPLORER_URI_L1=$(grep -E "^EXPLORER_URI_L1 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
EXPLORER_URI_L2=$(grep -E "^EXPLORER_URI_L2 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
EXPLORER_API_KEY_L1=$(grep -E "^EXPLORER_API_KEY_L1 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
EXPLORER_API_KEY_L2=$(grep -E "^EXPLORER_API_KEY_L2 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
ALTERNATIVE_GAS_TOKEN_ENABLED=$(grep -E "^ALTERNATIVE_GAS_TOKEN_ENABLED =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2-)
TEST_ENV_MOCK_FINALIZE_ENABLED=$(grep -E "^TEST_ENV_MOCK_FINALIZE_ENABLED =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2-)

# extract contract name and address
extract_contract_info() {
contract_name=$(cut -d "=" -f 1 <<< "$line" | tr -d '"')
contract_addr=$(cut -d "=" -f 2 <<< "$line" | tr -d '"' | tr -d ' ')
}

get_source_code_name() {
# specially handle the case where alternative gas token is enabled
if [[ "$ALTERNATIVE_GAS_TOKEN_ENABLED" == "true" && "$1" =~ ^(L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR|L2_TX_FEE_VAULT_ADDR)$ ]]; then
case "$1" in
L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR) echo L1ScrollMessengerNonETH ;;
L2_TX_FEE_VAULT_ADDR) echo L2TxFeeVaultWithGasToken ;;
*)
esac
# specially handle the case where mock finalize is enabled
elif [[ "$TEST_ENV_MOCK_FINALIZE_ENABLED" == "true" && "$1" =~ ^(L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR)$ ]]; then
case "$1" in
L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR) echo ScrollChainMockFinalize ;;
*)
esac
else
case "$1" in
L1_WETH_ADDR) echo WrappedEther ;;
L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR) echo EmptyContract ;;
L1_PROXY_ADMIN_ADDR) echo ProxyAdminSetOwner ;;
L1_WHITELIST_ADDR) echo Whitelist ;;
L1_SCROLL_CHAIN_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_SCROLL_MESSENGER_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR) echo EnforcedTxGateway ;;
L1_ENFORCED_TX_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_ZKEVM_VERIFIER_V2_ADDR) echo ZkEvmVerifierV2 ;;
L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR ) echo MultipleVersionRollupVerifierSetOwner ;;
L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR) echo L1MessageQueueWithGasPriceOracle ;;
L1_MESSAGE_QUEUE_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR) echo ScrollChain ;;
L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR) echo L1GatewayRouter ;;
L1_GATEWAY_ROUTER_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_ETH_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_WETH_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_ERC721_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_ERC1155_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L2_MESSAGE_QUEUE_ADDR) echo L2MessageQueue ;;
L1_GAS_PRICE_ORACLE_ADDR) echo L1GasPriceOracle ;;
L1_GAS_TOKEN_GATEWAY_IMPLEMENTATION_ADDR) echo L1GasTokenGateway ;;
L1_GAS_TOKEN_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L1_WRAPPED_TOKEN_GATEWAY_ADDR) echo L1WrappedTokenGateway ;;
L2_WHITELIST_ADDR) echo Whitelist ;;
L2_WETH_ADDR) echo WrappedEther ;;
L2_TX_FEE_VAULT_ADDR) echo L2TxFeeVault ;;
L2_PROXY_ADMIN_ADDR) echo ProxyAdminSetOwner ;;
L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR) echo EmptyContract ;;
L2_SCROLL_MESSENGER_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L2_ETH_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L2_WETH_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L2_ERC721_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L2_ERC1155_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L2_SCROLL_STANDARD_ERC20_ADDR) echo ScrollStandardERC20 ;;
L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR) echo ScrollStandardERC20FactorySetOwner ;;
L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR) echo L1ScrollMessenger ;;
L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR) echo L1StandardERC20Gateway ;;
L1_ETH_GATEWAY_IMPLEMENTATION_ADDR) echo L1ETHGateway ;;
L1_WETH_GATEWAY_IMPLEMENTATION_ADDR) echo L1WETHGateway ;;
L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR) echo L1CustomERC20Gateway ;;
L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR) echo L1ERC721Gateway ;;
L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR ) echo L1ERC1155Gateway ;;
L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR) echo L2ScrollMessenger ;;
L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR) echo L2GatewayRouter ;;
L2_GATEWAY_ROUTER_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR) echo L2StandardERC20Gateway ;;
L2_ETH_GATEWAY_IMPLEMENTATION_ADDR) echo L2ETHGateway ;;
L2_WETH_GATEWAY_IMPLEMENTATION_ADDR) echo L2WETHGateway ;;
L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR) echo L2CustomERC20Gateway ;;
L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR) echo L2ERC721Gateway ;;
L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR) echo L2ERC1155Gateway ;;
*) echo "" ;; # default: return void string
esac
fi
}

# read the file line by line
while IFS= read -r line; do
extract_contract_info "$line"

# get contracts deployment layer
if [[ "$contract_name" =~ ^L1 ]]; then
layer="L1"
elif [[ "$contract_name" =~ ^L2 ]]; then
layer="L2"
# specially handle contract_name L1_GAS_PRICE_ORACLE_ADDR
if [[ "$contract_name" == "L1_GAS_PRICE_ORACLE_ADDR" ]]; then
layer="L1"
fi
else
echo "wrong contract name, not starts with L1 or L2, contract_name: $contract_name"
continue
fi

source_code_name=$(get_source_code_name $contract_name)

# skip if source_code_name or contract_addr is empty
if [[ -z $source_code_name || -z $contract_addr ]]; then
echo "empty source_code_name: $source_code_name or contract_addr: $contract_addr"
continue
fi

# verify contract
echo ""
echo "verifing contract $contract_name with address $contract_addr on $layer"
EXTRA_PARAMS=""
if [[ "$layer" == "L1" ]]; then
if [[ "$VERIFIER_TYPE_L1" == "etherscan" ]]; then
EXTRA_PARAMS="--api-key $EXPLORER_API_KEY_L1"
elif [[ "$VERIFIER_TYPE_L1" == "blockscout" ]]; then
EXTRA_PARAMS="--verifier-url ${EXPLORER_URI_L1}/api/ --verifier $VERIFIER_TYPE_L1"
elif [[ "$VERIFIER_TYPE_L1" == "sourcify" ]]; then
EXTRA_PARAMS="--api-key $EXPLORER_API_KEY_L1 --verifier-url $EXPLORER_URI_L1 --verifier $VERIFIER_TYPE_L1"
fi
forge verify-contract $contract_addr $source_code_name --rpc-url $RPC_URI_L1 --chain-id $CHAIN_ID_L1 --watch --guess-constructor-args --skip-is-verified-check $EXTRA_PARAMS
elif [[ "$layer" == "L2" ]]; then
if [[ "$VERIFIER_TYPE_L2" == "etherscan" ]]; then
EXTRA_PARAMS="--api-key $EXPLORER_API_KEY_L2"
elif [[ "$VERIFIER_TYPE_L2" == "blockscout" ]]; then
EXTRA_PARAMS="--verifier-url ${EXPLORER_URI_L2}/api/ --verifier $VERIFIER_TYPE_L2"
elif [[ "$VERIFIER_TYPE_L2" == "sourcify" ]]; then
EXTRA_PARAMS="--api-key $EXPLORER_API_KEY_L2 --verifier-url $EXPLORER_URI_L2 --verifier $VERIFIER_TYPE_L2"
fi
forge verify-contract $contract_addr $source_code_name --rpc-url $RPC_URI_L2 --chain-id $CHAIN_ID_L2 --watch --guess-constructor-args --skip-is-verified-check $EXTRA_PARAMS
fi
done < ./volume/config-contracts.toml
34 changes: 3 additions & 31 deletions scripts/deterministic/DeployScroll.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity =0.8.24;

import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import {ProxyAdminSetOwner} from "./contracts/ProxyAdminSetOwner.sol";
import {TransparentUpgradeableProxy, ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

Expand All @@ -19,7 +19,7 @@ import {L1ScrollMessenger} from "../../src/L1/L1ScrollMessenger.sol";
import {L1StandardERC20Gateway} from "../../src/L1/gateways/L1StandardERC20Gateway.sol";
import {L1WETHGateway} from "../../src/L1/gateways/L1WETHGateway.sol";
import {L2GasPriceOracle} from "../../src/L1/rollup/L2GasPriceOracle.sol";
import {MultipleVersionRollupVerifier} from "../../src/L1/rollup/MultipleVersionRollupVerifier.sol";
import {MultipleVersionRollupVerifierSetOwner} from "./contracts/MultipleVersionRollupVerifierSetOwner.sol";
import {ScrollChain} from "../../src/L1/rollup/ScrollChain.sol";
import {ZkEvmVerifierV2} from "../../src/libraries/verifier/ZkEvmVerifierV2.sol";
import {GasTokenExample} from "../../src/alternative-gas-token/GasTokenExample.sol";
Expand All @@ -42,7 +42,7 @@ import {L2TxFeeVaultWithGasToken} from "../../src/alternative-gas-token/L2TxFeeV
import {Whitelist} from "../../src/L2/predeploys/Whitelist.sol";
import {WrappedEther} from "../../src/L2/predeploys/WrappedEther.sol";
import {ScrollStandardERC20} from "../../src/libraries/token/ScrollStandardERC20.sol";
import {ScrollStandardERC20Factory} from "../../src/libraries/token/ScrollStandardERC20Factory.sol";
import {ScrollStandardERC20FactorySetOwner} from "./contracts/ScrollStandardERC20FactorySetOwner.sol";

import {ScrollChainMockFinalize} from "../../src/mocks/ScrollChainMockFinalize.sol";

Expand All @@ -53,34 +53,6 @@ import "./DeterministicDeployment.sol";
/// @dev The minimum deployer account balance.
uint256 constant MINIMUM_DEPLOYER_BALANCE = 0.1 ether;

contract ProxyAdminSetOwner is ProxyAdmin {
/// @dev allow setting the owner in the constructor, otherwise
/// DeterministicDeploymentProxy would become the owner.
constructor(address owner) {
_transferOwnership(owner);
}
}

contract MultipleVersionRollupVerifierSetOwner is MultipleVersionRollupVerifier {
/// @dev allow setting the owner in the constructor, otherwise
/// DeterministicDeploymentProxy would become the owner.
constructor(
address owner,
uint256[] memory _versions,
address[] memory _verifiers
) MultipleVersionRollupVerifier(_versions, _verifiers) {
_transferOwnership(owner);
}
}

contract ScrollStandardERC20FactorySetOwner is ScrollStandardERC20Factory {
/// @dev allow setting the owner in the constructor, otherwise
/// DeterministicDeploymentProxy would become the owner.
constructor(address owner, address _implementation) ScrollStandardERC20Factory(_implementation) {
_transferOwnership(owner);
}
}

contract DeployScroll is DeterministicDeployment {
using stdToml for string;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.24;

import {MultipleVersionRollupVerifier} from "../../../src/L1/rollup/MultipleVersionRollupVerifier.sol";

contract MultipleVersionRollupVerifierSetOwner is MultipleVersionRollupVerifier {
/// @dev allow setting the owner in the constructor, otherwise
/// DeterministicDeploymentProxy would become the owner.
constructor(
address owner,
uint256[] memory _versions,
address[] memory _verifiers
) MultipleVersionRollupVerifier(_versions, _verifiers) {
_transferOwnership(owner);
}
}
12 changes: 12 additions & 0 deletions scripts/deterministic/contracts/ProxyAdminSetOwner.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.24;

import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";

contract ProxyAdminSetOwner is ProxyAdmin {
/// @dev allow setting the owner in the constructor, otherwise
/// DeterministicDeploymentProxy would become the owner.
constructor(address owner) {
_transferOwnership(owner);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.24;

import {ScrollStandardERC20Factory} from "../../../src/libraries/token/ScrollStandardERC20Factory.sol";

contract ScrollStandardERC20FactorySetOwner is ScrollStandardERC20Factory {
/// @dev allow setting the owner in the constructor, otherwise
/// DeterministicDeploymentProxy would become the owner.
constructor(address owner, address _implementation) ScrollStandardERC20Factory(_implementation) {
_transferOwnership(owner);
}
}
Loading