diff --git a/.changeset/tasty-apricots-move.md b/.changeset/tasty-apricots-move.md new file mode 100644 index 000000000..0b2d1ad86 --- /dev/null +++ b/.changeset/tasty-apricots-move.md @@ -0,0 +1,5 @@ +--- +"@ethereum-waffle/chai": patch +--- + +🗾 Extend matching of Hardhat revert reasons diff --git a/waffle-chai/src/matchers/revertedWith.ts b/waffle-chai/src/matchers/revertedWith.ts index 7e5b9ee95..28178f195 100644 --- a/waffle-chai/src/matchers/revertedWith.ts +++ b/waffle-chai/src/matchers/revertedWith.ts @@ -1,11 +1,11 @@ import {decodeRevertString} from '@ethereum-waffle/provider'; +import {ethers} from 'ethers'; import {callPromise} from '../call-promise'; import JSONbig from 'json-bigint'; export function supportRevertedWith(Assertion: Chai.AssertionStatic) { Assertion.addMethod('revertedWith', function (this: any, revertReason: string | RegExp) { callPromise(this); - const assertNotReverted = () => this.assert( false, 'Expected transaction to be reverted', @@ -42,6 +42,7 @@ export function supportRevertedWith(Assertion: Chai.AssertionStatic) { }); } +const errorInterface = new ethers.utils.Interface(['function Error(string)']); const decodeHardhatError = (error: any, context: any) => { const tryDecode = (error: any) => { if ( @@ -60,6 +61,13 @@ const decodeHardhatError = (error: any, context: any) => { context.txErrorName = error.errorName; return error.errorName; } + if (error?.data) { + try { + const decodedReason = errorInterface.decodeFunctionData('Error', error.data); + if (decodedReason[0]) return decodedReason[0]; + } catch {} + } + const errorString = String(error); { // eslint-disable-next-line max-len @@ -95,8 +103,14 @@ const decodeHardhatError = (error: any, context: any) => { } } { - const regexp = new RegExp('revert(ed)? with reason (string )?"(.*?)"'); - + const regexp = /revert(ed)? with reason (string )?("(?:[^\\"]|\\.)*")/; + const matches = regexp.exec(errorString); + if (matches && matches.length >= 1) { + return JSON.parse(matches[matches.length - 1]); // parse escapes + } + } + { + const regexp = new RegExp('revert(ed)? with reason (string )?\'(.*)\''); const matches = regexp.exec(errorString); if (matches && matches.length >= 1) { return matches[matches.length - 1]; diff --git a/waffle-chai/test/contracts/Matchers.ts b/waffle-chai/test/contracts/Matchers.ts index d464d4c36..7f41714f3 100644 --- a/waffle-chai/test/contracts/Matchers.ts +++ b/waffle-chai/test/contracts/Matchers.ts @@ -1,3 +1,5 @@ +/* eslint-disable max-len, no-useless-escape */ + export const MATCHERS_SOURCE = ` pragma solidity ^0.8.0; @@ -59,6 +61,10 @@ export const MATCHERS_SOURCE = ` function requireFalseWithSingleQuote() external view { require(false, "asset doesn't have feed"); } + + function requireFalseWithDoubleQuote() external view { + require(false, "asset \"something\" doesn't have feed"); + } } `; @@ -158,6 +164,13 @@ export const MATCHERS_ABI = [ stateMutability: 'view', type: 'function' }, + { + inputs: [], + name: 'requireFalseWithDoubleQuote', + outputs: [], + stateMutability: 'view', + type: 'function' + }, { inputs: [], name: 'requireFalseWithSingleQuote', @@ -167,5 +180,4 @@ export const MATCHERS_ABI = [ } ]; -// eslint-disable-next-line max-len -export const MATCHERS_BYTECODE = '608060405234801561001057600080fd5b50610823806100206000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c8063afc874d21161008c578063d51033db11610066578063d51033db1461012e578063d64ee4531461014d578063eacf8a5714610157578063fff78f9c14610161576100cf565b8063afc874d214610110578063b217ca111461011a578063be3e2e6014610124576100cf565b806301236db4146100d45780632f576f20146100de578063841caf38146100e85780639817185d146100f2578063a6f34dcb146100fc578063af9b573914610106575b600080fd5b6100dc61016b565b005b6100e66101bf565b005b6100f06101c1565b005b6100fa6101eb565b005b610104610201565b005b61010e61025d565b005b610118610298565b005b6101226102d3565b005b61012c6102ee565b005b610136610331565b6040516101449291906104b8565b60405180910390f35b610155610354565b005b61015f610397565b005b6101696103da565b005b600160008082825461017d9190610592565b925050819055506040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101b6906104e1565b60405180910390fd5b565b60016000808282546101d39190610592565b9250508190555060006101e9576101e861066d565b5b565b6000808160016101fb91906105e8565b90505050565b60016000808282546102139190610592565b92505081905550600061025b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161025290610501565b60405180910390fd5b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161028f90610541565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ca906104e1565b60405180910390fd5b60016000808282546102e59190610592565b92505081905550565b600161032f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032690610561565b60405180910390fd5b565b60008073b319771f2db6113a745bcdeea63ec939bf72620761262b915091509091565b6000610395576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038c90610521565b60405180910390fd5b565b60006103d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103cf90610501565b60405180910390fd5b565b60006103e9576103e861066d565b5b565b6103f481610619565b82525050565b6000610407600c83610581565b9150610412826106fa565b602082019050919050565b600061042a600d83610581565b915061043582610723565b602082019050919050565b600061044d601783610581565b91506104588261074c565b602082019050919050565b6000610470602283610581565b915061047b82610775565b604082019050919050565b6000610493601083610581565b915061049e826107c4565b602082019050919050565b6104b281610655565b82525050565b60006040820190506104cd60008301856103eb565b6104da60208301846104a9565b9392505050565b600060208201905081810360008301526104fa816103fa565b9050919050565b6000602082019050818103600083015261051a8161041d565b9050919050565b6000602082019050818103600083015261053a81610440565b9050919050565b6000602082019050818103600083015261055a81610463565b9050919050565b6000602082019050818103600083015261057a81610486565b9050919050565b600082825260208201905092915050565b600061059d8261064b565b91506105a88361064b565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156105dd576105dc61069c565b5b828201905092915050565b60006105f38261064b565b91506105fe8361064b565b92508261060e5761060d6106cb565b5b828204905092915050565b60006106248261062b565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006bffffffffffffffffffffffff82169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f5265766572742063617573650000000000000000000000000000000000000000600082015250565b7f5265717569726520636175736500000000000000000000000000000000000000600082015250565b7f617373657420646f65736e277420686176652066656564000000000000000000600082015250565b7f52657665727420636175736520287769746820636f6d706c657820726561736f60008201527f6e29000000000000000000000000000000000000000000000000000000000000602082015250565b7f4e6576657220746f206265207365656e0000000000000000000000000000000060008201525056fea2646970667358221220211ac0b27eb7e77bdda6b606a94c0f573d58fba3257013d527dd369eb984c62a64736f6c63430008070033'; +export const MATCHERS_BYTECODE = '608060405234801561001057600080fd5b5061091d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063b217ca111161008c578063d51033db11610066578063d51033db14610153578063d64ee45314610172578063eacf8a571461017c578063fff78f9c14610186576100ea565b8063b217ca1114610135578063b45453bc1461013f578063be3e2e6014610149576100ea565b80639817185d116100c85780639817185d1461010d578063a6f34dcb14610117578063af9b573914610121578063afc874d21461012b576100ea565b806301236db4146100ef5780632f576f20146100f9578063841caf3814610103575b600080fd5b6100f7610190565b005b6101016101e4565b005b61010b6101e6565b005b610115610210565b005b61011f610226565b005b610129610282565b005b6101336102bd565b005b61013d6102f8565b005b610147610313565b005b610151610356565b005b61015b610399565b604051610169929190610543565b60405180910390f35b61017a6103bc565b005b6101846103ff565b005b61018e610442565b005b60016000808282546101a2919061063d565b925050819055506040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101db9061056c565b60405180910390fd5b565b60016000808282546101f8919061063d565b92505081905550600061020e5761020d610718565b5b565b6000808160016102209190610693565b90505050565b6001600080828254610238919061063d565b925050819055506000610280576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102779061058c565b60405180910390fd5b565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b4906105ec565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ef9061056c565b60405180910390fd5b600160008082825461030a919061063d565b92505081905550565b6000610354576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161034b906105cc565b60405180910390fd5b565b6001610397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038e9061060c565b60405180910390fd5b565b60008073b319771f2db6113a745bcdeea63ec939bf72620761262b915091509091565b60006103fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f4906105ac565b60405180910390fd5b565b6000610440576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104379061058c565b60405180910390fd5b565b600061045157610450610718565b5b565b61045c816106c4565b82525050565b600061046f600c8361062c565b915061047a826107a5565b602082019050919050565b6000610492600d8361062c565b915061049d826107ce565b602082019050919050565b60006104b560178361062c565b91506104c0826107f7565b602082019050919050565b60006104d860238361062c565b91506104e382610820565b604082019050919050565b60006104fb60228361062c565b91506105068261086f565b604082019050919050565b600061051e60108361062c565b9150610529826108be565b602082019050919050565b61053d81610700565b82525050565b60006040820190506105586000830185610453565b6105656020830184610534565b9392505050565b6000602082019050818103600083015261058581610462565b9050919050565b600060208201905081810360008301526105a581610485565b9050919050565b600060208201905081810360008301526105c5816104a8565b9050919050565b600060208201905081810360008301526105e5816104cb565b9050919050565b60006020820190508181036000830152610605816104ee565b9050919050565b6000602082019050818103600083015261062581610511565b9050919050565b600082825260208201905092915050565b6000610648826106f6565b9150610653836106f6565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561068857610687610747565b5b828201905092915050565b600061069e826106f6565b91506106a9836106f6565b9250826106b9576106b8610776565b5b828204905092915050565b60006106cf826106d6565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006bffffffffffffffffffffffff82169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f5265766572742063617573650000000000000000000000000000000000000000600082015250565b7f5265717569726520636175736500000000000000000000000000000000000000600082015250565b7f617373657420646f65736e277420686176652066656564000000000000000000600082015250565b7f61737365742022736f6d657468696e672220646f65736e27742068617665206660008201527f6565640000000000000000000000000000000000000000000000000000000000602082015250565b7f52657665727420636175736520287769746820636f6d706c657820726561736f60008201527f6e29000000000000000000000000000000000000000000000000000000000000602082015250565b7f4e6576657220746f206265207365656e0000000000000000000000000000000060008201525056fea26469706673582212206cecacac45c934a83b2529a447a6537ca44856329c3d9fbe23d3c05a8147918f64736f6c63430008070033'; diff --git a/waffle-chai/test/matchers/revertedWithTest.ts b/waffle-chai/test/matchers/revertedWithTest.ts index 1a687aca9..ed0317d6c 100644 --- a/waffle-chai/test/matchers/revertedWithTest.ts +++ b/waffle-chai/test/matchers/revertedWithTest.ts @@ -239,7 +239,14 @@ export const revertedWithTest = (provider: TestProvider, options: RevertedWithTe await expect(matchers.requireFalseWithSingleQuote()) .to.be.revertedWith('asset doesn\'t have feed'); await expect(matchers.requireFalseWithSingleQuote()) - .to.be.revertedWith('asset doesn\'t have feed'); + .to.be.revertedWith("asset doesn't have feed"); // eslint-disable-line quotes + }); + + it('Revert with double quote in message', async () => { + await expect(matchers.requireFalseWithDoubleQuote()) + .to.be.revertedWith('asset "something" doesn\'t have feed'); + await expect(matchers.requireFalseWithDoubleQuote()) + .to.be.revertedWith("asset \"something\" doesn't have feed"); // eslint-disable-line quotes }); it('Catches wrong message with single quote in it', async () => {