Skip to content
Draft
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
10 changes: 5 additions & 5 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ jobs:

- name: Set nitro contracts image
run: |
echo "NITRO_CONTRACTS_GHCR_IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/chain-sdk-nitro-contracts:v3.2.0-2f747c7" >> "$GITHUB_ENV"
echo "NITRO_CONTRACTS_GHCR_IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/chain-sdk-nitro-contracts-anvil:v3.2.0-2f747c7" >> "$GITHUB_ENV"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Expand Down Expand Up @@ -281,7 +281,7 @@ jobs:

- name: Set token bridge contracts image
run: |
echo "TOKEN_BRIDGE_CONTRACTS_GHCR_IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/chain-sdk-token-bridge-contracts:v1.2.2" >> "$GITHUB_ENV"
echo "TOKEN_BRIDGE_CONTRACTS_GHCR_IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/chain-sdk-token-bridge-contracts-anvil:v1.2.5-5975d8f73608" >> "$GITHUB_ENV"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Expand All @@ -307,7 +307,7 @@ jobs:
uses: docker/build-push-action@v6
with:
context: ./token-bridge-contracts
file: ./token-bridge-contracts/Dockerfile
file: ./token-bridge-contracts/Dockerfile.anvil
push: true
tags: |
${{ env.TOKEN_BRIDGE_CONTRACTS_GHCR_IMAGE }}
Expand All @@ -327,8 +327,8 @@ jobs:

- name: Set nitro contracts image
run: |
echo "NITRO_CONTRACTS_GHCR_IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/chain-sdk-nitro-contracts:v3.2.0-2f747c7" >> "$GITHUB_ENV"
echo "TOKEN_BRIDGE_CONTRACTS_GHCR_IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/chain-sdk-token-bridge-contracts:v1.2.2" >> "$GITHUB_ENV"
echo "NITRO_CONTRACTS_GHCR_IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/chain-sdk-nitro-contracts-anvil:v3.2.0-2f747c7" >> "$GITHUB_ENV"
echo "TOKEN_BRIDGE_CONTRACTS_GHCR_IMAGE=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/chain-sdk-token-bridge-contracts-anvil:v1.2.5-5975d8f73608" >> "$GITHUB_ENV"

- name: Log in to GHCR
uses: docker/login-action@v3
Expand Down
7 changes: 2 additions & 5 deletions nitro-contracts/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@ FROM ghcr.io/foundry-rs/foundry:v1.3.1 AS foundry

FROM node:20-bullseye-slim AS builder

ARG NITRO_CONTRACTS_REPO_URL=https://github.com/OffchainLabs/nitro-contracts.git
ARG NITRO_CONTRACTS_GIT_COMMIT=2f747c722d98d5fd662bfda08cd86aa534b22be2

COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge

RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*

WORKDIR /workspace

RUN git init . \
&& git remote add origin "${NITRO_CONTRACTS_REPO_URL}" \
&& git fetch --depth 1 origin "${NITRO_CONTRACTS_GIT_COMMIT}" \
&& git remote add origin https://github.com/OffchainLabs/nitro-contracts.git \
&& git fetch --depth 1 origin 2f747c722d98d5fd662bfda08cd86aa534b22be2 \
&& git checkout --detach FETCH_HEAD \
&& git submodule update --init --recursive --depth 1

Expand Down
File renamed without changes.
28 changes: 28 additions & 0 deletions src/contracts/Inbox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export const inboxABI = [
{
stateMutability: 'view',
type: 'function',
inputs: [
{ name: 'dataLength', type: 'uint256' },
{ name: 'baseFee', type: 'uint256' },
],
name: 'calculateRetryableSubmissionFee',
outputs: [{ type: 'uint256' }],
},
{
stateMutability: 'payable',
type: 'function',
inputs: [
{ name: 'to', type: 'address' },
{ name: 'l2CallValue', type: 'uint256' },
{ name: 'maxSubmissionCost', type: 'uint256' },
{ name: 'excessFeeRefundAddress', type: 'address' },
{ name: 'callValueRefundAddress', type: 'address' },
{ name: 'gasLimit', type: 'uint256' },
{ name: 'maxFeePerGas', type: 'uint256' },
{ name: 'data', type: 'bytes' },
],
name: 'createRetryableTicketNoRefundAliasRewrite',
outputs: [{ type: 'uint256' }],
},
] as const;
4 changes: 4 additions & 0 deletions src/createTokenBridge.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { scaleFrom18DecimalsToNativeTokenDecimals } from './utils/decimals';
import { getWethAddress } from './utils/getWethAddress';
import { isAnvilTestMode, getAnvilTestStack } from './integrationTestHelpers/injectedMode';
import { Address } from 'viem';
import { testConstants } from './integrationTestHelpers/constants';

