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

refactor: remove native token #2280

Merged
merged 9 commits into from
Sep 15, 2023
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
4 changes: 2 additions & 2 deletions docs/docs/dev_docs/dapps/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ We can have private transactions that work fine locally, but are dropped by the

#### A public call fails locally

Public function calls can be caught failing locally similar to how we catch private function calls. For this example, we use a [`NativeTokenContract`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/noir-contracts/src/contracts/native_token_contract/src/main.nr) instead of a private one.
Public function calls can be caught failing locally similar to how we catch private function calls. For this example, we use a [`TokenContract`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr) instead of a private one.

:::info
Keep in mind that public function calls behave as in EVM blockchains, in that they are executed by the sequencer and not locally. Local simulation helps alert the user of a potential failure, but the actual execution path of a public function call will depend on when it gets mined.
Expand Down Expand Up @@ -141,7 +141,7 @@ We can query the RPC server for all notes encrypted for a given user in a contra

#### Querying public state

[Public state](../../concepts/foundation/state_model.md#public-state) behaves as a key-value store, much like in the EVM. This scenario is much more straightforward, in that we can directly query the target slot and get the result back as a buffer. Note that we use the [`NativeTokenContract`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/noir-contracts/src/contracts/native_token_contract/src/main.nr) in this example, which defines a mapping of public balances on slot 4.
[Public state](../../concepts/foundation/state_model.md#public-state) behaves as a key-value store, much like in the EVM. This scenario is much more straightforward, in that we can directly query the target slot and get the result back as a buffer. Note that we use the [`TokenContract`](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr) in this example, which defines a mapping of public balances on slot 6.

#include_code public-storage /yarn-project/end-to-end/src/guides/dapp_testing.test.ts typescript

Expand Down
1 change: 0 additions & 1 deletion yarn-project/end-to-end/src/cli_docs_sandbox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ EscrowContractAbi
ImportTestContractAbi
LendingContractAbi
MultiTransferContractAbi
NativeTokenContractAbi
NonNativeTokenContractAbi
ParentContractAbi
PendingCommitmentsContractAbi
Expand Down
140 changes: 91 additions & 49 deletions yarn-project/end-to-end/src/guides/dapp_testing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import {
CheatCodes,
Fr,
L2BlockL2Logs,
computeMessageSecretHash,
createAccount,
createAztecRpcClient,
getSandboxAccountsWallets,
waitForSandbox,
} from '@aztec/aztec.js';
import { toBigIntBE } from '@aztec/foundation/bigint-buffer';
import { NativeTokenContract, PrivateTokenContract, TestContract } from '@aztec/noir-contracts/types';
import { TestContract, TokenContract } from '@aztec/noir-contracts/types';

const { SANDBOX_URL = 'http://localhost:8080', ETHEREUM_HOST = 'http://localhost:8545' } = process.env;

describe('guides/dapp/testing', () => {
describe('on in-proc sandbox', () => {
Expand All @@ -20,86 +23,91 @@ describe('guides/dapp/testing', () => {
let stop: () => Promise<void>;
let owner: AccountWallet;
let recipient: AccountWallet;
let token: PrivateTokenContract;
let token: TokenContract;

beforeAll(async () => {
// docs:start:in-proc-sandbox
({ rpcServer: rpc, stop } = await createSandbox());
// docs:end:in-proc-sandbox
owner = await createAccount(rpc);
recipient = await createAccount(rpc);
token = await PrivateTokenContract.deploy(owner, 100n, owner.getAddress()).send().deployed();
token = await TokenContract.deploy(owner).send().deployed();
await token.methods._initialize({ address: owner.getAddress() }).send().wait();
}, 60_000);

// docs:start:stop-in-proc-sandbox
afterAll(() => stop());
// docs:end:stop-in-proc-sandbox

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);
it('increases recipient funds on mint', async () => {
expect(await token.methods.balance_of_private({ address: recipient.getAddress() }).view()).toEqual(0n);
const secret = Fr.random();
const secretHash = await computeMessageSecretHash(secret);
await token.methods.mint_private(20n, secretHash).send().wait();
await token.methods.redeem_shield({ address: recipient.getAddress() }, 20n, secret).send().wait();
expect(await token.methods.balance_of_private({ address: recipient.getAddress() }).view()).toEqual(20n);
});
});
});

describe('on local sandbox', () => {
beforeAll(async () => {
const { SANDBOX_URL = 'http://localhost:8080' } = process.env;
const rpc = createAztecRpcClient(SANDBOX_URL);
await waitForSandbox(rpc);
});

// docs:start:sandbox-example
describe('private token contract', () => {
const { SANDBOX_URL = 'http://localhost:8080' } = process.env;

let rpc: AztecRPC;
let owner: AccountWallet;
let recipient: AccountWallet;
let token: PrivateTokenContract;
let token: TokenContract;

beforeEach(async () => {
rpc = createAztecRpcClient(SANDBOX_URL);
owner = await createAccount(rpc);
recipient = await createAccount(rpc);
token = await PrivateTokenContract.deploy(owner, 100n, owner.getAddress()).send().deployed();
token = await TokenContract.deploy(owner).send().deployed();
await token.methods._initialize({ address: owner.getAddress() }).send().wait();
}, 30_000);

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);
it('increases recipient funds on mint', async () => {
expect(await token.methods.balance_of_private({ address: recipient.getAddress() }).view()).toEqual(0n);
const secret = Fr.random();
const secretHash = await computeMessageSecretHash(secret);
await token.methods.mint_private(20n, secretHash).send().wait();
await token.methods.redeem_shield({ address: recipient.getAddress() }, 20n, secret).send().wait();
expect(await token.methods.balance_of_private({ address: recipient.getAddress() }).view()).toEqual(20n);
Copy link
Member

Choose a reason for hiding this comment

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

As this is being used in the example we should probably limit the level of chaining in the calls

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ye, just wasted a lot of space otherwise, but maybe fine to include the waitForSuccess or just do the wait and ignore the status as we are doing in quite a few places anyway 🤷

});
});
// docs:end:sandbox-example

describe('private token contract with initial accounts', () => {
const { SANDBOX_URL = 'http://localhost:8080' } = process.env;

let rpc: AztecRPC;
let owner: AccountWallet;
let recipient: AccountWallet;
let token: PrivateTokenContract;
let token: TokenContract;

beforeEach(async () => {
// docs:start:use-existing-wallets
rpc = createAztecRpcClient(SANDBOX_URL);
[owner, recipient] = await getSandboxAccountsWallets(rpc);
token = await PrivateTokenContract.deploy(owner, 100n, owner.getAddress()).send().deployed();
token = await TokenContract.deploy(owner).send().deployed();
await token.methods._initialize({ address: owner.getAddress() }).send().wait();
// docs:end:use-existing-wallets
}, 30_000);

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);
it('increases recipient funds on mint', async () => {
expect(await token.methods.balance_of_private({ address: recipient.getAddress() }).view()).toEqual(0n);
const secret = Fr.random();
const secretHash = await computeMessageSecretHash(secret);
await token.methods.mint_private(20n, secretHash).send().wait();
await token.methods.redeem_shield({ address: recipient.getAddress() }, 20n, secret).send().wait();
expect(await token.methods.balance_of_private({ address: recipient.getAddress() }).view()).toEqual(20n);
});
});

describe('cheats', () => {
const { SANDBOX_URL = 'http://localhost:8080', ETHEREUM_HOST = 'http://localhost:8545' } = process.env;

let rpc: AztecRPC;
let owner: AccountWallet;
let testContract: TestContract;
Expand All @@ -122,29 +130,32 @@ describe('guides/dapp/testing', () => {
});

describe('assertions', () => {
const { SANDBOX_URL = 'http://localhost:8080', ETHEREUM_HOST = 'http://localhost:8545' } = process.env;

let rpc: AztecRPC;
let owner: AccountWallet;
let recipient: AccountWallet;
let token: PrivateTokenContract;
let nativeToken: NativeTokenContract;
let testContract: TestContract;
let token: TokenContract;
let cheats: CheatCodes;
let ownerSlot: Fr;

beforeAll(async () => {
rpc = createAztecRpcClient(SANDBOX_URL);
owner = await createAccount(rpc);
recipient = await createAccount(rpc);
token = await PrivateTokenContract.deploy(owner, 100n, owner.getAddress()).send().deployed();
nativeToken = await NativeTokenContract.deploy(owner, 100n, owner.getAddress()).send().deployed();
testContract = await TestContract.deploy(owner).send().deployed();
token = await TokenContract.deploy(owner).send().deployed();
await token.methods._initialize({ address: owner.getAddress() }).send().wait();
const secret = Fr.random();
const secretHash = await computeMessageSecretHash(secret);
await token.methods.mint_private(100n, secretHash).send().wait();
await token.methods.redeem_shield({ address: owner.getAddress() }, 100n, secret).send().wait();

// docs:start:calc-slot
cheats = await CheatCodes.create(ETHEREUM_HOST, rpc);
// The balances mapping is defined on storage slot 1 and is indexed by user address
ownerSlot = cheats.aztec.computeSlotInMap(1n, owner.getAddress());
// The balances mapping is defined on storage slot 3 and is indexed by user address
ownerSlot = cheats.aztec.computeSlotInMap(3n, owner.getAddress());
// docs:end:calc-slot
}, 30_000);
}, 60_000);

it('checks private storage', async () => {
// docs:start:private-storage
Expand All @@ -157,40 +168,61 @@ describe('guides/dapp/testing', () => {

it('checks public storage', async () => {
// docs:start:public-storage
await nativeToken.methods.owner_mint_pub(owner.getAddress(), 100n).send().wait();
const ownerPublicBalanceSlot = cheats.aztec.computeSlotInMap(4n, owner.getAddress());
const balance = await rpc.getPublicStorageAt(nativeToken.address, ownerPublicBalanceSlot);
await token.methods.mint_public({ address: owner.getAddress() }, 100n).send().wait();
const ownerPublicBalanceSlot = cheats.aztec.computeSlotInMap(6n, owner.getAddress());
const balance = await rpc.getPublicStorageAt(token.address, ownerPublicBalanceSlot);
expect(toBigIntBE(balance!)).toEqual(100n);
// docs:end:public-storage
});

it('checks unencrypted logs', async () => {
it('checks unencrypted logs, [Kinda broken with current implementation]', async () => {
Copy link
Member

Choose a reason for hiding this comment

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

issue to fix?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created #2306 for it, will update

// docs:start:unencrypted-logs
const tx = await nativeToken.methods.owner_mint_pub(owner.getAddress(), 100n).send().wait();
const value = Fr.fromString('ef'); // Only 1 bytes will make its way in there :( so no larger stuff
const tx = await testContract.methods.emit_unencrypted(value).send().wait();
const logs = await rpc.getUnencryptedLogs(tx.blockNumber!, 1);
const textLogs = L2BlockL2Logs.unrollLogs(logs).map(log => log.toString('ascii'));
expect(textLogs).toEqual(['Coins minted']);
const log = L2BlockL2Logs.unrollLogs(logs)[0];
expect(Fr.fromBuffer(log)).toEqual(value);
// docs:end:unencrypted-logs
});

it('asserts a local transaction simulation fails by calling simulate', async () => {
// docs:start:local-tx-fails
const call = token.methods.transfer(200n, recipient.getAddress());
const call = token.methods.transfer(
{ address: owner.getAddress() },
{ address: recipient.getAddress() },
200n,
0,
);
await expect(call.simulate()).rejects.toThrowError(/Balance too low/);
// docs:end:local-tx-fails
});

it('asserts a local transaction simulation fails by calling send', async () => {
// docs:start:local-tx-fails-send
const call = token.methods.transfer(200n, recipient.getAddress());
const call = token.methods.transfer(
{ address: owner.getAddress() },
{ address: recipient.getAddress() },
200n,
0,
);
await expect(call.send().wait()).rejects.toThrowError(/Balance too low/);
// docs:end:local-tx-fails-send
});

it('asserts a transaction is dropped', async () => {
// docs:start:tx-dropped
const call1 = token.methods.transfer(80n, recipient.getAddress());
const call2 = token.methods.transfer(50n, recipient.getAddress());
const call1 = token.methods.transfer(
{ address: owner.getAddress() },
{ address: recipient.getAddress() },
80n,
0,
);
const call2 = token.methods.transfer(
{ address: owner.getAddress() },
{ address: recipient.getAddress() },
50n,
0,
);

await call1.simulate();
await call2.simulate();
Expand All @@ -202,14 +234,24 @@ describe('guides/dapp/testing', () => {

it('asserts a simulation for a public function call fails', async () => {
// docs:start:local-pub-fails
const call = nativeToken.methods.transfer_pub(recipient.getAddress(), 1000n);
await expect(call.simulate()).rejects.toThrowError(/Balance too low/);
const call = token.methods.transfer_public(
{ address: owner.getAddress() },
{ address: recipient.getAddress() },
1000n,
0,
);
await expect(call.simulate()).rejects.toThrowError(/Underflow/);
// docs:end:local-pub-fails
});

it('asserts a transaction with a failing public call is dropped (until we get public reverts)', async () => {
// docs:start:pub-dropped
const call = nativeToken.methods.transfer_pub(recipient.getAddress(), 1000n);
const call = token.methods.transfer_public(
{ address: owner.getAddress() },
{ address: recipient.getAddress() },
1000n,
0,
);
await expect(call.send({ skipPublicSimulation: true }).wait()).rejects.toThrowError(/dropped/);
// docs:end:pub-dropped
});
Expand Down
1 change: 0 additions & 1 deletion yarn-project/noir-contracts/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ members = [
"src/contracts/import_test_contract",
"src/contracts/lending_contract",
"src/contracts/multi_transfer_contract",
"src/contracts/native_token_contract",
"src/contracts/non_native_token_contract",
"src/contracts/parent_contract",
"src/contracts/pending_commitments_contract",
Expand Down

This file was deleted.

Loading