Skip to content

Commit a976769

Browse files
authored
feat: support contracts verification (#57)
1 parent a507de4 commit a976769

File tree

10 files changed

+263
-33
lines changed

10 files changed

+263
-33
lines changed

.github/workflows/docker-release.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,16 @@ jobs:
6363
file: docker/Dockerfile.gen-configs
6464
tags: |
6565
${{ env.REPOSITORY }}:gen-configs-${{ github.sha }}
66+
67+
- name: Build verify image
68+
id: build_verify_image
69+
env:
70+
REPOSITORY: scrolltech/scroll-stack-contracts
71+
uses: docker/build-push-action@v3
72+
with:
73+
platforms: linux/amd64,linux/arm64
74+
push: true
75+
context: .
76+
file: docker/Dockerfile.verify
77+
tags: |
78+
${{ env.REPOSITORY }}:verify-${{ github.sha }}

docker/Dockerfile.deploy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ RUN curl -L https://foundry.paradigm.xyz | bash
1818
ENV PATH="/root/.foundry/bin:${PATH}"
1919

2020
# Run foundryup to update Foundry
21-
RUN foundryup -v nightly-56dbd20c7179570c53b6c17ff34daa7273a4ddae
21+
RUN foundryup -v nightly-fdd321bac95f0935529164a88faf99d4d5cfa321
2222

2323
# copy dependencies
2424
COPY ./lib /contracts/lib

docker/Dockerfile.gen-configs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ RUN curl -L https://foundry.paradigm.xyz | bash
1818
ENV PATH="/root/.foundry/bin:${PATH}"
1919

2020
# Run foundryup to update Foundry
21-
RUN foundryup -v nightly-56dbd20c7179570c53b6c17ff34daa7273a4ddae
21+
RUN foundryup -v nightly-fdd321bac95f0935529164a88faf99d4d5cfa321
2222

2323
# copy dependencies
2424
COPY ./lib /contracts/lib

docker/Dockerfile.verify

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Use the latest node Debian slim base image
2+
# This makes installing yarn dep much easier
3+
FROM node:20-bookworm-slim
4+
5+
# Switch to bash shell
6+
SHELL ["/bin/bash", "-c"]
7+
8+
WORKDIR /root
9+
10+
# Install dependencies
11+
RUN apt update
12+
RUN apt install --yes curl bash coreutils git jq ca-certificates
13+
14+
# Download and run the Foundry installation script
15+
RUN curl -L https://foundry.paradigm.xyz | bash
16+
17+
# Set the environment variables to ensure Foundry tools are in the PATH
18+
ENV PATH="/root/.foundry/bin:${PATH}"
19+
20+
# Run foundryup to update Foundry
21+
RUN foundryup -v nightly-fdd321bac95f0935529164a88faf99d4d5cfa321
22+
23+
# copy dependencies
24+
COPY ./lib /contracts/lib
25+
COPY ./node_modules/@openzeppelin /contracts/node_modules/@openzeppelin
26+
COPY ./node_modules/hardhat /contracts/node_modules/hardhat
27+
28+
# copy configurations
29+
COPY foundry.toml /contracts/foundry.toml
30+
COPY remappings.txt /contracts/remappings.txt
31+
32+
# copy source code
33+
COPY ./src /contracts/src
34+
COPY ./scripts /contracts/scripts
35+
36+
# compile contracts
37+
ENV FOUNDRY_EVM_VERSION="cancun"
38+
ENV FOUNDRY_BYTECODE_HASH="none"
39+
40+
WORKDIR /contracts
41+
RUN forge build
42+
43+
COPY ./docker/scripts/verify.sh /contracts/docker/scripts/verify.sh
44+
45+
ENTRYPOINT ["/bin/bash", "/contracts/docker/scripts/verify.sh"]

docker/config-example.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ L2_WHITELIST = "0x5300000000000000000000000000000000000003"
104104
L2_WETH = "0x5300000000000000000000000000000000000004"
105105
L2_TX_FEE_VAULT = "0x5300000000000000000000000000000000000005"
106106

107+
[contracts.verify]
108+
109+
VERIFIER_TYPE_L1 = "blockscout"
110+
VERIFIER_TYPE_L2 = "blockscout"
111+
EXPLORER_URI_L1 = "http://l1-explorer.scrollsdk"
112+
EXPLORER_URI_L2 = "http://blockscout.scrollsdk"
113+
RPC_URI_L1 = "http://l1-devnet.scrollsdk"
114+
RPC_URI_L2 = "http://l2-rpc.scrollsdk"
115+
EXPLORER_API_KEY_L1 = ""
116+
EXPLORER_API_KEY_L2 = ""
107117

108118
[coordinator]
109119

docker/scripts/verify.sh

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/bin/sh
2+
3+
# extract values from config file
4+
config_file="./volume/config.toml"
5+
CHAIN_ID_L1=$(grep -E "^CHAIN_ID_L1 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2-)
6+
CHAIN_ID_L2=$(grep -E "^CHAIN_ID_L2 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2-)
7+
RPC_URI_L1=$(grep -E "^RPC_URI_L1 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
8+
RPC_URI_L2=$(grep -E "^RPC_URI_L2 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
9+
VERIFIER_TYPE_L1=$(grep -E "^VERIFIER_TYPE_L1 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
10+
VERIFIER_TYPE_L2=$(grep -E "^VERIFIER_TYPE_L2 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
11+
EXPLORER_URI_L1=$(grep -E "^EXPLORER_URI_L1 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
12+
EXPLORER_URI_L2=$(grep -E "^EXPLORER_URI_L2 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
13+
EXPLORER_API_KEY_L1=$(grep -E "^EXPLORER_API_KEY_L1 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
14+
EXPLORER_API_KEY_L2=$(grep -E "^EXPLORER_API_KEY_L2 =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2- | tr -d '"')
15+
ALTERNATIVE_GAS_TOKEN_ENABLED=$(grep -E "^ALTERNATIVE_GAS_TOKEN_ENABLED =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2-)
16+
TEST_ENV_MOCK_FINALIZE_ENABLED=$(grep -E "^TEST_ENV_MOCK_FINALIZE_ENABLED =" "$config_file" | sed 's/ *= */=/' | cut -d'=' -f2-)
17+
18+
# extract contract name and address
19+
extract_contract_info() {
20+
contract_name=$(cut -d "=" -f 1 <<< "$line" | tr -d '"')
21+
contract_addr=$(cut -d "=" -f 2 <<< "$line" | tr -d '"' | tr -d ' ')
22+
}
23+
24+
get_source_code_name() {
25+
# specially handle the case where alternative gas token is enabled
26+
if [[ "$ALTERNATIVE_GAS_TOKEN_ENABLED" == "true" && "$1" =~ ^(L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR|L2_TX_FEE_VAULT_ADDR)$ ]]; then
27+
case "$1" in
28+
L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR) echo L1ScrollMessengerNonETH ;;
29+
L2_TX_FEE_VAULT_ADDR) echo L2TxFeeVaultWithGasToken ;;
30+
*)
31+
esac
32+
# specially handle the case where mock finalize is enabled
33+
elif [[ "$TEST_ENV_MOCK_FINALIZE_ENABLED" == "true" && "$1" =~ ^(L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR)$ ]]; then
34+
case "$1" in
35+
L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR) echo ScrollChainMockFinalize ;;
36+
*)
37+
esac
38+
else
39+
case "$1" in
40+
L1_WETH_ADDR) echo WrappedEther ;;
41+
L1_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR) echo EmptyContract ;;
42+
L1_PROXY_ADMIN_ADDR) echo ProxyAdminSetOwner ;;
43+
L1_WHITELIST_ADDR) echo Whitelist ;;
44+
L1_SCROLL_CHAIN_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
45+
L1_SCROLL_MESSENGER_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
46+
L1_ENFORCED_TX_GATEWAY_IMPLEMENTATION_ADDR) echo EnforcedTxGateway ;;
47+
L1_ENFORCED_TX_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
48+
L1_ZKEVM_VERIFIER_V2_ADDR) echo ZkEvmVerifierV2 ;;
49+
L1_MULTIPLE_VERSION_ROLLUP_VERIFIER_ADDR ) echo MultipleVersionRollupVerifierSetOwner ;;
50+
L1_MESSAGE_QUEUE_IMPLEMENTATION_ADDR) echo L1MessageQueueWithGasPriceOracle ;;
51+
L1_MESSAGE_QUEUE_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
52+
L1_SCROLL_CHAIN_IMPLEMENTATION_ADDR) echo ScrollChain ;;
53+
L1_GATEWAY_ROUTER_IMPLEMENTATION_ADDR) echo L1GatewayRouter ;;
54+
L1_GATEWAY_ROUTER_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
55+
L1_ETH_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
56+
L1_WETH_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
57+
L1_STANDARD_ERC20_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
58+
L1_CUSTOM_ERC20_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
59+
L1_ERC721_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
60+
L1_ERC1155_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
61+
L2_MESSAGE_QUEUE_ADDR) echo L2MessageQueue ;;
62+
L1_GAS_PRICE_ORACLE_ADDR) echo L1GasPriceOracle ;;
63+
L1_GAS_TOKEN_GATEWAY_IMPLEMENTATION_ADDR) echo L1GasTokenGateway ;;
64+
L1_GAS_TOKEN_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
65+
L1_WRAPPED_TOKEN_GATEWAY_ADDR) echo L1WrappedTokenGateway ;;
66+
L2_WHITELIST_ADDR) echo Whitelist ;;
67+
L2_WETH_ADDR) echo WrappedEther ;;
68+
L2_TX_FEE_VAULT_ADDR) echo L2TxFeeVault ;;
69+
L2_PROXY_ADMIN_ADDR) echo ProxyAdminSetOwner ;;
70+
L2_PROXY_IMPLEMENTATION_PLACEHOLDER_ADDR) echo EmptyContract ;;
71+
L2_SCROLL_MESSENGER_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
72+
L2_ETH_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
73+
L2_WETH_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
74+
L2_STANDARD_ERC20_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
75+
L2_CUSTOM_ERC20_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
76+
L2_ERC721_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
77+
L2_ERC1155_GATEWAY_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
78+
L2_SCROLL_STANDARD_ERC20_ADDR) echo ScrollStandardERC20 ;;
79+
L2_SCROLL_STANDARD_ERC20_FACTORY_ADDR) echo ScrollStandardERC20FactorySetOwner ;;
80+
L1_SCROLL_MESSENGER_IMPLEMENTATION_ADDR) echo L1ScrollMessenger ;;
81+
L1_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR) echo L1StandardERC20Gateway ;;
82+
L1_ETH_GATEWAY_IMPLEMENTATION_ADDR) echo L1ETHGateway ;;
83+
L1_WETH_GATEWAY_IMPLEMENTATION_ADDR) echo L1WETHGateway ;;
84+
L1_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR) echo L1CustomERC20Gateway ;;
85+
L1_ERC721_GATEWAY_IMPLEMENTATION_ADDR) echo L1ERC721Gateway ;;
86+
L1_ERC1155_GATEWAY_IMPLEMENTATION_ADDR ) echo L1ERC1155Gateway ;;
87+
L2_SCROLL_MESSENGER_IMPLEMENTATION_ADDR) echo L2ScrollMessenger ;;
88+
L2_GATEWAY_ROUTER_IMPLEMENTATION_ADDR) echo L2GatewayRouter ;;
89+
L2_GATEWAY_ROUTER_PROXY_ADDR) echo TransparentUpgradeableProxy ;;
90+
L2_STANDARD_ERC20_GATEWAY_IMPLEMENTATION_ADDR) echo L2StandardERC20Gateway ;;
91+
L2_ETH_GATEWAY_IMPLEMENTATION_ADDR) echo L2ETHGateway ;;
92+
L2_WETH_GATEWAY_IMPLEMENTATION_ADDR) echo L2WETHGateway ;;
93+
L2_CUSTOM_ERC20_GATEWAY_IMPLEMENTATION_ADDR) echo L2CustomERC20Gateway ;;
94+
L2_ERC721_GATEWAY_IMPLEMENTATION_ADDR) echo L2ERC721Gateway ;;
95+
L2_ERC1155_GATEWAY_IMPLEMENTATION_ADDR) echo L2ERC1155Gateway ;;
96+
*) echo "" ;; # default: return void string
97+
esac
98+
fi
99+
}
100+
101+
# read the file line by line
102+
while IFS= read -r line; do
103+
extract_contract_info "$line"
104+
105+
# get contracts deployment layer
106+
if [[ "$contract_name" =~ ^L1 ]]; then
107+
layer="L1"
108+
elif [[ "$contract_name" =~ ^L2 ]]; then
109+
layer="L2"
110+
# specially handle contract_name L1_GAS_PRICE_ORACLE_ADDR
111+
if [[ "$contract_name" == "L1_GAS_PRICE_ORACLE_ADDR" ]]; then
112+
layer="L1"
113+
fi
114+
else
115+
echo "wrong contract name, not starts with L1 or L2, contract_name: $contract_name"
116+
continue
117+
fi
118+
119+
source_code_name=$(get_source_code_name $contract_name)
120+
121+
# skip if source_code_name or contract_addr is empty
122+
if [[ -z $source_code_name || -z $contract_addr ]]; then
123+
echo "empty source_code_name: $source_code_name or contract_addr: $contract_addr"
124+
continue
125+
fi
126+
127+
# verify contract
128+
echo ""
129+
echo "verifing contract $contract_name with address $contract_addr on $layer"
130+
EXTRA_PARAMS=""
131+
if [[ "$layer" == "L1" ]]; then
132+
if [[ "$VERIFIER_TYPE_L1" == "etherscan" ]]; then
133+
EXTRA_PARAMS="--api-key $EXPLORER_API_KEY_L1"
134+
elif [[ "$VERIFIER_TYPE_L1" == "blockscout" ]]; then
135+
EXTRA_PARAMS="--verifier-url ${EXPLORER_URI_L1}/api/ --verifier $VERIFIER_TYPE_L1"
136+
elif [[ "$VERIFIER_TYPE_L1" == "sourcify" ]]; then
137+
EXTRA_PARAMS="--api-key $EXPLORER_API_KEY_L1 --verifier-url $EXPLORER_URI_L1 --verifier $VERIFIER_TYPE_L1"
138+
fi
139+
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
140+
elif [[ "$layer" == "L2" ]]; then
141+
if [[ "$VERIFIER_TYPE_L2" == "etherscan" ]]; then
142+
EXTRA_PARAMS="--api-key $EXPLORER_API_KEY_L2"
143+
elif [[ "$VERIFIER_TYPE_L2" == "blockscout" ]]; then
144+
EXTRA_PARAMS="--verifier-url ${EXPLORER_URI_L2}/api/ --verifier $VERIFIER_TYPE_L2"
145+
elif [[ "$VERIFIER_TYPE_L2" == "sourcify" ]]; then
146+
EXTRA_PARAMS="--api-key $EXPLORER_API_KEY_L2 --verifier-url $EXPLORER_URI_L2 --verifier $VERIFIER_TYPE_L2"
147+
fi
148+
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
149+
fi
150+
done < ./volume/config-contracts.toml

