|
18 | 18 |
|
19 | 19 | import static com.hedera.services.bdd.junit.TestTags.TOKEN;
|
20 | 20 | import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec;
|
| 21 | +import static com.hedera.services.bdd.spec.HapiSpec.propertyPreservingHapiSpec; |
21 | 22 | import static com.hedera.services.bdd.spec.assertions.NoTokenTransfers.emptyTokenTransfers;
|
22 | 23 | import static com.hedera.services.bdd.spec.assertions.SomeFungibleTransfers.changingFungibleBalances;
|
23 | 24 | import static com.hedera.services.bdd.spec.assertions.TransactionRecordAsserts.recordWith;
|
|
41 | 42 | import static com.hedera.services.bdd.spec.transactions.TxnVerbs.tokenUnfreeze;
|
42 | 43 | import static com.hedera.services.bdd.spec.transactions.TxnVerbs.tokenUpdate;
|
43 | 44 | import static com.hedera.services.bdd.spec.transactions.TxnVerbs.uploadInitCode;
|
| 45 | +import static com.hedera.services.bdd.spec.transactions.token.HapiTokenAssociate.DEFAULT_FEE; |
44 | 46 | import static com.hedera.services.bdd.spec.transactions.token.TokenMovement.moving;
|
45 | 47 | import static com.hedera.services.bdd.spec.utilops.CustomSpecAssert.allRunFor;
|
46 | 48 | import static com.hedera.services.bdd.spec.utilops.UtilVerbs.newKeyNamed;
|
| 49 | +import static com.hedera.services.bdd.spec.utilops.UtilVerbs.overridingTwo; |
47 | 50 | import static com.hedera.services.bdd.spec.utilops.UtilVerbs.sleepFor;
|
48 | 51 | import static com.hedera.services.bdd.spec.utilops.UtilVerbs.sourcing;
|
49 | 52 | import static com.hedera.services.bdd.spec.utilops.UtilVerbs.withOpContext;
|
| 53 | +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ACCOUNT_DELETED; |
50 | 54 | import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ACCOUNT_FROZEN_FOR_TOKEN;
|
51 | 55 | import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ACCOUNT_IS_TREASURY;
|
52 | 56 | import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_ACCOUNT_ID;
|
53 | 57 | import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_SIGNATURE;
|
54 | 58 | import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_TOKEN_ID;
|
| 59 | +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SUCCESS; |
| 60 | +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKENS_PER_ACCOUNT_LIMIT_EXCEEDED; |
| 61 | +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT; |
| 62 | +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_ID_REPEATED_IN_TOKEN_LIST; |
55 | 63 | import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_NOT_ASSOCIATED_TO_ACCOUNT;
|
| 64 | +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_WAS_DELETED; |
56 | 65 | import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TRANSACTION_REQUIRES_ZERO_TOKEN_BALANCES;
|
57 | 66 | import static com.hederahashgraph.api.proto.java.TokenFreezeStatus.FreezeNotApplicable;
|
58 | 67 | import static com.hederahashgraph.api.proto.java.TokenFreezeStatus.Unfrozen;
|
@@ -121,6 +130,59 @@ public boolean canRunConcurrent() {
|
121 | 130 | return true;
|
122 | 131 | }
|
123 | 132 |
|
| 133 | + @HapiTest |
| 134 | + public HapiSpec canHandleInvalidAssociateTransactions() { |
| 135 | + final String alice = "ALICE"; |
| 136 | + final String bob = "BOB"; |
| 137 | + final String unknownID = "0.0." + Long.MAX_VALUE; |
| 138 | + return defaultHapiSpec("CanHandleInvalidAssociateTransactions") |
| 139 | + .given( |
| 140 | + newKeyNamed(MULTI_KEY), |
| 141 | + cryptoCreate(alice), |
| 142 | + cryptoCreate(bob), |
| 143 | + cryptoDelete(bob), |
| 144 | + tokenCreate(VANILLA_TOKEN), |
| 145 | + tokenCreate(KNOWABLE_TOKEN), |
| 146 | + tokenAssociate(alice, KNOWABLE_TOKEN), |
| 147 | + tokenCreate(TBD_TOKEN).adminKey(MULTI_KEY), |
| 148 | + tokenDelete(TBD_TOKEN)) |
| 149 | + .when() |
| 150 | + .then( |
| 151 | + tokenAssociate(null, VANILLA_TOKEN) |
| 152 | + .fee(DEFAULT_FEE) |
| 153 | + .signedBy(DEFAULT_PAYER) |
| 154 | + .hasPrecheck(INVALID_ACCOUNT_ID), |
| 155 | + tokenAssociate(unknownID, VANILLA_TOKEN) |
| 156 | + .fee(DEFAULT_FEE) |
| 157 | + .signedBy(DEFAULT_PAYER) |
| 158 | + .hasPrecheck(INVALID_ACCOUNT_ID), |
| 159 | + tokenAssociate(bob, VANILLA_TOKEN).fee(DEFAULT_FEE).hasKnownStatus(ACCOUNT_DELETED), |
| 160 | + tokenAssociate(alice, List.of()).hasKnownStatus(SUCCESS), |
| 161 | + tokenAssociate(alice, VANILLA_TOKEN, VANILLA_TOKEN) |
| 162 | + .hasPrecheck(TOKEN_ID_REPEATED_IN_TOKEN_LIST), |
| 163 | + tokenAssociate(alice, unknownID).hasKnownStatus(INVALID_TOKEN_ID), |
| 164 | + tokenAssociate(alice, TBD_TOKEN).hasKnownStatus(TOKEN_WAS_DELETED), |
| 165 | + tokenAssociate(alice, KNOWABLE_TOKEN).hasKnownStatus(TOKEN_ALREADY_ASSOCIATED_TO_ACCOUNT)); |
| 166 | + } |
| 167 | + |
| 168 | + @HapiTest |
| 169 | + public HapiSpec canLimitMaxTokensPerAccountTransactions() { |
| 170 | + final String alice = "ALICE"; |
| 171 | + final String treasury2 = "TREASURY_2"; |
| 172 | + return propertyPreservingHapiSpec("CanHandleInvalidAssociateTransactions") |
| 173 | + .preserving("tokens.maxPerAccount", "entities.limitTokenAssociations") |
| 174 | + .given( |
| 175 | + overridingTwo("tokens.maxPerAccount", "1", "entities.limitTokenAssociations", "true"), |
| 176 | + cryptoCreate(alice), |
| 177 | + cryptoCreate(TOKEN_TREASURY), |
| 178 | + cryptoCreate(treasury2), |
| 179 | + tokenCreate(VANILLA_TOKEN).treasury(TOKEN_TREASURY), |
| 180 | + tokenCreate(KNOWABLE_TOKEN).treasury(treasury2), |
| 181 | + tokenAssociate(alice, KNOWABLE_TOKEN)) |
| 182 | + .when() |
| 183 | + .then(tokenAssociate(alice, VANILLA_TOKEN).hasKnownStatus(TOKENS_PER_ACCOUNT_LIMIT_EXCEEDED)); |
| 184 | + } |
| 185 | + |
124 | 186 | @HapiTest
|
125 | 187 | public HapiSpec handlesUseOfDefaultTokenId() {
|
126 | 188 | return defaultHapiSpec("HandlesUseOfDefaultTokenId", SnapshotMatchMode.NONDETERMINISTIC_TRANSACTION_FEES)
|
|
0 commit comments