Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c63dc45
wip: use create2 for factory deployment
godzillaba Jun 24, 2025
0040293
remove key from config
godzillaba Jun 24, 2025
40b97dd
fmt
godzillaba Jun 24, 2025
22ad2fa
fix signatures
godzillaba Jun 24, 2025
9b38201
Merge branch 'develop' into deterministic-factory-deployments
godzillaba Jun 24, 2025
17be158
inline up exec deployment
godzillaba Jun 25, 2025
8aed0c3
salt length check
godzillaba Jun 30, 2025
7c0fd72
update tests
godzillaba Jun 30, 2025
4412691
Merge branch 'develop' into deterministic-factory-deployments
godzillaba Jun 30, 2025
1a12320
fmt
godzillaba Jun 30, 2025
64a519a
Merge branch 'deterministic-factory-deployments' of https://github.co…
godzillaba Jun 30, 2025
c4887b3
remove SetTemplatesArgs struct
godzillaba Jul 1, 2025
f4ba76f
remove ownership from bridge creator
godzillaba Jul 1, 2025
5953155
add CREATE2_FACTORY env and deployment instructions
godzillaba Jul 1, 2025
9429824
fix signatures
godzillaba Jul 1, 2025
f760491
factory owner as deployAllContracts arg
godzillaba Jul 1, 2025
bd06fb1
set deployer as owner in local deployment
godzillaba Jul 1, 2025
a2d4228
chore: disable metahash and align hardhat foundry (#363)
godzillaba Jul 3, 2025
1b86d38
fix: deploy create2 factory for local deployment
gzeoneth Jul 3, 2025
89baf3a
fix: wait for funding
gzeoneth Jul 3, 2025
d74b01b
ci: use geth-allow-pre155
gzeoneth Jul 3, 2025
9373a97
fix: _uint256ToAddress helper
gzeoneth Jul 3, 2025
152da5b
fix: deploy4844 script
gzeoneth Jul 7, 2025
f7523fb
fix: apply review comments
gzeoneth Jul 17, 2025
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
1 change: 1 addition & 0 deletions .env-sample
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ L1_PRIV_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
CONFIG_NETWORK_NAME="custom"
DEPLOYED_CONTRACTS_DIR="./scripts/files/"
DISABLE_VERIFICATION=true
FACTORY_OWNER=0x000000000000000000000000000000000000dead

# to use the 'custom' hardhat network, set the following variables
CUSTOM_RPC_URL="http://127.0.0.1:8545"
Expand Down
29 changes: 2 additions & 27 deletions scripts/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,33 +38,8 @@ async function main() {
console.log('Ignoring maxDataSize warning')
}

try {
// Deploying all contracts
const contracts = await deployAllContracts(
signer,
ethers.BigNumber.from(maxDataSize),
true
)

// Call setTemplates with the deployed contract addresses
console.log('Waiting for the Template to be set on the Rollup Creator')
await contracts.rollupCreator.setTemplates(
contracts.bridgeCreator.address,
contracts.osp.address,
contracts.challengeManager.address,
contracts.rollupAdmin.address,
contracts.rollupUser.address,
contracts.upgradeExecutor.address,
contracts.validatorWalletCreator.address,
contracts.deployHelper.address
)
console.log('Template is set on the Rollup Creator')
} catch (error) {
console.error(
'Deployment failed:',
error instanceof Error ? error.message : error
)
}
// Deploying all contracts
await deployAllContracts(signer, ethers.BigNumber.from(maxDataSize), true)
}

main()
Expand Down
217 changes: 175 additions & 42 deletions scripts/deploymentUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ import {
ArbOwnerPublic__factory,
ArbSys__factory,
CacheManager__factory,
IReader4844__factory,
} from '../build/types'
import {
concat,
getCreate2Address,
hexDataLength,
keccak256,
} from 'ethers/lib/utils'
import { bytecode as Reader4844Bytecode } from '../out/yul/Reader4844.yul/Reader4844.json'

