Skip to content

Commit

Permalink
🤡 Optimism integration (#728)
Browse files Browse the repository at this point in the history
  • Loading branch information
yivlad authored May 16, 2022
1 parent 79a421f commit e69f739
Show file tree
Hide file tree
Showing 29 changed files with 338 additions and 33 deletions.
6 changes: 6 additions & 0 deletions .changeset/dirty-walls-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@ethereum-waffle/chai": patch
"@ethereum-waffle/optimism": patch
---

Support testing on optimism
41 changes: 41 additions & 0 deletions .github/workflows/optimism-testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Optimism testing

on:
push:
branches:
- changeset-release/*
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
# test against a known version and a current master
OPTIMISM_GIT_HEAD: ["b0a54509a6f99194221f5ade230ceae7892b3393", "master"]
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: pnpm/action-setup@v2
with:
version: 6.32.4
- name: Setup Node.js 16.x
uses: actions/setup-node@v3.0.0
with:
node-version: 16.x
- name: Build project
run: |
pnpm install
pnpm build
- name: Setup optimism node
run: |
cd ..
git clone https://github.com/ethereum-optimism/optimism.git
cd optimism/ops
git checkout ${{ matrix.OPTIMISM_GIT_HEAD }}
docker-compose pull
docker-compose up &
scripts/wait-for-sequencer.sh && echo "System is ready to accept transactions"
- name: Test optimism
run: |
cd waffle-optimism
pnpm run test:optimism
17 changes: 17 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions waffle-chai/src/matchers/changeEtherBalance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ export async function getBalanceChange(
const gasPrice = txResponse.gasPrice ?? txReceipt.effectiveGasPrice;
const gasUsed = txReceipt.gasUsed;
const txFee = gasPrice.mul(gasUsed);
const provider = account.provider as any;
if (typeof provider.getL1Fee === 'function') {
const l1Fee = await provider.getL1Fee(txReceipt.transactionHash);
return balanceAfter.add(txFee).add(l1Fee).sub(balanceBefore);
}

return balanceAfter.add(txFee).sub(balanceBefore);
} else {
Expand Down
5 changes: 5 additions & 0 deletions waffle-chai/src/matchers/changeEtherBalances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ async function getTxFees(
const gasPrice = txResponse.gasPrice ?? txReceipt.effectiveGasPrice;
const gasUsed = txReceipt.gasUsed;
const txFee = gasPrice.mul(gasUsed);
const provider = account.provider as any;
if (typeof provider.getL1Fee === 'function') {
const l1Fee = await provider.getL1Fee(txReceipt.transactionHash);
return txFee.add(l1Fee);
}

return txFee;
}
Expand Down
18 changes: 18 additions & 0 deletions waffle-chai/src/matchers/revertedWith.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export function supportRevertedWith(Assertion: Chai.AssertionStatic) {
const onError = (error: any) => {
const revertString = error?.receipt?.revertString ??
decodeHardhatError(error, this) ??
decodeOptimismError(error) ??
decodeRevertString(error);

const isReverted = revertReason instanceof RegExp
Expand Down Expand Up @@ -73,3 +74,20 @@ const decodeHardhatError = (error: any, context: any) => {

return tryDecode(error) ?? tryDecode(error.error); // the error may be wrapped
};

const decodeOptimismError = (error: any) => {
const tryDecode = (error: any) => {
const body = error?.body;
if (body) {
const regexp = /"execution reverted: (.*)"/g;
const matches = regexp.exec(body);
if (matches && matches.length >= 1) {
return matches[1];
}
}
};

return tryDecode(error) ??
tryDecode(error?.error) ??
tryDecode(error?.error?.error);
};
3 changes: 2 additions & 1 deletion waffle-chai/test/matchers/changeEtherBalance.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {changeEtherBalanceTest} from './changeEtherBalanceTest';
import {BASE_FEE_PER_GAS, TX_GAS} from './constants';
import {describeMockProviderCases} from './MockProviderCases';

describeMockProviderCases('INTEGRATION: changeEtherBalance matcher', (provider) => {
changeEtherBalanceTest(provider);
changeEtherBalanceTest(provider, {txGasFees: TX_GAS * BASE_FEE_PER_GAS, baseFeePerGas: BASE_FEE_PER_GAS});
});
28 changes: 18 additions & 10 deletions waffle-chai/test/matchers/changeEtherBalanceTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,28 @@ import {MockProvider} from '@ethereum-waffle/provider';
import {expect, AssertionError} from 'chai';
import {BigNumber, Contract, Wallet} from 'ethers';

import {BASE_FEE_PER_GAS, TX_GAS} from './constants';

export const changeEtherBalanceTest = (provider: MockProvider) => {
interface ChangeEtherBalanceTestOptions {
txGasFees: number | (() => number);
baseFeePerGas: number;
}

export const changeEtherBalanceTest = (
provider: MockProvider,
options: ChangeEtherBalanceTestOptions
) => {
let txGasFees: number;
let baseFeePerGas: number;
let sender: Wallet;
let receiver: Wallet;
let contract: Contract;
let txGasFees: number;

before(() => {
txGasFees = typeof options.txGasFees === 'function' ? options.txGasFees() : options.txGasFees;
baseFeePerGas = options.baseFeePerGas;
const wallets = provider.getWallets();
sender = wallets[0];
receiver = wallets[1];
contract = new Contract(receiver.address, [], provider);
txGasFees = BASE_FEE_PER_GAS * TX_GAS;
});

describe('Transaction Callback', () => {
Expand All @@ -42,7 +50,7 @@ export const changeEtherBalanceTest = (provider: MockProvider) => {
await expect(() =>
sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalance(sender, -(txGasFees + 200), {includeFee: true});
Expand All @@ -52,7 +60,7 @@ export const changeEtherBalanceTest = (provider: MockProvider) => {
await expect(() =>
sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalance(receiver, 200, {includeFee: true});
Expand All @@ -62,7 +70,7 @@ export const changeEtherBalanceTest = (provider: MockProvider) => {
await expect(() =>
sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalance(sender, -200);
Expand Down Expand Up @@ -91,13 +99,13 @@ export const changeEtherBalanceTest = (provider: MockProvider) => {
expect(() =>
sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalance(sender, -200, {includeFee: true})
).to.be.eventually.rejectedWith(
AssertionError,
`Expected "${sender.address}" to change balance by -200 wei, but it has changed by -18375000000200 wei`
`Expected "${sender.address}" to change balance by -200 wei, but it has changed by -${txGasFees + 200} wei`
);
});

Expand Down
3 changes: 2 additions & 1 deletion waffle-chai/test/matchers/changeEtherBalances.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {changeEtherBalancesTest} from './changeEtherBalancesTest';
import {TX_GAS, BASE_FEE_PER_GAS} from './constants';
import {describeMockProviderCases} from './MockProviderCases';

describeMockProviderCases('INTEGRATION: changeEtherBalances matcher', (provider) => {
changeEtherBalancesTest(provider);
changeEtherBalancesTest(provider, {txGasFees: TX_GAS * BASE_FEE_PER_GAS, baseFeePerGas: BASE_FEE_PER_GAS});
});
38 changes: 23 additions & 15 deletions waffle-chai/test/matchers/changeEtherBalancesTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,30 @@ import {MockProvider} from '@ethereum-waffle/provider';
import {expect, AssertionError} from 'chai';
import {Contract, Wallet} from 'ethers';

import {BASE_FEE_PER_GAS, TX_GAS} from './constants';

export const changeEtherBalancesTest = (provider: MockProvider) => {
interface ChangeEtherBalancesTestOptions {
txGasFees: number | (() => number);
baseFeePerGas: number;
}

export const changeEtherBalancesTest = (
provider: MockProvider,
options: ChangeEtherBalancesTestOptions
) => {
let txGasFees: number;
let baseFeePerGas: number;
let sender: Wallet;
let receiver: Wallet;
let contractWallet: Wallet;
let contract: Contract;
let txGasFees: number;

before(() => {
txGasFees = typeof options.txGasFees === 'function' ? options.txGasFees() : options.txGasFees;
baseFeePerGas = options.baseFeePerGas;
const wallets = provider.getWallets();
sender = wallets[0];
receiver = wallets[1];
contractWallet = wallets[2];
contract = new Contract(contractWallet.address, [], provider);
txGasFees = BASE_FEE_PER_GAS * TX_GAS;
});

describe('Transaction Callback', () => {
Expand All @@ -37,7 +45,7 @@ export const changeEtherBalancesTest = (provider: MockProvider) => {
await expect(() =>
sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalances([sender, receiver], ['-200', 200]);
Expand All @@ -47,7 +55,7 @@ export const changeEtherBalancesTest = (provider: MockProvider) => {
await expect(() =>
sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalances([sender, receiver, contract], [-(txGasFees + 200), 200, 0], {includeFee: true});
Expand All @@ -57,7 +65,7 @@ export const changeEtherBalancesTest = (provider: MockProvider) => {
await expect(() =>
sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.not.changeEtherBalances([sender, receiver], [-(txGasFees + 201), 200]);
Expand All @@ -74,7 +82,7 @@ export const changeEtherBalancesTest = (provider: MockProvider) => {
expect(() =>
sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalances([sender, receiver], [-200, 201])
Expand All @@ -87,7 +95,7 @@ export const changeEtherBalancesTest = (provider: MockProvider) => {
expect(() =>
sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalances([sender, receiver], [-201, 200])
Expand All @@ -103,7 +111,7 @@ export const changeEtherBalancesTest = (provider: MockProvider) => {
expect(() =>
sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.not.changeEtherBalances([sender, receiver], [-200, 200])
Expand Down Expand Up @@ -131,7 +139,7 @@ export const changeEtherBalancesTest = (provider: MockProvider) => {
it('Should pass when all expected balance changes are equal to actual values', async () => {
await expect(await sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalances([sender, receiver], [(-(txGasFees + 200)).toString(), 200], {includeFee: true});
Expand All @@ -140,7 +148,7 @@ export const changeEtherBalancesTest = (provider: MockProvider) => {
it('Should take into account transaction fee', async () => {
await expect(await sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalances([sender, receiver, contract], [-(txGasFees + 200), 200, 0], {includeFee: true});
Expand All @@ -164,14 +172,14 @@ export const changeEtherBalancesTest = (provider: MockProvider) => {
await expect(
expect(await sender.sendTransaction({
to: receiver.address,
gasPrice: BASE_FEE_PER_GAS,
gasPrice: baseFeePerGas,
value: 200
})
).to.changeEtherBalances([sender, receiver], [-200, 200], {includeFee: true})
).to.be.eventually.rejectedWith(
AssertionError,
`Expected ${sender.address},${receiver.address} to change balance ` +
'by -200,200 wei, but it has changed by -18375000000200,200 wei'
`by -200,200 wei, but it has changed by -${txGasFees + 200},200 wei`
);
});

Expand Down
15 changes: 11 additions & 4 deletions waffle-chai/test/matchers/revertedWithTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import {MATCHERS_ABI, MATCHERS_BYTECODE} from '../contracts/Matchers';

import {MockProvider} from '@ethereum-waffle/provider';

export const revertedWithTest = (provider: MockProvider) => {
interface RevertedWithTestingOptions {
includePanicCodes?: boolean;
}

export const revertedWithTest = (provider: MockProvider, options: RevertedWithTestingOptions = {}) => {
const panicCodes = options.includePanicCodes ?? true;
let wallet: Wallet;
let matchers: Contract;

Expand Down Expand Up @@ -182,7 +187,9 @@ export const revertedWithTest = (provider: MockProvider) => {
).to.be.eventually.rejected;
});

it('Handle panic error', async () => {
await expect(matchers.doPanic()).to.be.revertedWith('panic code 0x12');
});
if (panicCodes) {
it('Handle panic error', async () => {
await expect(matchers.doPanic()).to.be.revertedWith('panic code 0x12');
});
}
};
3 changes: 2 additions & 1 deletion waffle-hardhat/test/changeEtherBalance.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {waffle} from 'hardhat';
import {MockProvider} from 'ethereum-waffle';
import {changeEtherBalanceTest} from '@ethereum-waffle/chai/test';
import {TX_GAS, BASE_FEE_PER_GAS} from './constants';

describe('INTEGRATION: changeEtherBalance matcher', () => {
const provider = waffle.provider as MockProvider;
Expand All @@ -9,5 +10,5 @@ describe('INTEGRATION: changeEtherBalance matcher', () => {
await provider.send('hardhat_reset', []);
});

changeEtherBalanceTest(provider);
changeEtherBalanceTest(provider, {txGasFees: TX_GAS * BASE_FEE_PER_GAS, baseFeePerGas: BASE_FEE_PER_GAS});
});
Loading

0 comments on commit e69f739

Please sign in to comment.