const env = isAnvilTestMode() ? getAnvilTestStack() : undefined;

Expand Down Expand Up @@ -54,16 +55,19 @@ if (env) {
const l1Client = createPublicClient({
chain: env ? env.l1.chain : nitroTestnodeL1,
transport: env ? http(env.l1.rpcUrl) : http(nitroTestnodeL1.rpcUrls.default.http[0]),
...(env ? { pollingInterval: testConstants.POLLING_INTERVAL } : {}),
});

const l2Client = createPublicClient({
chain: env ? env.l2.chain : nitroTestnodeL2,
transport: env ? http(env.l2.rpcUrl) : http(nitroTestnodeL2.rpcUrls.default.http[0]),
...(env ? { pollingInterval: testConstants.POLLING_INTERVAL } : {}),
});

const l3Client = createPublicClient({
chain: env ? env.l3.chain : nitroTestnodeL3,
transport: env ? http(env.l3.rpcUrl) : http(nitroTestnodeL3.rpcUrls.default.http[0]),
...(env ? { pollingInterval: testConstants.POLLING_INTERVAL } : {}),
});

function checkTokenBridgeContracts(tokenBridgeContracts: TokenBridgeContracts) {
Expand Down
5 changes: 4 additions & 1 deletion src/ethers-compat/publicClientToProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,8 @@ export function publicClientToProvider<TChain extends Chain | undefined>(
const transportUrl = publicClient.transport.url as string | undefined;
const url = transportUrl ?? chain.rpcUrls.default.http[0];

return new providers.StaticJsonRpcProvider(url, network);
const provider = new providers.StaticJsonRpcProvider(url, network);
provider.pollingInterval = publicClient.pollingInterval;

return provider;
}
37 changes: 25 additions & 12 deletions src/integrationTestHelpers/anvilHarness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,13 @@ export function hydrateAnvilTestStack(env: InjectedAnvilTestStack): AnvilTestSta
publicClient: createPublicClient({
chain: l2Chain,
transport: http(env.l2.rpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
}),
walletClient: createWalletClient({
chain: l2Chain,
transport: http(env.l2.rpcUrl),
account: blockAdvancerAccount,
pollingInterval: testConstants.POLLING_INTERVAL,
}),
account: blockAdvancerAccount,
}),
Expand Down Expand Up @@ -316,15 +318,15 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
dockerNetworkName = `chain-sdk-int-test-net-${Date.now()}`;
createDockerNetwork(dockerNetworkName);

const l2ChainId = testConstants.DEFAULT_L2_CHAIN_ID;
const l2ChainId = testConstants.L2_CHAIN_ID;
const l3ChainId = l2ChainId + 1;
const l1RpcPort = testConstants.DEFAULT_L1_RPC_PORT;
const l2RpcPort = testConstants.DEFAULT_L2_RPC_PORT;
const l3RpcPort = testConstants.DEFAULT_L3_RPC_PORT;
const anvilImage = testConstants.DEFAULT_ANVIL_IMAGE;
const nitroImage = testConstants.DEFAULT_NITRO_IMAGE;
const sepoliaBeaconRpc = testConstants.DEFAULT_SEPOLIA_BEACON_RPC;
const anvilForkUrl = testConstants.DEFAULT_SEPOLIA_RPC;
const l1RpcPort = testConstants.L1_RPC_PORT;
const l2RpcPort = testConstants.L2_RPC_PORT;
const l3RpcPort = testConstants.L3_RPC_PORT;
const anvilImage = testConstants.ANVIL_IMAGE;
const nitroImage = testConstants.NITRO_IMAGE;
const sepoliaBeaconRpc = testConstants.SEPOLIA_BEACON_RPC;
const anvilForkUrl = testConstants.SEPOLIA_RPC;
const rollupCreatorVersion: RollupCreatorSupportedVersion = 'v3.2';
const rollupTimingParams: CustomTimingParams = {
confirmPeriodBlocks: 150n,
Expand Down Expand Up @@ -353,7 +355,7 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
});

