Skip to content

Commit 2e496ce

Browse files
chore: cherry-pick Dont modify allowances on token reject (#14289)
Signed-off-by: Neeharika-Sompalli <[email protected]>
1 parent 2b65890 commit 2e496ce

File tree

2 files changed

+1
-139
lines changed

2 files changed

+1
-139
lines changed

hedera-node/hedera-token-service-impl/src/main/java/com/hedera/node/app/service/token/impl/handlers/TokenRejectHandler.java

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,13 @@
7272
import com.hedera.node.app.spi.workflows.PreHandleContext;
7373
import com.hedera.node.app.spi.workflows.TransactionHandler;
7474
import com.hedera.node.config.data.FeesConfig;
75-
import com.hedera.node.config.data.HederaConfig;
7675
import com.hedera.node.config.data.LedgerConfig;
7776
import com.hedera.node.config.data.TokensConfig;
7877
import com.swirlds.base.utility.Pair;
7978
import edu.umd.cs.findbugs.annotations.NonNull;
8079
import java.util.ArrayList;
8180
import java.util.HashSet;
8281
import java.util.List;
83-
import java.util.Objects;
8482
import java.util.stream.Collectors;
8583
import javax.inject.Inject;
8684
import javax.inject.Singleton;
@@ -172,7 +170,6 @@ public void handle(@NonNull final HandleContext context) throws HandleException
172170
final var rejectingAccountID = op.ownerOrElse(context.payer());
173171
final var rejections = op.rejections();
174172

175-
final var hederaConfig = context.configuration().getConfigData(HederaConfig.class);
176173
final var ledgerConfig = context.configuration().getConfigData(LedgerConfig.class);
177174
final var tokensConfig = context.configuration().getConfigData(TokensConfig.class);
178175
validateTrue(tokensConfig.tokenRejectEnabled(), NOT_SUPPORTED);
@@ -186,18 +183,12 @@ public void handle(@NonNull final HandleContext context) throws HandleException
186183
final var processedRejectTransfers = processRejectionsForTransfer(rejections, context, rejectingAccount);
187184

188185
// Apply all changes to the handleContext's states by performing the transfer to the treasuries
186+
// Allowances will not be affected with the token reject
189187
final var transferContext = new TransferContextImpl(context);
190188
final var fungibleTokensStep = new AdjustFungibleTokenChangesStep(processedRejectTransfers, context.payer());
191189
final var nftOwnersChangeStep = new NFTOwnersChangeStep(processedRejectTransfers, context.payer());
192190
fungibleTokensStep.doIn(transferContext);
193191
nftOwnersChangeStep.doIn(transferContext);
194-
195-
// Update the token allowances
196-
if (hederaConfig.allowancesIsEnabled()) {
197-
final var nftStore = context.storeFactory().writableStore(WritableNftStore.class);
198-
updateFungibleAllowances(rejectingAccount, rejections, accountStore);
199-
updateNFTAllowances(rejections, nftStore);
200-
}
201192
}
202193

