From c4fa7c03726e50f7c2bd1d1b5d5e6a3024922180 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Fri, 13 Oct 2023 16:57:24 +0100 Subject: [PATCH 1/3] feat: add deployed contract to PXE from CLI --- yarn-project/cli/src/index.ts | 34 +++++++++++++++++++++++++++++++++- yarn-project/cli/src/utils.ts | 16 +++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 5fe1099d6bd..1ece5a3a7a0 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -1,6 +1,8 @@ import { + AztecAddress, Contract, ContractDeployer, + EthAddress, Fr, GrumpkinScalar, NotePreimage, @@ -33,6 +35,7 @@ import { getFunctionArtifact, getTxSender, parseAztecAddress, + parseEthereumAddress, parseField, parseFields, parseOptionalAztecAddress, @@ -223,9 +226,11 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { debugLogger(`Deploy tx sent with hash ${txHash}`); if (wait) { const deployed = await tx.wait(); - log(`\nContract deployed at ${deployed.contractAddress!.toString()}\n`); + log(`\nContract deployed at ${deployed.contract.completeAddress.address.toString()}\n`); + log(`\nContract partial address ${deployed.contract.completeAddress.partialAddress.toString()}\n`); } else { log(`\nContract Address: ${tx.completeContractAddress?.address.toString() ?? 'N/A'}`); + log(`\nContract Partial Address: ${tx.completeContractAddress?.partialAddress.toString() ?? 'N/A'}`); log(`Deployment transaction hash: ${txHash}\n`); } }); @@ -247,6 +252,33 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { else log(`\nNo contract found at ${address.toString()}\n`); }); + program + .command('add-contract') + .description( + 'Adds an existing contract to the PXE. This is useful if you have deployed a contract outside of the PXE and want to use it with the PXE.', + ) + .requiredOption( + '-c, --contract-artifact ', + "A compiled Aztec.nr contract's ABI in JSON format or name of a contract ABI exported by @aztec/noir-contracts", + ) + .requiredOption('-ca, --contract-address
', 'Aztec address of the contract.', parseAztecAddress) + .requiredOption('--partial-address
', 'Partial address of the contract', parsePartialAddress) + .option('--public-key ', 'Optional public key for this contract', parsePublicKey) + .option('-pa, --portal-address
', 'Optional address to a portal contract on L1', parseEthereumAddress) + .addOption(pxeOption) + .action(async options => { + const artifact = await getContractArtifact(options.contractArtifact, log); + const contractAddress: AztecAddress = options.contractAddress; + const completeAddress = new CompleteAddress( + contractAddress, + options.publicKey ?? Fr.ZERO, + options.partialAddress, + ); + const portalContract: EthAddress = options.portalContract ?? EthAddress.ZERO; + const client = await createCompatibleClient(options.rpcUrl, debugLogger); + + await client.addContracts([{ artifact, completeAddress, portalContract }]); + }); program .command('get-tx-receipt') .description('Gets the receipt for the specified transaction hash.') diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts index 708212b212c..6c9d81cdae5 100644 --- a/yarn-project/cli/src/utils.ts +++ b/yarn-project/cli/src/utils.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr, FunctionSelector, GrumpkinScalar, PXE, Point, TxHash } from '@aztec/aztec.js'; +import { AztecAddress, EthAddress, Fr, FunctionSelector, GrumpkinScalar, PXE, Point, TxHash } from '@aztec/aztec.js'; import { L1ContractArtifactsForDeployment, createEthereumChain, deployL1Contracts } from '@aztec/ethereum'; import { ContractArtifact } from '@aztec/foundation/abi'; import { DebugLogger, LogFn } from '@aztec/foundation/log'; @@ -211,6 +211,20 @@ export function parseAztecAddress(address: string): AztecAddress { } } +/** + * Parses an Ethereum address from a string. + * @param address - A serialized Ethereum address + * @returns An Ethereum address + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parseEthereumAddress(address: string): EthAddress { + try { + return EthAddress.fromString(address); + } catch { + throw new InvalidArgumentError(`Invalid address: ${address}`); + } +} + /** * Parses an AztecAddress from a string. * @param address - A serialized Aztec address From ebdb42205cc7b110da3b28e4fef3159cf64ef3ad Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Fri, 13 Oct 2023 17:08:09 +0100 Subject: [PATCH 2/3] fix: print partial address with --no-wait --- yarn-project/cli/src/index.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 1ece5a3a7a0..1d6eb23797c 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -221,16 +221,19 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { const args = encodeArgs(rawArgs, constructorArtifact!.parameters); debugLogger(`Encoded arguments: ${args.join(', ')}`); - const tx = deployer.deploy(...args).send({ contractAddressSalt: salt }); + const deploy = deployer.deploy(...args); + + await deploy.create({ contractAddressSalt: salt }); + const tx = deploy.send({ contractAddressSalt: salt }); const txHash = await tx.getTxHash(); debugLogger(`Deploy tx sent with hash ${txHash}`); if (wait) { const deployed = await tx.wait(); log(`\nContract deployed at ${deployed.contract.completeAddress.address.toString()}\n`); - log(`\nContract partial address ${deployed.contract.completeAddress.partialAddress.toString()}\n`); + log(`Contract partial address ${deployed.contract.completeAddress.partialAddress.toString()}\n`); } else { - log(`\nContract Address: ${tx.completeContractAddress?.address.toString() ?? 'N/A'}`); - log(`\nContract Partial Address: ${tx.completeContractAddress?.partialAddress.toString() ?? 'N/A'}`); + log(`\nContract Address: ${deploy.completeAddress?.address.toString() ?? 'N/A'}`); + log(`Contract Partial Address: ${deploy.completeAddress?.partialAddress.toString() ?? 'N/A'}`); log(`Deployment transaction hash: ${txHash}\n`); } }); From ec74ce6ddd6aef8652c15a5b4b3e27ddf7a1bce3 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Fri, 13 Oct 2023 17:10:32 +0100 Subject: [PATCH 3/3] fix: print success message --- yarn-project/cli/src/index.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 1d6eb23797c..04ebfed912a 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -265,9 +265,9 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { "A compiled Aztec.nr contract's ABI in JSON format or name of a contract ABI exported by @aztec/noir-contracts", ) .requiredOption('-ca, --contract-address
', 'Aztec address of the contract.', parseAztecAddress) - .requiredOption('--partial-address
', 'Partial address of the contract', parsePartialAddress) - .option('--public-key ', 'Optional public key for this contract', parsePublicKey) - .option('-pa, --portal-address
', 'Optional address to a portal contract on L1', parseEthereumAddress) + .requiredOption('-pa, --partial-address
', 'Partial address of the contract', parsePartialAddress) + .option('-p, --public-key ', 'Optional public key for this contract', parsePublicKey) + .option('--portal-address
', 'Optional address to a portal contract on L1', parseEthereumAddress) .addOption(pxeOption) .action(async options => { const artifact = await getContractArtifact(options.contractArtifact, log); @@ -281,6 +281,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { const client = await createCompatibleClient(options.rpcUrl, debugLogger); await client.addContracts([{ artifact, completeAddress, portalContract }]); + log(`\nContract added to PXE at ${contractAddress.toString()}\n`); }); program .command('get-tx-receipt')