Skip to content

Commit

Permalink
burn & burn_multiple_nfts logic + test
Browse files Browse the repository at this point in the history
  • Loading branch information
marc0olo committed Jul 5, 2023
1 parent d6a5b60 commit a49432c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 12 deletions.
30 changes: 18 additions & 12 deletions development/smart-contracts/contracts/AENSWrapping.aes
Expand Up @@ -177,13 +177,7 @@ main contract AENSWrapping : IAEX141, IAENSWrapping =
// burnable extension

stateful entrypoint burn(token_id: int) =
let owner = require_authorized(token_id)
__remove_approval(token_id)
put(state{ balances[owner] @balance = balance - 1
, total_supply = state.total_supply - 1
, token_to_owner = Map.delete(token_id, state.token_to_owner)
, owner_to_tokens[owner] @owners_tokens = Set.delete(token_id, owners_tokens) })
Chain.event(Burn(owner, token_id))
__burn_single(token_id)

// AENSWrapping

Expand Down Expand Up @@ -513,8 +507,7 @@ main contract AENSWrapping : IAEX141, IAENSWrapping =
/// @notice burns a set of NFTs (only possible if AENS names are expired)
/// @param nft_ids the ids of the NFTs to burn
stateful entrypoint burn_multiple_nfts(nft_ids: Set.set(int)) =
// TODO
()
List.foreach(Set.to_list(nft_ids), (id) => __burn_single(id))

// external helpers for AEX-141

Expand All @@ -523,6 +516,12 @@ main contract AENSWrapping : IAEX141, IAENSWrapping =

// internal helper functions

function require_expired_if_wrapped(nft_id: int) =
let Some(MetadataMap(nft_metadata_map)) = Map.lookup(nft_id, state.metadata)
if(Map.size(nft_metadata_map) > 0)
let Some(FixedTTL(expiration_height)) = Map.lookup(nft_id, state.token_to_name_expiration)
require(Chain.block_height > expiration_height, "WRAPPED_NAMES_NOT_EXPIRED")

function require_can_receive_name(target_nft_id: int, target_owner: address) =
switch(get_nft_config(target_nft_id, target_owner))
None => abort("RECEIVING_NAME_NOT_ALLOWED")
Expand Down Expand Up @@ -630,11 +629,18 @@ main contract AENSWrapping : IAEX141, IAENSWrapping =
if(Map.member(token_id, state.approvals))
put(state{ approvals = Map.delete(token_id, state.approvals) })

stateful function __burn(owner: address, token_id: int) =
put(state{ balances[owner] @owner_balance = owner_balance - 1
stateful function __burn_single(token_id: int) =
let owner = require_authorized(token_id)
require_expired_if_wrapped(token_id)
__remove_approval(token_id)
put(state{ balances[owner] @balance = balance - 1
, total_supply = state.total_supply - 1
, token_to_owner = Map.delete(token_id, state.token_to_owner)
, owner_to_tokens[owner] @owners_tokens = Set.delete(token_id, owners_tokens) })
, owner_to_tokens[owner] @owners_tokens = Set.delete(token_id, owners_tokens)
, token_to_name_expiration = Map.delete(token_id, state.token_to_name_expiration)
, token_to_config = Map.delete(token_id, state.token_to_config)
, metadata = Map.delete(token_id, state.metadata) })
Chain.event(Burn(owner, token_id))

function get_possible_reward(owner: address, owner_cfg : config, expiration_height: int) : int =
let delta = expiration_height - Chain.block_height
Expand Down
51 changes: 51 additions & 0 deletions development/smart-contracts/test/aensWrappingTest.js
Expand Up @@ -749,6 +749,57 @@ describe('AENSWrapping', () => {
assert.equal(extendAllForRewardTx.decodedEvents[0].args[1], otherAccount.address);
assert.equal(extendAllForRewardTx.decodedEvents[0].args[2], globalConfig.emergency_reward);
});
it('burn & burn_multiple_nfts', async () => {
// prepare: mint 3 different NFTs
await contract.mint(aeSdk.selectedAddress);
await contract.mint(aeSdk.selectedAddress);
await contract.mint(aeSdk.selectedAddress);

// checks before burning
let totalSupply = (await contract.total_supply()).decodedResult;
let nftBalance = (await contract.balance(aeSdk.selectedAddress)).decodedResult;
let ownedTokens = (await contract.get_owned_tokens(aeSdk.selectedAddress)).decodedResult;
assert.equal(totalSupply, 3);
assert.equal(nftBalance, 3);
assert.deepEqual(ownedTokens, [1n, 2n, 3n]);

// burn a single NFT
const burnTx = await contract.burn(2);

// check Burn event
assert.equal(burnTx.decodedEvents[0].name, 'Burn');
assert.equal(burnTx.decodedEvents[0].args[0], aeSdk.selectedAddress);
assert.equal(burnTx.decodedEvents[0].args[1], 2);

// checks after burning a single nft
totalSupply = (await contract.total_supply()).decodedResult;
nftBalance = (await contract.balance(aeSdk.selectedAddress)).decodedResult;
ownedTokens = (await contract.get_owned_tokens(aeSdk.selectedAddress)).decodedResult;
assert.equal(totalSupply, 2);
assert.equal(nftBalance, 2);
assert.deepEqual(ownedTokens, [1n, 3n]);

const burnMultipleNftsTx = await contract.burn_multiple_nfts([1,3]);

// check Burn events
assert.equal(burnMultipleNftsTx.decodedEvents[0].name, 'Burn');
assert.equal(burnMultipleNftsTx.decodedEvents[0].args[0], aeSdk.selectedAddress);
assert.equal(burnMultipleNftsTx.decodedEvents[0].args[1], 3);
assert.equal(burnMultipleNftsTx.decodedEvents[1].name, 'Burn');
assert.equal(burnMultipleNftsTx.decodedEvents[1].args[0], aeSdk.selectedAddress);
assert.equal(burnMultipleNftsTx.decodedEvents[1].args[1], 1);

// checks after burning multiple nfts
totalSupply = (await contract.total_supply()).decodedResult;
nftBalance = (await contract.balance(aeSdk.selectedAddress)).decodedResult;
ownedTokens = (await contract.get_owned_tokens(aeSdk.selectedAddress)).decodedResult;
assert.equal(totalSupply, 0);
assert.equal(nftBalance, 0);
assert.deepEqual(ownedTokens, []);

// TODO test burning with expired names
// blocked by https://github.com/aeternity/aeproject/issues/470
});
});
});
});

0 comments on commit a49432c

Please sign in to comment.