203194
/**
@@ -290,49 +281,6 @@ private TokenTransferList processFungibleTokenRejection(
290281
return createFungibleTransfer(tokenId, accountID, tokenRelation.balance(), token.treasuryAccountId());
291282
}
292283

293-
/**
294-
* Updates the NFT allowances in the state after the token transfers have been processed,
295-
* by setting the spender to null.
296-
*
297-
* @param tokenReferences The list of tokens that were rejected.
298-
* @param nftStore The store to access writable NFT information.
299-
*/
300-
private void updateNFTAllowances(
301-
@NonNull final List<TokenReference> tokenReferences, @NonNull final WritableNftStore nftStore) {
302-
tokenReferences.stream()
303-
.filter(TokenReference::hasNft)
304-
.map(reference -> getIfUsable(reference.nftOrThrow(), nftStore))
305-
.forEach(nft -> {
306-
if (nft.hasSpenderId()) {
307-
nftStore.put(
308-
nft.copyBuilder().spenderId((AccountID) null).build());
309-
}
310-
});
311-
}
312-
313-
/**
314-
* Updates the fungible token allowances in the state after the token transfers to the treasuries have been processed.
315-
*
316-
* @param rejectingAccount The account rejecting the tokens.
317-
* @param tokenReferences The list of tokens that were rejected.
318-
* @param accountStore The store to access writable account information.
319-
*/
320-
private void updateFungibleAllowances(
321-
@NonNull final Account rejectingAccount,
322-
@NonNull final List<TokenReference> tokenReferences,
323-
@NonNull final WritableAccountStore accountStore) {
324-
final var updatedFungibleTokenAllowances = new ArrayList<>(rejectingAccount.tokenAllowances());
325-
updatedFungibleTokenAllowances.removeIf(allowance -> tokenReferences.stream()
326-
.filter(TokenReference::hasFungibleToken)
327-
.anyMatch(fungibleToken -> Objects.equals(fungibleToken.fungibleToken(), allowance.tokenId())));
328-
329-
final var updatedAccount = rejectingAccount
330-
.copyBuilder()
331-
.tokenAllowances(updatedFungibleTokenAllowances)
332-
.build();
333-
accountStore.put(updatedAccount);
334-
}
335-
336284
@NonNull
337285
@Override
338286
public Fees calculateFees(final FeeContext feeContext) {

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

Lines changed: 0 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,9 @@
1919
import static com.google.protobuf.ByteString.copyFromUtf8;
2020
import static com.hedera.services.bdd.junit.TestTags.TOKEN;
2121
import static com.hedera.services.bdd.spec.HapiSpec.defaultHapiSpec;
22-
import static com.hedera.services.bdd.spec.assertions.AccountDetailsAsserts.accountDetailsWith;
2322
import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountBalance;
24-
import static com.hedera.services.bdd.spec.queries.QueryVerbs.getAccountDetails;
2523
import static com.hedera.services.bdd.spec.queries.QueryVerbs.getTokenNftInfo;
2624
import static com.hedera.services.bdd.spec.queries.QueryVerbs.getTxnRecord;
27-
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoApproveAllowance;
2825
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate;
2926
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoTransfer;
3027
import static com.hedera.services.bdd.spec.transactions.TxnVerbs.mintToken;
@@ -42,13 +39,9 @@
4239
import static com.hedera.services.bdd.spec.transactions.token.HapiTokenReject.rejectingToken;
4340
import static com.hedera.services.bdd.spec.transactions.token.TokenMovement.moving;
4441
import static com.hedera.services.bdd.spec.transactions.token.TokenMovement.movingUnique;
45-
import static com.hedera.services.bdd.spec.transactions.token.TokenMovement.movingWithAllowance;
4642
import static com.hedera.services.bdd.spec.utilops.CustomSpecAssert.allRunFor;
4743
import static com.hedera.services.bdd.spec.utilops.UtilVerbs.newKeyNamed;
4844
import static com.hedera.services.bdd.spec.utilops.UtilVerbs.withOpContext;
49-
import static com.hedera.services.bdd.suites.HapiSuite.DEFAULT_PAYER;
50-
import static com.hedera.services.bdd.suites.HapiSuite.GENESIS;
51-
import static com.hedera.services.bdd.suites.HapiSuite.ONE_HBAR;
5245
import static com.hedera.services.bdd.suites.HapiSuite.ONE_HUNDRED_HBARS;
5346
import static com.hedera.services.bdd.suites.HapiSuite.ONE_MILLION_HBARS;
5447
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.ACCOUNT_AMOUNT_TRANSFERS_ONLY_ALLOWED_FOR_FUNGIBLE_COMMON;
@@ -60,7 +53,6 @@
6053
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_NFT_ID;
6154
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_OWNER_ID;
6255
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_SIGNATURE;
63-
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SPENDER_DOES_NOT_HAVE_ALLOWANCE;
6456
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_IS_PAUSED;
6557
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_NOT_ASSOCIATED_TO_ACCOUNT;
6658
import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.TOKEN_REFERENCE_REPEATED;
@@ -213,84 +205,6 @@ final Stream<DynamicTest> tokenRejectWorksWithFungibleAndNFTTokens() {
213205
getAccountBalance(TOKEN_TREASURY).logged().hasTokenBalance(FUNGIBLE_TOKEN_A, 1000L));
214206
}
215207

