From 2e3d459136c5d57a933bd2b8ce60cdf1b2e05545 Mon Sep 17 00:00:00 2001 From: nullun Date: Fri, 22 Aug 2025 11:07:38 +0100 Subject: [PATCH 1/5] tests: Cover all asset wellFormed errors --- data/transactions/asset_test.go | 182 ++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 data/transactions/asset_test.go diff --git a/data/transactions/asset_test.go b/data/transactions/asset_test.go new file mode 100644 index 0000000000..1e8c6ab9cb --- /dev/null +++ b/data/transactions/asset_test.go @@ -0,0 +1,182 @@ +package transactions + +import ( + "fmt" + "strings" + "testing" + + "github.com/algorand/go-algorand/config" + "github.com/algorand/go-algorand/data/basics" + "github.com/algorand/go-algorand/protocol" + "github.com/algorand/go-algorand/test/partitiontest" + "github.com/stretchr/testify/require" +) + +func TestAxferWellFormedErrors(t *testing.T) { + partitiontest.PartitionTest(t) + t.Parallel() + + cases := []struct { + axfer AssetTransferTxnFields + expectedError string + }{ + { + axfer: AssetTransferTxnFields{ + XferAsset: basics.AssetIndex(0), + AssetAmount: 0, + AssetReceiver: basics.Address{}, + }, + }, + { + axfer: AssetTransferTxnFields{ + XferAsset: basics.AssetIndex(0), + AssetAmount: 1, + AssetReceiver: basics.Address{0x01}, + }, + expectedError: "asset ID cannot be zero", + }, + { + axfer: AssetTransferTxnFields{ + XferAsset: basics.AssetIndex(1), + AssetAmount: 0, + AssetSender: basics.Address{0x01}, + AssetCloseTo: basics.Address{0x02}, + }, + expectedError: "cannot close asset by clawback", + }, + } + + for i, ax := range cases { + name := fmt.Sprintf("axfer_i=%d", i) + if ax.expectedError != "" { + name = ax.expectedError + } + t.Run(name, func(t *testing.T) { + err := ax.axfer.wellFormed() + if ax.expectedError != "" { + require.ErrorContains(t, err, ax.expectedError) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestAcfgWellFormedErrors(t *testing.T) { + partitiontest.PartitionTest(t) + t.Parallel() + + cv18 := protocol.ConsensusV18 + cv20 := protocol.ConsensusV20 + cv28 := protocol.ConsensusV28 + + cases := []struct { + acfg AssetConfigTxnFields + cv protocol.ConsensusVersion + expectedError string + }{ + { + acfg: AssetConfigTxnFields{ + AssetParams: basics.AssetParams{ + AssetName: strings.Repeat("A", 33), + }, + }, + cv: cv18, + expectedError: "transaction asset name too big: 33 > 32", + }, + { + acfg: AssetConfigTxnFields{ + AssetParams: basics.AssetParams{ + UnitName: strings.Repeat("B", 9), + }, + }, + expectedError: "transaction asset unit name too big: 9 > 8", + }, + { + acfg: AssetConfigTxnFields{ + AssetParams: basics.AssetParams{ + URL: strings.Repeat("C", 33), + }, + }, + cv: cv18, + expectedError: "transaction asset url too big: 33 > 32", + }, + { + acfg: AssetConfigTxnFields{ + AssetParams: basics.AssetParams{ + Decimals: 20, + }, + }, + cv: cv20, + expectedError: "transaction asset decimals is too high (max is 19)", + }, + { + acfg: AssetConfigTxnFields{ + AssetParams: basics.AssetParams{ + URL: strings.Repeat("D", 97), + }, + }, + cv: cv28, + expectedError: "transaction asset url too big: 97 > 96", + }, + } + + for i, ac := range cases { + name := fmt.Sprintf("acfg_i=%d", i) + if ac.expectedError != "" { + name = ac.expectedError + } + t.Run(name, func(t *testing.T) { + cv := ac.cv + if cv == "" { + cv = protocol.ConsensusFuture + } + err := ac.acfg.wellFormed(config.Consensus[cv]) + if ac.expectedError != "" { + require.ErrorContains(t, err, ac.expectedError) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestAfrzWellFormedErrors(t *testing.T) { + partitiontest.PartitionTest(t) + t.Parallel() + + cases := []struct { + afrz AssetFreezeTxnFields + expectedError string + }{ + { + afrz: AssetFreezeTxnFields{ + FreezeAccount: basics.Address{0x01}, + FreezeAsset: 0, + }, + expectedError: "asset ID cannot be zero", + }, + { + afrz: AssetFreezeTxnFields{ + FreezeAccount: basics.Address{}, + FreezeAsset: 1, + }, + expectedError: "freeze account cannot be empty", + }, + } + + for i, ac := range cases { + name := fmt.Sprintf("afrz_i=%d", i) + if ac.expectedError != "" { + name = ac.expectedError + } + t.Run(name, func(t *testing.T) { + err := ac.afrz.wellFormed() + if ac.expectedError != "" { + require.ErrorContains(t, err, ac.expectedError) + } else { + require.NoError(t, err) + } + }) + } +} From c1781140023388e824d5674fb14ca2fd84c15ac2 Mon Sep 17 00:00:00 2001 From: nullun Date: Fri, 22 Aug 2025 11:31:30 +0100 Subject: [PATCH 2/5] tests: add e2e 0-axfer tests --- test/scripts/e2e_subs/asset-misc.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/scripts/e2e_subs/asset-misc.sh b/test/scripts/e2e_subs/asset-misc.sh index 35198091e2..3e21bead7a 100755 --- a/test/scripts/e2e_subs/asset-misc.sh +++ b/test/scripts/e2e_subs/asset-misc.sh @@ -187,4 +187,28 @@ else exit 1 fi +# Test Scenario - check transfering of the 0 asset +# case 1: send 0 units of 0 asset to self should fail +EXPERROR='asset 0 does not exist or has been deleted' +RES=$(${gcmd} asset send --from "${ACCOUNT}" --to "${ACCOUNT}" --assetid 0 --amount 0 2>&1 || true) +if [[ $RES != *"${EXPERROR}"* ]]; then + date '+asset-zero FAIL asset transfer of 0 units of 0 asset should not be allowed to self in %Y%m%d_%H%M%S' + exit 1 +else + echo ok +fi + +# case 2: send 0 units of 0 asset to someone else should succeed +${gcmd} asset send --from "${ACCOUNT}" --to "${ACCOUNTB}" --assetid 0 --amount 0 + +# case 3: send 0 units of 0 asset to someone else including a close-to should fail +EXPERROR='asset 0 not present in account' +RES=$(${gcmd} asset send --from "${ACCOUNT}" --to "${ACCOUNTB}" --assetid 0 --amount 0 --close-to "${ACCOUNTB}" 2>&1 || true) +if [[ $RES != *"${EXPERROR}"* ]]; then + date '+asset-zero FAIL asset transfer of 0 units of 0 asset including a close-to should not be allowed in %Y%m%d_%H%M%S' + exit 1 +else + echo ok +fi + date "+$scriptname OK %Y%m%d_%H%M%S" From 3c89b4d62116c008c42f5dee7df372236286447a Mon Sep 17 00:00:00 2001 From: nullun Date: Thu, 25 Sep 2025 10:20:19 +0100 Subject: [PATCH 3/5] correct test name in error message --- test/scripts/e2e_subs/asset-misc.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/scripts/e2e_subs/asset-misc.sh b/test/scripts/e2e_subs/asset-misc.sh index 3e21bead7a..b61ac6358a 100755 --- a/test/scripts/e2e_subs/asset-misc.sh +++ b/test/scripts/e2e_subs/asset-misc.sh @@ -106,7 +106,7 @@ ${gcmd} asset create --creator "${ACCOUNT}" --manager "${ACCOUNTB}" --reserve "$ EXPERROR='account asset info not found' RES=$(${gcmd} asset info --creator $ACCOUNT --unitname dma 2>&1 || true) if [[ $RES != *"${EXPERROR}"* ]]; then - date '+asset-misc FAIL asset info should fail unless reserve account was opted in %Y%m%d_%H%M%S' + date "+${scriptname} FAIL asset info should fail unless reserve account was opted in %Y%m%d_%H%M%S" exit 1 else echo ok @@ -192,7 +192,7 @@ fi EXPERROR='asset 0 does not exist or has been deleted' RES=$(${gcmd} asset send --from "${ACCOUNT}" --to "${ACCOUNT}" --assetid 0 --amount 0 2>&1 || true) if [[ $RES != *"${EXPERROR}"* ]]; then - date '+asset-zero FAIL asset transfer of 0 units of 0 asset should not be allowed to self in %Y%m%d_%H%M%S' + date "+${scriptname} FAIL asset transfer of 0 units of 0 asset should not be allowed to self in %Y%m%d_%H%M%S" exit 1 else echo ok @@ -205,7 +205,7 @@ ${gcmd} asset send --from "${ACCOUNT}" --to "${ACCOUNTB}" --assetid 0 --amount 0 EXPERROR='asset 0 not present in account' RES=$(${gcmd} asset send --from "${ACCOUNT}" --to "${ACCOUNTB}" --assetid 0 --amount 0 --close-to "${ACCOUNTB}" 2>&1 || true) if [[ $RES != *"${EXPERROR}"* ]]; then - date '+asset-zero FAIL asset transfer of 0 units of 0 asset including a close-to should not be allowed in %Y%m%d_%H%M%S' + date "+${scriptname} FAIL asset transfer of 0 units of 0 asset including a close-to should not be allowed in %Y%m%d_%H%M%S" exit 1 else echo ok From 049519a3297df61c3f1e462b99a55fc3811ad640 Mon Sep 17 00:00:00 2001 From: nullun Date: Thu, 25 Sep 2025 10:45:09 +0100 Subject: [PATCH 4/5] added copyright license info --- data/transactions/asset_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/data/transactions/asset_test.go b/data/transactions/asset_test.go index 1e8c6ab9cb..b4e1cbf53c 100644 --- a/data/transactions/asset_test.go +++ b/data/transactions/asset_test.go @@ -1,3 +1,19 @@ +// Copyright (C) 2019-2025 Algorand, Inc. +// This file is part of go-algorand +// +// go-algorand is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// go-algorand is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with go-algorand. If not, see . + package transactions import ( From f38ceff6d6ca5a98269eb19201eaa9b90fada925 Mon Sep 17 00:00:00 2001 From: nullun Date: Thu, 2 Oct 2025 17:15:22 +0100 Subject: [PATCH 5/5] Update test/scripts/e2e_subs/asset-misc.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- test/scripts/e2e_subs/asset-misc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/scripts/e2e_subs/asset-misc.sh b/test/scripts/e2e_subs/asset-misc.sh index b61ac6358a..58d27fbb0d 100755 --- a/test/scripts/e2e_subs/asset-misc.sh +++ b/test/scripts/e2e_subs/asset-misc.sh @@ -187,7 +187,7 @@ else exit 1 fi -# Test Scenario - check transfering of the 0 asset +# Test Scenario - check transferring of the 0 asset # case 1: send 0 units of 0 asset to self should fail EXPERROR='asset 0 does not exist or has been deleted' RES=$(${gcmd} asset send --from "${ACCOUNT}" --to "${ACCOUNT}" --assetid 0 --amount 0 2>&1 || true)