Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan committed Sep 2, 2024
1 parent 5c2f992 commit a0283e4
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 6 deletions.
38 changes: 34 additions & 4 deletions noir-projects/noir-contracts/contracts/nft_contract/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,25 @@ contract NFT {
storage.public_owners.at(token_id).write(to);
}

// TODO(#8238): Remove ther randomness argument below
// We have only public burn flow because the flow is not that common for it to be worth it to clutter
// the contract with a private one.
#[aztec(public)]
fn burn(from: AztecAddress, token_id: 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 public_owner = storage.public_owners.at(token_id).read();
assert(public_owner.eq(from), "invalid owner");

storage.nft_exists.at(token_id).write(false);
storage.public_owners.at(token_id).write(AztecAddress::zero());
}

// TODO(#8238): Remove ther randomness argument below once we have partial notes delivery (then we can just fetch
// the randomness from oracle).
#[aztec(private)]
fn prepare_shield(finalizer: AztecAddress, randomness: Field) {
// We create a partial NFT note with unpopulated/zero token id for msg_sender
Expand Down Expand Up @@ -215,7 +233,7 @@ contract NFT {
let mut options = NoteGetterOptions::new();
options = options.select(NFTNote::properties().token_id, token_id, Option::none()).set_limit(1);
let notes = nfts.at(from).pop_notes(options);
assert(notes.len() == 1, "NFT not found");
assert(notes.len() == 1, "NFT not found when transferring");

let from_ovpk_m = get_current_public_keys(&mut context, from).ovpk_m;
let to_keys = get_current_public_keys(&mut context, to);
Expand All @@ -225,13 +243,25 @@ contract NFT {
}

#[aztec(private)]
fn unshield(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) {
fn unshield(from: AztecAddress, to: AztecAddress, token_id: Field, nonce: Field) {
if (!from.eq(context.msg_sender())) {
assert_current_call_valid_authwit(&mut context, from);
} else {
assert(nonce == 0, "invalid nonce");
}
// ...

let mut options = NoteGetterOptions::new();
options = options.select(NFTNote::properties().token_id, token_id, Option::none()).set_limit(1);
let notes = storage.private_nfts.at(from).pop_notes(options);
assert(notes.len() == 1, "NFT not found when unshielding");

NFT::at(context.this_address())._finish_unshield(to, token_id).enqueue(&mut context);
}

#[aztec(public)]
#[aztec(internal)]
fn _finish_unshield(to: AztecAddress, token_id: Field) {
storage.public_owners.at(token_id).write(to);
}

// Returns zero address when the token does not have public owner. Reverts if the token does not exist.
Expand Down
31 changes: 29 additions & 2 deletions yarn-project/end-to-end/src/e2e_nft.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('NFT', () => {
expect(ownerAfterMint).toEqual(user1Wallet.getAddress());
});

it('user shields', async () => {
it('shields', async () => {
// In a simple shield flow the finalizer is the user itself (in the uniswap swap to shield flow it would be
// the uniswap contract)
const finalizer = user1Wallet.getAddress();
Expand Down Expand Up @@ -102,10 +102,37 @@ describe('NFT', () => {
// console.log('txEffect', txEffect);
});

it('user privately sends', async () => {
it('privately sends', async () => {
await nftContractAsUser1.methods
.transfer_from(user1Wallet.getAddress(), user2Wallet.getAddress(), TOKEN_ID, 0)
.send()
.wait();
});

it('unshields', async () => {
await nftContractAsUser2.methods
.unshield(user2Wallet.getAddress(), user2Wallet.getAddress(), TOKEN_ID, 0)
.send()
.wait();

const publicOwnerAfter = await nftContractAsUser2.methods.owner_of(TOKEN_ID).simulate();
expect(publicOwnerAfter).toEqual(user2Wallet.getAddress());
});

it('publicly sends', async () => {
await nftContractAsUser2.methods
.transfer_public(user2Wallet.getAddress(), user1Wallet.getAddress(), TOKEN_ID, 0)
.send()
.wait();

const publicOwnerAfter = await nftContractAsUser2.methods.owner_of(TOKEN_ID).simulate();
expect(publicOwnerAfter).toEqual(user1Wallet.getAddress());
});

it('burns', async () => {
await nftContractAsUser1.methods.burn(user1Wallet.getAddress(), TOKEN_ID, 0).send().wait();

const publicOwnerAfter = await nftContractAsUser1.methods.owner_of(TOKEN_ID).simulate();
expect(publicOwnerAfter).toEqual(AztecAddress.ZERO);
});
});

0 comments on commit a0283e4

Please sign in to comment.