216-
@HapiTest
217-
final Stream<DynamicTest> tokenRejectWorksWithFungibleAndNFTTokensAndRemovesAllowancesCorrectly() {
218-
return defaultHapiSpec("tokenRejectWorksWithFungibleAndNFTTokensAndRemovesAllowances")
219-
.given(
220-
newKeyNamed(MULTI_KEY),
221-
cryptoCreate(ACCOUNT).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(3),
222-
cryptoCreate(ACCOUNT_1).maxAutomaticTokenAssociations(3),
223-
cryptoCreate(SPENDER).balance(ONE_HUNDRED_HBARS).maxAutomaticTokenAssociations(3),
224-
cryptoCreate(TOKEN_TREASURY),
225-
tokenCreate(FUNGIBLE_TOKEN_A)
226-
.initialSupply(TOTAL_SUPPLY)
227-
.adminKey(MULTI_KEY)
228-
.supplyKey(MULTI_KEY)
229-
.treasury(TOKEN_TREASURY),
230-
tokenCreate(NON_FUNGIBLE_TOKEN_B)
231-
.initialSupply(0)
232-
.adminKey(MULTI_KEY)
233-
.supplyKey(MULTI_KEY)
234-
.treasury(TOKEN_TREASURY)
235-
.tokenType(TokenType.NON_FUNGIBLE_UNIQUE),
236-
tokenAssociate(ACCOUNT, FUNGIBLE_TOKEN_A, NON_FUNGIBLE_TOKEN_B),
237-
mintToken(NON_FUNGIBLE_TOKEN_B, List.of(copyFromUtf8("memo"), copyFromUtf8("memo"))),
238-
cryptoTransfer(
239-
moving(250L, FUNGIBLE_TOKEN_A).between(TOKEN_TREASURY, ACCOUNT),
240-
movingUnique(NON_FUNGIBLE_TOKEN_B, 1L, 2L).between(TOKEN_TREASURY, ACCOUNT)),
241-
cryptoApproveAllowance()
242-
.payingWith(DEFAULT_PAYER)
243-
.addTokenAllowance(ACCOUNT, FUNGIBLE_TOKEN_A, SPENDER, 200L)
244-
.addTokenAllowance(TOKEN_TREASURY, FUNGIBLE_TOKEN_A, ACCOUNT, 50L)
245-
.signedBy(DEFAULT_PAYER, ACCOUNT, SPENDER, TOKEN_TREASURY)
246-
.fee(ONE_HBAR),
247-
// Verify Account's allowance works and exists:
248-
cryptoTransfer(movingWithAllowance(50, FUNGIBLE_TOKEN_A).between(ACCOUNT, ACCOUNT_1))
249-
.payingWith(SPENDER)
250-
.signedBy(SPENDER),
251-
getAccountDetails(ACCOUNT)
252-
.payingWith(GENESIS)
253-
.logged()
254-
.has(accountDetailsWith().tokenAllowancesContaining(FUNGIBLE_TOKEN_A, SPENDER, 150)))
255-
.when(withOpContext((spec, opLog) -> allRunFor(
256-
spec,
257-
// Try rejecting only when having allowance, without balance
258-
tokenAssociate(SPENDER, FUNGIBLE_TOKEN_A),
259-
tokenReject(SPENDER, rejectingToken(FUNGIBLE_TOKEN_A))
260-
.hasKnownStatus(INSUFFICIENT_TOKEN_BALANCE),
261-
tokenReject(
262-
ACCOUNT,
263-
rejectingToken(FUNGIBLE_TOKEN_A),
264-
rejectingNFT(NON_FUNGIBLE_TOKEN_B, 1L),
265-
rejectingNFT(NON_FUNGIBLE_TOKEN_B, 2L))
266-
.via("tokenRejectRemovesAllowance"),
267-
// Verify Spender's allowance is removed:
268-
cryptoTransfer(movingWithAllowance(50, FUNGIBLE_TOKEN_A).between(ACCOUNT, ACCOUNT_1))
269-
.payingWith(ACCOUNT)
270-
.signedBy(ACCOUNT)
271-
.hasKnownStatus(SPENDER_DOES_NOT_HAVE_ALLOWANCE))))
272-
.then(
273-
getTxnRecord("tokenRejectRemovesAllowance")
274-
.andAllChildRecords()
275-
.logged(),
276-
getTokenNftInfo(NON_FUNGIBLE_TOKEN_B, 1L)
277-
.hasAccountID(TOKEN_TREASURY)
278-
.hasNoSpender(),
279-
getTokenNftInfo(NON_FUNGIBLE_TOKEN_B, 2L)
280-
.hasAccountID(TOKEN_TREASURY)
281-
.hasNoSpender(),
282-
getAccountBalance(ACCOUNT).logged().hasTokenBalance(FUNGIBLE_TOKEN_A, 0L),
283-
getAccountDetails(ACCOUNT)
284-
.payingWith(GENESIS)
285-
.logged()
286-
.has(accountDetailsWith().noAllowances()),
287-
getAccountDetails(TOKEN_TREASURY)
288-
.payingWith(GENESIS)
289-
.logged()
290-
.has(accountDetailsWith().tokenAllowancesContaining(FUNGIBLE_TOKEN_A, ACCOUNT, 50)),
291-
getAccountBalance(TOKEN_TREASURY).logged().hasTokenBalance(FUNGIBLE_TOKEN_A, 950L));
292-
}
293-
294208
@HapiTest
295209
final Stream<DynamicTest> tokenRejectCasesWhileFreezeOrPausedOrSigRequired() {
296210
return defaultHapiSpec("tokenRejectWorksWhileFreezeOrPausedOrSigRequired")

0 commit comments

Comments
 (0)