Skip to content

Commit d43210c

Browse files
test: Negative cases for getTokenCustomFees, approve, approveNFT (#12454)
Signed-off-by: Stanimir Stoyanov <[email protected]> Co-authored-by: Mustafa Uzun <[email protected]>
1 parent a2632d4 commit d43210c

File tree

2 files changed

+155
-3
lines changed

2 files changed

+155
-3
lines changed

hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/TokenInfoHTSSuite.java

+75-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.hedera.services.bdd.suites.contract.precompile;
1818

1919
import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT;
20+
import static com.hedera.services.bdd.junit.TestTags.TOKEN;
2021
import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec;
2122
import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith;
2223
import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith;
@@ -153,11 +154,11 @@ List<HapiSpec> negativeSpecs() {
153154
return List.of(
154155
getInfoOnDeletedFungibleTokenWorks(),
155156
getInfoOnInvalidFungibleTokenFails(),
156-
getInfoOnDeletedNonFungibleTokenWorks(),
157157
getInfoOnInvalidNonFungibleTokenFails(),
158158
getInfoForFungibleTokenByNFTTokenAddressWorks(),
159159
getInfoForNFTByFungibleTokenAddressFails(),
160-
getInfoForTokenByAccountAddressFails());
160+
getInfoForTokenByAccountAddressFails(),
161+
getTokenCustomFeesNegativeCases());
161162
}
162163

163164
List<HapiSpec> positiveSpecs() {
@@ -1035,6 +1036,78 @@ final HapiSpec happyPathGetNonFungibleTokenCustomFees() {
10351036
.withCustomFees(getCustomFeeForNFT(spec))))))));
10361037
}
10371038

