Skip to content

Commit 6cff375

Browse files
authored
Mocks + DoubleProvider (#30)
* simplify test-e2e.bash * add v5 to v6 conversion functions and add a note * return both versions of wallets and providers * mocks * move util to scripts/template * ... * getEnv fix * Revert "getEnv fix" This reverts commit f985a44684a070be3cc2b197ead5cfdde63a259c. * double provider (#33) * double provider * inheritance * better types * ... * update readme
1 parent 84db337 commit 6cff375

File tree

8 files changed

+82
-36
lines changed

8 files changed

+82
-36
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ To add the fork test setup to an existing hardhat+foundry project:
4444
- Copy `test/fork/` directory
4545
- Copy `test:fork` package script
4646

47-
## E2E Tests and the Arbitrum SDK
47+
## E2E Tests, the Arbitrum SDK, and `DoubleWallet` / `DoubleProvider`
4848
End to end tests are located in `test/e2e/`, and ran by `yarn test:e2e`.
4949

5050
The GitHub workflow defined in `.github/workflows/test-e2e.yml` will run test files against an L1+L2 nitro testnode setup by default. There are commented out jobs that add an L3 with ETH or custom fees.
@@ -57,6 +57,16 @@ A separate ethers v5 dev dependency is included and can be imported for use with
5757
import { ethers as ethersv5 } from 'ethers-v5'
5858
```
5959

60+
Instead of using providers and wallets directly, use `DoubleProvider` and `DoubleWallet` defined in `scripts/template/util.ts`. Using these classes / types makes dealing with the two ethers version much easier.
61+
62+
## Using Mock Contracts
63+
Mock contracts like test tokens should live in `test/mocks`. Hardhat does not generate artifacts or types for contracts in `test/`, so to deploy and use them you should use foundry artifacts. For example:
64+
65+
```typescript
66+
import ArbSysMockArtifact from 'out/ArbSysMock.sol/ArbSysMock.json'
67+
new ContractFactory(ArbSysMockArtifact.abi, ArbSysMockArtifact.bytecode, signer).deploy()
68+
```
69+
6070
### Disabling / Removing
6171
To disable the end to end testing CI jobs, remove `on: pull_request:` from `.github/workflows/test-e2e.yml`
6272

scripts/template/delete-samples.bash

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,8 @@ rm test/fork/Sample.t.sol test/fork/Sample.test.ts
1414
# remove sample e2e tests
1515
rm test/e2e/Counter.test.ts
1616

17+
# remove sample mock
18+
rm test/mocks/SampleMock.sol
19+
1720
# delete this script as it is no longer needed
1821
rm scripts/template/delete-samples.bash

scripts/template/util.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { JsonRpcProvider, Provider, Wallet } from 'ethers'
2+
import { ethers as ethersv5 } from 'ethers-v5'
3+
4+
export type Unwrap<T> = T extends Promise<infer U> ? U : T
5+
6+
export function getEnv(name: string): string {
7+
const value = process.env[name] || ''
8+
if (value === '') {
9+
throw new Error(`Environment variable ${name} is not defined`)
10+
}
11+
return value
12+
}
13+
14+
export class DoubleProvider extends JsonRpcProvider {
15+
public readonly v5: ethersv5.providers.JsonRpcProvider
16+
constructor(public readonly url: string) {
17+
super(url)
18+
this.v5 = new ethersv5.providers.JsonRpcProvider(url)
19+
}
20+
}
21+
22+
export class DoubleWallet extends Wallet {
23+
public readonly provider!: Provider
24+
public readonly v5: ethersv5.Wallet & {
25+
provider: ethersv5.providers.JsonRpcProvider
26+
}
27+
28+
constructor(
29+
privateKey: string,
30+
public readonly doubleProvider: DoubleProvider
31+
) {
32+
super(privateKey, doubleProvider)
33+
this.v5 = new ethersv5.Wallet(
34+
privateKey,
35+
doubleProvider.v5
36+
) as ethersv5.Wallet & { provider: ethersv5.providers.JsonRpcProvider }
37+
}
38+
}

test/e2e/Counter.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ This repository uses ethers v6, but the arbitrum sdk uses ethers v5.
77
88
Using the sdk might be a bit tricky, but you can import v5 like this:
99
import { ethers as ethersv5 } from 'ethers-v5'
10+
11+
testSetup will return both v5 and v6 versions of signers and providers.
1012
*/
1113

1214
describe('E2E Sample', () => {

test/e2e/test-e2e.bash

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,11 @@ else
1212
export ORBIT_TEST=1
1313
fi
1414

15-
cd lib/arbitrum-sdk && yarn gen:network && cd -
16-
17-
# if the above command fails, exit
18-
if [ $? -ne 0 ]; then
19-
echo "Failed to generate network"
20-
exit 1
21-
fi
15+
set -e
2216

23-
yarn hardhat compile
17+
cd lib/arbitrum-sdk && yarn gen:network && cd -
2418

25-
if [ $? -ne 0 ]; then
26-
echo "Failed to compile"
27-
exit 1
28-
fi
19+
yarn build
2920

3021
yarn mocha test/e2e/ --timeout 30000000 --bail
3122

test/e2e/testSetup.ts

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
1-
import { JsonRpcProvider, Wallet } from 'ethers'
21
import { testSetup as sdkTestSetup } from '../../lib/arbitrum-sdk/scripts/testSetup'
32
import { L1Network, L2Network, getL1Network } from '../../lib/arbitrum-sdk/src'
4-
import { getEnv } from '../util/util'
3+
import {
4+
DoubleProvider,
5+
DoubleWallet,
6+
getEnv,
7+
} from '../../scripts/template/util'
58

69
export const isTestingOrbit = process.env.ORBIT_TEST === '1'
710

811
type BaseTestSetup = {
912
l1Network: L1Network
1013
l2Network: L2Network
11-
l1Signer: Wallet
12-
l2Signer: Wallet
13-
l1Provider: JsonRpcProvider
14-
l2Provider: JsonRpcProvider
14+
l1Signer: DoubleWallet
15+
l2Signer: DoubleWallet
16+
l1Provider: DoubleProvider
17+
l2Provider: DoubleProvider
1518
}
1619

1720
export type OrbitTestSetup = BaseTestSetup & {
1821
isTestingOrbit: true
1922
l3Network: L2Network
20-
l3Provider: JsonRpcProvider
21-
l3Signer: Wallet
23+
l3Provider: DoubleProvider
24+
l3Signer: DoubleWallet
2225
}
2326

2427
export type NonOrbitTestSetup = BaseTestSetup & {
@@ -28,16 +31,16 @@ export type NonOrbitTestSetup = BaseTestSetup & {
2831
export type TestSetup = OrbitTestSetup | NonOrbitTestSetup
2932

3033
export async function testSetup(): Promise<TestSetup> {
31-
const l1Provider = new JsonRpcProvider(getEnv('LOCAL_L1_URL'))
32-
const l2Provider = new JsonRpcProvider(getEnv('LOCAL_L2_URL'))
33-
const l1Signer = new Wallet(getEnv('LOCAL_L1_KEY'), l1Provider)
34-
const l2Signer = new Wallet(getEnv('LOCAL_L2_KEY'), l2Provider)
34+
const l1Provider = new DoubleProvider(getEnv('LOCAL_L1_URL'))
35+
const l2Provider = new DoubleProvider(getEnv('LOCAL_L2_URL'))
36+
const l1Signer = new DoubleWallet(getEnv('LOCAL_L1_KEY'), l1Provider)
37+
const l2Signer = new DoubleWallet(getEnv('LOCAL_L2_KEY'), l2Provider)
3538

3639
const setup = await sdkTestSetup()
3740

3841
if (isTestingOrbit) {
39-
const l3Provider = new JsonRpcProvider(getEnv('LOCAL_L3_URL'))
40-
const l3Signer = new Wallet(getEnv('LOCAL_L3_KEY'), l3Provider)
42+
const l3Provider = new DoubleProvider(getEnv('LOCAL_L3_URL'))
43+
const l3Signer = new DoubleWallet(getEnv('LOCAL_L3_KEY'), l3Provider)
4144

4245
const l1Network = await getL1Network(
4346
(setup.l1Network as L2Network).partnerChainID

test/mocks/SampleMock.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.16;
3+
4+
contract SampleMock {
5+
function arbOSVersion() external pure returns (uint256) {
6+
return 1;
7+
}
8+
}

test/util/util.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)