Skip to content

Commit

Permalink
Fix ethers-v5 constructor arg structs (#540)
Browse files Browse the repository at this point in the history
Co-authored-by: Kris Kaczor <[email protected]>
  • Loading branch information
zemse and krzkaczor authored Nov 7, 2021
1 parent 39b4612 commit ba4c18a
Show file tree
Hide file tree
Showing 7 changed files with 228 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/stale-dolls-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@typechain/ethers-v5": patch
---

Fix support for constructors with structs
15 changes: 15 additions & 0 deletions packages/hardhat-test/contracts/Demo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;

contract Demo {
struct Struct1 {
uint a;
uint b;
}
struct Struct2 {
uint a;
uint b;
}
constructor(Struct1 memory input1, Struct2[] memory input2) public {}
}
80 changes: 80 additions & 0 deletions packages/hardhat-test/typechain-types/Demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */

import {
ethers,
EventFilter,
Signer,
BigNumber,
BigNumberish,
PopulatedTransaction,
BaseContract,
ContractTransaction,
} from "ethers";
import { BytesLike } from "@ethersproject/bytes";
import { Listener, Provider } from "@ethersproject/providers";
import { FunctionFragment, EventFragment, Result } from "@ethersproject/abi";
import type {
TypedEventFilter,
TypedEvent,
TypedListener,
OnEvent,
} from "./common";

export type Struct1Struct = { a: BigNumberish; b: BigNumberish };

export type Struct1StructOutput = [BigNumber, BigNumber] & {
a: BigNumber;
b: BigNumber;
};

export type Struct2Struct = { a: BigNumberish; b: BigNumberish };

export type Struct2StructOutput = [BigNumber, BigNumber] & {
a: BigNumber;
b: BigNumber;
};

export interface DemoInterface extends ethers.utils.Interface {
functions: {};

events: {};
}

export interface Demo extends BaseContract {
connect(signerOrProvider: Signer | Provider | string): this;
attach(addressOrName: string): this;
deployed(): Promise<this>;

interface: DemoInterface;

queryFilter<TEvent extends TypedEvent>(
event: TypedEventFilter<TEvent>,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined
): Promise<Array<TEvent>>;

listeners<TEvent extends TypedEvent>(
eventFilter?: TypedEventFilter<TEvent>
): Array<TypedListener<TEvent>>;
listeners(eventName?: string): Array<Listener>;
removeAllListeners<TEvent extends TypedEvent>(
eventFilter: TypedEventFilter<TEvent>
): this;
removeAllListeners(eventName?: string): this;
off: OnEvent<this>;
on: OnEvent<this>;
once: OnEvent<this>;
removeListener: OnEvent<this>;

functions: {};

callStatic: {};

filters: {};

estimateGas: {};

populateTransaction: {};
}
105 changes: 105 additions & 0 deletions packages/hardhat-test/typechain-types/factories/Demo__factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */

import { Signer, utils, Contract, ContractFactory, Overrides } from "ethers";
import { Provider, TransactionRequest } from "@ethersproject/providers";
import type {
Demo,
DemoInterface,
Struct1Struct,
Struct2Struct,
} from "../Demo";

const _abi = [
{
inputs: [
{
components: [
{
internalType: "uint256",
name: "a",
type: "uint256",
},
{
internalType: "uint256",
name: "b",
type: "uint256",
},
],
internalType: "struct Demo.Struct1",
name: "input1",
type: "tuple",
},
{
components: [
{
internalType: "uint256",
name: "a",
type: "uint256",
},
{
internalType: "uint256",
name: "b",
type: "uint256",
},
],
internalType: "struct Demo.Struct2[]",
name: "input2",
type: "tuple[]",
},
],
stateMutability: "nonpayable",
type: "constructor",
},
];

const _bytecode =
"0x608060405234801561001057600080fd5b5060405161028038038061028083398181016040528101906100329190610169565b5050610233565b600082601f83011261004a57600080fd5b815161005d610058826101ea565b6101bd565b9150818183526020840193506020810190508385604084028201111561008257600080fd5b60005b838110156100b257816100988882610108565b845260208401935060408301925050600181019050610085565b5050505092915050565b6000604082840312156100ce57600080fd5b6100d860406101bd565b905060006100e884828501610154565b60008301525060206100fc84828501610154565b60208301525092915050565b60006040828403121561011a57600080fd5b61012460406101bd565b9050600061013484828501610154565b600083015250602061014884828501610154565b60208301525092915050565b6000815190506101638161021c565b92915050565b6000806060838503121561017c57600080fd5b600061018a858286016100bc565b925050604083015167ffffffffffffffff8111156101a757600080fd5b6101b385828601610039565b9150509250929050565b6000604051905081810181811067ffffffffffffffff821117156101e057600080fd5b8060405250919050565b600067ffffffffffffffff82111561020157600080fd5b602082029050602081019050919050565b6000819050919050565b61022581610212565b811461023057600080fd5b50565b603f806102416000396000f3fe6080604052600080fdfea264697066735822122020c868aa8bada3514eace30686b8a1d861902ad26698a9f8a5d12c006dc583de64736f6c63430006080033";

type DemoConstructorParams =
| [signer?: Signer]
| ConstructorParameters<typeof ContractFactory>;

const isSuperArgs = (
xs: DemoConstructorParams
): xs is ConstructorParameters<typeof ContractFactory> => xs.length > 1;

export class Demo__factory extends ContractFactory {
constructor(...args: DemoConstructorParams) {
if (isSuperArgs(args)) {
super(...args);
} else {
super(_abi, _bytecode, args[0]);
}
}

deploy(
input1: Struct1Struct,
input2: Struct2Struct[],
overrides?: Overrides & { from?: string | Promise<string> }
): Promise<Demo> {
return super.deploy(input1, input2, overrides || {}) as Promise<Demo>;
}
getDeployTransaction(
input1: Struct1Struct,
input2: Struct2Struct[],
overrides?: Overrides & { from?: string | Promise<string> }
): TransactionRequest {
return super.getDeployTransaction(input1, input2, overrides || {});
}
attach(address: string): Demo {
return super.attach(address) as Demo;
}
connect(signer: Signer): Demo__factory {
return super.connect(signer) as Demo__factory;
}
static readonly bytecode = _bytecode;
static readonly abi = _abi;
static createInterface(): DemoInterface {
return new utils.Interface(_abi) as DemoInterface;
}
static connect(address: string, signerOrProvider: Signer | Provider): Demo {
return new Contract(address, _abi, signerOrProvider) as Demo;
}
}
9 changes: 9 additions & 0 deletions packages/hardhat-test/typechain-types/hardhat.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,21 @@ declare module "hardhat/types/runtime" {
name: "Counter",
signerOrOptions?: ethers.Signer | FactoryOptions
): Promise<Contracts.Counter__factory>;
getContractFactory(
name: "Demo",
signerOrOptions?: ethers.Signer | FactoryOptions
): Promise<Contracts.Demo__factory>;

getContractAt(
name: "Counter",
address: string,
signer?: ethers.Signer
): Promise<Contracts.Counter>;
getContractAt(
name: "Demo",
address: string,
signer?: ethers.Signer
): Promise<Contracts.Demo>;

// default types
getContractFactory(
Expand Down
2 changes: 2 additions & 0 deletions packages/hardhat-test/typechain-types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@
/* tslint:disable */
/* eslint-disable */
export type { Counter } from "./Counter";
export type { Demo } from "./Demo";

export { Counter__factory } from "./factories/Counter__factory";
export { Demo__factory } from "./factories/Demo__factory";
15 changes: 12 additions & 3 deletions packages/target-ethers-v5/src/codegen/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { values } from 'lodash'
import { BytecodeWithLinkReferences, CodegenConfig, Contract } from 'typechain'
import { BytecodeWithLinkReferences, CodegenConfig, Contract, StructType } from 'typechain'

import { FACTORY_POSTFIX } from '../common'
import { FACTORY_POSTFIX, STRUCT_INPUT_POSTFIX } from '../common'
import {
EVENT_IMPORTS,
EVENT_METHOD_OVERRIDES,
Expand Down Expand Up @@ -198,8 +198,17 @@ export function codegenAbstractContractFactory(contract: Contract, abi: any): st
}

function codegenCommonContractFactory(contract: Contract, abi: any): { header: string; body: string } {
const constructorStructs: string[] = []
contract.constructor[0]?.inputs.forEach(({ type }) => {
const { structName } = type as StructType
if (structName) {
constructorStructs.push(structName + STRUCT_INPUT_POSTFIX)
}
})
const header = `
import type { ${contract.name}, ${contract.name}Interface } from "../${contract.name}";
import type { ${[contract.name, contract.name + 'Interface', ...constructorStructs].join(', ')} } from "../${
contract.name
}";
const _abi = ${JSON.stringify(abi, null, 2)};
`.trim()
Expand Down

0 comments on commit ba4c18a

Please sign in to comment.