scripts/deterministic/DeployScroll.s.sol

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
pragma solidity =0.8.24;
33

44
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
5-
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
5+
import {ProxyAdminSetOwner} from "./contracts/ProxyAdminSetOwner.sol";
66
import {TransparentUpgradeableProxy, ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
77
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
88

@@ -19,7 +19,7 @@ import {L1ScrollMessenger} from "../../src/L1/L1ScrollMessenger.sol";
1919
import {L1StandardERC20Gateway} from "../../src/L1/gateways/L1StandardERC20Gateway.sol";
2020
import {L1WETHGateway} from "../../src/L1/gateways/L1WETHGateway.sol";
2121
import {L2GasPriceOracle} from "../../src/L1/rollup/L2GasPriceOracle.sol";
22-
import {MultipleVersionRollupVerifier} from "../../src/L1/rollup/MultipleVersionRollupVerifier.sol";
22+
import {MultipleVersionRollupVerifierSetOwner} from "./contracts/MultipleVersionRollupVerifierSetOwner.sol";
2323
import {ScrollChain} from "../../src/L1/rollup/ScrollChain.sol";
2424
import {ZkEvmVerifierV2} from "../../src/libraries/verifier/ZkEvmVerifierV2.sol";
2525
import {GasTokenExample} from "../../src/alternative-gas-token/GasTokenExample.sol";
@@ -42,7 +42,7 @@ import {L2TxFeeVaultWithGasToken} from "../../src/alternative-gas-token/L2TxFeeV
4242
import {Whitelist} from "../../src/L2/predeploys/Whitelist.sol";
4343
import {WrappedEther} from "../../src/L2/predeploys/WrappedEther.sol";
4444
import {ScrollStandardERC20} from "../../src/libraries/token/ScrollStandardERC20.sol";
45-
import {ScrollStandardERC20Factory} from "../../src/libraries/token/ScrollStandardERC20Factory.sol";
45+
import {ScrollStandardERC20FactorySetOwner} from "./contracts/ScrollStandardERC20FactorySetOwner.sol";
4646

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

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

56-
contract ProxyAdminSetOwner is ProxyAdmin {
57-
/// @dev allow setting the owner in the constructor, otherwise
58-
/// DeterministicDeploymentProxy would become the owner.
59-
constructor(address owner) {
60-
_transferOwnership(owner);
61-
}
62-
}
63-
64-
contract MultipleVersionRollupVerifierSetOwner is MultipleVersionRollupVerifier {
65-
/// @dev allow setting the owner in the constructor, otherwise
66-
/// DeterministicDeploymentProxy would become the owner.
67-
constructor(
68-
address owner,
69-
uint256[] memory _versions,
70-
address[] memory _verifiers
71-
) MultipleVersionRollupVerifier(_versions, _verifiers) {
72-
_transferOwnership(owner);
73-
}
74-
}
75-
76-
contract ScrollStandardERC20FactorySetOwner is ScrollStandardERC20Factory {
77-
/// @dev allow setting the owner in the constructor, otherwise
78-
/// DeterministicDeploymentProxy would become the owner.
79-
constructor(address owner, address _implementation) ScrollStandardERC20Factory(_implementation) {
80-
_transferOwnership(owner);
81-
}
82-
}
83-
8456
contract DeployScroll is DeterministicDeployment {
8557
using stdToml for string;
8658

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity =0.8.24;
3+
4+
import {MultipleVersionRollupVerifier} from "../../../src/L1/rollup/MultipleVersionRollupVerifier.sol";
5+
6+
contract MultipleVersionRollupVerifierSetOwner is MultipleVersionRollupVerifier {
7+
/// @dev allow setting the owner in the constructor, otherwise
8+
/// DeterministicDeploymentProxy would become the owner.
9+
constructor(
10+
address owner,
11+
uint256[] memory _versions,
12+
address[] memory _verifiers
13+
) MultipleVersionRollupVerifier(_versions, _verifiers) {
14+
_transferOwnership(owner);
15+
}
16+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity =0.8.24;
3+
4+
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
5+
6+
contract ProxyAdminSetOwner is ProxyAdmin {
7+
/// @dev allow setting the owner in the constructor, otherwise
8+
/// DeterministicDeploymentProxy would become the owner.
9+
constructor(address owner) {
10+
_transferOwnership(owner);
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity =0.8.24;
3+
4+
import {ScrollStandardERC20Factory} from "../../../src/libraries/token/ScrollStandardERC20Factory.sol";
5+
6+
contract ScrollStandardERC20FactorySetOwner is ScrollStandardERC20Factory {
7+
/// @dev allow setting the owner in the constructor, otherwise
8+
/// DeterministicDeploymentProxy would become the owner.
9+
constructor(address owner, address _implementation) ScrollStandardERC20Factory(_implementation) {
10+
_transferOwnership(owner);
11+
}
12+
}

0 commit comments

Comments
 (0)