Skip to content

Commit

Permalink
Merge pull request #183 from OffchainLabs/e2e-withdraw
Browse files Browse the repository at this point in the history
Add fund withdrawal e2e test to CI
  • Loading branch information
gzeoneth authored Jul 1, 2024
2 parents cfd5cb8 + 4acde7d commit a1f57bf
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 83 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/contract-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ jobs:
- name: Setup nodejs
uses: actions/setup-node@v2
with:
node-version: '18'
node-version: 18
cache: 'yarn'
cache-dependency-path: '**/yarn.lock'

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
},
"private": false,
"devDependencies": {
"@arbitrum/sdk": "^3.1.3",
"@arbitrum/sdk": "^3.4.1",
"@ethersproject/providers": "^5.7.2",
"@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers@^0.3.0-beta.13",
"@nomiclabs/hardhat-etherscan": "^3.1.0",
Expand Down
7 changes: 4 additions & 3 deletions scripts/testSetup.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { JsonRpcProvider } from '@ethersproject/providers'
import { L1Network, L2Network } from '@arbitrum/sdk'
import { execSync } from 'child_process'
import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory'
import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory'
import { Bridge__factory, RollupAdminLogic__factory } from '../build/types'

export function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms))
Expand Down Expand Up @@ -77,6 +76,8 @@ export const getLocalNetworks = async (
isCustom: true,
name: 'ArbLocal',
partnerChainID: l1NetworkInfo.chainId,
partnerChainIDs: [],
blockTime: 1,
retryableLifetimeSeconds: 7 * 24 * 60 * 60,
nitroGenesisBlock: 0,
nitroGenesisL1Block: 0,
Expand All @@ -86,4 +87,4 @@ export const getLocalNetworks = async (
l1Network,
l2Network,
}
}
}
136 changes: 62 additions & 74 deletions test/e2e/orbitChain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,7 @@ describe('Orbit Chain', () => {
const userL2BalanceAfter = await l2Provider.getBalance(userL2Wallet.address)
let expectedL2BalanceIncrease = amountToDeposit
if (nativeToken) {
expectedL2BalanceIncrease = await _getScaledAmount(
nativeToken,
amountToDeposit
)
expectedL2BalanceIncrease = await _scaleFromNativeTo18(amountToDeposit)
}
expect(userL2BalanceAfter.sub(userL2Balance)).to.be.eq(
expectedL2BalanceIncrease
Expand Down Expand Up @@ -267,10 +264,7 @@ describe('Orbit Chain', () => {
/// deposit tokens using retryable
let retryableTx: ContractTransaction
if (nativeToken) {
tokenTotalFeeAmount = await _getPrescaledAmount(
nativeToken,
retryableParams.deposit
)
tokenTotalFeeAmount = await _scaleFrom18ToNative(retryableParams.deposit)

await (
await nativeToken
Expand Down Expand Up @@ -353,7 +347,7 @@ describe('Orbit Chain', () => {
// due to rounding effect there can be some funds left on alias address
if (nativeToken && (await nativeToken.decimals()) < 18) {
expectedAliasL2BalanceExtraFunds = (
await _getScaledAmount(nativeToken, tokenTotalFeeAmount)
await _scaleFromNativeTo18(tokenTotalFeeAmount)
).sub(retryableParams.deposit)
}
expect(aliasL2BalanceAfter.sub(expectedAliasL2BalanceExtraFunds)).to.be.eq(
Expand Down Expand Up @@ -442,10 +436,7 @@ describe('Orbit Chain', () => {
/// execute retryable
let retryableTx: ContractTransaction
if (nativeToken) {
tokenTotalFeeAmount = await _getPrescaledAmount(
nativeToken,
retryableParams.deposit
)
tokenTotalFeeAmount = await _scaleFrom18ToNative(retryableParams.deposit)

await (
await nativeToken
Expand Down Expand Up @@ -531,7 +522,7 @@ describe('Orbit Chain', () => {
// due to rounding effect there can be some funds left on alias address
if (nativeToken && (await nativeToken.decimals()) < 18) {
expectedAliasL2BalanceExtraFunds = (
await _getScaledAmount(nativeToken, tokenTotalFeeAmount)
await _scaleFromNativeTo18(tokenTotalFeeAmount)
).sub(retryableParams.deposit)
}
expect(aliasL2BalanceAfter.sub(expectedAliasL2BalanceExtraFunds)).to.be.eq(
Expand All @@ -551,7 +542,7 @@ describe('Orbit Chain', () => {
)
})

xit('can withdraw funds from L2 to L1', async function () {
it('can withdraw funds from L2 to L1', async function () {
// snapshot state before issuing retryable
let userL1NativeAssetBalance: BigNumber
let bridgeL1NativeAssetBalance: BigNumber
Expand All @@ -578,7 +569,7 @@ describe('Orbit Chain', () => {
'0x0000000000000000000000000000000000000064',
l2Provider
)
const withdrawAmount = await _applyDecimalsToAmount('1')
const withdrawAmount = ethers.utils.parseEther('1')
const withdrawTx = await arbSys
.connect(userL2Wallet)
.sendTxToL1(userL1Wallet.address, '0x', {
Expand All @@ -588,8 +579,6 @@ describe('Orbit Chain', () => {
const l2Receipt = new L2TransactionReceipt(withdrawReceipt)

// wait until dispute period passes and withdrawal is ready for execution
await sleep(5 * 1000)

const messages = await l2Receipt.getL2ToL1Messages(userL1Wallet)
const l2ToL1Msg = messages[0]
const timeToWaitMs = 60 * 1000
Expand All @@ -599,29 +588,46 @@ describe('Orbit Chain', () => {
await (await l2ToL1Msg.execute(l2Provider)).wait()

// check balances after withdrawal is processed
let userL1TokenAfter, bridgeL1TokenAfter: BigNumber
if (nativeToken) {
userL1TokenAfter = await nativeToken.balanceOf(userL1Wallet.address)
const withdrawAmountInNativeDecimals =
nativeToken == undefined
? withdrawAmount
: await _scaleFrom18ToNative(withdrawAmount)

bridgeL1TokenAfter = await nativeToken.balanceOf(
let userL1NativeAssetBalanceAfter,
bridgeL1NativeAssetBalanceAfter: BigNumber
if (nativeToken) {
userL1NativeAssetBalanceAfter = await nativeToken.balanceOf(
userL1Wallet.address
)
bridgeL1NativeAssetBalanceAfter = await nativeToken.balanceOf(
l2Network.ethBridge.bridge
)
expect(
userL1NativeAssetBalanceAfter.sub(userL1NativeAssetBalance)
).to.be.eq(withdrawAmountInNativeDecimals)
} else {
userL1TokenAfter = await l1Provider.getBalance(userL1Wallet.address)

bridgeL1TokenAfter = await l1Provider.getBalance(
userL1NativeAssetBalanceAfter = await l1Provider.getBalance(
userL1Wallet.address
)
bridgeL1NativeAssetBalanceAfter = await l1Provider.getBalance(
l2Network.ethBridge.bridge
)
expect(
userL1NativeAssetBalanceAfter.sub(userL1NativeAssetBalance)
).to.be.lte(withdrawAmount)
expect(
userL1NativeAssetBalanceAfter.sub(userL1NativeAssetBalance)
).to.be.gt(BigNumber.from(0))
}
expect(userL1NativeAssetBalance.sub(userL1TokenAfter)).to.be.eq(
withdrawAmount
)
expect(bridgeL1TokenAfter.sub(bridgeL1NativeAssetBalance)).to.be.eq(
withdrawAmount
)

expect(
bridgeL1NativeAssetBalance.sub(bridgeL1NativeAssetBalanceAfter)
).to.be.eq(withdrawAmountInNativeDecimals)

const userL2BalanceAfter = await l2Provider.getBalance(userL2Wallet.address)
expect(userL2BalanceAfter).to.be.lte(userL2Balance.sub(withdrawAmount))
expect(userL2BalanceAfter).to.be.lte(
userL2Balance.sub(withdrawAmountInNativeDecimals)
)
})

it('can deploy deterministic factories to L2', async function () {
Expand All @@ -646,39 +652,35 @@ describe('Orbit Chain', () => {
// as there could be rounding effect for each one of them
fee = BigNumber.from(0)
fee = fee.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(
await deployHelper.NICK_CREATE2_VALUE()
).add(maxFeePerGas.mul(BigNumber.from(21000)))
)
)
fee = fee.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(
await deployHelper.ERC2470_VALUE()
).add(maxFeePerGas.mul(BigNumber.from(21000)))
)
)
fee = fee.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(
await deployHelper.ZOLTU_VALUE()
).add(maxFeePerGas.mul(BigNumber.from(21000)))
)
)
fee = fee.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(
await deployHelper.ERC1820_VALUE()
).add(maxFeePerGas.mul(BigNumber.from(21000)))
)
)
} else {
fee = await _getPrescaledAmount(nativeToken, fee)
fee = await _scaleFrom18ToNative(fee)
}

await (
Expand Down Expand Up @@ -743,39 +745,35 @@ describe('Orbit Chain', () => {
// as there could be rounding effect for each one of them
fee = BigNumber.from(0)
fee = fee.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(
await deployHelper.NICK_CREATE2_VALUE()
).add(maxFeePerGas.mul(BigNumber.from(21000)))
)
)
fee = fee.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(
await deployHelper.ERC2470_VALUE()
).add(maxFeePerGas.mul(BigNumber.from(21000)))
)
)
fee = fee.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(
await deployHelper.ZOLTU_VALUE()
).add(maxFeePerGas.mul(BigNumber.from(21000)))
)
)
fee = fee.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(
await deployHelper.ERC1820_VALUE()
).add(maxFeePerGas.mul(BigNumber.from(21000)))
)
)
} else {
fee = await _getPrescaledAmount(nativeToken, fee)
fee = await _scaleFrom18ToNative(fee)
}

await (
Expand Down Expand Up @@ -926,31 +924,26 @@ describe('Orbit Chain', () => {
const gasCost = maxFeePerGas.mul(BigNumber.from(21000))
expectedAmountToBeMinted = BigNumber.from(0)
expectedAmountToBeMinted = expectedAmountToBeMinted.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(await deployHelper.NICK_CREATE2_VALUE()).add(gasCost)
)
)
expectedAmountToBeMinted = expectedAmountToBeMinted.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(await deployHelper.ERC2470_VALUE()).add(gasCost)
)
)
expectedAmountToBeMinted = expectedAmountToBeMinted.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(await deployHelper.ZOLTU_VALUE()).add(gasCost)
)
)
expectedAmountToBeMinted = expectedAmountToBeMinted.add(
await _getPrescaledAmount(
nativeToken,
await _scaleFrom18ToNative(
(await deployHelper.ERC1820_VALUE()).add(gasCost)
)
)
expectedAmountToBeMinted = await _getScaledAmount(
nativeToken,
expectedAmountToBeMinted = await _scaleFromNativeTo18(
expectedAmountToBeMinted
)
}
Expand All @@ -971,9 +964,9 @@ describe('Orbit Chain', () => {
)
expect(transferedFromDeployer.length).to.be.eq(1)
amountTransferedFromDeployer = transferedFromDeployer[0].value
expect(
await _getScaledAmount(nativeToken, amountTransferedFromDeployer)
).to.be.eq(amountToBeMinted)
expect(await _scaleFromNativeTo18(amountTransferedFromDeployer)).to.be.eq(
amountToBeMinted
)
} else {
amountTransferedFromDeployer = userL1NativeAssetBalance.sub(
await l1Provider.getBalance(userL1Wallet.address)
Expand Down Expand Up @@ -1030,9 +1023,8 @@ async function _verifyInboxMsg(
.add(maxFeePerGasForRetryables.mul(21000))
.add(_submissionCost(gasPrice))
if (nativeToken && (await nativeToken.decimals()) < 18) {
expectedAmountToBeMinted = await _getScaledAmount(
nativeToken,
await _getPrescaledAmount(nativeToken, expectedAmountToBeMinted)
expectedAmountToBeMinted = await _scaleFromNativeTo18(
await _scaleFrom18ToNative(expectedAmountToBeMinted)
)
}
expect(msg1.amountToBeMintedOnChildChain).to.be.eq(expectedAmountToBeMinted)
Expand Down Expand Up @@ -1123,11 +1115,8 @@ async function _getFeeToken(
return feeToken
}

async function _getScaledAmount(
nativeToken: ERC20,
amount: BigNumber
): Promise<BigNumber> {
const decimals = BigNumber.from(await nativeToken.decimals())
async function _scaleFromNativeTo18(amount: BigNumber): Promise<BigNumber> {
const decimals = BigNumber.from(await nativeToken!.decimals())
if (decimals.lt(BigNumber.from(18))) {
return amount.mul(BigNumber.from(10).pow(BigNumber.from(18).sub(decimals)))
} else if (decimals.gt(BigNumber.from(18))) {
Expand All @@ -1137,11 +1126,10 @@ async function _getScaledAmount(
return amount
}

async function _getPrescaledAmount(
nativeToken: ERC20,
async function _scaleFrom18ToNative(
amount: ethers.BigNumber
): Promise<BigNumber> {
const decimals = BigNumber.from(await nativeToken.decimals())
const decimals = BigNumber.from(await nativeToken!.decimals())
if (decimals.lt(BigNumber.from(18))) {
const scalingFactor = BigNumber.from(10).pow(
BigNumber.from(18).sub(decimals)
Expand Down
Loading

0 comments on commit a1f57bf

Please sign in to comment.