From 9858385a4c7880db8b6c191148f7bde5038707d7 Mon Sep 17 00:00:00 2001 From: Federico Giacon <58218759+fedgiac@users.noreply.github.com> Date: Mon, 9 Aug 2021 08:51:22 +0000 Subject: [PATCH] Enable London for hardhat network (gnosis/gp-v2-contracts#774) * Bump hardhat from 2.5.0 to 2.6.0 Bumps [hardhat](https://github.com/nomiclabs/hardhat) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/nomiclabs/hardhat/releases) - [Commits](https://github.com/nomiclabs/hardhat/compare/hardhat-core-v2.5.0...hardhat-core-v2.6.0) --- updated-dependencies: - dependency-name: hardhat dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Update tests to work in London Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hardhat.config.ts | 5 + package.json | 2 +- src/ts/settlement.ts | 7 ++ test/e2e/orderRefunds.test.ts | 172 ---------------------------------- yarn.lock | 18 ++-- 5 files changed, 22 insertions(+), 182 deletions(-) delete mode 100644 test/e2e/orderRefunds.test.ts diff --git a/hardhat.config.ts b/hardhat.config.ts index 6fc2ffae..4bd8ee56 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -43,6 +43,7 @@ if (["rinkeby", "mainnet"].includes(argv.network) && INFURA_KEY === undefined) { } const mocha: MochaOptions = {}; +let initialBaseFeePerGas: number | undefined = undefined; switch (MOCHA_CONF) { case undefined: break; @@ -53,6 +54,9 @@ switch (MOCHA_CONF) { // - coverage compiles without optimizer and, unlike Waffle, hardhat-deploy // strictly enforces the contract size limits from EIP-170 mocha.grep = /^(?!E2E|Task)/; + // Note: unit is Wei, not GWei. This is a workaround to make the coverage + // tool work with the London hardfork. + initialBaseFeePerGas = 1; break; case "ignored in coverage": mocha.grep = /^E2E|Task/; @@ -91,6 +95,7 @@ export default { networks: { hardhat: { blockGasLimit: 12.5e6, + initialBaseFeePerGas, }, mainnet: { ...sharedNetworkConfig, diff --git a/package.json b/package.json index 54d2dfe6..41bc5185 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "ethereum-waffle": "^3.4.0", "ethers": "^5.4.4", "globby": "^11.0.4", - "hardhat": "^2.5.0", + "hardhat": "^2.6.0", "hardhat-deploy": "^0.7.3", "hardhat-gas-reporter": "^1.0.4", "prettier": "^2.3.2", diff --git a/src/ts/settlement.ts b/src/ts/settlement.ts index 7759196c..b09af5a6 100644 --- a/src/ts/settlement.ts +++ b/src/ts/settlement.ts @@ -115,6 +115,13 @@ export interface TradeExecution { /** * Order refund data. + * + * Note: after the London hardfork (specifically the introduction of EIP-3529) + * order refunds have become meaningless as the refunded amount is less than the + * gas cost of triggering the refund. The logic surrounding this feature is kept + * in order to keep full test coverage and in case the value of a refund will be + * increased again in the future. However, order refunds should not be used in + * an actual settlement. */ export interface OrderRefunds { /** Refund storage used for order filled amount */ diff --git a/test/e2e/orderRefunds.test.ts b/test/e2e/orderRefunds.test.ts deleted file mode 100644 index 97e640bd..00000000 --- a/test/e2e/orderRefunds.test.ts +++ /dev/null @@ -1,172 +0,0 @@ -import ERC20 from "@openzeppelin/contracts/build/contracts/ERC20PresetMinterPauser.json"; -import { expect } from "chai"; -import Debug from "debug"; -import { Contract, Wallet } from "ethers"; -import { ethers, waffle } from "hardhat"; - -import { - OrderKind, - OrderRefunds, - SettlementEncoder, - SigningScheme, - TypedDataDomain, - computeOrderUid, - domain, -} from "../../src/ts"; - -import { deployTestContracts } from "./fixture"; - -const debug = Debug("e2e:orderRefunds"); - -describe("E2E: Expired Order Gas Refunds", () => { - let deployer: Wallet; - let solver: Wallet; - let traders: Wallet[]; - - let settlement: Contract; - let vaultRelayer: Contract; - let domainSeparator: TypedDataDomain; - - let owl: Contract; - let dai: Contract; - - beforeEach(async () => { - const deployment = await deployTestContracts(); - - ({ - deployer, - settlement, - vaultRelayer, - wallets: [solver, ...traders], - } = deployment); - - const { authenticator, manager } = deployment; - await authenticator.connect(manager).addSolver(solver.address); - - const { chainId } = await ethers.provider.getNetwork(); - domainSeparator = domain(chainId, settlement.address); - - owl = await waffle.deployContract(deployer, ERC20, ["OWL", 18]); - dai = await waffle.deployContract(deployer, ERC20, ["DAI", 18]); - }); - - it("should claim a gas refund for expired orders", async () => { - // Settle the same trvial batch between two overlapping trades twice: - // - // /--(1. SELL 100 OWL for DAI if p(OWL/DAI) >= 1)---\ - // | v - // [DAI] [OWL] - // ^ | - // \--(2. BUY 100 OWL for DAI if p(OWL/DAI) <= 1.1)--/ - - // NOTE: Mint extra tokens for all traders and the settlement contract to - // ensure that things like un-zeroing or zeroing a balance does not affect - // the gas usage results. - for (const token of [owl, dai]) { - await token.mint(settlement.address, ethers.utils.parseEther("1.0")); - for (const trader of traders.slice(0, 2)) { - await token.mint(trader.address, ethers.utils.parseEther("1000000.0")); - await token - .connect(trader) - .approve(vaultRelayer.address, ethers.constants.MaxUint256); - } - } - - const ORDER_VALIDITY = 60; // seconds - const prepareBatch = async (): Promise< - [SettlementEncoder, OrderRefunds] - > => { - const { timestamp } = await ethers.provider.getBlock("latest"); - const validTo = timestamp + ORDER_VALIDITY; - - const sellOrder = { - kind: OrderKind.SELL, - partiallyFillable: false, - sellToken: owl.address, - buyToken: dai.address, - sellAmount: ethers.utils.parseEther("100.0"), - buyAmount: ethers.utils.parseEther("100.0"), - feeAmount: ethers.utils.parseEther("0.1"), - validTo, - appData: 1, - }; - - const buyOrder = { - kind: OrderKind.BUY, - partiallyFillable: false, - buyToken: owl.address, - sellToken: dai.address, - buyAmount: ethers.utils.parseEther("100.0"), - sellAmount: ethers.utils.parseEther("110.0"), - feeAmount: ethers.utils.parseEther("0.1"), - validTo, - appData: 2, - }; - - const encoder = new SettlementEncoder(domainSeparator); - - const sellOrderUid = computeOrderUid( - domainSeparator, - sellOrder, - traders[0].address, - ); - await encoder.signEncodeTrade( - sellOrder, - traders[0], - SigningScheme.EIP712, - ); - - const buyOrderUid = computeOrderUid( - domainSeparator, - buyOrder, - traders[1].address, - ); - await settlement.connect(traders[1]).setPreSignature(buyOrderUid, true); - encoder.encodeTrade(buyOrder, { - scheme: SigningScheme.PRESIGN, - data: traders[1].address, - }); - - return [ - encoder, - { - filledAmounts: [sellOrderUid, buyOrderUid], - preSignatures: [buyOrderUid], - }, - ]; - }; - - const [encoder1, orderRefunds] = await prepareBatch(); - - const txWithoutRefunds = await settlement.connect(solver).settle( - ...encoder1.encodedSettlement({ - [owl.address]: ethers.utils.parseEther("1.05"), - [dai.address]: ethers.utils.parseEther("1.0"), - }), - ); - const { gasUsed: gasUsedWithoutRefunds } = await txWithoutRefunds.wait(); - - await ethers.provider.send("evm_increaseTime", [ORDER_VALIDITY + 1]); - await ethers.provider.send("evm_mine", []); - - const [encoder2] = await prepareBatch(); - encoder2.encodeOrderRefunds(orderRefunds); - - const txWithRefunds = await settlement.connect(solver).settle( - ...encoder2.encodedSettlement({ - [owl.address]: ethers.utils.parseEther("1.05"), - [dai.address]: ethers.utils.parseEther("1.0"), - }), - ); - const { gasUsed: gasUsedWithRefunds } = await txWithRefunds.wait(); - - const gasSavingsPerRefund = gasUsedWithoutRefunds - .sub(gasUsedWithRefunds) - .div( - orderRefunds.filledAmounts.length + orderRefunds.preSignatures.length, - ); - debug(`Gas savings per refund: ${gasSavingsPerRefund}`); - - expect(gasSavingsPerRefund.gt(4000)).to.be.true; - }); -}); diff --git a/yarn.lock b/yarn.lock index 64af0d9b..64ad67f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -304,10 +304,10 @@ "@ethereumjs/common" "^2.4.0" ethereumjs-util "^7.1.0" -"@ethereumjs/vm@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.5.0.tgz#d389c5792320ef28c51366a643b8ab9d64e10a31" - integrity sha512-h6Kr6WqKUP8nVuEzCWPWEPrC63v7HFwt3gRuK7CJiyg9S0iWSBKUA/YVD4YgaSVACuxUfWaOBbwV5uGVupm5PQ== +"@ethereumjs/vm@^5.5.2": + version "5.5.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.5.2.tgz#918a2c1000aaa9fdbe6007a4fdc2c62833122adf" + integrity sha512-AydZ4wfvZAsBuFzs3xVSA2iU0hxhL8anXco3UW3oh9maVC34kTEytOfjHf06LTEfN0MF9LDQ4ciLa7If6ZN/sg== dependencies: "@ethereumjs/block" "^3.4.0" "@ethereumjs/blockchain" "^5.4.0" @@ -5500,16 +5500,16 @@ hardhat-gas-reporter@^1.0.4: eth-gas-reporter "^0.2.20" sha1 "^1.1.1" -hardhat@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.5.0.tgz#0a10bf85d9b2c3c7c12cfa4e35454296c670c054" - integrity sha512-S5CWcmiFZlFF2qFGyf5LlgVnJDXwTs5UBKU3GPQCjsUD3NAIWzXr/4xDSij3YWdg751axgLiKAJM01cHcxGb7A== +hardhat@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.6.0.tgz#a00a44d36559a880c170dca6363cc33f7545364b" + integrity sha512-NEM2pe11QXWXB7k49heOLQA9vxihG4DJ0712KjMT9NYSZgLOMcWswJ3tvn+/ND6vzLn6Z4pqr2x/kWSfllWFuw== dependencies: "@ethereumjs/block" "^3.4.0" "@ethereumjs/blockchain" "^5.4.0" "@ethereumjs/common" "^2.4.0" "@ethereumjs/tx" "^3.3.0" - "@ethereumjs/vm" "^5.5.0" + "@ethereumjs/vm" "^5.5.2" "@ethersproject/abi" "^5.1.2" "@sentry/node" "^5.18.1" "@solidity-parser/parser" "^0.11.0"