-
Notifications
You must be signed in to change notification settings - Fork 162
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🦙 Add tests for calling contract from another contract (#753)
- Loading branch information
Showing
8 changed files
with
208 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@ethereum-waffle/chai": patch | ||
--- | ||
|
||
Improve called on contract matchers error messages |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import type {MockProvider} from '@ethereum-waffle/provider'; | ||
import {Contract} from 'ethers'; | ||
import {EncodingError} from './error'; | ||
|
||
export function assertFunctionCalled(chai: Chai.AssertionStatic, contract: Contract, fnName: string) { | ||
const fnSighash = contract.interface.getSighash(fnName); | ||
|
||
chai.assert( | ||
(contract.provider as unknown as MockProvider).callHistory.some( | ||
call => call.address === contract.address && call.data.startsWith(fnSighash) | ||
), | ||
`Expected contract function ${fnName} to be called`, | ||
`Expected contract function ${fnName} NOT to be called`, | ||
undefined | ||
); | ||
} | ||
|
||
export function assertCalledWithParams( | ||
chai: Chai.AssertionStatic, | ||
contract: Contract, | ||
fnName: string, | ||
parameters: any[], | ||
negated: boolean | ||
) { | ||
if (!negated) { | ||
assertFunctionCalled(chai, contract, fnName); | ||
} | ||
|
||
let funCallData: string; | ||
try { | ||
funCallData = contract.interface.encodeFunctionData(fnName, parameters); | ||
} catch (e) { | ||
const error = new EncodingError('Something went wrong - probably wrong parameters format'); | ||
error.error = e as any; | ||
throw error; | ||
} | ||
|
||
chai.assert( | ||
(contract.provider as unknown as MockProvider).callHistory.some( | ||
call => call.address === contract.address && call.data === funCallData | ||
), | ||
generateWrongParamsMessage(contract, fnName, parameters), | ||
`Expected contract function ${fnName} not to be called with parameters ${parameters}, but it was`, | ||
undefined | ||
); | ||
} | ||
|
||
function generateWrongParamsMessage(contract: Contract, fnName: string, parameters: any[]) { | ||
const fnSighash = contract.interface.getSighash(fnName); | ||
const functionCalls = (contract.provider as unknown as MockProvider) | ||
.callHistory.filter( | ||
call => call.address === contract.address && call.data.startsWith(fnSighash) | ||
); | ||
const paramsToDisplay = functionCalls.slice(0, 3); | ||
const leftParamsCount = functionCalls.length - paramsToDisplay.length; | ||
|
||
return `Expected contract function ${fnName} to be called with parameters ${parameters} \ | ||
but it was called with parameters: | ||
${paramsToDisplay.map(call => contract.interface.decodeFunctionData(fnName, call.data).toString()).join('\n')}` + | ||
(leftParamsCount > 0 ? `\n...and ${leftParamsCount} more.` : ''); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 4 additions & 12 deletions
16
waffle-chai/src/matchers/calledOnContract/calledOnContractWith.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,15 @@ | ||
import {MockProvider} from '@ethereum-waffle/provider'; | ||
import {validateContract, validateFnName, validateMockProvider} from './calledOnContractValidators'; | ||
import {assertCalledWithParams} from './assertions'; | ||
|
||
export function supportCalledOnContractWith(Assertion: Chai.AssertionStatic) { | ||
Assertion.addMethod('calledOnContractWith', function (contract: any, parameters: any[]) { | ||
Assertion.addMethod('calledOnContractWith', function (this: any, contract: any, parameters: any[]) { | ||
const fnName = this._obj; | ||
const negated = this.__flags.negate; | ||
|
||
validateContract(contract); | ||
validateMockProvider(contract.provider); | ||
validateFnName(fnName, contract); | ||
|
||
const funCallData = contract.interface.encodeFunctionData(fnName, parameters); | ||
|
||
this.assert( | ||
(contract.provider as unknown as MockProvider).callHistory.some( | ||
call => call.address === contract.address && call.data === funCallData | ||
), | ||
'Expected contract function with parameters to be called', | ||
'Expected contract function with parameters NOT to be called', | ||
undefined | ||
); | ||
assertCalledWithParams(this, contract, fnName, parameters, negated); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,38 @@ | ||
export const CALLS_SOURCE = ` | ||
pragma solidity ^0.6.0; | ||
pragma solidity ^0.8.0; | ||
contract Calls { | ||
function callWithoutParameter() pure public {} | ||
function callWithParameter(uint param) public {} | ||
function callWithParameters(uint param1, uint param2) public {} | ||
function forwardCallWithoutParameter(address addr) pure public { | ||
Calls other = Calls(addr); | ||
other.callWithoutParameter(); | ||
} | ||
function forwardCallWithParameter(address addr, uint param) public { | ||
Calls other = Calls(addr); | ||
other.callWithParameter(param); | ||
} | ||
function forwardCallWithParameters(address addr, uint param1, uint param2) public { | ||
Calls other = Calls(addr); | ||
other.callWithParameters(param1, param2); | ||
} | ||
} | ||
`; | ||
|
||
export const CALLS_ABI = [ | ||
'function callWithoutParameter() public', | ||
'function callWithParameter(uint param) public', | ||
'function callWithParameters(uint param1, uint param2) public' | ||
'function callWithParameters(uint param1, uint param2) public', | ||
'function forwardCallWithoutParameter(address addr) public', | ||
'function forwardCallWithParameter(address addr, uint param) public', | ||
'function forwardCallWithParameters(address addr, uint param1, uint param2) public' | ||
]; | ||
|
||
// eslint-disable-next-line max-len | ||
export const CALLS_BYTECODE = '608060405234801561001057600080fd5b5060e88061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c8063270f7979146041578063586a7e23146049578063c3e86c6614607e575b600080fd5b604760a9565b005b607c60048036036040811015605d57600080fd5b81019080803590602001909291908035906020019092919050505060ab565b005b60a760048036036020811015609257600080fd5b810190808035906020019092919050505060af565b005b565b5050565b5056fea2646970667358221220042e49619d2f4371b311b491637d1c6a9c9ad3c55696a6a77435579e3f1baf6b64736f6c63430006000033'; | ||
export const CALLS_BYTECODE = '608060405234801561001057600080fd5b506104a9806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063270f7979146100675780632934744d14610071578063586a7e231461008d578063ac5a5f08146100a9578063b920040e146100c5578063c3e86c66146100e1575b600080fd5b61006f6100fd565b005b61008b600480360381019061008691906102f3565b6100ff565b005b6100a760048036038101906100a29190610346565b610177565b005b6100c360048036038101906100be9190610386565b61017b565b005b6100df60048036038101906100da91906103b3565b6101e2565b005b6100fb60048036038101906100f691906103f3565b610257565b005b565b60008390508073ffffffffffffffffffffffffffffffffffffffff1663586a7e2384846040518363ffffffff1660e01b815260040161013f92919061042f565b600060405180830381600087803b15801561015957600080fd5b505af115801561016d573d6000803e3d6000fd5b5050505050505050565b5050565b60008190508073ffffffffffffffffffffffffffffffffffffffff1663270f79796040518163ffffffff1660e01b815260040160006040518083038186803b1580156101c657600080fd5b505afa1580156101da573d6000803e3d6000fd5b505050505050565b60008290508073ffffffffffffffffffffffffffffffffffffffff1663c3e86c66836040518263ffffffff1660e01b81526004016102209190610458565b600060405180830381600087803b15801561023a57600080fd5b505af115801561024e573d6000803e3d6000fd5b50505050505050565b50565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028a8261025f565b9050919050565b61029a8161027f565b81146102a557600080fd5b50565b6000813590506102b781610291565b92915050565b6000819050919050565b6102d0816102bd565b81146102db57600080fd5b50565b6000813590506102ed816102c7565b92915050565b60008060006060848603121561030c5761030b61025a565b5b600061031a868287016102a8565b935050602061032b868287016102de565b925050604061033c868287016102de565b9150509250925092565b6000806040838503121561035d5761035c61025a565b5b600061036b858286016102de565b925050602061037c858286016102de565b9150509250929050565b60006020828403121561039c5761039b61025a565b5b60006103aa848285016102a8565b91505092915050565b600080604083850312156103ca576103c961025a565b5b60006103d8858286016102a8565b92505060206103e9858286016102de565b9150509250929050565b6000602082840312156104095761040861025a565b5b6000610417848285016102de565b91505092915050565b610429816102bd565b82525050565b60006040820190506104446000830185610420565b6104516020830184610420565b9392505050565b600060208201905061046d6000830184610420565b9291505056fea2646970667358221220cbb99a2aa41a58fe79554ea90b3044fae17e2139eac9d7a96525ddc7a9b17cea64736f6c634300080f0033'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters