Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Choose constructor method in Contract.deploy #4939

Merged
merged 1 commit into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions yarn-project/aztec.js/src/contract/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ export class Contract extends ContractBase {
* @param wallet - The wallet for executing the deployment.
* @param artifact - Build artifact of the contract to deploy
* @param args - Arguments for the constructor.
* @param constructorName - The name of the constructor function to call.
*/
public static deploy(wallet: Wallet, artifact: ContractArtifact, args: any[]) {
public static deploy(wallet: Wallet, artifact: ContractArtifact, args: any[], constructorName?: string) {
const postDeployCtor = (address: AztecAddress, wallet: Wallet) => Contract.at(address, artifact, wallet);
return new DeployMethod(Point.ZERO, wallet, artifact, postDeployCtor, args);
return new DeployMethod(Point.ZERO, wallet, artifact, postDeployCtor, args, constructorName);
}

/**
Expand All @@ -48,9 +49,16 @@ export class Contract extends ContractBase {
* @param wallet - The wallet for executing the deployment.
* @param artifact - Build artifact of the contract.
* @param args - Arguments for the constructor.
* @param constructorName - The name of the constructor function to call.
*/
public static deployWithPublicKey(publicKey: PublicKey, wallet: Wallet, artifact: ContractArtifact, args: any[]) {
public static deployWithPublicKey(
publicKey: PublicKey,
wallet: Wallet,
artifact: ContractArtifact,
args: any[],
constructorName?: string,
) {
const postDeployCtor = (address: AztecAddress, wallet: Wallet) => Contract.at(address, artifact, wallet);
return new DeployMethod(publicKey, wallet, artifact, postDeployCtor, args);
return new DeployMethod(publicKey, wallet, artifact, postDeployCtor, args, constructorName);
}
}
3 changes: 2 additions & 1 deletion yarn-project/aztec.js/src/contract/deploy_method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
private artifact: ContractArtifact,
private postDeployCtor: (address: AztecAddress, wallet: Wallet) => Promise<TContract>,
private args: any[] = [],
constructorName: string = 'constructor',
) {
super(wallet);
const constructorArtifact = artifact.functions.find(f => f.name === 'constructor');
const constructorArtifact = artifact.functions.find(f => f.name === constructorName);
if (!constructorArtifact) {
throw new Error('Cannot find constructor in the artifact.');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: probably helps to include the variable name in the error here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do in a subsequent PR!

}
Expand Down
16 changes: 14 additions & 2 deletions yarn-project/aztec.js/src/deployment/contract_deployer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import { Contract } from '../contract/index.js';
* @remarks Keeping this around even though we have Aztec.nr contract types because it can be useful for non-TS users.
*/
export class ContractDeployer {
constructor(private artifact: ContractArtifact, private wallet: Wallet, private publicKey?: PublicKey) {}
constructor(
private artifact: ContractArtifact,
private wallet: Wallet,
private publicKey?: PublicKey,
private constructorName?: string,
) {}

/**
* Deploy a contract using the provided ABI and constructor arguments.
Expand All @@ -25,6 +30,13 @@ export class ContractDeployer {
*/
public deploy(...args: any[]) {
const postDeployCtor = (address: AztecAddress, wallet: Wallet) => Contract.at(address, this.artifact, wallet);
return new DeployMethod(this.publicKey ?? Point.ZERO, this.wallet, this.artifact, postDeployCtor, args);
return new DeployMethod(
this.publicKey ?? Point.ZERO,
this.wallet,
this.artifact,
postDeployCtor,
args,
this.constructorName,
);
}
}
12 changes: 12 additions & 0 deletions yarn-project/end-to-end/src/e2e_deploy_contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,18 @@ describe('e2e_deploy_contract', () => {
expect(await token.methods.is_minter(owner).view()).toEqual(true);
}, 60_000);

it('publicly deploys and initializes via a public function', async () => {
const owner = accounts[0];
logger.debug(`Deploying contract via a public constructor`);
const contract = await StatefulTestContract.deployWithOpts({ wallet, method: 'public_constructor' }, owner, 42)
.send()
.deployed();
expect(await contract.methods.get_public_value(owner).view()).toEqual(42n);
logger.debug(`Calling a private function to ensure the contract was properly initialized`);
await contract.methods.create_note(owner, 30).send().wait();
expect(await contract.methods.summed_values(owner).view()).toEqual(30n);
}, 60_000);

it.skip('publicly deploys and calls a public function in the same batched call', async () => {
// TODO(@spalladino)
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,31 @@ function generateDeploy(input: ContractArtifact) {
* Creates a tx to deploy a new instance of this contract.
*/
public static deploy(wallet: Wallet, ${args}) {
return new DeployMethod<${input.name}Contract>(Point.ZERO, wallet, ${artifactName}, ${contractName}.at, Array.from(arguments).slice(1));
return new DeployMethod<${contractName}>(Point.ZERO, wallet, ${artifactName}, ${contractName}.at, Array.from(arguments).slice(1));
}

/**
* Creates a tx to deploy a new instance of this contract using the specified public key to derive the address.
*/
public static deployWithPublicKey(publicKey: PublicKey, wallet: Wallet, ${args}) {
return new DeployMethod<${input.name}Contract>(publicKey, wallet, ${artifactName}, ${contractName}.at, Array.from(arguments).slice(2));
return new DeployMethod<${contractName}>(publicKey, wallet, ${artifactName}, ${contractName}.at, Array.from(arguments).slice(2));
}

/**
* Creates a tx to deploy a new instance of this contract using the specified constructor method.
*/
public static deployWithOpts<M extends keyof ${contractName}['methods']>(
opts: { publicKey?: PublicKey; method?: M; wallet: Wallet },
...args: Parameters<${contractName}['methods'][M]>
) {
return new DeployMethod<${contractName}>(
opts.publicKey ?? Point.ZERO,
opts.wallet,
${artifactName},
${contractName}.at,
Array.from(arguments).slice(1),
opts.method ?? 'constructor',
);
}
`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ export class ClientExecutionContext extends ViewDataOracle {
// side-effects occurred in the TX. Ultimately the private kernel should
// just output everything in the proper order without any counters.
this.log(
`Enqueued call to public function (with side-effect counter #${sideEffectCounter}) ${targetContractAddress}:${functionSelector}`,
`Enqueued call to public function (with side-effect counter #${sideEffectCounter}) ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`,
);

this.enqueuedPublicFunctionCalls.push(enqueuedRequest);
Expand Down
Loading