const INIT_CACHE_SIZE = 536870912
const INIT_DECAY = 10322197911
Expand Down Expand Up @@ -72,6 +80,7 @@ export async function deployContract(
signer: any,
constructorArgs: any[] = [],
verify: boolean = true,
useCreate2: boolean = false,
overrides?: Overrides
): Promise<Contract> {
const factory: ContractFactory = await ethers.getContractFactory(contractName)
Expand All @@ -88,10 +97,21 @@ export async function deployContract(
// deploymentArgs.push(overrides)
}

const contract: Contract = await connectedFactory.deploy(...deploymentArgs)
await contract.deployTransaction.wait()
let contract: Contract
if (useCreate2) {
contract = await create2(
connectedFactory,
constructorArgs,
ethers.constants.HashZero,
overrides
)
} else {
contract = await connectedFactory.deploy(...deploymentArgs)
await contract.deployTransaction.wait()
}

console.log(
`* New ${contractName} created at address: ${
`* ${contractName} created at address: ${
contract.address
} ${constructorArgs.join(' ')}`
)
Expand All @@ -102,15 +122,38 @@ export async function deployContract(
return contract
}

// Deploy upgrade executor from imported bytecode
export async function deployUpgradeExecutor(signer: any): Promise<Contract> {
const upgradeExecutorFac = await ethers.getContractFactory(
UpgradeExecutorABI,
UpgradeExecutorBytecode
)
const connectedFactory: ContractFactory = upgradeExecutorFac.connect(signer)
const upgradeExecutor = await connectedFactory.deploy()
return upgradeExecutor
export async function create2(
fac: ContractFactory,
deploymentArgs: Array<any>,
salt = ethers.constants.HashZero,
overrides?: Overrides
): Promise<Contract> {
if (hexDataLength(salt) !== 32) {
throw new Error('Salt must be a 32-byte hex string')
}

const FACTORY = '0x4e59b44847b379578588920cA78FbF26c0B4956C'
if ((await fac.signer.provider!.getCode(FACTORY)).length <= 2) {
throw new Error('Factory contract not deployed at address: ' + FACTORY)
}
const data = fac.getDeployTransaction(...deploymentArgs).data
if (!data) {
throw new Error('No deploy data found for contract factory')
}

const address = getCreate2Address(FACTORY, salt, keccak256(data))
if ((await fac.signer.provider!.getCode(address)).length > 2) {
return fac.attach(address)
}

const tx = await fac.signer.sendTransaction({
to: FACTORY,
data: concat([salt, data]),
...overrides,
})
await tx.wait()

return fac.attach(address)
}

// Function to handle all deployments of core contracts using deployContract function
Expand All @@ -119,66 +162,108 @@ export async function deployAllContracts(
maxDataSize: BigNumber,
verify: boolean = true
): Promise<Record<string, Contract>> {
const FACTORY_OWNER = process.env.FACTORY_OWNER
if (!FACTORY_OWNER) {
throw new Error('FACTORY_OWNER environment variable is not set')
}

const isOnArb = await _isRunningOnArbitrum(signer)

const ethBridge = await deployContract('Bridge', signer, [], verify)
const ethBridge = await deployContract('Bridge', signer, [], verify, true)

const reader4844 = isOnArb
? ethers.constants.AddressZero
: (await Toolkit4844.deployReader4844(signer)).address
: (
await create2(
new ContractFactory(
IReader4844__factory.abi,
Reader4844Bytecode,
signer
),
[],
ethers.constants.HashZero
)
).address

const ethSequencerInbox = await deployContract(
'SequencerInbox',
signer,
[maxDataSize, reader4844, false, false],
verify
verify,
true
)
const ethSequencerInboxDelayBufferable = await deployContract(
'SequencerInbox',
signer,
[maxDataSize, reader4844, false, true],
verify
verify,
true
)

const ethInbox = await deployContract('Inbox', signer, [maxDataSize], verify)
const ethInbox = await deployContract(
'Inbox',
signer,
[maxDataSize],
verify,
true
)
const ethRollupEventInbox = await deployContract(
'RollupEventInbox',
signer,
[],
verify
verify,
true
)
const ethOutbox = await deployContract('Outbox', signer, [], verify)
const ethOutbox = await deployContract('Outbox', signer, [], verify, true)

const erc20Bridge = await deployContract('ERC20Bridge', signer, [], verify)
const erc20Bridge = await deployContract(
'ERC20Bridge',
signer,
[],
verify,
true
)
const erc20SequencerInbox = await deployContract(
'SequencerInbox',
signer,
[maxDataSize, reader4844, true, false],
verify
verify,
true
)
const erc20SequencerInboxDelayBufferable = await deployContract(
'SequencerInbox',
signer,
[maxDataSize, reader4844, true, true],
verify
verify,
true
)
const erc20Inbox = await deployContract(
'ERC20Inbox',
signer,
[maxDataSize],
verify
verify,
true
)
const erc20RollupEventInbox = await deployContract(
'ERC20RollupEventInbox',
signer,
[],
verify
verify,
true
)
const erc20Outbox = await deployContract(
'ERC20Outbox',
signer,
[],
verify,
true
)
const erc20Outbox = await deployContract('ERC20Outbox', signer, [], verify)

const bridgeCreator = await deployContract(
'BridgeCreator',
signer,
[
FACTORY_OWNER,
[
ethBridge.address,
ethSequencerInbox.address,
Expand All @@ -196,26 +281,36 @@ export async function deployAllContracts(
erc20Outbox.address,
],
],
verify
verify,
true
)
const prover0 = await deployContract(
'OneStepProver0',
signer,
[],
verify,
true
)
const prover0 = await deployContract('OneStepProver0', signer, [], verify)
const proverMem = await deployContract(
'OneStepProverMemory',
signer,
[],
verify
verify,
true
)
const proverMath = await deployContract(
'OneStepProverMath',
signer,
[],
verify
verify,
true
)
const proverHostIo = await deployContract(
'OneStepProverHostIo',
signer,
[],
verify
verify,
true
)
const osp: Contract = await deployContract(
'OneStepProofEntry',
Expand All @@ -226,40 +321,78 @@ export async function deployAllContracts(
proverMath.address,
proverHostIo.address,
],
verify
verify,
true
)
const challengeManager = await deployContract(
'EdgeChallengeManager',
signer,
[],
verify
verify,
true
)
const rollupAdmin = await deployContract(
'RollupAdminLogic',
signer,
[],
verify
verify,
true
)
const rollupUser = await deployContract(
'RollupUserLogic',
signer,
[],
verify,
true
)
const upgradeExecutor = await create2(
(
await ethers.getContractFactory(
UpgradeExecutorABI,
UpgradeExecutorBytecode
)
).connect(signer),
[]
)
const rollupUser = await deployContract('RollupUserLogic', signer, [], verify)
const upgradeExecutor = await deployUpgradeExecutor(signer)
await upgradeExecutor.deployTransaction.wait()
const validatorWalletCreator = await deployContract(
'ValidatorWalletCreator',
signer,
[],
verify
verify,
true
)
const rollupCreator = await deployContract(
'RollupCreator',
const deployHelper = await deployContract(
'DeployHelper',
signer,
[],
verify
verify,
true
)
const deployHelper = await deployContract('DeployHelper', signer, [], verify)
if (verify && !process.env.DISABLE_VERIFICATION) {
// Deploy RollupProxy contract only for verification, should not be used anywhere else
await deployContract('RollupProxy', signer, [], verify)
await deployContract('RollupProxy', signer, [], verify, true)
}

const rollupCreator = await deployContract(
'RollupCreator',
signer,
[
FACTORY_OWNER,
{
bridgeCreator: bridgeCreator.address,
osp: osp.address,
challengeManagerLogic: challengeManager.address,
rollupAdminLogic: rollupAdmin.address,
rollupUserLogic: rollupUser.address,
upgradeExecutorLogic: upgradeExecutor.address,
validatorWalletCreator: validatorWalletCreator.address,
l2FactoriesDeployer: deployHelper.address,
},
],
verify,
true
)

return {
bridgeCreator,
prover0,
Expand Down
Loading
Loading