diff --git a/packages/devtools-evm-hardhat/src/omnigraph/coordinates.ts b/packages/devtools-evm-hardhat/src/omnigraph/coordinates.ts index 296f4c49b..ee3125ee5 100644 --- a/packages/devtools-evm-hardhat/src/omnigraph/coordinates.ts +++ b/packages/devtools-evm-hardhat/src/omnigraph/coordinates.ts @@ -40,11 +40,18 @@ export const createContractFactory = (environmentFactory = createGetHreByEid()): // And if we only have the address, we need to go get it from deployments by address if (address != null) { + // The deployments can contain multiple deployment files for the same address + // + // This happens (besides of course a case of switching RPC URLs without changing network names) + // when using proxies - hardhat-deploy will create multiple deployment files + // with complete and partial ABIs + // + // To handle this case we'll merge the ABIs to make sure we have all the methods available const deployments = await env.deployments.getDeploymentsFromAddress(address) assert(deployments.length > 0, `Could not find a deployment for address '${address}'`) - const abis = deployments.flatMap((deployment) => deployment.abi) - return { eid, contract: new Contract(address, abis) } + const mergedAbis = deployments.flatMap((deployment) => deployment.abi) + return { eid, contract: new Contract(address, mergedAbis) } } assert(false, 'At least one of contractName, address must be specified for OmniPointHardhat') diff --git a/packages/devtools-evm-hardhat/test/omnigraph/coordinates.test.ts b/packages/devtools-evm-hardhat/test/omnigraph/coordinates.test.ts index dddf933a1..cf40372e4 100644 --- a/packages/devtools-evm-hardhat/test/omnigraph/coordinates.test.ts +++ b/packages/devtools-evm-hardhat/test/omnigraph/coordinates.test.ts @@ -107,7 +107,7 @@ describe('omnigraph/coordinates', () => { ) }) - it('should resolve when contract has been deployed', async () => { + it('should resolve when there is only one deployment for the contract', async () => { await fc.assert( fc.asyncProperty(evmAddressArbitrary, async (address) => { const environmentFactory = createGetHreByEid(hre) @@ -135,6 +135,44 @@ describe('omnigraph/coordinates', () => { }) ) }) + + it('should merge ABIs when there are multiple deployments with the same address (proxy deployments)', async () => { + await fc.assert( + fc.asyncProperty(evmAddressArbitrary, async (address) => { + const environmentFactory = createGetHreByEid(hre) + const contractFactory = createContractFactory(environmentFactory) + + const env = await environmentFactory(EndpointId.ETHEREUM_V2_MAINNET) + jest.spyOn(env.deployments, 'getDeploymentsFromAddress').mockResolvedValue([ + { + address: makeZeroAddress(undefined), + abi: [ + { name: 'implementation', outputs: [], stateMutability: 'view', type: 'function' }, + ], + }, + { + address: makeZeroAddress(undefined), + abi: [ + { name: 'contractMethod', outputs: [], stateMutability: 'view', type: 'function' }, + ], + }, + ]) + + // Then check whether the factory will get it for us + const omniContract = await contractFactory({ + eid: EndpointId.ETHEREUM_V2_MAINNET, + address, + }) + + expect(omniContract).toEqual({ + eid: EndpointId.ETHEREUM_V2_MAINNET, + contract: expect.any(Contract), + }) + expect(omniContract.contract.implementation).toBeInstanceOf(Function) + expect(omniContract.contract.contractMethod).toBeInstanceOf(Function) + }) + ) + }) }) }) })