diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index 08b4006f56b..d6b7aadd779 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -29,6 +29,7 @@ members = [ "contracts/slow_tree_contract", "contracts/stateful_test_contract", "contracts/test_contract", + "contracts/test_token_contract", "contracts/token_contract", "contracts/token_blacklist_contract", "contracts/token_bridge_contract", diff --git a/noir-projects/noir-contracts/contracts/test_token_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/test_token_contract/Nargo.toml new file mode 100644 index 00000000000..b31f13c0b44 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/test_token_contract/Nargo.toml @@ -0,0 +1,10 @@ +[package] +name = "test_token_contract" +authors = [""] +compiler_version = ">=0.18.0" +type = "contract" + +[dependencies] +aztec = { path = "../../../aztec-nr/aztec" } +compressed_string = { path = "../../../aztec-nr/compressed-string" } +authwit = { path = "../../../aztec-nr/authwit" } diff --git a/noir-projects/noir-contracts/contracts/test_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_token_contract/src/main.nr new file mode 100644 index 00000000000..60eb8b5e396 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/test_token_contract/src/main.nr @@ -0,0 +1,314 @@ +mod types; + +// Copy of the TokenContract that skips initializer checks for all public functions. +// Meant to be used for public simulator tests at simulator/src/public/index.test.ts. + +contract TestToken { + // Libs + use dep::std::option::Option; + + use dep::compressed_string::FieldCompressedString; + + use dep::aztec::{ + note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader, utils as note_utils}, + hash::{compute_secret_hash}, state_vars::{Map, PublicMutable, SharedImmutable, PrivateSet}, + protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress} + }; + + use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; + + use crate::types::{transparent_note::TransparentNote, token_note::{TokenNote, TOKEN_NOTE_LEN}, balances_map::BalancesMap}; + + struct Storage { + admin: PublicMutable, + minters: Map>, + balances: BalancesMap, + total_supply: PublicMutable, + pending_shields: PrivateSet, + public_balances: Map>, + symbol: SharedImmutable, + name: SharedImmutable, + decimals: SharedImmutable, + } + + #[aztec(private)] + #[aztec(initializer)] + fn constructor(admin: AztecAddress, name: str<31>, symbol: str<31>, decimals: u8) { + let selector = FunctionSelector::from_signature("_initialize((Field),(Field),(Field),u8)"); + let name_s = FieldCompressedString::from_string(name); + let symbol_s = FieldCompressedString::from_string(symbol); + context.call_public_function( + context.this_address(), + selector, + [admin.to_field(), name_s.serialize()[0], symbol_s.serialize()[0], decimals as Field] + ); + } + + #[aztec(public)] + #[aztec(noinitcheck)] + fn set_admin(new_admin: AztecAddress) { + assert(storage.admin.read().eq(context.msg_sender()), "caller is not admin"); + storage.admin.write(new_admin); + } + + #[aztec(public)] + #[aztec(noinitcheck)] + fn public_get_name() -> pub FieldCompressedString { + storage.name.read_public() + } + + #[aztec(private)] + fn private_get_name() -> pub FieldCompressedString { + storage.name.read_private() + } + + unconstrained fn un_get_name() -> pub [u8; 31] { + storage.name.read_public().to_bytes() + } + + #[aztec(public)] + #[aztec(noinitcheck)] + fn public_get_symbol() -> pub FieldCompressedString { + storage.symbol.read_public() + } + + #[aztec(private)] + fn private_get_symbol() -> pub FieldCompressedString { + storage.symbol.read_private() + } + + unconstrained fn un_get_symbol() -> pub [u8; 31] { + storage.symbol.read_public().to_bytes() + } + + #[aztec(public)] + #[aztec(noinitcheck)] + fn public_get_decimals() -> pub u8 { + storage.decimals.read_public() + } + + #[aztec(private)] + fn private_get_decimals() -> pub u8 { + storage.decimals.read_private() + } + + unconstrained fn un_get_decimals() -> pub u8 { + storage.decimals.read_public() + } + + #[aztec(public)] + #[aztec(noinitcheck)] + fn set_minter(minter: AztecAddress, approve: bool) { + assert(storage.admin.read().eq(context.msg_sender()), "caller is not admin"); + storage.minters.at(minter).write(approve); + } + + #[aztec(public)] + #[aztec(noinitcheck)] + fn mint_public(to: AztecAddress, amount: Field) { + assert(storage.minters.at(context.msg_sender()).read(), "caller is not minter"); + let amount = U128::from_integer(amount); + let new_balance = storage.public_balances.at(to).read().add(amount); + let supply = storage.total_supply.read().add(amount); + + storage.public_balances.at(to).write(new_balance); + storage.total_supply.write(supply); + } + + #[aztec(public)] + #[aztec(noinitcheck)] + fn mint_private(amount: Field, secret_hash: Field) { + assert(storage.minters.at(context.msg_sender()).read(), "caller is not minter"); + let pending_shields = storage.pending_shields; + let mut note = TransparentNote::new(amount, secret_hash); + let supply = storage.total_supply.read().add(U128::from_integer(amount)); + + storage.total_supply.write(supply); + pending_shields.insert_from_public(&mut note); + } + + #[aztec(private)] + fn privately_mint_private_note(amount: Field) { + storage.balances.add(context.msg_sender(), U128::from_integer(amount)); + let selector = FunctionSelector::from_signature("assert_minter_and_mint((Field),Field)"); + let _void = context.call_public_function( + context.this_address(), + selector, + [context.msg_sender().to_field(), amount] + ); + } + + #[aztec(public)] + #[aztec(noinitcheck)] + internal fn assert_minter_and_mint(minter: AztecAddress, amount: Field) { + assert(storage.minters.at(minter).read(), "caller is not minter"); + let supply = storage.total_supply.read() + U128::from_integer(amount); + storage.total_supply.write(supply); + } + + #[aztec(public)] + #[aztec(noinitcheck)] + fn shield(from: AztecAddress, amount: Field, secret_hash: Field, nonce: Field) { + if (!from.eq(context.msg_sender())) { + // The redeem is only spendable once, so we need to ensure that you cannot insert multiple shields from the same message. + assert_current_call_valid_authwit_public(&mut context, from); + } else { + assert(nonce == 0, "invalid nonce"); + } + + let amount = U128::from_integer(amount); + let from_balance = storage.public_balances.at(from).read().sub(amount); + + let pending_shields = storage.pending_shields; + let mut note = TransparentNote::new(amount.to_integer(), secret_hash); + + storage.public_balances.at(from).write(from_balance); + pending_shields.insert_from_public(&mut note); + } + + #[aztec(public)] + #[aztec(noinitcheck)] + fn transfer_public(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { + if (!from.eq(context.msg_sender())) { + assert_current_call_valid_authwit_public(&mut context, from); + } else { + assert(nonce == 0, "invalid nonce"); + } + + let amount = U128::from_integer(amount); + let from_balance = storage.public_balances.at(from).read().sub(amount); + storage.public_balances.at(from).write(from_balance); + + let to_balance = storage.public_balances.at(to).read().add(amount); + storage.public_balances.at(to).write(to_balance); + } + + #[aztec(public)] + #[aztec(noinitcheck)] + fn burn_public(from: AztecAddress, amount: Field, nonce: Field) { + if (!from.eq(context.msg_sender())) { + assert_current_call_valid_authwit_public(&mut context, from); + } else { + assert(nonce == 0, "invalid nonce"); + } + + let amount = U128::from_integer(amount); + let from_balance = storage.public_balances.at(from).read().sub(amount); + storage.public_balances.at(from).write(from_balance); + + let new_supply = storage.total_supply.read().sub(amount); + storage.total_supply.write(new_supply); + } + + #[aztec(private)] + fn redeem_shield(to: AztecAddress, amount: Field, secret: Field) { + let pending_shields = storage.pending_shields; + let secret_hash = compute_secret_hash(secret); + // Get 1 note (set_limit(1)) which has amount stored in field with index 0 (select(0, amount)) and secret_hash + // stored in field with index 1 (select(1, secret_hash)). + let options = NoteGetterOptions::new().select(0, amount, Option::none()).select(1, secret_hash, Option::none()).set_limit(1); + let notes = pending_shields.get_notes(options); + let note = notes[0].unwrap_unchecked(); + // Remove the note from the pending shields set + pending_shields.remove(note); + + // Add the token note to user's balances set + storage.balances.add(to, U128::from_integer(amount)); + } + + #[aztec(private)] + fn unshield(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { + if (!from.eq(context.msg_sender())) { + assert_current_call_valid_authwit(&mut context, from); + } else { + assert(nonce == 0, "invalid nonce"); + } + + storage.balances.sub(from, U128::from_integer(amount)); + + let selector = FunctionSelector::from_signature("_increase_public_balance((Field),Field)"); + let _void = context.call_public_function(context.this_address(), selector, [to.to_field(), amount]); + } + + #[aztec(private)] + fn transfer(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { + if (!from.eq(context.msg_sender())) { + assert_current_call_valid_authwit(&mut context, from); + } else { + assert(nonce == 0, "invalid nonce"); + } + + let amount = U128::from_integer(amount); + storage.balances.sub(from, amount); + storage.balances.add(to, amount); + } + + #[aztec(private)] + fn burn(from: AztecAddress, amount: Field, nonce: Field) { + if (!from.eq(context.msg_sender())) { + assert_current_call_valid_authwit(&mut context, from); + } else { + assert(nonce == 0, "invalid nonce"); + } + + storage.balances.sub(from, U128::from_integer(amount)); + + let selector = FunctionSelector::from_signature("_reduce_total_supply(Field)"); + let _void = context.call_public_function(context.this_address(), selector, [amount]); + } + + #[aztec(public)] + #[aztec(noinitcheck)] + internal fn _initialize( + new_admin: AztecAddress, + name: FieldCompressedString, + symbol: FieldCompressedString, + decimals: u8 + ) { + assert(!new_admin.is_zero(), "invalid admin"); + storage.admin.write(new_admin); + storage.minters.at(new_admin).write(true); + storage.name.initialize(name); + storage.symbol.initialize(symbol); + storage.decimals.initialize(decimals); + } + + /// Internal /// + + #[aztec(public)] + #[aztec(noinitcheck)] + internal fn _increase_public_balance(to: AztecAddress, amount: Field) { + let new_balance = storage.public_balances.at(to).read().add(U128::from_integer(amount)); + storage.public_balances.at(to).write(new_balance); + } + + #[aztec(public)] + #[aztec(noinitcheck)] + internal fn _reduce_total_supply(amount: Field) { + // Only to be called from burn. + let new_supply = storage.total_supply.read().sub(U128::from_integer(amount)); + storage.total_supply.write(new_supply); + } + + /// Unconstrained /// + + unconstrained fn admin() -> pub Field { + storage.admin.read().to_field() + } + + unconstrained fn is_minter(minter: AztecAddress) -> pub bool { + storage.minters.at(minter).read() + } + + unconstrained fn total_supply() -> pub Field { + storage.total_supply.read().to_integer() + } + + unconstrained fn balance_of_private(owner: AztecAddress) -> pub Field { + storage.balances.balance_of(owner).to_integer() + } + + unconstrained fn balance_of_public(owner: AztecAddress) -> pub Field { + storage.public_balances.at(owner).read().to_integer() + } +} diff --git a/noir-projects/noir-contracts/contracts/test_token_contract/src/types.nr b/noir-projects/noir-contracts/contracts/test_token_contract/src/types.nr new file mode 100644 index 00000000000..62a1bb2a363 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/test_token_contract/src/types.nr @@ -0,0 +1,3 @@ +mod transparent_note; +mod balances_map; +mod token_note; diff --git a/noir-projects/noir-contracts/contracts/test_token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/test_token_contract/src/types/balances_map.nr new file mode 100644 index 00000000000..740d328413f --- /dev/null +++ b/noir-projects/noir-contracts/contracts/test_token_contract/src/types/balances_map.nr @@ -0,0 +1,118 @@ +use dep::std::option::Option; +use dep::aztec::{ + context::{PrivateContext, PublicContext, Context}, hash::pedersen_hash, + protocol_types::{address::AztecAddress, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}, + state_vars::{PrivateSet, Map}, + note::{ + note_getter::view_notes, note_getter_options::{NoteGetterOptions, SortOrder}, + note_viewer_options::NoteViewerOptions, note_header::NoteHeader, note_interface::NoteInterface +} +}; +use crate::types::token_note::{TokenNote, OwnedNote}; + +struct BalancesMap { + map: Map> +} + +impl BalancesMap { + pub fn new(context: Context, storage_slot: Field) -> Self { + assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); + Self { + map: Map::new( + context, + storage_slot, + |context, slot| PrivateSet::new(context, slot) + ) + } + } + + unconstrained pub fn balance_of(self: Self, owner: AztecAddress) -> U128 where T: NoteInterface + OwnedNote { + self.balance_of_with_offset(owner, 0) + } + + unconstrained pub fn balance_of_with_offset( + self: Self, + owner: AztecAddress, + offset: u32 + ) -> U128 where T: NoteInterface + OwnedNote { + let mut balance = U128::from_integer(0); + // docs:start:view_notes + let options = NoteViewerOptions::new().set_offset(offset); + let opt_notes = self.map.at(owner).view_notes(options); + // docs:end:view_notes + let len = opt_notes.len(); + for i in 0..len { + if opt_notes[i].is_some() { + balance = balance + opt_notes[i].unwrap_unchecked().get_amount(); + } + } + if (opt_notes[len - 1].is_some()) { + balance = balance + self.balance_of_with_offset(owner, offset + opt_notes.len() as u32); + } + + balance + } + + pub fn add( + self: Self, + owner: AztecAddress, + addend: U128 + ) where T: NoteInterface + OwnedNote { + let mut addend_note = T::new(addend, owner); + + // docs:start:insert + self.map.at(owner).insert(&mut addend_note, true); + // docs:end:insert + } + + pub fn sub( + self: Self, + owner: AztecAddress, + subtrahend: U128 + ) where T: NoteInterface + OwnedNote { + // docs:start:get_notes + let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); + let maybe_notes = self.map.at(owner).get_notes(options); + // docs:end:get_notes + + let mut minuend: U128 = U128::from_integer(0); + for i in 0..maybe_notes.len() { + if maybe_notes[i].is_some() { + let note = maybe_notes[i].unwrap_unchecked(); + + // Removes the note from the owner's set of notes. + // This will call the the `compute_nullifer` function of the `token_note` + // which require knowledge of the secret key (currently the users encryption key). + // The contract logic must ensure that the spending key is used as well. + // docs:start:remove + self.map.at(owner).remove(note); + // docs:end:remove + + minuend = minuend + note.get_amount(); + } + } + + // This is to provide a nicer error msg, + // without it minuend-subtrahend would still catch it, but more generic error then. + // without the == true, it includes 'minuend.ge(subtrahend)' as part of the error. + assert(minuend >= subtrahend, "Balance too low"); + + self.add(owner, minuend - subtrahend); + } +} + +pub fn filter_notes_min_sum( + notes: [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], + min_sum: U128 +) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where T: NoteInterface + OwnedNote { + let mut selected = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]; + let mut sum = U128::from_integer(0); + for i in 0..notes.len() { + if notes[i].is_some() & sum < min_sum { + let note = notes[i].unwrap_unchecked(); + selected[i] = Option::some(note); + sum = sum.add(note.get_amount()); + } + } + selected +} diff --git a/noir-projects/noir-contracts/contracts/test_token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/test_token_contract/src/types/token_note.nr new file mode 100644 index 00000000000..c9233038f30 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/test_token_contract/src/types/token_note.nr @@ -0,0 +1,124 @@ +use dep::aztec::{ + protocol_types::address::AztecAddress, + note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, + context::PrivateContext, log::emit_encrypted_log, hash::pedersen_hash +}; +use dep::aztec::oracle::{rand::rand, nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key}; +use dep::std::option::Option; + +trait OwnedNote { + fn new(amount: U128, owner: AztecAddress) -> Self; + fn get_amount(self) -> U128; + fn get_owner(self) -> AztecAddress; +} + +global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. + +struct TokenNote { + // the amount of tokens in the note + amount: U128, + // the provider of secrets for the nullifier. The owner (recipient) to ensure that the note + // can be privately spent. When nullifier secret and encryption private key is same + // we can simply use the owner for this one. + owner: AztecAddress, + // randomness of the note to hide contents. + randomness: Field, + // the note header (contract_address, nonce, storage_slot) + // included in the note such that it becomes part of encrypted logs for later use. + header: NoteHeader, +} + +impl NoteInterface for TokenNote { + fn serialize_content(self) -> [Field; TOKEN_NOTE_LEN] { + [self.amount.to_field(), self.owner.to_field(), self.randomness] + } + + fn deserialize_content(serialized_note: [Field; TOKEN_NOTE_LEN]) -> Self { + Self { + // TODO: check this type cast is right + amount: U128::from_integer(serialized_note[0]), + owner: AztecAddress::from_field(serialized_note[1]), + randomness: serialized_note[2], + header: NoteHeader::empty(), + } + } + + fn compute_note_content_hash(self) -> Field { + // TODO(#1205) Should use a non-zero generator index. + pedersen_hash(self.serialize_content(), 0) + } + + // docs:start:nullifier + fn compute_nullifier(self, context: &mut PrivateContext) -> Field { + let note_hash_for_nullify = compute_note_hash_for_consumption(self); + let secret = context.request_nullifier_secret_key(self.owner); + // TODO(#1205) Should use a non-zero generator index. + pedersen_hash([ + note_hash_for_nullify, + secret.low, + secret.high, + ],0) + } + // docs:end:nullifier + + fn compute_nullifier_without_context(self) -> Field { + let note_hash_for_nullify = compute_note_hash_for_consumption(self); + let secret = get_nullifier_secret_key(self.owner); + // TODO(#1205) Should use a non-zero generator index. + pedersen_hash([ + note_hash_for_nullify, + secret.low, + secret.high, + ],0) + } + + fn set_header(&mut self, header: NoteHeader) { + self.header = header; + } + + fn get_header(self) -> NoteHeader { + self.header + } + + // Broadcasts the note as an encrypted log on L1. + fn broadcast(self, context: &mut PrivateContext, slot: Field) { + // We only bother inserting the note if non-empty to save funds on gas. + if !(self.amount == U128::from_integer(0)) { + let encryption_pub_key = get_public_key(self.owner); + emit_encrypted_log( + context, + (*context).this_address(), + slot, + Self::get_note_type_id(), + encryption_pub_key, + self.serialize_content(), + ); + } + } + + fn get_note_type_id() -> Field { + // TODO(#4519): autogenerate + // python -c "print(int(''.join(str(ord(c)) for c in 'TokenNote')))" + 8411110710111078111116101 + } +} + +impl OwnedNote for TokenNote { + fn new(amount: U128, owner: AztecAddress) -> Self { + Self { + amount, + owner, + randomness: rand(), + header: NoteHeader::empty(), + } + } + + fn get_amount(self) -> U128 { + self.amount + } + + fn get_owner(self) -> AztecAddress { + self.owner + } + +} diff --git a/noir-projects/noir-contracts/contracts/test_token_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/test_token_contract/src/types/transparent_note.nr new file mode 100644 index 00000000000..a444d27df26 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/test_token_contract/src/types/transparent_note.nr @@ -0,0 +1,89 @@ +// docs:start:token_types_all +use dep::aztec::{ + note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, + hash::{compute_secret_hash, pedersen_hash}, context::PrivateContext +}; + +global TRANSPARENT_NOTE_LEN: Field = 2; + +// Transparent note represents a note that is created in the clear (public execution), +// but can only be spent by those that know the preimage of the "secret_hash" +struct TransparentNote { + amount: Field, + secret_hash: Field, + // the secret is just here for ease of use and won't be (de)serialized + secret: Field, + // header is just here to satisfy the NoteInterface + header: NoteHeader, +} + +impl NoteInterface for TransparentNote { + fn serialize_content(self) -> [Field; TRANSPARENT_NOTE_LEN] { + [self.amount, self.secret_hash] + } + + fn deserialize_content(serialized_note: [Field; TRANSPARENT_NOTE_LEN]) -> Self { + TransparentNote { + amount: serialized_note[0], + secret_hash: serialized_note[1], + secret: 0, + header: NoteHeader::empty(), + } + } + + fn compute_note_content_hash(self) -> Field { + // TODO(#1205) Should use a non-zero generator index. + pedersen_hash(self.serialize_content(), 0) + } + + fn compute_nullifier(self, _context: &mut PrivateContext) -> Field { + self.compute_nullifier_without_context() + } + + fn compute_nullifier_without_context(self) -> Field { + let siloed_note_hash = compute_note_hash_for_consumption(self); + // TODO(#1205) Should use a non-zero generator index. + pedersen_hash([self.secret, siloed_note_hash],0) + } + + fn set_header(&mut self, header: NoteHeader) { + self.header = header; + } + + fn get_header(self) -> NoteHeader { + self.header + } + + fn broadcast(self, context: &mut PrivateContext, slot: Field) { + assert(false, "TransparentNote does not support broadcast"); + } + + fn get_note_type_id() -> Field { + // TODO(#4519): autogenerate + // python -c "print(int(''.join(str(ord(c)) for c in 'TransparentNote')))" + 84114971101151129711410111011678111116101 + } +} + +impl TransparentNote { + + // CONSTRUCTORS + + pub fn new(amount: Field, secret_hash: Field) -> Self { + TransparentNote { amount, secret_hash, secret: 0, header: NoteHeader::empty() } + } + + // new oracle call primitive + // get me the secret corresponding to this hash + pub fn new_from_secret(amount: Field, secret: Field) -> Self { + TransparentNote { amount, secret_hash: compute_secret_hash(secret), secret, header: NoteHeader::empty() } + } + + // CUSTOM FUNCTIONS FOR THIS NOTE TYPE + + pub fn knows_secret(self, secret: Field) { + let hash = compute_secret_hash(secret); + assert(self.secret_hash == hash); + } +} +// docs:end:token_types_all \ No newline at end of file diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 810c0745c01..162983c4e9d 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -17,7 +17,7 @@ import { Fr } from '@aztec/foundation/fields'; import { ChildContractArtifact } from '@aztec/noir-contracts.js/Child'; import { ParentContractArtifact } from '@aztec/noir-contracts.js/Parent'; import { TestContractArtifact } from '@aztec/noir-contracts.js/Test'; -import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token'; +import { TestTokenContractArtifact } from '@aztec/noir-contracts.js/TestToken'; import { MockProxy, mock } from 'jest-mock-extended'; import { type MemDown, default as memdown } from 'memdown'; @@ -60,7 +60,7 @@ describe('ACIR public execution simulator', () => { describe('mint', () => { it('should run the mint_public function', async () => { const contractAddress = AztecAddress.random(); - const mintArtifact = TokenContractArtifact.functions.find(f => f.name === 'mint_public')!; + const mintArtifact = TestTokenContractArtifact.functions.find(f => f.name === 'mint_public')!; const functionData = FunctionData.fromAbi(mintArtifact); const mintAmount = 140n; @@ -138,7 +138,7 @@ describe('ACIR public execution simulator', () => { beforeEach(() => { contractAddress = AztecAddress.random(); - transferArtifact = TokenContractArtifact.functions.find(f => f.name === 'transfer_public')!; + transferArtifact = TestTokenContractArtifact.functions.find(f => f.name === 'transfer_public')!; functionData = new FunctionData(FunctionSelector.empty(), false, false, false); sender = AztecAddress.random(); args = encodeArguments(transferArtifact, [sender, recipient, 140n, 0n]); @@ -303,7 +303,7 @@ describe('ACIR public execution simulator', () => { }); it('Should be able to create a note hash from the public context', async () => { - const shieldArtifact = TokenContractArtifact.functions.find(f => f.name === 'shield')!; + const shieldArtifact = TestTokenContractArtifact.functions.find(f => f.name === 'shield')!; const msgSender = AztecAddress.random(); const secretHash = Fr.random();