l1RpcCachingProxy = await startRpcCachingProxy(anvilForkUrl, cacheFilePath, {
forkBlockNumber: testConstants.DEFAULT_SEPOLIA_FORK_BLOCK_NUMBER,
forkBlockNumber: testConstants.SEPOLIA_FORK_BLOCK_NUMBER,
});

const l1RpcUrlWithCaching = l1RpcCachingProxy.proxyUrl;
Expand All @@ -374,7 +376,7 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
l1RpcPort,
anvilImage,
anvilForkUrl: l1RpcUrlWithCaching,
anvilForkBlockNumber: testConstants.DEFAULT_SEPOLIA_FORK_BLOCK_NUMBER,
anvilForkBlockNumber: testConstants.SEPOLIA_FORK_BLOCK_NUMBER,
chainId: sepolia.id,
});

Expand All @@ -389,6 +391,7 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
const l1Client = createPublicClient({
chain: l1Chain,
transport: http(l1RpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
});
registerChainForRpcUrl({ rpcUrl: l1RpcUrl, chain: l1Chain });

Expand Down Expand Up @@ -462,7 +465,7 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
validatorPrivateKey: validatorAccount.privateKey,
stakeToken: l2RollupConfig.stakeToken,
parentChainId: sepolia.id,
parentChainRpcUrl: `http://${l1ContainerName}:8545`,
parentChainRpcUrl: `http://${l1ContainerName}:${l1RpcPort}`,
parentChainBeaconRpcUrl: sepoliaBeaconRpc,
});

Expand Down Expand Up @@ -535,12 +538,14 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
let l2Client: PublicClient<Transport, Chain> = createPublicClient({
chain: l2BootstrapChain,
transport: http(l2RpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
});

const l2WalletClient = createWalletClient({
chain: l2BootstrapChain,
transport: http(l2RpcUrl),
account: harnessDeployer,
pollingInterval: testConstants.POLLING_INTERVAL,
});

const l2BlockAdvancer = createBlockAdvancer({
Expand All @@ -549,6 +554,7 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
chain: l2BootstrapChain,
transport: http(l2RpcUrl),
account: l2BlockAdvancerAccount,
pollingInterval: testConstants.POLLING_INTERVAL,
}),
account: l2BlockAdvancerAccount,
});
Expand All @@ -566,6 +572,8 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
console.log('L2 create2 factory is ready\n');

const l2Provider = new ethers.providers.JsonRpcProvider(l2RpcUrl);
l2Provider.pollingInterval = testConstants.POLLING_INTERVAL;

const l2Signer = new ethers.Wallet(harnessDeployer.privateKey, l2Provider);

console.log('Deploying L2 custom gas token...');
Expand Down Expand Up @@ -635,6 +643,7 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
l2Client = createPublicClient({
chain: l2Chain,
transport: http(l2RpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
});

console.log('Deploying L3 rollup contracts on L2...');
Expand Down Expand Up @@ -679,7 +688,7 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
stakeToken: l3RollupConfig.stakeToken,
parentChainId: l2ChainId as ParentChainId,
parentChainIsArbitrum: true,
parentChainRpcUrl: `http://${l2ContainerName}:8449`,
parentChainRpcUrl: `http://${l2ContainerName}:${l2RpcPort}`,
});

if (
Expand Down Expand Up @@ -737,11 +746,13 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
const l3Client = createPublicClient({
chain: l3Chain,
transport: http(l3RpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
});
const l3WalletClient = createWalletClient({
chain: l3Chain,
transport: http(l3RpcUrl),
account: harnessDeployer,
pollingInterval: testConstants.POLLING_INTERVAL,
});

await (
Expand Down Expand Up @@ -814,6 +825,7 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
chain: l2Chain,
transport: http(l2RpcUrl),
account: l2BlockAdvancerAccount,
pollingInterval: testConstants.POLLING_INTERVAL,
});

const l3BlockAdvancer = createBlockAdvancer({
Expand All @@ -822,6 +834,7 @@ export async function setupAnvilTestStack(): Promise<AnvilTestStack> {
chain: l3Chain,
transport: http(l3RpcUrl),
account: l3BlockAdvancerAccount,
pollingInterval: testConstants.POLLING_INTERVAL,
}),
account: l3BlockAdvancerAccount,
});
Expand Down
46 changes: 34 additions & 12 deletions src/integrationTestHelpers/anvilHarnessHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import { ethers } from 'ethers';

