-
Notifications
You must be signed in to change notification settings - Fork 323
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add TestToken without init checks for testing purposes
- Loading branch information
1 parent
b7ce0c5
commit 521a258
Showing
8 changed files
with
663 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
noir-projects/noir-contracts/contracts/test_token_contract/Nargo.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" } |
314 changes: 314 additions & 0 deletions
314
noir-projects/noir-contracts/contracts/test_token_contract/src/main.nr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<AztecAddress>, | ||
minters: Map<AztecAddress, PublicMutable<bool>>, | ||
balances: BalancesMap<TokenNote>, | ||
total_supply: PublicMutable<U128>, | ||
pending_shields: PrivateSet<TransparentNote>, | ||
public_balances: Map<AztecAddress, PublicMutable<U128>>, | ||
symbol: SharedImmutable<FieldCompressedString>, | ||
name: SharedImmutable<FieldCompressedString>, | ||
decimals: SharedImmutable<u8>, | ||
} | ||
|
||
#[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() | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
noir-projects/noir-contracts/contracts/test_token_contract/src/types.nr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
mod transparent_note; | ||
mod balances_map; | ||
mod token_note; |
Oops, something went wrong.