Skip to content

Commit

Permalink
transfer_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 a49432c commit caa1163
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 17 deletions.
33 changes: 18 additions & 15 deletions development/smart-contracts/contracts/AENSWrapping.aes
Expand Up @@ -107,18 +107,7 @@ main contract AENSWrapping : IAEX141, IAENSWrapping =
Map.lookup(token_id, state.token_to_owner)

stateful entrypoint transfer(to: address, token_id: int, data: option(string)) =
let from = require_authorized(token_id)
require(from != to, "SENDER_MUST_NOT_BE_RECEIVER")
__remove_approval(token_id)
put(state{ balances[from] @balance1 = balance1 - 1
, balances[to = 0] @balance2 = balance2 + 1
, token_to_owner[token_id] = to
, owner_to_tokens[from] @from_tokens = Set.delete(token_id, from_tokens)
, owner_to_tokens[to = Set.new()] @to_tokens = Set.insert(token_id, to_tokens)
, token_to_config @token_config = Map.delete(token_id, token_config) })
switch(invoke_nft_receiver(Some(from), to, token_id, data))
(true, false) => abort("SAFE_TRANSFER_FAILED")
_ => Chain.event(Transfer(from, to, token_id))
__transfer_single_nft(to, token_id, data)

stateful entrypoint transfer_to_contract(token_id: int) =
let to = Call.caller
Expand Down Expand Up @@ -500,9 +489,23 @@ main contract AENSWrapping : IAEX141, IAENSWrapping =
/// @notice transfers a set of NFTs to the desired recipient
/// @param recipient the address to become new owner of the NFTs
/// @param nft_ids the ids of the NFTs to transfer
stateful entrypoint transfer_multiple_nfts(recipient: address, nft_ids: Set.set(int)) =
// TODO
()
/// @param data optional data to be provided to a contract receiver
stateful entrypoint transfer_multiple_nfts(recipient: address, nft_ids: Set.set(int), data: option(string)) =
List.foreach(Set.to_list(nft_ids), (id) => __transfer_single_nft(recipient, id, data))

stateful function __transfer_single_nft(to: address, token_id: int, data: option(string)) =
let from = require_authorized(token_id)
require(from != to, "SENDER_MUST_NOT_BE_RECEIVER")
__remove_approval(token_id)
put(state{ balances[from] @balance1 = balance1 - 1
, balances[to = 0] @balance2 = balance2 + 1
, token_to_owner[token_id] = to
, owner_to_tokens[from] @from_tokens = Set.delete(token_id, from_tokens)
, owner_to_tokens[to = Set.new()] @to_tokens = Set.insert(token_id, to_tokens)
, token_to_config @token_config = Map.delete(token_id, token_config) })
switch(invoke_nft_receiver(Some(from), to, token_id, data))
(true, false) => abort("SAFE_TRANSFER_FAILED")
_ => Chain.event(Transfer(from, to, token_id))

/// @notice burns a set of NFTs (only possible if AENS names are expired)
/// @param nft_ids the ids of the NFTs to burn
Expand Down
Expand Up @@ -211,7 +211,8 @@ contract interface IAENSWrapping =
/// @notice transfers a set of NFTs to the desired recipient
/// @param recipient the address to become new owner of the NFTs
/// @param nft_ids the ids of the NFTs to transfer
stateful entrypoint transfer_multiple_nfts : (address, Set.set(int)) => unit
/// @param data optional data to be provided to a contract receiver
stateful entrypoint transfer_multiple_nfts : (address, Set.set(int), option(string)) => unit

/// @notice burns a set of NFTs (only possible if AENS names are expired)
/// @param nft_ids the ids of the NFTs to burn
Expand Down
43 changes: 43 additions & 0 deletions development/smart-contracts/test/aensWrappingTest.js
Expand Up @@ -527,6 +527,49 @@ describe('AENSWrapping', () => {
assert.deepEqual(resolveNftIdAndOwnerTxDryRun.decodedResult, [1n, otherAccount.address]);
});

it('transfer_multiple_nfts', async () => {
// prepare: claim and wrap names
await claimNames(aensNames);
const namesDelegationSigs = await getDelegationSignatures(aensNames, contractId);
await contract.wrap_and_mint(namesDelegationSigs);

await contract.mint(aeSdk.selectedAddress);

const otherAccount = utils.getDefaultAccounts()[1];

// check owner before transfer
await expectNameOwnerContract(aensNames, aeSdk.selectedAddress);
let ownerDryRunTx = await contract.owner(1);
assert.equal(ownerDryRunTx.decodedResult, aeSdk.selectedAddress);
ownerDryRunTx = await contract.owner(2);
assert.equal(ownerDryRunTx.decodedResult, aeSdk.selectedAddress);
let resolveNftIdAndOwnerTxDryRun = await contract.resolve_nft_id_and_owner(aensNames[0]);
assert.deepEqual(resolveNftIdAndOwnerTxDryRun.decodedResult, [1n, aeSdk.selectedAddress]);

// transfer NFTs to other account
const transferMultipleNftsTx = await contract.transfer_multiple_nfts(otherAccount.address, [1, 2]);
console.log(`Gas used (transfer_multiple_nfts): ${transferMultipleNftsTx.result.gasUsed}`);

// check Transfer events
assert.equal(transferMultipleNftsTx.decodedEvents[0].name, 'Transfer');
assert.equal(transferMultipleNftsTx.decodedEvents[0].args[0], aeSdk.selectedAddress);
assert.equal(transferMultipleNftsTx.decodedEvents[0].args[1], otherAccount.address);
assert.equal(transferMultipleNftsTx.decodedEvents[0].args[2], 2);
assert.equal(transferMultipleNftsTx.decodedEvents[1].name, 'Transfer');
assert.equal(transferMultipleNftsTx.decodedEvents[1].args[0], aeSdk.selectedAddress);
assert.equal(transferMultipleNftsTx.decodedEvents[1].args[1], otherAccount.address);
assert.equal(transferMultipleNftsTx.decodedEvents[1].args[2], 1);

// check after transfer
await expectNameOwnerContract(aensNames, otherAccount.address);
ownerDryRunTx = await contract.owner(1);
assert.equal(ownerDryRunTx.decodedResult, otherAccount.address);
ownerDryRunTx = await contract.owner(2);
assert.equal(ownerDryRunTx.decodedResult, otherAccount.address);
resolveNftIdAndOwnerTxDryRun = await contract.resolve_nft_id_and_owner(aensNames[0]);
assert.deepEqual(resolveNftIdAndOwnerTxDryRun.decodedResult, [1n, otherAccount.address]);
});

it('extend_all', async () => {
// prepare: claim and wrap names
await claimNames(aensNames);
Expand Down
3 changes: 2 additions & 1 deletion docs/contract-interface.md
Expand Up @@ -257,7 +257,8 @@ contract interface IAENSWrapping : IAEX141 =
/// @notice transfers a set of NFTs to the desired recipient
/// @param recipient the address to become new owner of the NFTs
/// @param nft_ids the ids of the NFTs to transfer
stateful entrypoint transfer_multiple_nfts : (address, Set.set(int)) => unit
/// @param data optional data to be provided to a contract receiver
stateful entrypoint transfer_multiple_nfts : (address, Set.set(int), option(string)) => unit
/// @notice burns a set of NFTs (only possible if AENS names are expired)
/// @param nft_ids the ids of the NFTs to burn
Expand Down

0 comments on commit caa1163

Please sign in to comment.