1039+
@HapiTest
1040+
final HapiSpec getTokenCustomFeesNegativeCases() {
1041+
final int maxSupply = 10;
1042+
final var accountAddressForToken = "accountAddressForToken";
1043+
final var tokenWithNoFees = "tokenWithNoFees";
1044+
return defaultHapiSpec("negativeGetTokenCustomFeesCases")
1045+
.given(
1046+
cryptoCreate(TOKEN_TREASURY).balance(0L),
1047+
cryptoCreate(NFT_OWNER),
1048+
cryptoCreate(HTS_COLLECTOR),
1049+
newKeyNamed(SUPPLY_KEY),
1050+
uploadInitCode(TOKEN_INFO_CONTRACT),
1051+
contractCreate(TOKEN_INFO_CONTRACT).gas(1_000_000L),
1052+
tokenCreate(FEE_DENOM).treasury(HTS_COLLECTOR),
1053+
tokenCreate(NON_FUNGIBLE_TOKEN_NAME)
1054+
.tokenType(TokenType.NON_FUNGIBLE_UNIQUE)
1055+
.supplyType(TokenSupplyType.FINITE)
1056+
.entityMemo(MEMO)
1057+
.name(NON_FUNGIBLE_TOKEN_NAME)
1058+
.symbol(NON_FUNGIBLE_SYMBOL)
1059+
.treasury(TOKEN_TREASURY)
1060+
.maxSupply(maxSupply)
1061+
.initialSupply(0)
1062+
.supplyKey(SUPPLY_KEY)
1063+
.withCustom(royaltyFeeWithFallback(
1064+
1, 2, fixedHtsFeeInheritingRoyaltyCollector(100, FEE_DENOM), HTS_COLLECTOR)),
1065+
tokenAssociate(NFT_OWNER, List.of(NON_FUNGIBLE_TOKEN_NAME)),
1066+
tokenCreate(TOKEN))
1067+
.when(withOpContext((spec, opLog) -> allRunFor(
1068+
spec,
1069+
contractCall(
1070+
TOKEN_INFO_CONTRACT,
1071+
GET_CUSTOM_FEES_FOR_TOKEN,
1072+
HapiParserUtil.asHeadlongAddress(
1073+
asAddress(spec.registry().getAccountID(NFT_OWNER))))
1074+
.hasKnownStatus(CONTRACT_REVERT_EXECUTED)
1075+
.via(accountAddressForToken),
1076+
contractCall(
1077+
TOKEN_INFO_CONTRACT,
1078+
GET_CUSTOM_FEES_FOR_TOKEN,
1079+
HapiParserUtil.asHeadlongAddress(
1080+
asAddress(spec.registry().getTokenID(TOKEN))))
1081+
.hasKnownStatus(SUCCESS)
1082+
.via(tokenWithNoFees))))
1083+
.then(withOpContext((spec, opLog) -> allRunFor(
1084+
spec,
1085+
childRecordsCheck(
1086+
accountAddressForToken,
1087+
CONTRACT_REVERT_EXECUTED,
1088+
recordWith().status(INVALID_TOKEN_ID)),
1089+
childRecordsCheck(
1090+
tokenWithNoFees,
1091+
SUCCESS,
1092+
recordWith()
1093+
.status(SUCCESS)
1094+
.contractCallResult(resultWith()
1095+
.contractCallResult(htsPrecompileResult()
1096+
.forFunction(FunctionType.HAPI_GET_TOKEN_CUSTOM_FEES)
1097+
.withCustomFees(List.of(CustomFee.newBuilder()
1098+
.setFixedFee(
1099+
FixedFee.newBuilder()
1100+
.build())
1101+
.setFractionalFee(
1102+
FractionalFee.newBuilder()
1103+
.build())
1104+
.setRoyaltyFee(
1105+
RoyaltyFee.newBuilder()
1106+
.build())
1107+
.build()))
1108+
.withStatus(SUCCESS)))))));
1109+
}
1110+
10381111
private TokenNftInfo getTokenNftInfoForCheck(
10391112
final HapiSpec spec, final HapiGetTokenInfo getTokenInfoQuery, final ByteString meta, ByteString ledgerId) {
10401113
final var tokenId =

hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/crypto/CryptoApproveAllowanceSuite.java

+80-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import static com.hedera.services.bdd.spec.transactions.token.TokenMovement.movingUnique;
4949
import static com.hedera.services.bdd.spec.transactions.token.TokenMovement.movingUniqueWithAllowance;
5050
import static com.hedera.services.bdd.spec.transactions.token.TokenMovement.movingWithAllowance;
51+
import static com.hedera.services.bdd.spec.utilops.UtilVerbs.emptyChildRecordsCheck;
5152
import static com.hedera.services.bdd.spec.utilops.UtilVerbs.newKeyNamed;
5253
import static com.hedera.services.bdd.spec.utilops.UtilVerbs.sourcing;
5354
import static com.hedera.services.bdd.spec.utilops.UtilVerbs.validateChargedUsdWithin;
@@ -67,7 +68,9 @@
6768
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.NFT_IN_FUNGIBLE_TOKEN_ALLOWANCES;
6869
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.PAYER_ACCOUNT_NOT_FOUND;
6970
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SENDER_DOES_NOT_OWN_NFT_SERIAL_NO;
71+
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SPENDER_ACCOUNT_SAME_AS_OWNER;
7072
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SPENDER_DOES_NOT_HAVE_ALLOWANCE;
73+
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SUCCESS;
7174
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_NOT_ASSOCIATED_TO_ACCOUNT;
7275
import static com.hederahashgraph.api.proto.java.TokenType.FUNGIBLE_COMMON;
7376
import static com.hederahashgraph.api.proto.java.TokenType.NON_FUNGIBLE_UNIQUE;
@@ -156,7 +159,8 @@ public List<HapiSpec> getSpecsInSuite() {
156159
scheduledCryptoApproveAllowanceWorks(),
157160
canDeleteAllowanceFromDeletedSpender(),
158161
cannotPayForAnyTransactionWithContractAccount(),
159-
transferringMissingNftViaApprovalFailsWithInvalidNftId());
162+
transferringMissingNftViaApprovalFailsWithInvalidNftId(),
163+
approveNegativeCases());
160164
}
161165

162166
@HapiTest
@@ -1678,6 +1682,81 @@ final HapiSpec scheduledCryptoApproveAllowanceWorks() {
16781682
getAccountBalance(RECEIVER).hasTinyBars(15 * ONE_HBAR));
16791683
}
16801684

