From 5e3c5d1c65ef3352947989ba9f51a1047bf7ba0c Mon Sep 17 00:00:00 2001 From: smartcontracts Date: Tue, 1 Jun 2021 21:01:58 -0400 Subject: [PATCH] fix[smock]: fix broken call assertions for overloaded functions (#996) * fix[smock]: fix broken call assertions for overloaded functions * chore: add changeset * minor correction and add a test * add a test for non-overloaded functions --- .changeset/cool-baboons-guess.md | 5 ++ packages/smock/src/smockit/smockit.ts | 11 ++- .../test/contracts/TestHelpers_MockCaller.sol | 8 +++ .../test/smockit/call-assertions.spec.ts | 72 +++++++++++++++++++ 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 .changeset/cool-baboons-guess.md create mode 100644 packages/smock/test/contracts/TestHelpers_MockCaller.sol create mode 100644 packages/smock/test/smockit/call-assertions.spec.ts diff --git a/.changeset/cool-baboons-guess.md b/.changeset/cool-baboons-guess.md new file mode 100644 index 000000000000..aa0ea6cea3e9 --- /dev/null +++ b/.changeset/cool-baboons-guess.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/smock': patch +--- + +Fixes a bug that would break call assertions for overloaded smocked functions diff --git a/packages/smock/src/smockit/smockit.ts b/packages/smock/src/smockit/smockit.ts index 9ca98ba8c087..1673064518aa 100644 --- a/packages/smock/src/smockit/smockit.ts +++ b/packages/smock/src/smockit/smockit.ts @@ -79,18 +79,25 @@ const smockifyFunction = ( let data: any = toHexString(calldataBuf) try { - data = contract.interface.decodeFunctionData(fragment.name, data) + data = contract.interface.decodeFunctionData( + fragment.format(), + data + ) } catch (e) { console.error(e) } return { functionName: fragment.name, + functionSignature: fragment.format(), data, } }) .filter((functionResult: any) => { - return functionResult.functionName === functionName + return ( + functionResult.functionName === functionName || + functionResult.functionSignature === functionName + ) }) .map((functionResult: any) => { return functionResult.data diff --git a/packages/smock/test/contracts/TestHelpers_MockCaller.sol b/packages/smock/test/contracts/TestHelpers_MockCaller.sol new file mode 100644 index 000000000000..818f3d77087a --- /dev/null +++ b/packages/smock/test/contracts/TestHelpers_MockCaller.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +contract TestHelpers_MockCaller { + function callMock(address _target, bytes memory _data) public { + _target.call(_data); + } +} diff --git a/packages/smock/test/smockit/call-assertions.spec.ts b/packages/smock/test/smockit/call-assertions.spec.ts new file mode 100644 index 000000000000..f4c920410669 --- /dev/null +++ b/packages/smock/test/smockit/call-assertions.spec.ts @@ -0,0 +1,72 @@ +/* Imports: External */ +import hre from 'hardhat' +import { expect } from 'chai' +import { Contract } from 'ethers' + +/* Imports: Internal */ +import { MockContract, smockit } from '../../src' + +describe('[smock]: call assertion tests', () => { + const ethers = (hre as any).ethers + + let mock: MockContract + beforeEach(async () => { + mock = await smockit('TestHelpers_BasicReturnContract') + }) + + let mockCaller: Contract + before(async () => { + const mockCallerFactory = await ethers.getContractFactory( + 'TestHelpers_MockCaller' + ) + mockCaller = await mockCallerFactory.deploy() + }) + + describe('call assertions for functions', () => { + it('should be able to make assertions about a non-overloaded function', async () => { + mock.smocked.getInputtedUint256.will.return.with(0) + + const expected1 = ethers.BigNumber.from(1234) + await mockCaller.callMock( + mock.address, + mock.interface.encodeFunctionData('getInputtedUint256(uint256)', [ + expected1, + ]) + ) + + expect(mock.smocked.getInputtedUint256.calls[0]).to.deep.equal([ + expected1, + ]) + }) + + it('should be able to make assertions about both versions of an overloaded function', async () => { + mock.smocked['overloadedFunction(uint256)'].will.return.with(0) + mock.smocked['overloadedFunction(uint256,uint256)'].will.return.with(0) + + const expected1 = ethers.BigNumber.from(1234) + await mockCaller.callMock( + mock.address, + mock.interface.encodeFunctionData('overloadedFunction(uint256)', [ + expected1, + ]) + ) + + expect( + mock.smocked['overloadedFunction(uint256)'].calls[0] + ).to.deep.equal([expected1]) + + const expected2 = ethers.BigNumber.from(5678) + await mockCaller.callMock( + mock.address, + mock.interface.encodeFunctionData( + 'overloadedFunction(uint256,uint256)', + [expected2, expected2] + ) + ) + + expect( + mock.smocked['overloadedFunction(uint256,uint256)'].calls[0] + ).to.deep.equal([expected2, expected2]) + }) + }) +})