Skip to content

Commit

Permalink
requested changes from PR
Browse files Browse the repository at this point in the history
Signed-off-by: Simeon Nakov <[email protected]>
  • Loading branch information
simzzz committed Jan 31, 2025
1 parent b8f539a commit 47a08ef
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 66 deletions.
2 changes: 2 additions & 0 deletions test/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ const GAS_LIMIT_5_000_000 = { gasLimit: 5_000_000 };
const GAS_LIMIT_10_000_000 = { gasLimit: 10_000_000 };
const GAS_LIMIT_800000 = { gasLimit: 800000 };
const GAS_LIMIT_8000000 = { gasLimit: 8000000 };
const ONE_HBAR = ethers.parseEther('1');
const TOKEN_NAME = 'tokenName';
const TOKEN_SYMBOL = 'tokenSymbol';
const TOKEN_URL = 'tokenUrl';
Expand Down Expand Up @@ -254,4 +255,5 @@ module.exports = {
GWEI,
HTS_SYSTEM_CONTRACT_ID,
HAS_SYSTEM_CONTRACT_ID,
ONE_HBAR,
};
167 changes: 101 additions & 66 deletions test/system-contracts/hedera-token-service/hrc-904/AirdropContract.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,60 +33,7 @@ describe('HIP904 AirdropContract Test Suite', function () {
let signers;
let owner;
let accounts;

async function setupToken() {
const tokenAddress =
await utils.createFungibleTokenWithSECP256K1AdminKeyWithoutKYC(
tokenCreateContract,
owner,
utils.getSignerCompressedPublicKey()
);

await utils.updateTokenKeysViaHapi(tokenAddress, [
await airdropContract.getAddress(),
await tokenCreateContract.getAddress(),
]);

await utils.associateToken(
tokenCreateContract,
tokenAddress,
Constants.Contract.TokenCreateContract
);

return tokenAddress;
}

async function setupNft() {
const nftTokenAddress =
await utils.createNonFungibleTokenWithSECP256K1AdminKeyWithoutKYC(
tokenCreateContract,
owner,
utils.getSignerCompressedPublicKey()
);

await utils.updateTokenKeysViaHapi(
nftTokenAddress,
[
await airdropContract.getAddress(),
await tokenCreateContract.getAddress(),
],
true,
true,
false,
true,
true,
true,
false
);

await utils.associateToken(
tokenCreateContract,
nftTokenAddress,
Constants.Contract.TokenCreateContract
);

return nftTokenAddress;
}
let contractAddresses;

before(async function () {
signers = await ethers.getSigners();
Expand All @@ -103,19 +50,32 @@ describe('HIP904 AirdropContract Test Suite', function () {
owner = signers[0].address;
accounts = signers.slice(1, 3).map((s) => s.address);

await utils.updateAccountKeysViaHapi([
contractAddresses = [
await airdropContract.getAddress(),
await tokenCreateContract.getAddress(),
]);
];
await utils.updateAccountKeysViaHapi(contractAddresses);

tokenAddress = await setupToken();
nftTokenAddress = await setupNft();
tokenAddress = await utils.setupToken(
tokenCreateContract,
owner,
contractAddresses
);
nftTokenAddress = await utils.setupNft(
tokenCreateContract,
owner,
contractAddresses
);
});

it('should airdrop a fungible token (FT) to a single account', async function () {
const ftAmount = BigInt(1);
const receiver = signers[1].address;
const tokenAddress = await setupToken();
const tokenAddress = await utils.setupToken(
tokenCreateContract,
owner,
contractAddresses
);

const initialBalance = await erc20Contract.balanceOf(
tokenAddress,
Expand Down Expand Up @@ -162,7 +122,11 @@ describe('HIP904 AirdropContract Test Suite', function () {
it('should airdrop fungible token (FT) to a single account using distribute', async function () {
const ftAmount = BigInt(1);
const receiver = signers[1].address;
const tokenAddress = await setupToken();
const tokenAddress = await utils.setupToken(
tokenCreateContract,
owner,
contractAddresses
);

const initialBalance = await erc20Contract.balanceOf(
tokenAddress,
Expand All @@ -187,7 +151,11 @@ describe('HIP904 AirdropContract Test Suite', function () {

it('should airdrop fungible tokens (FT) to multiple accounts', async function () {
const ftAmount = BigInt(1);
const tokenAddress = await setupToken();
const tokenAddress = await utils.setupToken(
tokenCreateContract,
owner,
contractAddresses
);

const getBalances = async () =>
Promise.all(
Expand Down Expand Up @@ -234,8 +202,14 @@ describe('HIP904 AirdropContract Test Suite', function () {
expect(nftOwner).to.equal(receiver);
});

// TODO: Test skipped due to missing error code support in services implementation
// See: https://github.com/hashgraph/hedera-services/issues/17409
it.skip('should airdrop non-fungible tokens (NFT) to multiple accounts', async function () {
const nftTokenAddress = await setupNft();
const nftTokenAddress = await utils.setupNft(
tokenCreateContract,
owner,
contractAddresses
);
const serials = [];
serials.push(
await utils.mintNFTToAddress(tokenCreateContract, nftTokenAddress)
Expand Down Expand Up @@ -269,7 +243,9 @@ describe('HIP904 AirdropContract Test Suite', function () {
const tokens = [];
// Every accountAmount counts as 1 transfer so 5x2=10
for (let i = 0; i < 5; i++) {
tokens.push(await setupToken());
tokens.push(
await utils.setupToken(tokenCreateContract, owner, contractAddresses)
);
}
for (let i = 0; i < accounts.length; i++) {
const tx = await airdropContract.multipleFtAirdrop(
Expand All @@ -292,7 +268,11 @@ describe('HIP904 AirdropContract Test Suite', function () {
const tokens = [];
const serials = [];
for (let i = 0; i < count; i++) {
const tokenAddress = await setupNft();
const tokenAddress = await utils.setupNft(
tokenCreateContract,
owner,
contractAddresses
);
const serial = await utils.mintNFTToAddress(
tokenCreateContract,
tokenAddress
Expand Down Expand Up @@ -400,7 +380,11 @@ describe('HIP904 AirdropContract Test Suite', function () {
const nftTokens = [];
const nftSerials = [];
for (let i = 0; i < 11; i++) {
const tokenAddress = await setupNft();
const tokenAddress = await utils.setupNft(
tokenCreateContract,
owner,
contractAddresses
);
const serial = await utils.mintNFTToAddress(
tokenCreateContract,
tokenAddress
Expand Down Expand Up @@ -432,7 +416,9 @@ describe('HIP904 AirdropContract Test Suite', function () {
const ftAmount = BigInt(1);
const tokens = [];
for (let i = 0; i < 6; i++) {
tokens.push(await setupToken());
tokens.push(
await utils.setupToken(tokenCreateContract, airdropContract, owner)
);
}
const tx = await airdropContract.multipleFtAirdrop(
tokens,
Expand All @@ -447,4 +433,53 @@ describe('HIP904 AirdropContract Test Suite', function () {
expect(error.shortMessage).to.eq('transaction execution reverted');
}
});

it('should handle airdrop to account with no available association slots', async function () {
const ftAmount = BigInt(1);
const receiver = ethers.Wallet.createRandom().connect(ethers.provider);
await signers[0].sendTransaction({
to: receiver.address,
value: ethers.parseEther('100'),
});
const IHRC904AccountFacade = new ethers.Interface(
(await hre.artifacts.readArtifact('IHRC904AccountFacade')).abi
);

walletIHRC904AccountFacade = new ethers.Contract(
receiver.address,
IHRC904AccountFacade,
receiver
);

const disableAutoAssociations =
await walletIHRC904AccountFacade.setUnlimitedAutomaticAssociations(
false,
{
gasLimit: 2_000_000,
}
);
await disableAutoAssociations.wait();

const tx = await airdropContract.tokenAirdrop(
tokenAddress,
signers[0].address,
receiver.address,
ftAmount,
{
gasLimit: 2_000_000,
value: Constants.ONE_HBAR,
}
);
await tx.wait();

const responseCode = await utils.getHTSResponseCode(tx.hash);
expect(responseCode).to.eq('22');

// The airdrop will be pending, so the balance should still be 0
const balance = await erc20Contract.balanceOf(
tokenAddress,
receiver.address
);
expect(balance).to.equal(0n);
});
});
58 changes: 58 additions & 0 deletions test/system-contracts/hedera-token-service/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,64 @@ class Utils {
);
return BigInt(precompileAction.result_data).toString();
}

static async setupNft(tokenCreateContract, owner, contractAddresses) {
const nftTokenAddress =
await this.createNonFungibleTokenWithSECP256K1AdminKeyWithoutKYC(
tokenCreateContract,
owner,
this.getSignerCompressedPublicKey()
);

await this.updateTokenKeysViaHapi(
nftTokenAddress,
contractAddresses,
true,
true,
false,
true,
true,
true,
false
);

await this.associateToken(
tokenCreateContract,
nftTokenAddress,
Constants.Contract.TokenCreateContract
);

return nftTokenAddress;
}

static async setupToken(tokenCreateContract, owner, contractAddresses) {
const tokenAddress =
await this.createFungibleTokenWithSECP256K1AdminKeyWithoutKYC(
tokenCreateContract,
owner,
this.getSignerCompressedPublicKey()
);

await this.updateTokenKeysViaHapi(
tokenAddress,
contractAddresses,
true,
true,
false,
true,
true,
true,
false
);

await this.associateToken(
tokenCreateContract,
tokenAddress,
Constants.Contract.TokenCreateContract
);

return tokenAddress;
}
}

module.exports = Utils;

0 comments on commit 47a08ef

Please sign in to comment.