1685+
@HapiTest
1686+
final HapiSpec approveNegativeCases() {
1687+
final var tryApprovingTheSender = "tryApprovingTheSender";
1688+
final var tryApprovingAboveBalance = "tryApprovingAboveBalance";
1689+
final var tryApprovingNFTToOwner = "tryApprovingNFTToOwner";
1690+
final var tryApprovingNFTWithInvalidSerial = "tryApprovingNFTWithInvalidSerial";
1691+
return defaultHapiSpec("approveNegativeCases")
1692+
.given(
1693+
newKeyNamed(SUPPLY_KEY),
1694+
cryptoCreate(OWNER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(10),
1695+
cryptoCreate(SPENDER).balance(ONE_HUNDRED_HBARS),
1696+
cryptoCreate(TOKEN_TREASURY)
1697+
.balance(100 * ONE_HUNDRED_HBARS)
1698+
.maxAutomaticTokenAssociations(10),
1699+
tokenCreate(FUNGIBLE_TOKEN)
1700+
.supplyType(TokenSupplyType.FINITE)
1701+
.tokenType(FUNGIBLE_COMMON)
1702+
.supplyKey(SUPPLY_KEY)
1703+
.treasury(TOKEN_TREASURY)
1704+
.maxSupply(10000)
1705+
.initialSupply(5000),
1706+
tokenCreate(NON_FUNGIBLE_TOKEN)
1707+
.supplyType(TokenSupplyType.FINITE)
1708+
.tokenType(NON_FUNGIBLE_UNIQUE)
1709+
.treasury(TOKEN_TREASURY)
1710+
.maxSupply(12L)
1711+
.supplyKey(SUPPLY_KEY)
1712+
.initialSupply(0L),
1713+
mintToken(FUNGIBLE_TOKEN, 500L).via(FUNGIBLE_TOKEN_MINT_TXN),
1714+
mintToken(
1715+
NON_FUNGIBLE_TOKEN,
1716+
List.of(
1717+
ByteString.copyFromUtf8("1"),
1718+
ByteString.copyFromUtf8("2"),
1719+
ByteString.copyFromUtf8("3"))),
1720+
tokenAssociate(OWNER, FUNGIBLE_TOKEN, NON_FUNGIBLE_TOKEN),
1721+
cryptoTransfer(
1722+
moving(500L, FUNGIBLE_TOKEN).between(TOKEN_TREASURY, OWNER),
1723+
movingUnique(NON_FUNGIBLE_TOKEN, 1L, 2L, 3L).between(TOKEN_TREASURY, OWNER)))
1724+
.when(
1725+
cryptoApproveAllowance()
1726+
.payingWith(DEFAULT_PAYER)
1727+
.addTokenAllowance(OWNER, FUNGIBLE_TOKEN, OWNER, 100L)
1728+
.signedBy(DEFAULT_PAYER, OWNER)
1729+
.hasKnownStatus(SUCCESS)
1730+
.via(tryApprovingTheSender),
1731+
cryptoApproveAllowance()
1732+
.payingWith(DEFAULT_PAYER)
1733+
.addTokenAllowance(OWNER, FUNGIBLE_TOKEN, SPENDER, 1000L)
1734+
.signedBy(DEFAULT_PAYER, OWNER)
1735+
.hasKnownStatus(SUCCESS)
1736+
.via(tryApprovingAboveBalance),
1737+
cryptoApproveAllowance()
1738+
.payingWith(DEFAULT_PAYER)
1739+
.addNftAllowance(OWNER, NON_FUNGIBLE_TOKEN, OWNER, false, List.of(1L))
1740+
.signedBy(DEFAULT_PAYER, OWNER)
1741+
.hasKnownStatus(SPENDER_ACCOUNT_SAME_AS_OWNER)
1742+
.via(tryApprovingNFTToOwner),
1743+
cryptoApproveAllowance()
1744+
.payingWith(DEFAULT_PAYER)
1745+
.addNftAllowance(OWNER, NON_FUNGIBLE_TOKEN, SPENDER, false, List.of(1L, 2L, 3L, 4L))
1746+
.signedBy(DEFAULT_PAYER, OWNER)
1747+
.hasKnownStatus(INVALID_TOKEN_NFT_SERIAL_NUMBER)
1748+
.via(tryApprovingNFTWithInvalidSerial))
1749+
.then(
1750+
emptyChildRecordsCheck(tryApprovingTheSender, SUCCESS),
1751+
emptyChildRecordsCheck(tryApprovingAboveBalance, SUCCESS),
1752+
emptyChildRecordsCheck(tryApprovingNFTToOwner, SPENDER_ACCOUNT_SAME_AS_OWNER),
1753+
emptyChildRecordsCheck(tryApprovingNFTWithInvalidSerial, INVALID_TOKEN_NFT_SERIAL_NUMBER),
1754+
getAccountBalance(OWNER).hasTokenBalance(FUNGIBLE_TOKEN, 500L),
1755+
getAccountBalance(SPENDER).hasTokenBalance(FUNGIBLE_TOKEN, 0L),
1756+
getAccountBalance(OWNER).hasTokenBalance(NON_FUNGIBLE_TOKEN, 3L),
1757+
getAccountBalance(SPENDER).hasTokenBalance(NON_FUNGIBLE_TOKEN, 0L));
1758+
}
1759+
16811760
@Override
16821761
protected Logger getResultsLogger() {
16831762
return log;

0 commit comments

Comments
 (0)