import { arbOwnerABI, arbOwnerAddress } from '../contracts/ArbOwner';
import { erc20ABI } from '../contracts/ERC20';
import { erc20InboxABI } from '../contracts/IERC20Inbox';
import { inboxABI } from '../contracts/Inbox';
import { erc20InboxABI } from '../contracts/ERC20Inbox';
import { tokenBridgeCreatorAddress } from '../contracts/TokenBridgeCreator';
import { testConstants } from './constants';
import {
Expand Down Expand Up @@ -92,7 +93,7 @@ async function getRequiredRetryableFunding(

const retryableSubmissionFee = await l1Client.readContract({
address: inbox,
abi: testConstants.inboxFundingAbi,
abi: inboxABI,
functionName: 'calculateRetryableSubmissionFee',
args: [0n, l1BaseFeePerGas],
});
Expand Down Expand Up @@ -197,13 +198,25 @@ export async function fundL2Deployer(params: {
inbox: Address;
}) {
const { l1RpcUrl, l2RpcUrl, l2Chain, deployer, inbox } = params;
const l1Client = createPublicClient({ chain: sepolia, transport: http(l1RpcUrl) });

const l1Client = createPublicClient({
chain: sepolia,
transport: http(l1RpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
});

const l1WalletClient = createWalletClient({
chain: sepolia,
transport: http(l1RpcUrl),
account: deployer,
pollingInterval: testConstants.POLLING_INTERVAL,
});

const l2Client = createPublicClient({
chain: l2Chain,
transport: http(l2RpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
});
const l2Client = createPublicClient({ chain: l2Chain, transport: http(l2RpcUrl) });

const fundAmount = parseEther('1000');
const retryableGasLimit = BigInt(100_000);
Expand All @@ -225,7 +238,7 @@ export async function fundL2Deployer(params: {
to: inbox,
value: fundAmount + maxSubmissionCost + retryableGasLimit * l2MaxFeePerGas,
data: encodeFunctionData({
abi: testConstants.inboxFundingAbi,
abi: inboxABI,
functionName: 'createRetryableTicketNoRefundAliasRewrite',
args: [
deployer.address,
Expand All @@ -250,7 +263,7 @@ export async function fundL2Deployer(params: {
return currentBalance;
}

await sleep(1000);
await sleep(100);
}

throw new Error(
Expand Down Expand Up @@ -309,8 +322,7 @@ export async function bridgeNativeTokenToOrbitChain(params: {
if (updatedBalance >= targetBalance) {
return updatedBalance;
}

await sleep(1000);
await sleep(100);
}

const finalBalance = await childPublicClient.getBalance({ address: depositor.address });
Expand Down Expand Up @@ -359,15 +371,21 @@ export async function setBalanceOnL1(params: {
address: Address;
balance: bigint;
}) {
const publicClient = createPublicClient({ transport: http(params.rpcUrl) });
const publicClient = createPublicClient({
transport: http(params.rpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
});
await publicClient.request({
method: 'anvil_setBalance' as never,
params: [params.address, `0x${params.balance.toString(16)}`] as never,
});
}

export async function refreshForkTime(params: { rpcUrl: string }) {
const publicClient = createPublicClient({ transport: http(params.rpcUrl) });
const publicClient = createPublicClient({
transport: http(params.rpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
});
const now = Math.floor(Date.now() / 1000);

await publicClient.request({
Expand Down Expand Up @@ -428,7 +446,7 @@ export function startBlockAdvancing(blockAdvancer: BlockAdvancer): void {
// ignore and keep advancing blocks
}

await sleep(1000);
await sleep(100);
}
} finally {
if (blockAdvancingStates.get(blockAdvancer) === state) {
Expand Down Expand Up @@ -498,7 +516,11 @@ export async function deployTokenBridgeCreator(
(chain.contracts.tokenBridgeCreator as ChainContract).address = address;
} else {
const chainId =
chain?.id ?? (await createPublicClient({ transport: http(params.rpcUrl) }).getChainId());
chain?.id ??
(await createPublicClient({
transport: http(params.rpcUrl),
pollingInterval: testConstants.POLLING_INTERVAL,
}).getChainId());
(tokenBridgeCreatorAddress as Record<number, Address>)[chainId] = address;
}

Expand Down
Loading
Loading