diff --git a/docs/docs/external/up-quick-start.md b/docs/docs/external/up-quick-start.md
index d6fb502788c9..b62d371cd884 100644
--- a/docs/docs/external/up-quick-start.md
+++ b/docs/docs/external/up-quick-start.md
@@ -12,7 +12,7 @@ The sandbox is preloaded with two [accounts](../concepts/foundation/accounts/mai
#include_code declare-accounts yarn-project/end-to-end/src/guides/up_quick_start.sh bash noTitle,noLineNumbers,noSourceLink
-Start by deploying a private token [contract](../concepts/foundation/contracts.md), minting an initial supply of private tokens to Alice:
+Start by deploying a token [contract](../concepts/foundation/contracts.md), initializing it and minting tokens to Alice:
#include_code deploy yarn-project/end-to-end/src/guides/up_quick_start.sh bash noTitle,noLineNumbers,noSourceLink
diff --git a/yarn-project/acir-simulator/src/client/private_execution.test.ts b/yarn-project/acir-simulator/src/client/private_execution.test.ts
index e6ba3fc37939..ad1551990059 100644
--- a/yarn-project/acir-simulator/src/client/private_execution.test.ts
+++ b/yarn-project/acir-simulator/src/client/private_execution.test.ts
@@ -38,7 +38,7 @@ import {
ParentContractAbi,
PendingCommitmentsContractAbi,
PrivateTokenAirdropContractAbi,
- PrivateTokenContractAbi,
+ StatefulTestContractAbi,
TestContractAbi,
} from '@aztec/noir-contracts/artifacts';
import { PackedArguments, TxExecutionRequest } from '@aztec/types';
@@ -401,7 +401,7 @@ describe('Private Execution test suite', () => {
});
});
- describe('private token contract', () => {
+ describe('stateful test contract contract', () => {
const contractAddress = defaultContractAddress;
const mockFirstNullifier = new Fr(1111);
let currentNoteIndex = 0n;
@@ -439,7 +439,7 @@ describe('Private Execution test suite', () => {
oracle.getFunctionABI.mockImplementation((_, selector) =>
Promise.resolve(
- PrivateTokenContractAbi.functions.find(f =>
+ StatefulTestContractAbi.functions.find(f =>
selector.equals(FunctionSelector.fromNameAndParameters(f.name, f.parameters)),
)!,
),
@@ -484,9 +484,9 @@ describe('Private Execution test suite', () => {
});
it('should a constructor with arguments that inserts notes', async () => {
- const abi = getFunctionAbi(PrivateTokenContractAbi, 'constructor');
+ const abi = getFunctionAbi(StatefulTestContractAbi, 'constructor');
- const result = await runSimulator({ args: [140, owner], abi });
+ const result = await runSimulator({ args: [owner, 140], abi });
expect(result.newNotes).toHaveLength(1);
const newNote = result.newNotes[0];
@@ -501,10 +501,10 @@ describe('Private Execution test suite', () => {
);
});
- it('should run the mint function', async () => {
- const abi = getFunctionAbi(PrivateTokenContractAbi, 'mint');
+ it('should run the create_note function', async () => {
+ const abi = getFunctionAbi(StatefulTestContractAbi, 'create_note');
- const result = await runSimulator({ args: [140, owner], abi });
+ const result = await runSimulator({ args: [owner, 140], abi });
expect(result.newNotes).toHaveLength(1);
const newNote = result.newNotes[0];
@@ -519,9 +519,9 @@ describe('Private Execution test suite', () => {
);
});
- it('should run the transfer function', async () => {
+ it('should run the destroy_and_create function', async () => {
const amountToTransfer = 100n;
- const abi = getFunctionAbi(PrivateTokenContractAbi, 'transfer');
+ const abi = getFunctionAbi(StatefulTestContractAbi, 'destroy_and_create');
const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm);
const recipientStorageSlot = computeSlotForMapping(new Fr(1n), recipient.toField(), circuitsWasm);
@@ -534,7 +534,7 @@ describe('Private Execution test suite', () => {
);
await insertLeaves(consumedNotes.map(n => n.siloedNoteHash));
- const args = [amountToTransfer, recipient];
+ const args = [recipient, amountToTransfer];
const result = await runSimulator({ args, abi, msgSender: owner });
// The two notes were nullified
@@ -565,10 +565,10 @@ describe('Private Execution test suite', () => {
expect(readRequests).toEqual(expect.arrayContaining(consumedNotes.map(n => n.uniqueSiloedNoteHash)));
});
- it('should be able to transfer with dummy notes', async () => {
+ it('should be able to destroy_and_create with dummy notes', async () => {
const amountToTransfer = 100n;
const balance = 160n;
- const abi = getFunctionAbi(PrivateTokenContractAbi, 'transfer');
+ const abi = getFunctionAbi(StatefulTestContractAbi, 'destroy_and_create');
const storageSlot = computeSlotForMapping(new Fr(1n), owner.toField(), circuitsWasm);
@@ -580,7 +580,7 @@ describe('Private Execution test suite', () => {
);
await insertLeaves(consumedNotes.map(n => n.siloedNoteHash));
- const args = [amountToTransfer, recipient];
+ const args = [recipient, amountToTransfer];
const result = await runSimulator({ args, abi, msgSender: owner });
const newNullifiers = result.callStackItem.publicInputs.newNullifiers.filter(field => !field.equals(Fr.ZERO));
diff --git a/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts b/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts
index ec318a9f6a59..3e38c3999b48 100644
--- a/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts
+++ b/yarn-project/acir-simulator/src/client/unconstrained_execution.test.ts
@@ -3,7 +3,7 @@ import { FunctionSelector, encodeArguments } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr, GrumpkinScalar } from '@aztec/foundation/fields';
-import { PrivateTokenContractAbi } from '@aztec/noir-contracts/artifacts';
+import { StatefulTestContractAbi } from '@aztec/noir-contracts/artifacts';
import { FunctionCall } from '@aztec/types';
import { mock } from 'jest-mock-extended';
@@ -39,9 +39,9 @@ describe('Unconstrained Execution test suite', () => {
});
});
- it('should run the getBalance function', async () => {
+ it('should run the summed_values function', async () => {
const contractAddress = AztecAddress.random();
- const abi = PrivateTokenContractAbi.functions.find(f => f.name === 'getBalance')!;
+ const abi = StatefulTestContractAbi.functions.find(f => f.name === 'summed_values')!;
const preimages = [...Array(5).fill(buildNote(1n, owner)), ...Array(2).fill(buildNote(2n, owner))];
diff --git a/yarn-project/end-to-end/src/canary/browser.ts b/yarn-project/end-to-end/src/canary/browser.ts
index c455d9e95eaa..7aa320a2079b 100644
--- a/yarn-project/end-to-end/src/canary/browser.ts
+++ b/yarn-project/end-to-end/src/canary/browser.ts
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
import * as AztecJs from '@aztec/aztec.js';
-import { PrivateTokenContractAbi } from '@aztec/noir-contracts/artifacts';
+import { TokenContractAbi } from '@aztec/noir-contracts/artifacts';
import { Server } from 'http';
import Koa from 'koa';
@@ -111,60 +111,66 @@ export const browserTestSuite = (setup: () => Server, pageLogger: AztecJs.DebugL
expect(stringAccounts.includes(result)).toBeTruthy();
}, 15_000);
- it('Deploys Private Token contract', async () => {
- await deployPrivateTokenContract();
- }, 30_000);
+ it('Deploys Token contract', async () => {
+ await deployTokenContract();
+ }, 60_000);
it("Gets the owner's balance", async () => {
const result = await page.evaluate(
- async (rpcUrl, contractAddress, PrivateTokenContractAbi) => {
+ async (rpcUrl, contractAddress, TokenContractAbi) => {
const { Contract, AztecAddress, createAztecRpcClient } = window.AztecJs;
const client = createAztecRpcClient(rpcUrl!);
const owner = (await client.getRegisteredAccounts())[0].address;
const [wallet] = await AztecJs.getSandboxAccountsWallets(client);
- const contract = await Contract.at(AztecAddress.fromString(contractAddress), PrivateTokenContractAbi, wallet);
- const balance = await contract.methods.getBalance(owner).view({ from: owner });
- console.log(`Owner's balance: ${balance}`);
+ const contract = await Contract.at(AztecAddress.fromString(contractAddress), TokenContractAbi, wallet);
+ const balance = await contract.methods.balance_of_private({ address: owner }).view({ from: owner });
return balance;
},
SANDBOX_URL,
- (await getPrivateTokenAddress()).toString(),
- PrivateTokenContractAbi,
+ (await getTokenAddress()).toString(),
+ TokenContractAbi,
);
expect(result).toEqual(initialBalance);
});
it('Sends a transfer TX', async () => {
const result = await page.evaluate(
- async (rpcUrl, contractAddress, transferAmount, PrivateTokenContractAbi) => {
+ async (rpcUrl, contractAddress, transferAmount, TokenContractAbi) => {
console.log(`Starting transfer tx`);
const { AztecAddress, Contract, createAztecRpcClient } = window.AztecJs;
const client = createAztecRpcClient(rpcUrl!);
const accounts = await client.getRegisteredAccounts();
- const owner = accounts[0].address;
const receiver = accounts[1].address;
const [wallet] = await AztecJs.getSandboxAccountsWallets(client);
- const contract = await Contract.at(AztecAddress.fromString(contractAddress), PrivateTokenContractAbi, wallet);
- await contract.methods.transfer(transferAmount, receiver).send().wait();
+ const contract = await Contract.at(AztecAddress.fromString(contractAddress), TokenContractAbi, wallet);
+ await contract.methods
+ .transfer({ address: accounts[0].address }, { address: receiver }, transferAmount, 0)
+ .send()
+ .wait();
console.log(`Transferred ${transferAmount} tokens to new Account`);
- const receiverBalance = await contract.methods.getBalance(receiver).view({ from: receiver });
- console.log(`Receiver's balance is now: ${receiverBalance}`);
- const senderBalance = await contract.methods.getBalance(owner).view({ from: owner });
- console.log(`Updated sender balance: ${senderBalance}`);
- return receiverBalance;
+ return await contract.methods.balance_of_private({ address: receiver }).view({ from: receiver });
},
SANDBOX_URL,
- (await getPrivateTokenAddress()).toString(),
+ (await getTokenAddress()).toString(),
transferAmount,
- PrivateTokenContractAbi,
+ TokenContractAbi,
);
expect(result).toEqual(transferAmount);
}, 60_000);
- const deployPrivateTokenContract = async () => {
+ const deployTokenContract = async () => {
const txHash = await page.evaluate(
- async (rpcUrl, privateKeyString, initialBalance, PrivateTokenContractAbi) => {
- const { GrumpkinScalar, DeployMethod, createAztecRpcClient, getUnsafeSchnorrAccount } = window.AztecJs;
+ async (rpcUrl, privateKeyString, initialBalance, TokenContractAbi) => {
+ const {
+ GrumpkinScalar,
+ DeployMethod,
+ createAztecRpcClient,
+ getUnsafeSchnorrAccount,
+ Contract,
+ Fr,
+ computeMessageSecretHash,
+ getSandboxAccountsWallets,
+ } = window.AztecJs;
const client = createAztecRpcClient(rpcUrl!);
let accounts = await client.getRegisteredAccounts();
if (accounts.length === 0) {
@@ -173,20 +179,25 @@ export const browserTestSuite = (setup: () => Server, pageLogger: AztecJs.DebugL
await getUnsafeSchnorrAccount(client, privateKey).waitDeploy();
accounts = await client.getRegisteredAccounts();
}
- const owner = accounts[0];
- const tx = new DeployMethod(owner.publicKey, client, PrivateTokenContractAbi, [
- initialBalance,
- owner.address,
- ]).send();
+ const [owner] = await getSandboxAccountsWallets(client);
+ const tx = new DeployMethod(accounts[0].publicKey, client, TokenContractAbi).send();
await tx.wait();
const receipt = await tx.getReceipt();
console.log(`Contract Deployed: ${receipt.contractAddress}`);
+
+ const token = await Contract.at(receipt.contractAddress!, TokenContractAbi, owner);
+ await token.methods._initialize({ address: owner.getAddress() }).send().wait();
+ const secret = Fr.random();
+ const secretHash = await computeMessageSecretHash(secret);
+ await token.methods.mint_private(initialBalance, secretHash).send().wait();
+ await token.methods.redeem_shield({ address: owner.getAddress() }, initialBalance, secret).send().wait();
+
return receipt.txHash.toString();
},
SANDBOX_URL,
privKey.toString(),
initialBalance,
- PrivateTokenContractAbi,
+ TokenContractAbi,
);
const txResult = await testClient.getTxReceipt(AztecJs.TxHash.fromString(txHash));
@@ -194,9 +205,9 @@ export const browserTestSuite = (setup: () => Server, pageLogger: AztecJs.DebugL
contractAddress = txResult.contractAddress!;
};
- const getPrivateTokenAddress = async () => {
+ const getTokenAddress = async () => {
if (!contractAddress) {
- await deployPrivateTokenContract();
+ await deployTokenContract();
}
return contractAddress;
};
diff --git a/yarn-project/end-to-end/src/canary/cli.ts b/yarn-project/end-to-end/src/canary/cli.ts
index 7cda9b1c3bd6..2cc7442ef29a 100644
--- a/yarn-project/end-to-end/src/canary/cli.ts
+++ b/yarn-project/end-to-end/src/canary/cli.ts
@@ -1,4 +1,4 @@
-import { AztecAddress, AztecRPC, CompleteAddress, DebugLogger } from '@aztec/aztec.js';
+import { AztecAddress, AztecRPC, CompleteAddress, DebugLogger, Fr, computeMessageSecretHash } from '@aztec/aztec.js';
import { getProgram } from '@aztec/cli';
import stringArgv from 'string-argv';
@@ -52,7 +52,9 @@ export const cliTestSuite = (
if (addRpcUrl) {
args.push('--rpc-url', rpcUrl);
}
- return cli.parseAsync(args);
+ const res = cli.parseAsync(args);
+ resetCli();
+ return res;
};
// Returns first match across all logs collected so far
@@ -115,8 +117,8 @@ export const cliTestSuite = (
expect(foundAddress).toBeDefined();
const ownerAddress = AztecAddress.fromString(foundAddress!);
- debug('Deploy Private Token Contract using created account.');
- await run(`deploy PrivateTokenContractAbi --args ${INITIAL_BALANCE} ${ownerAddress} --salt 0`);
+ debug('Deploy Token Contract using created account.');
+ await run(`deploy TokenContractAbi --salt 0`);
const loggedAddress = findInLogs(/Contract\sdeployed\sat\s+(?
0x[a-fA-F0-9]+)/)?.groups?.address;
expect(loggedAddress).toBeDefined();
contractAddress = AztecAddress.fromString(loggedAddress!);
@@ -129,6 +131,22 @@ export const cliTestSuite = (
const checkResult = findInLogs(/Contract\sfound\sat\s+(?0x[a-fA-F0-9]+)/)?.groups?.address;
expect(checkResult).toEqual(deployedContract?.contractAddress.toString());
+ debug('Initialize token contract.');
+ await run(
+ `send _initialize --args ${ownerAddress} --contract-abi TokenContractAbi --contract-address ${contractAddress.toString()} --private-key ${privKey}`,
+ );
+
+ const secret = Fr.random();
+ const secretHash = await computeMessageSecretHash(secret);
+
+ debug('Mint initial tokens.');
+ await run(
+ `send mint_private --args ${INITIAL_BALANCE} ${secretHash} --contract-abi TokenContractAbi --contract-address ${contractAddress.toString()} --private-key ${privKey}`,
+ );
+ await run(
+ `send redeem_shield --args ${ownerAddress} ${INITIAL_BALANCE} ${secret} --contract-abi TokenContractAbi --contract-address ${contractAddress.toString()} --private-key ${privKey}`,
+ );
+
// clear logs
clearLogs();
await run(`get-contract-data ${loggedAddress}`);
@@ -137,7 +155,7 @@ export const cliTestSuite = (
debug("Check owner's balance");
await run(
- `call getBalance --args ${ownerAddress} --contract-abi PrivateTokenContractAbi --contract-address ${contractAddress.toString()}`,
+ `call balance_of_private --args ${ownerAddress} --contract-abi TokenContractAbi --contract-address ${contractAddress.toString()}`,
);
const balance = findInLogs(/View\sresult:\s+(?\S+)/)?.groups?.data;
expect(balance!).toEqual(`${BigInt(INITIAL_BALANCE).toString()}n`);
@@ -148,7 +166,7 @@ export const cliTestSuite = (
const receiver = existingAccounts.find(acc => acc.address.toString() !== ownerAddress.toString());
await run(
- `send transfer --args ${TRANSFER_BALANCE} ${receiver?.address.toString()} --contract-address ${contractAddress.toString()} --contract-abi PrivateTokenContractAbi --private-key ${privKey}`,
+ `send transfer --args ${ownerAddress.toString()} ${receiver?.address.toString()} ${TRANSFER_BALANCE} 0 --contract-address ${contractAddress.toString()} --contract-abi TokenContractAbi --private-key ${privKey}`,
);
const txHash = findInLogs(/Transaction\shash:\s+(?\S+)/)?.groups?.txHash;
@@ -159,13 +177,11 @@ export const cliTestSuite = (
expect(parsedResult.txHash).toEqual(txHash);
expect(parsedResult.status).toEqual('mined');
debug("Check Receiver's balance");
- // Reset CLI as we're calling getBalance again
- resetCli();
clearLogs();
await run(
- `call getBalance --args ${receiver?.address.toString()} --contract-abi PrivateTokenContractAbi --contract-address ${contractAddress.toString()}`,
+ `call balance_of_private --args ${receiver?.address.toString()} --contract-abi TokenContractAbi --contract-address ${contractAddress.toString()}`,
);
const receiverBalance = findInLogs(/View\sresult:\s+(?\S+)/)?.groups?.data;
expect(receiverBalance).toEqual(`${BigInt(TRANSFER_BALANCE).toString()}n`);
- }, 30_000);
+ }, 100_000);
});
diff --git a/yarn-project/end-to-end/src/cli_docs_sandbox.test.ts b/yarn-project/end-to-end/src/cli_docs_sandbox.test.ts
index 921c1b28a3c0..055d605e0dce 100644
--- a/yarn-project/end-to-end/src/cli_docs_sandbox.test.ts
+++ b/yarn-project/end-to-end/src/cli_docs_sandbox.test.ts
@@ -101,6 +101,7 @@ PublicTokenContractAbi
SchnorrAccountContractAbi
SchnorrHardcodedAccountContractAbi
SchnorrSingleKeyAccountContractAbi
+StatefulTestContractAbi
TestContractAbi
TokenContractAbi
UniswapContractAbi
diff --git a/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts b/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts
index 554ad930ff69..94e8aeba8af6 100644
--- a/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts
+++ b/yarn-project/end-to-end/src/e2e_2_rpc_servers.test.ts
@@ -1,10 +1,10 @@
import { AztecNodeService } from '@aztec/aztec-node';
import { AztecRPCServer, EthAddress, Fr } from '@aztec/aztec-rpc';
-import { AztecAddress, Wallet } from '@aztec/aztec.js';
+import { AztecAddress, Wallet, computeMessageSecretHash } from '@aztec/aztec.js';
import { DebugLogger } from '@aztec/foundation/log';
import { retryUntil } from '@aztec/foundation/retry';
import { toBigInt } from '@aztec/foundation/serialize';
-import { ChildContract, PrivateTokenContract } from '@aztec/noir-contracts/types';
+import { ChildContract, TokenContract } from '@aztec/noir-contracts/types';
import { AztecRPC, CompleteAddress, TxStatus } from '@aztec/types';
import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup, setupAztecRPCServer } from './fixtures/utils.js';
@@ -71,15 +71,27 @@ describe('e2e_2_rpc_servers', () => {
await awaitUserSynchronised(wallet, owner);
// Then check the balance
- const contractWithWallet = await PrivateTokenContract.at(tokenAddress, wallet);
- const balance = await contractWithWallet.methods.getBalance(owner).view({ from: owner });
+ const contractWithWallet = await TokenContract.at(tokenAddress, wallet);
+ const balance = await contractWithWallet.methods.balance_of_private({ address: owner }).view({ from: owner });
logger(`Account ${owner} balance: ${balance}`);
expect(balance).toBe(expectedBalance);
};
- const deployPrivateTokenContract = async (initialBalance: bigint, owner: AztecAddress) => {
- logger(`Deploying PrivateToken contract...`);
- const contract = await PrivateTokenContract.deploy(walletA, initialBalance, owner).send().deployed();
+ const deployTokenContract = async (initialBalance: bigint, owner: AztecAddress) => {
+ logger(`Deploying Token contract...`);
+ const contract = await TokenContract.deploy(walletA).send().deployed();
+ expect((await contract.methods._initialize({ address: owner }).send().wait()).status).toBe(TxStatus.MINED);
+
+ const secret = Fr.random();
+ const secretHash = await computeMessageSecretHash(secret);
+
+ expect((await contract.methods.mint_private(initialBalance, secretHash).send().wait()).status).toEqual(
+ TxStatus.MINED,
+ );
+ expect(
+ (await contract.methods.redeem_shield({ address: owner }, initialBalance, secret).send().wait()).status,
+ ).toEqual(TxStatus.MINED);
+
logger('L2 contract deployed');
return contract.completeAddress;
@@ -90,7 +102,7 @@ describe('e2e_2_rpc_servers', () => {
const transferAmount1 = 654n;
const transferAmount2 = 323n;
- const completeTokenAddress = await deployPrivateTokenContract(initialBalance, userA.address);
+ const completeTokenAddress = await deployTokenContract(initialBalance, userA.address);
const tokenAddress = completeTokenAddress.address;
// Add account B to wallet A
@@ -98,10 +110,10 @@ describe('e2e_2_rpc_servers', () => {
// Add account A to wallet B
await aztecRpcServerB.registerRecipient(userA);
- // Add privateToken to RPC server B
+ // Add token to RPC server B
await aztecRpcServerB.addContracts([
{
- abi: PrivateTokenContract.abi,
+ abi: TokenContract.abi,
completeAddress: completeTokenAddress,
portalContract: EthAddress.ZERO,
},
@@ -113,12 +125,11 @@ describe('e2e_2_rpc_servers', () => {
await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 1);
// Transfer funds from A to B via RPC server A
- const contractWithWalletA = await PrivateTokenContract.at(tokenAddress, walletA);
- const txAToB = contractWithWalletA.methods.transfer(transferAmount1, userB.address).send();
-
- await txAToB.isMined({ interval: 0.1 });
- const receiptAToB = await txAToB.getReceipt();
-
+ const contractWithWalletA = await TokenContract.at(tokenAddress, walletA);
+ const receiptAToB = await contractWithWalletA.methods
+ .transfer({ address: userA.address }, { address: userB.address }, transferAmount1, 0)
+ .send()
+ .wait();
expect(receiptAToB.status).toBe(TxStatus.MINED);
// Check balances and logs are as expected
@@ -127,8 +138,11 @@ describe('e2e_2_rpc_servers', () => {
await expectsNumOfEncryptedLogsInTheLastBlockToBe(aztecNode, 2);
// Transfer funds from B to A via RPC server B
- const contractWithWalletB = await PrivateTokenContract.at(tokenAddress, walletB);
- await contractWithWalletB.methods.transfer(transferAmount2, userA.address).send().wait({ interval: 0.1 });
+ const contractWithWalletB = await TokenContract.at(tokenAddress, walletB);
+ await contractWithWalletB.methods
+ .transfer({ address: userB.address }, { address: userA.address }, transferAmount2, 0)
+ .send()
+ .wait({ interval: 0.1 });
// Check balances and logs are as expected
await expectTokenBalance(walletA, tokenAddress, userA.address, initialBalance - transferAmount1 + transferAmount2);
diff --git a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts
index 5121aaafdc7f..94571b751e1f 100644
--- a/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts
+++ b/yarn-project/end-to-end/src/e2e_escrow_contract.test.ts
@@ -1,11 +1,11 @@
import { AztecNodeService } from '@aztec/aztec-node';
import { AztecRPCServer } from '@aztec/aztec-rpc';
-import { AccountWallet, AztecAddress, BatchCall, generatePublicKey } from '@aztec/aztec.js';
+import { AccountWallet, AztecAddress, BatchCall, computeMessageSecretHash, generatePublicKey } from '@aztec/aztec.js';
import { CompleteAddress, Fr, GrumpkinPrivateKey, GrumpkinScalar, getContractDeploymentInfo } from '@aztec/circuits.js';
import { DebugLogger } from '@aztec/foundation/log';
import { EscrowContractAbi } from '@aztec/noir-contracts/artifacts';
-import { EscrowContract, PrivateTokenContract } from '@aztec/noir-contracts/types';
-import { AztecRPC, PublicKey } from '@aztec/types';
+import { EscrowContract, TokenContract } from '@aztec/noir-contracts/types';
+import { AztecRPC, PublicKey, TxStatus } from '@aztec/types';
import { setup } from './fixtures/utils.js';
@@ -17,7 +17,7 @@ describe('e2e_escrow_contract', () => {
let accounts: CompleteAddress[];
let logger: DebugLogger;
- let privateTokenContract: PrivateTokenContract;
+ let token: TokenContract;
let escrowContract: EscrowContract;
let owner: AztecAddress;
let recipient: AztecAddress;
@@ -51,8 +51,19 @@ describe('e2e_escrow_contract', () => {
logger(`Escrow contract deployed at ${escrowContract.address}`);
// Deploy Private Token contract and mint funds for the escrow contract
- privateTokenContract = await PrivateTokenContract.deploy(wallet, 100n, escrowContract.address).send().deployed();
- logger(`Token contract deployed at ${privateTokenContract.address}`);
+ token = await TokenContract.deploy(wallet).send().deployed();
+
+ expect((await token.methods._initialize({ address: owner }).send().wait()).status).toBe(TxStatus.MINED);
+
+ const secret = Fr.random();
+ const secretHash = await computeMessageSecretHash(secret);
+
+ expect((await token.methods.mint_private(100n, secretHash).send().wait()).status).toEqual(TxStatus.MINED);
+ expect(
+ (await token.methods.redeem_shield({ address: escrowContract.address }, 100n, secret).send().wait()).status,
+ ).toEqual(TxStatus.MINED);
+
+ logger(`Token contract deployed at ${token.address}`);
}, 100_000);
afterEach(async () => {
@@ -61,7 +72,7 @@ describe('e2e_escrow_contract', () => {
}, 30_000);
const expectBalance = async (who: AztecAddress, expectedBalance: bigint) => {
- const balance = await privateTokenContract.methods.getBalance(who).view({ from: who });
+ const balance = await token.methods.balance_of_private({ address: who }).view({ from: who });
logger(`Account ${who} balance: ${balance}`);
expect(balance).toBe(expectedBalance);
};
@@ -72,7 +83,7 @@ describe('e2e_escrow_contract', () => {
await expectBalance(escrowContract.address, 100n);
logger(`Withdrawing funds from token contract to ${recipient}`);
- await escrowContract.methods.withdraw(privateTokenContract.address, 30, recipient).send().wait();
+ await escrowContract.methods.withdraw(token.address, 30, recipient).send().wait();
await expectBalance(owner, 0n);
await expectBalance(recipient, 30n);
@@ -81,21 +92,25 @@ describe('e2e_escrow_contract', () => {
it('refuses to withdraw funds as a non-owner', async () => {
await expect(
- escrowContract
- .withWallet(recipientWallet)
- .methods.withdraw(privateTokenContract.address, 30, recipient)
- .simulate(),
+ escrowContract.withWallet(recipientWallet).methods.withdraw(token.address, 30, recipient).simulate(),
).rejects.toThrowError();
}, 60_000);
it('moves funds using multiple keys on the same tx (#1010)', async () => {
logger(`Minting funds in token contract to ${owner}`);
- await privateTokenContract.methods.mint(50, owner).send().wait();
+ const secret = Fr.random();
+ const secretHash = await computeMessageSecretHash(secret);
+
+ expect((await token.methods.mint_private(50n, secretHash).send().wait()).status).toEqual(TxStatus.MINED);
+ expect((await token.methods.redeem_shield({ address: owner }, 50n, secret).send().wait()).status).toEqual(
+ TxStatus.MINED,
+ );
+
await expectBalance(owner, 50n);
const actions = [
- privateTokenContract.methods.transfer(10, recipient).request(),
- escrowContract.methods.withdraw(privateTokenContract.address, 20, recipient).request(),
+ token.methods.transfer({ address: owner }, { address: recipient }, 10, 0).request(),
+ escrowContract.methods.withdraw(token.address, 20, recipient).request(),
];
await new BatchCall(wallet, actions).send().wait();
diff --git a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts
index 453a185ddf74..467c3de7d359 100644
--- a/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts
+++ b/yarn-project/end-to-end/src/e2e_multiple_accounts_1_enc_key.test.ts
@@ -1,9 +1,9 @@
import { AztecNodeService } from '@aztec/aztec-node';
import { AztecRPCServer } from '@aztec/aztec-rpc';
-import { AztecAddress, Wallet, generatePublicKey, getSchnorrAccount } from '@aztec/aztec.js';
-import { GrumpkinScalar } from '@aztec/circuits.js';
+import { AztecAddress, Wallet, computeMessageSecretHash, generatePublicKey, getSchnorrAccount } from '@aztec/aztec.js';
+import { Fr, GrumpkinScalar } from '@aztec/circuits.js';
import { DebugLogger } from '@aztec/foundation/log';
-import { PrivateTokenContract } from '@aztec/noir-contracts/types';
+import { TokenContract } from '@aztec/noir-contracts/types';
import { AztecRPC, TxStatus } from '@aztec/types';
import { expectsNumOfEncryptedLogsInTheLastBlockToBe, setup } from './fixtures/utils.js';
@@ -15,7 +15,7 @@ describe('e2e_multiple_accounts_1_enc_key', () => {
const accounts: AztecAddress[] = [];
let logger: DebugLogger;
- let privateTokenAddress: AztecAddress;
+ let tokenAddress: AztecAddress;
const initialBalance = 987n;
const numAccounts = 3;
@@ -42,12 +42,20 @@ describe('e2e_multiple_accounts_1_enc_key', () => {
expect(account.publicKey).toEqual(encryptionPublicKey);
}
- logger(`Deploying Private Token...`);
- privateTokenAddress = await PrivateTokenContract.deploy(wallets[0], initialBalance, accounts[0])
- .send()
- .deployed()
- .then(c => c.address);
- logger(`Private Token deployed at ${privateTokenAddress}`);
+ logger(`Deploying Token...`);
+ const token = await TokenContract.deploy(wallets[0]).send().deployed();
+ tokenAddress = token.address;
+ logger(`Token deployed at ${tokenAddress}`);
+
+ expect((await token.methods._initialize({ address: accounts[0] }).send().wait()).status).toBe(TxStatus.MINED);
+
+ const secret = Fr.random();
+ const secretHash = await computeMessageSecretHash(secret);
+
+ expect((await token.methods.mint_private(initialBalance, secretHash).send().wait()).status).toEqual(TxStatus.MINED);
+ expect(
+ (await token.methods.redeem_shield({ address: accounts[0] }, initialBalance, secret).send().wait()).status,
+ ).toEqual(TxStatus.MINED);
}, 100_000);
afterEach(async () => {
@@ -62,8 +70,8 @@ describe('e2e_multiple_accounts_1_enc_key', () => {
const owner = accounts[userIndex];
// Then check the balance
- const contractWithWallet = await PrivateTokenContract.at(privateTokenAddress, wallet);
- const balance = await contractWithWallet.methods.getBalance(owner).view({ from: owner });
+ const contractWithWallet = await TokenContract.at(tokenAddress, wallet);
+ const balance = await contractWithWallet.methods.balance_of_private({ address: owner }).view({ from: owner });
logger(`Account ${owner} balance: ${balance}`);
expect(balance).toBe(expectedBalance);
};
@@ -79,12 +87,12 @@ describe('e2e_multiple_accounts_1_enc_key', () => {
const sender = accounts[senderIndex];
const receiver = accounts[receiverIndex];
- const contractWithWallet = await PrivateTokenContract.at(privateTokenAddress, wallets[senderIndex]);
-
- const tx = contractWithWallet.methods.transfer(transferAmount, receiver).send();
- await tx.isMined({ interval: 0.1 });
- const receipt = await tx.getReceipt();
+ const contractWithWallet = await TokenContract.at(tokenAddress, wallets[senderIndex]);
+ const receipt = await contractWithWallet.methods
+ .transfer({ address: sender }, { address: receiver }, transferAmount, 0)
+ .send()
+ .wait();
expect(receipt.status).toBe(TxStatus.MINED);
for (let i = 0; i < expectedBalances.length; i++) {
diff --git a/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts b/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts
index 27ef20a82985..0e4058a2015d 100644
--- a/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts
+++ b/yarn-project/end-to-end/src/e2e_sandbox_example.test.ts
@@ -2,14 +2,21 @@
/* eslint-disable import/no-duplicates */
// docs:start:imports
-import { AztecRPC, createAztecRpcClient, createDebugLogger, getSchnorrAccount, waitForSandbox } from '@aztec/aztec.js';
+import {
+ AztecRPC,
+ Fr,
+ computeMessageSecretHash,
+ createDebugLogger,
+ getSchnorrAccount,
+ waitForSandbox,
+} from '@aztec/aztec.js';
// docs:end:imports
/* eslint-enable @typescript-eslint/no-unused-vars */
// Note: this is a hack to make the docs use http://localhost:8080 and CI to use the SANDBOX_URL
import { createAztecRpcClient as createAztecRpcClient2 } from '@aztec/aztec.js';
import { GrumpkinScalar } from '@aztec/circuits.js';
-import { PrivateTokenContract } from '@aztec/noir-contracts/types';
+import { TokenContract } from '@aztec/noir-contracts/types';
const { SANDBOX_URL = 'http://localhost:8080' } = process.env;
@@ -22,7 +29,7 @@ describe('e2e_sandbox_example', () => {
it('sandbox example works', async () => {
// docs:start:setup
////////////// CREATE THE CLIENT INTERFACE AND CONTACT THE SANDBOX //////////////
- const logger = createDebugLogger('private-token');
+ const logger = createDebugLogger('token');
const sandboxUrl = 'http://localhost:8080';
// We create AztecRPC client connected to the sandbox URL
@@ -88,41 +95,44 @@ describe('e2e_sandbox_example', () => {
expect(registeredAccounts.find(acc => acc.equals(bob))).toBeTruthy();
// docs:start:Deployment
- ////////////// DEPLOY OUR PRIVATE TOKEN CONTRACT //////////////
+ ////////////// DEPLOY OUR TOKEN CONTRACT //////////////
- // Deploy a private token contract, create a contract abstraction object and link it to the owner's wallet
+ // Deploy a token contract, create a contract abstraction object and link it to the owner's wallet
// The contract's constructor takes 2 arguments, the initial supply and the owner of that initial supply
const initialSupply = 1_000_000n;
- logger(`Deploying private token contract minting an initial ${initialSupply} tokens to Alice...`);
- const contract = await PrivateTokenContract.deploy(
- aztecRpc,
- initialSupply, // the initial supply
- alice, // the owner of the initial supply
- )
- .send()
- .deployed();
+ logger(`Deploying token contract minting an initial ${initialSupply} tokens to Alice...`);
+ const contract = await TokenContract.deploy(aztecRpc).send().deployed();
+
+ // Create the contract abstraction and link to Alice's wallet for future signing
+ const tokenContractAlice = await TokenContract.at(contract.address, await accounts[0].getWallet());
+
+ await tokenContractAlice.methods._initialize({ address: alice }).send().wait();
+ await tokenContractAlice.methods.set_minter({ address: bob }, true).send().wait();
logger(`Contract successfully deployed at address ${contract.address.toShortString()}`);
+
+ const secret = Fr.random();
+ const secretHash = await computeMessageSecretHash(secret);
+
+ await tokenContractAlice.methods.mint_private(initialSupply, secretHash).send().wait();
+ await tokenContractAlice.methods.redeem_shield({ address: alice }, initialSupply, secret).send().wait();
// docs:end:Deployment
- // ensure that private token contract is registered in the rpc
+ // ensure that token contract is registered in the rpc
expect(await aztecRpc.getContracts()).toEqual(expect.arrayContaining([contract.address]));
// docs:start:Balance
////////////// QUERYING THE TOKEN BALANCE FOR EACH ACCOUNT //////////////
- // Create the contract abstraction and link to Alice's wallet for future signing
- const tokenContractAlice = await PrivateTokenContract.at(contract.address, await accounts[0].getWallet());
-
// Bob wants to mint some funds, the contract is already deployed, create an abstraction and link it his wallet
- const tokenContractBob = await PrivateTokenContract.at(contract.address, await accounts[1].getWallet());
+ const tokenContractBob = await TokenContract.at(contract.address, await accounts[1].getWallet());
- let aliceBalance = await tokenContractAlice.methods.getBalance(alice).view();
+ let aliceBalance = await tokenContractAlice.methods.balance_of_private({ address: alice }).view();
logger(`Alice's balance ${aliceBalance}`);
- let bobBalance = await tokenContractBob.methods.getBalance(bob).view();
+ let bobBalance = await tokenContractBob.methods.balance_of_private({ address: bob }).view();
logger(`Bob's balance ${bobBalance}`);
// docs:end:Balance
@@ -136,13 +146,13 @@ describe('e2e_sandbox_example', () => {
// We will now transfer tokens from ALice to Bob
const transferQuantity = 543n;
logger(`Transferring ${transferQuantity} tokens from Alice to Bob...`);
- await tokenContractAlice.methods.transfer(transferQuantity, bob).send().wait();
+ await tokenContractAlice.methods.transfer({ address: alice }, { address: bob }, transferQuantity, 0).send().wait();
// Check the new balances
- aliceBalance = await tokenContractAlice.methods.getBalance(alice).view();
+ aliceBalance = await tokenContractAlice.methods.balance_of_private({ address: alice }).view();
logger(`Alice's balance ${aliceBalance}`);
- bobBalance = await tokenContractBob.methods.getBalance(bob).view();
+ bobBalance = await tokenContractBob.methods.balance_of_private({ address: bob }).view();
logger(`Bob's balance ${bobBalance}`);
// docs:end:Transfer
@@ -155,13 +165,14 @@ describe('e2e_sandbox_example', () => {
// Now mint some further funds for Bob
const mintQuantity = 10_000n;
logger(`Minting ${mintQuantity} tokens to Bob...`);
- await tokenContractBob.methods.mint(mintQuantity, bob).send().wait();
+ await tokenContractBob.methods.mint_private(mintQuantity, secretHash).send().wait();
+ await tokenContractBob.methods.redeem_shield({ address: bob }, mintQuantity, secret).send().wait();
// Check the new balances
- aliceBalance = await tokenContractAlice.methods.getBalance(alice).view();
+ aliceBalance = await tokenContractAlice.methods.balance_of_private({ address: alice }).view();
logger(`Alice's balance ${aliceBalance}`);
- bobBalance = await tokenContractBob.methods.getBalance(bob).view();
+ bobBalance = await tokenContractBob.methods.balance_of_private({ address: bob }).view();
logger(`Bob's balance ${bobBalance}`);
// docs:end:Mint
diff --git a/yarn-project/end-to-end/src/guides/up_quick_start.sh b/yarn-project/end-to-end/src/guides/up_quick_start.sh
index c27ff3454f37..7b25a747dd6f 100755
--- a/yarn-project/end-to-end/src/guides/up_quick_start.sh
+++ b/yarn-project/end-to-end/src/guides/up_quick_start.sh
@@ -4,48 +4,71 @@
set -eux
# docs:start:declare-accounts
-ALICE="0x2e13f0201905944184fc2c09d29fcf0cac07647be171656a275f63d99b819360"
-BOB="0x0d557417a3ce7d7b356a8f15d79a868fd8da2af9c5f4981feb9bcf0b614bd17e"
+ALICE="0x296904eaff80711ddd5fd39d75920bfc22725cc0ae3089f16a09a4ceb91be141"
+BOB="0x1106245c5c50798338e55094c38025db4053a25e96dd8cbc1e87c6dcbfb9d2ba"
+ALICE_PRIVATE_KEY="0x2153536ff6628eee01cf4024889ff977a18d9fa61d0e414422f7681cf085c281"
# docs:end:declare-accounts
# docs:start:deploy
aztec-cli deploy \
- PrivateTokenContractAbi \
- --args 1000000 $ALICE \
+ TokenContractAbi \
--salt 0
+
+aztec-cli check-deploy --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c
+
+aztec-cli send _initialize \
+ --args $ALICE \
+ --contract-abi TokenContractAbi \
+ --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c \
+ --private-key $ALICE_PRIVATE_KEY
# docs:end:deploy
-aztec-cli check-deploy --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f
+# docs:start:mint-private
+SECRET="0x29bf6afaf29f61cbcf2a4fa7da97be481fb418dc08bdab5338839974beb7b49f"
+SECRET_HASH="0x0a42b1fe22b652cc8610e33bb1128040ce2d2862e7041ff235aa871739822b74"
+
+aztec-cli send mint_private \
+ --args 1000 $SECRET_HASH \
+ --contract-abi TokenContractAbi \
+ --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c \
+ --private-key $ALICE_PRIVATE_KEY
+
+aztec-cli send redeem_shield \
+ --args $ALICE 1000 $SECRET \
+ --contract-abi TokenContractAbi \
+ --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c \
+ --private-key $ALICE_PRIVATE_KEY
+# docs:end:mint-private
# docs:start:get-balance
-aztec-cli call getBalance \
+aztec-cli call balance_of_private \
--args $ALICE \
- --contract-abi PrivateTokenContractAbi \
- --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f
+ --contract-abi TokenContractAbi \
+ --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c
# docs:end:get-balance
# docs:start:transfer
aztec-cli send transfer \
- --args 500 $ALICE $BOB \
- --contract-abi PrivateTokenContractAbi \
- --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f \
- --private-key 0xb2803ec899f76f6b2ac011480d24028f1a29587f8a3a92f7ee9d48d8c085c284
+ --args $ALICE $BOB 500 0 \
+ --contract-abi TokenContractAbi \
+ --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c \
+ --private-key $ALICE_PRIVATE_KEY
-aztec-cli call getBalance \
+aztec-cli call balance_of_private \
--args $ALICE \
- --contract-abi PrivateTokenContractAbi \
- --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f
+ --contract-abi TokenContractAbi \
+ --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c
-aztec-cli call getBalance \
+aztec-cli call balance_of_private \
--args $BOB \
- --contract-abi PrivateTokenContractAbi \
- --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f
+ --contract-abi TokenContractAbi \
+ --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c
# docs:end:transfer
aztec-cli get-logs
# Test end result
-BOB_BALANCE=$(aztec-cli call getBalance --args $BOB --contract-abi PrivateTokenContractAbi --contract-address 0x03b030d48607ba8a0562f0f1f82be26c3f091e45e10f74c2d8cebb80d526a69f)
+BOB_BALANCE=$(aztec-cli call balance_of_private --args $BOB --contract-abi TokenContractAbi --contract-address 0x2d23acefa3ce07b3c308caf78d86c064cdf8957bcea48b38753cf58441796c8c)
if ! echo $BOB_BALANCE | grep -q 500; then
echo "Incorrect Bob balance after transaction (expected 500 but got $BOB_BALANCE)"
exit 1
diff --git a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts
index 466240732e3d..7b9e848a28e0 100644
--- a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts
+++ b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts
@@ -1,8 +1,15 @@
import { AztecRPCServer } from '@aztec/aztec-rpc';
-import { AccountManager, AuthWitnessProvider, BaseAccountContract, CompleteAddress, Fr } from '@aztec/aztec.js';
+import {
+ AccountManager,
+ AuthWitnessProvider,
+ BaseAccountContract,
+ CompleteAddress,
+ Fr,
+ computeMessageSecretHash,
+} from '@aztec/aztec.js';
import { GrumpkinPrivateKey, GrumpkinScalar } from '@aztec/circuits.js';
import { Schnorr } from '@aztec/circuits.js/barretenberg';
-import { PrivateTokenContract, SchnorrHardcodedAccountContractAbi } from '@aztec/noir-contracts/types';
+import { SchnorrHardcodedAccountContractAbi, TokenContract } from '@aztec/noir-contracts/types';
import { AuthWitness } from '@aztec/types';
import { setup } from '../fixtures/utils.js';
@@ -59,14 +66,20 @@ describe('guides/writing_an_account_contract', () => {
logger(`Deployed account contract at ${address}`);
// docs:start:account-contract-works
- const token = await PrivateTokenContract.deploy(wallet, 100, address).send().deployed();
+ const token = await TokenContract.deploy(wallet).send().deployed();
logger(`Deployed token contract at ${token.address}`);
+ await token.methods._initialize({ address }).send().wait();
- await token.methods.mint(50, address).send().wait();
- const balance = await token.methods.getBalance(address).view();
+ const secret = Fr.random();
+ const secretHash = await computeMessageSecretHash(secret);
+
+ await token.methods.mint_private(50, secretHash).send().wait();
+ await token.methods.redeem_shield({ address }, 50, secret).send().wait();
+
+ const balance = await token.methods.balance_of_private({ address }).view();
logger(`Balance of wallet is now ${balance}`);
// docs:end:account-contract-works
- expect(balance).toEqual(150n);
+ expect(balance).toEqual(50n);
// docs:start:account-contract-fails
const walletAddress = wallet.getCompleteAddress();
@@ -77,7 +90,7 @@ describe('guides/writing_an_account_contract', () => {
const tokenWithWrongWallet = token.withWallet(wrongWallet);
try {
- await tokenWithWrongWallet.methods.mint(200, address).simulate();
+ await tokenWithWrongWallet.methods.mint_private(200, secretHash).simulate();
} catch (err) {
logger(`Failed to send tx: ${err}`);
}
diff --git a/yarn-project/end-to-end/src/sample-dapp/contracts.mjs b/yarn-project/end-to-end/src/sample-dapp/contracts.mjs
index d72e4f4bd5fe..b0892378b017 100644
--- a/yarn-project/end-to-end/src/sample-dapp/contracts.mjs
+++ b/yarn-project/end-to-end/src/sample-dapp/contracts.mjs
@@ -1,19 +1,11 @@
import { Contract } from '@aztec/aztec.js';
-import {
- PrivateTokenContractAbi as PrivateTokenArtifact,
- PublicTokenContractAbi as PublicTokenArtifact,
-} from '@aztec/noir-contracts/artifacts';
+import { TokenContractAbi } from '@aztec/noir-contracts/artifacts';
import { readFileSync } from 'fs';
// docs:start:get-tokens
-export async function getPrivateToken(client) {
+export async function getToken(client) {
const addresses = JSON.parse(readFileSync('addresses.json'));
- return Contract.at(addresses.privateToken, PrivateTokenArtifact, client);
-}
-
-export async function getPublicToken(client) {
- const addresses = JSON.parse(readFileSync('addresses.json'));
- return Contract.at(addresses.publicToken, PublicTokenArtifact, client);
+ return Contract.at(addresses.token, TokenContractAbi, client);
}
// docs:end:get-tokens
diff --git a/yarn-project/end-to-end/src/sample-dapp/deploy.mjs b/yarn-project/end-to-end/src/sample-dapp/deploy.mjs
index af8d7604f000..1fa4036fee56 100644
--- a/yarn-project/end-to-end/src/sample-dapp/deploy.mjs
+++ b/yarn-project/end-to-end/src/sample-dapp/deploy.mjs
@@ -1,8 +1,5 @@
-import { ContractDeployer, createAztecRpcClient } from '@aztec/aztec.js';
-import {
- PrivateTokenContractAbi as PrivateTokenArtifact,
- PublicTokenContractAbi as PublicTokenArtifact,
-} from '@aztec/noir-contracts/artifacts';
+import { Contract, ContractDeployer, createAztecRpcClient, getSandboxAccountsWallets } from '@aztec/aztec.js';
+import { TokenContractAbi } from '@aztec/noir-contracts/artifacts';
import { writeFileSync } from 'fs';
import { fileURLToPath } from 'url';
@@ -12,17 +9,15 @@ const { SANDBOX_URL = 'http://localhost:8080' } = process.env;
async function main() {
const client = createAztecRpcClient(SANDBOX_URL);
- const [owner] = await client.getRegisteredAccounts();
+ const [owner] = await getSandboxAccountsWallets(client);
- const privateTokenDeployer = new ContractDeployer(PrivateTokenArtifact, client);
- const { contractAddress: privateTokenAddress } = await privateTokenDeployer.deploy(100n, owner.address).send().wait();
- console.log(`Private token deployed at ${privateTokenAddress.toString()}`);
+ const token = await Contract.deploy(client, TokenContractAbi, []).send().deployed();
- const publicTokenDeployer = new ContractDeployer(PublicTokenArtifact, client);
- const { contractAddress: publicTokenAddress } = await publicTokenDeployer.deploy().send().wait();
- console.log(`Public token deployed at ${publicTokenAddress.toString()}`);
+ await token.withWallet(owner).methods._initialize({ address: owner.getAddress() }).send().wait();
- const addresses = { privateToken: privateTokenAddress.toString(), publicToken: publicTokenAddress.toString() };
+ console.log(`Token deployed at ${token.address.toString()}`);
+
+ const addresses = { token: token.address.toString() };
writeFileSync('addresses.json', JSON.stringify(addresses, null, 2));
}
// docs:end:dapp-deploy
diff --git a/yarn-project/end-to-end/src/sample-dapp/index.mjs b/yarn-project/end-to-end/src/sample-dapp/index.mjs
index a911862283f3..e07d8d78ed94 100644
--- a/yarn-project/end-to-end/src/sample-dapp/index.mjs
+++ b/yarn-project/end-to-end/src/sample-dapp/index.mjs
@@ -1,7 +1,13 @@
-import { L2BlockL2Logs, createAztecRpcClient, getSandboxAccountsWallets } from '@aztec/aztec.js';
+import {
+ Fr,
+ L2BlockL2Logs,
+ computeMessageSecretHash,
+ createAztecRpcClient,
+ getSandboxAccountsWallets,
+} from '@aztec/aztec.js';
import { fileURLToPath } from '@aztec/foundation/url';
-import { getPrivateToken, getPublicToken } from './contracts.mjs';
+import { getToken } from './contracts.mjs';
const { SANDBOX_URL = 'http://localhost:8080' } = process.env;
@@ -15,22 +21,37 @@ async function showAccounts(client) {
async function showPrivateBalances(client) {
// docs:start:showPrivateBalances
const accounts = await client.getRegisteredAccounts();
- const privateToken = await getPrivateToken(client);
+ const token = await getToken(client);
for (const account of accounts) {
// highlight-next-line:showPrivateBalances
- const balance = await privateToken.methods.getBalance(account.address).view();
+ const balance = await token.methods.balance_of_private({ address: account.address }).view();
console.log(`Balance of ${account.address}: ${balance}`);
}
// docs:end:showPrivateBalances
}
+async function mintPrivateFunds(client) {
+ const [owner] = await getSandboxAccountsWallets(client);
+ const token = await getToken(owner);
+
+ await showPrivateBalances(client);
+
+ const mintAmount = 20n;
+ const secret = Fr.random();
+ const secretHash = await computeMessageSecretHash(secret);
+ await token.methods.mint_private(mintAmount, secretHash).send().wait();
+ await token.methods.redeem_shield({ address: owner.getAddress() }, mintAmount, secret).send().wait();
+
+ await showPrivateBalances(client);
+}
+
async function transferPrivateFunds(client) {
// docs:start:transferPrivateFunds
const [owner, recipient] = await getSandboxAccountsWallets(client);
- const privateToken = await getPrivateToken(owner);
+ const token = await getToken(owner);
- const tx = privateToken.methods.transfer(1n, recipient.getAddress()).send();
+ const tx = token.methods.transfer({ address: owner.getAddress() }, { address: recipient.getAddress() }, 1n, 0).send();
console.log(`Sent transfer transaction ${await tx.getTxHash()}`);
await showPrivateBalances(client);
@@ -44,11 +65,11 @@ async function transferPrivateFunds(client) {
async function showPublicBalances(client) {
// docs:start:showPublicBalances
const accounts = await client.getRegisteredAccounts();
- const publicToken = await getPublicToken(client);
+ const token = await getToken(client);
for (const account of accounts) {
// highlight-next-line:showPublicBalances
- const balance = await publicToken.methods.publicBalanceOf(account.address).view();
+ const balance = await token.methods.balance_of_public({ address: account.address }).view();
console.log(`Balance of ${account.address}: ${balance}`);
}
// docs:end:showPublicBalances
@@ -57,9 +78,9 @@ async function showPublicBalances(client) {
async function mintPublicFunds(client) {
// docs:start:mintPublicFunds
const [owner] = await getSandboxAccountsWallets(client);
- const publicToken = await getPublicToken(owner);
+ const token = await getToken(owner);
- const tx = publicToken.methods.mint(100n, owner.getAddress()).send();
+ const tx = token.methods.mint_public({ address: owner.getAddress() }, 100n).send();
console.log(`Sent mint transaction ${await tx.getTxHash()}`);
await showPublicBalances(client);
@@ -84,6 +105,8 @@ async function main() {
await showAccounts(client);
+ await mintPrivateFunds(client);
+
await transferPrivateFunds(client);
await mintPublicFunds(client);
diff --git a/yarn-project/end-to-end/src/sample-dapp/index.test.mjs b/yarn-project/end-to-end/src/sample-dapp/index.test.mjs
index 001412e17f6b..88f8cf4d3355 100644
--- a/yarn-project/end-to-end/src/sample-dapp/index.test.mjs
+++ b/yarn-project/end-to-end/src/sample-dapp/index.test.mjs
@@ -1,15 +1,23 @@
import { createSandbox } from '@aztec/aztec-sandbox';
-import { Contract, createAccount } from '@aztec/aztec.js';
-import { PrivateTokenContractAbi as PrivateTokenArtifact } from '@aztec/noir-contracts/artifacts';
+import { Contract, Fr, computeMessageSecretHash, createAccount } from '@aztec/aztec.js';
+import { TokenContractAbi } from '@aztec/noir-contracts/artifacts';
-describe('private token', () => {
+describe('token', () => {
// docs:start:setup
let rpc, stop, owner, recipient, token;
beforeAll(async () => {
({ rpcServer: rpc, stop } = await createSandbox());
owner = await createAccount(rpc);
recipient = await createAccount(rpc);
- token = await Contract.deploy(owner, PrivateTokenArtifact, [100n, owner.getAddress()]).send().deployed();
+
+ token = await Contract.deploy(owner, TokenContractAbi, []).send().deployed();
+ await token.methods._initialize({ address: owner.getAddress() }).send().wait();
+
+ const initialBalance = 20n;
+ const secret = Fr.random();
+ const secretHash = await computeMessageSecretHash(secret);
+ await token.methods.mint_private(initialBalance, secretHash).send().wait();
+ await token.methods.redeem_shield({ address: owner.getAddress() }, initialBalance, secret).send().wait();
}, 60_000);
afterAll(() => stop());
@@ -17,9 +25,12 @@ describe('private token', () => {
// docs:start:test
it('increases recipient funds on transfer', async () => {
- expect(await token.methods.getBalance(recipient.getAddress()).view()).toEqual(0n);
- await token.methods.transfer(20n, recipient.getAddress()).send().wait();
- expect(await token.methods.getBalance(recipient.getAddress()).view()).toEqual(20n);
+ expect(await token.methods.balance_of_private({ address: recipient.getAddress() }).view()).toEqual(0n);
+ await token.methods
+ .transfer({ address: owner.getAddress() }, { address: recipient.getAddress() }, 20n, 0)
+ .send()
+ .wait();
+ expect(await token.methods.balance_of_private({ address: recipient.getAddress() }).view()).toEqual(20n);
});
// docs:end:test
});
diff --git a/yarn-project/noir-contracts/Nargo.toml b/yarn-project/noir-contracts/Nargo.toml
index 28bf8f460ee7..2d5cfebf5857 100644
--- a/yarn-project/noir-contracts/Nargo.toml
+++ b/yarn-project/noir-contracts/Nargo.toml
@@ -20,6 +20,7 @@ members = [
"src/contracts/schnorr_account_contract",
"src/contracts/schnorr_hardcoded_account_contract",
"src/contracts/schnorr_single_key_account_contract",
+ "src/contracts/stateful_test_contract",
"src/contracts/test_contract",
"src/contracts/token_contract",
"src/contracts/uniswap_contract",
diff --git a/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr
index 81131fae5e38..b287671792b7 100644
--- a/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr
+++ b/yarn-project/noir-contracts/src/contracts/escrow_contract/src/main.nr
@@ -1,5 +1,4 @@
mod address_note;
-mod private_token_contract_interface;
// Sample escrow contract that stores a balance of a private token on behalf of an owner.
contract Escrow {
@@ -14,6 +13,7 @@ contract Escrow {
utils as note_utils,
},
oracle::get_public_key::get_public_key,
+ oracle::compute_selector::compute_selector,
state_vars::set::Set,
};
@@ -23,8 +23,6 @@ contract Escrow {
ADDRESS_NOTE_LEN,
};
- use crate::private_token_contract_interface::PrivateTokenPrivateContextInterface;
-
struct Storage {
owners: Set,
}
@@ -59,9 +57,9 @@ contract Escrow {
// Withdraws balance. Requires that msg.sender is registered as an owner.
#[aztec(private)]
fn withdraw(
- token: pub Field,
- amount: pub Field,
- recipient: pub Field,
+ token: Field,
+ amount: Field,
+ recipient: Field,
) {
let this = context.this_address();
let sender = context.msg_sender();
@@ -75,7 +73,12 @@ contract Escrow {
assert(note.address == sender);
assert(note.owner == this);
- let _callStackItem = PrivateTokenPrivateContextInterface::at(token).transfer(&mut context, amount, recipient);
+ let selector = compute_selector("transfer((Field),(Field),Field,Field)");
+ let _callStackItem = context.call_private_function(
+ token,
+ selector,
+ [this, recipient, amount, 0]
+ );
}
unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, preimage: [Field; ADDRESS_NOTE_LEN]) -> [Field; 4] {
diff --git a/yarn-project/noir-contracts/src/contracts/escrow_contract/src/private_token_contract_interface.nr b/yarn-project/noir-contracts/src/contracts/escrow_contract/src/private_token_contract_interface.nr
deleted file mode 120000
index 0f8207f8b98e..000000000000
--- a/yarn-project/noir-contracts/src/contracts/escrow_contract/src/private_token_contract_interface.nr
+++ /dev/null
@@ -1 +0,0 @@
-../../private_token_contract/src/interface.nr
\ No newline at end of file
diff --git a/yarn-project/noir-contracts/src/contracts/stateful_test_contract/Nargo.toml b/yarn-project/noir-contracts/src/contracts/stateful_test_contract/Nargo.toml
new file mode 100644
index 000000000000..165aea0bfe41
--- /dev/null
+++ b/yarn-project/noir-contracts/src/contracts/stateful_test_contract/Nargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "stateful_test_contract"
+authors = [""]
+compiler_version = "0.1"
+type = "contract"
+
+[dependencies]
+aztec = { path = "../../../../aztec-nr/aztec" }
+value_note = { path = "../../../../aztec-nr/value-note"}
\ No newline at end of file
diff --git a/yarn-project/noir-contracts/src/contracts/stateful_test_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/stateful_test_contract/src/main.nr
new file mode 100644
index 000000000000..e8bb13a2a662
--- /dev/null
+++ b/yarn-project/noir-contracts/src/contracts/stateful_test_contract/src/main.nr
@@ -0,0 +1,99 @@
+// A contract used for testing a random hodgepodge of small features from simulator and end-to-end tests.
+contract StatefulTest {
+ use dep::std::option::Option;
+ use dep::value_note::{
+ balance_utils,
+ utils::{increment, decrement},
+ value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods},
+ };
+ use dep::aztec::{
+ context::{PrivateContext, PublicContext, Context},
+ note::{
+ note_header::NoteHeader,
+ utils as note_utils,
+ },
+ state_vars::{map::Map, public_state::PublicState, set::Set},
+ types::type_serialisation::field_serialisation::{
+ FieldSerialisationMethods, FIELD_SERIALISED_LEN,
+ },
+ };
+
+ struct Storage {
+ notes: Map>,
+ public_values: Map>,
+ }
+
+ impl Storage {
+ fn init(context: Context) -> pub Self {
+ Storage {
+ notes: Map::new(
+ context,
+ 1, // Storage slot
+ |context, slot| {
+ Set::new(context, slot, ValueNoteMethods)
+ },
+ ),
+ public_values: Map::new(
+ context,
+ 2,
+ |context, slot| {
+ PublicState::new(
+ context,
+ slot,
+ FieldSerialisationMethods,
+ )
+ },
+ ),
+ }
+ }
+ }
+
+ #[aztec(private)]
+ fn constructor(owner: Field, value: Field) {
+ let storage = Storage::init(Context::private(&mut context));
+ let loc = storage.notes.at(owner);
+ increment(loc, value, owner);
+ }
+
+ #[aztec(private)]
+ fn create_note(
+ owner: Field,
+ value: Field,
+ ) {
+ let storage = Storage::init(Context::private(&mut context));
+ if (value != 0){
+ let loc = storage.notes.at(owner);
+ increment(loc, value, owner);
+ }
+ }
+
+ #[aztec(private)]
+ fn destroy_and_create(
+ recipient: Field,
+ amount: Field,
+ ) {
+ let storage = Storage::init(Context::private(&mut context));
+ let sender = context.msg_sender();
+
+ let sender_notes = storage.notes.at(sender);
+ decrement(sender_notes, amount, sender);
+
+ let recipient_notes = storage.notes.at(recipient);
+ increment(recipient_notes, amount, recipient);
+ }
+
+ unconstrained fn summed_values(
+ owner: Field,
+ ) -> Field {
+ let storage = Storage::init(Context::none());
+ let owner_balance = storage.notes.at(owner);
+
+ // Return the sum of all notes in the set.
+ balance_utils::get_balance(owner_balance)
+ }
+
+ unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, preimage: [Field; VALUE_NOTE_LEN]) -> [Field; 4] {
+ let note_header = NoteHeader { contract_address, nonce, storage_slot };
+ note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage)
+ }
+}