diff --git a/extensions/tn_settlement/settlement_integration_test.go b/extensions/tn_settlement/settlement_integration_test.go index 29785f54..ec6a0e31 100644 --- a/extensions/tn_settlement/settlement_integration_test.go +++ b/extensions/tn_settlement/settlement_integration_test.go @@ -87,8 +87,8 @@ func testFindUnsettledMarkets(t *testing.T) func(context.Context, *kwilTesting.P require.NoError(t, err) // Give TRUF balance for market creation fee - // Cover one market's worth of fees: create_stream (6) + insert_records - // (6) + request_attestation (40) = 52 TRUF. Fund 100 TRUF for headroom. + // Cover one market's worth of fees: create_stream (1) + insert_records + // (1) + request_attestation (40) = 42 TRUF. Fund 100 TRUF for headroom. err = giveTrufBalance(ctx, platform, deployer.Address(), "100000000000000000000") // 100 TRUF require.NoError(t, err) @@ -165,8 +165,8 @@ func testAttestationExists(t *testing.T) func(context.Context, *kwilTesting.Plat require.NoError(t, err) // Give TRUF balance for market creation fee - // Cover one market's worth of fees: create_stream (6) + insert_records - // (6) + request_attestation (40) = 52 TRUF. Fund 100 TRUF for headroom. + // Cover one market's worth of fees: create_stream (1) + insert_records + // (1) + request_attestation (40) = 42 TRUF. Fund 100 TRUF for headroom. err = giveTrufBalance(ctx, platform, deployer.Address(), "100000000000000000000") // 100 TRUF require.NoError(t, err) @@ -242,8 +242,8 @@ func testSettleMarketViaAction(t *testing.T) func(context.Context, *kwilTesting. require.NoError(t, err) // Give TRUF balance for market creation fee - // Cover one market's worth of fees: create_stream (6) + insert_records - // (6) + request_attestation (40) = 52 TRUF. Fund 100 TRUF for headroom. + // Cover one market's worth of fees: create_stream (1) + insert_records + // (1) + request_attestation (40) = 42 TRUF. Fund 100 TRUF for headroom. err = giveTrufBalance(ctx, platform, deployer.Address(), "100000000000000000000") // 100 TRUF require.NoError(t, err) @@ -356,8 +356,8 @@ func testSkipMarketWithoutAttestation(t *testing.T) func(context.Context, *kwilT require.NoError(t, err) // Give TRUF balance for market creation fee - // Cover one market's worth of fees: create_stream (6) + insert_records - // (6) + request_attestation (40) = 52 TRUF. Fund 100 TRUF for headroom. + // Cover one market's worth of fees: create_stream (1) + insert_records + // (1) + request_attestation (40) = 42 TRUF. Fund 100 TRUF for headroom. err = giveTrufBalance(ctx, platform, deployer.Address(), "100000000000000000000") // 100 TRUF require.NoError(t, err) @@ -443,8 +443,8 @@ func testMultipleMarketsProcessing(t *testing.T) func(context.Context, *kwilTest err = erc20bridge.ForTestingInitializeExtension(ctx, platform) require.NoError(t, err) - // Cover three markets' worth of fees: 3 × (create_stream 6 + - // insert_records 6 + request_attestation 40) = 156 TRUF. Fund 500 TRUF + // Cover three markets' worth of fees: 3 × (create_stream 1 + + // insert_records 1 + request_attestation 40) = 126 TRUF. Fund 500 TRUF // for headroom. err = giveTrufBalance(ctx, platform, deployer.Address(), "500000000000000000000") // 500 TRUF require.NoError(t, err) diff --git a/internal/migrations/004-composed-taxonomy.prod.sql b/internal/migrations/004-composed-taxonomy.prod.sql index 107a560f..c4fde0a3 100644 --- a/internal/migrations/004-composed-taxonomy.prod.sql +++ b/internal/migrations/004-composed-taxonomy.prod.sql @@ -56,9 +56,10 @@ CREATE OR REPLACE ACTION insert_taxonomy( } -- ===== FEE COLLECTION ===== - -- Charge 6 TRUF per child to every caller. - $fee_per_stream := 6000000000000000000::NUMERIC(78, 0); -- 6 TRUF with 18 decimals - $total_fee := $fee_per_stream * $num_children::NUMERIC(78, 0); + -- Flat 1 TRUF per transaction (write-fee policy per issue #3805). + -- Cost is independent of $num_children: a taxonomy with N children + -- charges the same 1 TRUF as one with a single child. + $total_fee := 1000000000000000000::NUMERIC(78, 0); -- 1 TRUF with 18 decimals IF @leader_sender IS NULL { ERROR('Leader address not available for fee transfer'); @@ -68,8 +69,7 @@ CREATE OR REPLACE ACTION insert_taxonomy( $caller_balance := eth_truf.balance(@caller); IF $caller_balance < $total_fee { - -- Derive human-readable fee from $total_fee - ERROR('Insufficient balance for taxonomies creation. Required: ' || ($total_fee / 1000000000000000000::NUMERIC(78, 0))::TEXT || ' TRUF for ' || $num_children::TEXT || ' child stream(s)'); + ERROR('Insufficient balance for taxonomies creation. Required: 1 TRUF'); } eth_truf.transfer($leader_hex, $total_fee); diff --git a/internal/migrations/004-composed-taxonomy.sql b/internal/migrations/004-composed-taxonomy.sql index bf1a3c33..d3ccc48f 100644 --- a/internal/migrations/004-composed-taxonomy.sql +++ b/internal/migrations/004-composed-taxonomy.sql @@ -44,9 +44,10 @@ CREATE OR REPLACE ACTION insert_taxonomy( } -- ===== FEE COLLECTION ===== - -- Charge 6 TRUF per child to every caller. - $fee_per_stream := 6000000000000000000::NUMERIC(78, 0); -- 6 TRUF with 18 decimals - $total_fee := $fee_per_stream * $num_children::NUMERIC(78, 0); + -- Flat 1 TRUF per transaction (write-fee policy per issue #3805). + -- Cost is independent of $num_children: a taxonomy with N children + -- charges the same 1 TRUF as one with a single child. + $total_fee := 1000000000000000000::NUMERIC(78, 0); -- 1 TRUF with 18 decimals IF @leader_sender IS NULL { ERROR('Leader address not available for fee transfer'); @@ -56,8 +57,7 @@ CREATE OR REPLACE ACTION insert_taxonomy( $caller_balance := hoodi_tt.balance(@caller); IF $caller_balance < $total_fee { - -- Derive human-readable fee from $total_fee - ERROR('Insufficient balance for taxonomies creation. Required: ' || ($total_fee / 1000000000000000000::NUMERIC(78, 0))::TEXT || ' TRUF for ' || $num_children::TEXT || ' child stream(s)'); + ERROR('Insufficient balance for taxonomies creation. Required: 1 TRUF'); } hoodi_tt.transfer($leader_hex, $total_fee); diff --git a/tests/streams/taxonomy_fee_test.go b/tests/streams/taxonomy_fee_test.go index 26521a49..e14b5a4e 100644 --- a/tests/streams/taxonomy_fee_test.go +++ b/tests/streams/taxonomy_fee_test.go @@ -22,11 +22,13 @@ import ( // Test constants for taxonomy fees const ( - taxonomyFeeAmount = "6000000000000000000" // 6 TRUF with 18 decimals per child stream + // Flat 1 TRUF per insert_taxonomy transaction (issue #3805): child count + // no longer multiplies the fee. + taxonomyFeeAmount = "1000000000000000000" // 1 TRUF with 18 decimals per tx ) var ( - sixTRUFTaxonomy = mustParseBigInt(taxonomyFeeAmount) // 6 TRUF as big.Int, using shared helper from stream_creation_fee_test.go + oneTRUFTaxonomy = mustParseBigInt(taxonomyFeeAmount) // 1 TRUF as big.Int, using shared helper from stream_creation_fee_test.go ) // TestTaxonomyFees is the main test suite for insert_taxonomy transaction fees @@ -39,7 +41,7 @@ func TestTaxonomyFees(t *testing.T) { testTaxonomyWriterRolePaysFee(t), testTaxonomyNonExemptWalletPaysFee(t), testTaxonomyInsufficientBalance(t), - testTaxonomyMultipleChildrenFee(t), + testTaxonomyMultipleChildrenChargesFlatFee(t), }, }, testutils.GetTestOptionsWithCache()) } @@ -68,7 +70,7 @@ func setupTaxonomyTestEnvironment(t *testing.T) func(ctx context.Context, platfo } // Test 1: Wallet with network_writer role still pays insert_taxonomy fees. -// 100 TRUF in → 6 (composed) + 6 (child) + 6 (1-child taxonomy) = 18 TRUF spent. +// 100 TRUF in → 1 (composed) + 1 (child) + 1 (1-child taxonomy) = 3 TRUF spent. func testTaxonomyWriterRolePaysFee(t *testing.T) func(ctx context.Context, platform *kwilTesting.Platform) error { return func(ctx context.Context, platform *kwilTesting.Platform) error { writerAddrVal := util.Unsafe_NewEthereumAddressFromString("0x2111111111111111111111111111111111111111") @@ -104,17 +106,19 @@ func testTaxonomyWriterRolePaysFee(t *testing.T) func(ctx context.Context, platf finalBalance, err := getBalance(ctx, platform, writerAddr.Address()) require.NoError(t, err, "failed to get final balance") - // 6 (composed create) + 6 (child create) + 6 (taxonomy w/ 1 child) - eighteenTRUF := mustParseBigInt("18000000000000000000") - expectedBalance := new(big.Int).Sub(initialBalance, eighteenTRUF) + // 1 (composed create) + 1 (child create) + 1 (taxonomy w/ 1 child) — flat per tx. + threeTRUF := mustParseBigInt("3000000000000000000") + expectedBalance := new(big.Int).Sub(initialBalance, threeTRUF) require.Equal(t, 0, expectedBalance.Cmp(finalBalance), - "network_writer should pay 18 TRUF total, expected %s but got %s", expectedBalance, finalBalance) + "network_writer should pay 3 TRUF total, expected %s but got %s", expectedBalance, finalBalance) return nil } } -// Test 2: Non-exempt wallet (without network_writer role) pays 6 TRUF per child stream +// Test 2: Non-exempt wallet (without network_writer role) pays a flat 1 TRUF +// per write tx — fund precisely the 3 TRUF needed (1 composed + 1 child + 1 taxonomy) +// to prove the per-tx invariant. func testTaxonomyNonExemptWalletPaysFee(t *testing.T) func(ctx context.Context, platform *kwilTesting.Platform) error { return func(ctx context.Context, platform *kwilTesting.Platform) error { nonExemptAddrVal := util.Unsafe_NewEthereumAddressFromString("0x3222222222222222222222222222222222222222") @@ -124,34 +128,34 @@ func testTaxonomyNonExemptWalletPaysFee(t *testing.T) func(ctx context.Context, err := setup.CreateDataProviderWithoutRole(ctx, platform, nonExemptAddr.Address()) require.NoError(t, err, "failed to create data provider without role") - // Give 18 TRUF: 6 TRUF (composed stream fee) + 6 TRUF (child stream fee) + 6 TRUF (taxonomy fee) - eighteenTRUF := mustParseBigInt("18000000000000000000") // 18 TRUF - err = giveBalance(ctx, platform, nonExemptAddr.Address(), eighteenTRUF.String()) + // Give exactly 3 TRUF: 1 (composed stream fee) + 1 (child stream fee) + 1 (taxonomy fee) + threeTRUF := mustParseBigInt("3000000000000000000") // 3 TRUF + err = giveBalance(ctx, platform, nonExemptAddr.Address(), threeTRUF.String()) require.NoError(t, err, "failed to give balance") // Get initial balance initialBalance, err := getBalance(ctx, platform, nonExemptAddr.Address()) require.NoError(t, err, "failed to get initial balance") - require.Equal(t, eighteenTRUF, initialBalance, "Initial balance should be 18 TRUF") + require.Equal(t, threeTRUF, initialBalance, "Initial balance should be 3 TRUF") - // Create streams using direct engine calls (each costs 6 TRUF) + // Create streams using direct engine calls (each costs a flat 1 TRUF) composedStreamId := util.GenerateStreamId("taxonomy_nonexempt_composed") childStreamId := util.GenerateStreamId("taxonomy_nonexempt_child") - // Create composed stream (costs 6 TRUF) + // Create composed stream (costs 1 TRUF) err = createStream(ctx, platform, nonExemptAddr, composedStreamId.String(), "composed") require.NoError(t, err, "failed to create composed stream") - // Create child stream (costs 6 TRUF) + // Create child stream (costs 1 TRUF) err = createStream(ctx, platform, nonExemptAddr, childStreamId.String(), "primitive") require.NoError(t, err, "failed to create child stream") - // Balance after stream creation should be 6 TRUF (18 - 6 - 6) + // Balance after stream creation should be 1 TRUF (3 - 1 - 1) balanceAfterStreams, err := getBalance(ctx, platform, nonExemptAddr.Address()) require.NoError(t, err, "failed to get balance after stream creation") - require.Equal(t, sixTRUFTaxonomy, balanceAfterStreams, "Balance should be 6 TRUF after creating streams") + require.Equal(t, oneTRUFTaxonomy, balanceAfterStreams, "Balance should be 1 TRUF after creating streams") - // Insert taxonomy (1 child = 6 TRUF fee) + // Insert taxonomy (1 child, flat 1 TRUF fee) err = insertTaxonomy(ctx, platform, nonExemptAddr, nonExemptAddr.Address(), composedStreamId.String(), []string{nonExemptAddr.Address()}, @@ -160,7 +164,7 @@ func testTaxonomyNonExemptWalletPaysFee(t *testing.T) func(ctx context.Context, nil) require.NoError(t, err, "taxonomy insertion should succeed") - // Verify balance is now 0 (6 TRUF taxonomy fee charged) + // Verify balance is now 0 (1 TRUF taxonomy fee charged) finalBalance, err := getBalance(ctx, platform, nonExemptAddr.Address()) require.NoError(t, err, "failed to get final balance") @@ -180,12 +184,13 @@ func testTaxonomyInsufficientBalance(t *testing.T) func(ctx context.Context, pla err := setup.CreateDataProviderWithoutRole(ctx, platform, insufficientAddr.Address()) require.NoError(t, err, "failed to create data provider without role") - // Give 13 TRUF: Enough for streams (6+6=12) but not enough for taxonomy fee (need 6 more) - thirteenTRUF := mustParseBigInt("13000000000000000000") // 13 TRUF - err = giveBalance(ctx, platform, insufficientAddr.Address(), thirteenTRUF.String()) + // Give exactly 2 TRUF: enough for the two create_stream calls (1 + 1) + // but nothing left over for the 1 TRUF taxonomy fee. + twoTRUF := mustParseBigInt("2000000000000000000") + err = giveBalance(ctx, platform, insufficientAddr.Address(), twoTRUF.String()) require.NoError(t, err, "failed to give balance") - // Create streams (costs 12 TRUF total, leaving 1 TRUF) + // Create streams (costs 2 TRUF total, leaving 0) composedStreamId := util.GenerateStreamId("taxonomy_insufficient_composed") childStreamId := util.GenerateStreamId("taxonomy_insufficient_child") @@ -195,11 +200,10 @@ func testTaxonomyInsufficientBalance(t *testing.T) func(ctx context.Context, pla err = createStream(ctx, platform, insufficientAddr, childStreamId.String(), "primitive") require.NoError(t, err, "failed to create child stream") - // Should have 1 TRUF left (13 - 6 - 6 = 1), not enough for 6 TRUF taxonomy fee + // Should have 0 TRUF left (2 - 1 - 1 = 0), not enough for the 1 TRUF taxonomy fee remainingBalance, err := getBalance(ctx, platform, insufficientAddr.Address()) require.NoError(t, err, "failed to get remaining balance") - oneTRUF := mustParseBigInt("1000000000000000000") - require.Equal(t, oneTRUF, remainingBalance, "Should have 1 TRUF left after creating streams") + require.Equal(t, big.NewInt(0), remainingBalance, "Should have 0 TRUF left after creating streams") // Attempt to insert taxonomy - should fail due to insufficient balance err = insertTaxonomy(ctx, platform, insufficientAddr, @@ -211,14 +215,15 @@ func testTaxonomyInsufficientBalance(t *testing.T) func(ctx context.Context, pla require.Error(t, err, "taxonomy insertion should fail with insufficient balance") require.Contains(t, err.Error(), "Insufficient balance for taxonomies creation", "Error should mention insufficient balance") - require.Contains(t, err.Error(), "Required: 6 TRUF", "Error should mention 6 TRUF requirement") + require.Contains(t, err.Error(), "Required: 1 TRUF", "Error should mention 1 TRUF requirement") return nil } } -// Test 4: Multiple children - fee should be 6 TRUF per child -func testTaxonomyMultipleChildrenFee(t *testing.T) func(ctx context.Context, platform *kwilTesting.Platform) error { +// Test 4: Multi-child taxonomy charges a flat 1 TRUF regardless of child count. +// This is the key invariant of issue #3805 — pricing is per-tx, not per-child. +func testTaxonomyMultipleChildrenChargesFlatFee(t *testing.T) func(ctx context.Context, platform *kwilTesting.Platform) error { return func(ctx context.Context, platform *kwilTesting.Platform) error { multiAddrVal := util.Unsafe_NewEthereumAddressFromString("0x5444444444444444444444444444444444444444") multiAddr := &multiAddrVal @@ -227,39 +232,40 @@ func testTaxonomyMultipleChildrenFee(t *testing.T) func(ctx context.Context, pla err := setup.CreateDataProviderWithoutRole(ctx, platform, multiAddr.Address()) require.NoError(t, err, "failed to create data provider without role") - // Give 42 TRUF: 6 (composed) + 18 (3 children streams) + 18 (taxonomy fee for 3 children) - fortyTwoTRUF := mustParseBigInt("42000000000000000000") // 42 TRUF - err = giveBalance(ctx, platform, multiAddr.Address(), fortyTwoTRUF.String()) + // Give exactly 5 TRUF: 1 (composed) + 3 (3 children) + 1 (taxonomy, flat). + // If the migration were still per-child, the 3-child taxonomy would + // cost 3 TRUF and this test would fail with insufficient balance. + fiveTRUF := mustParseBigInt("5000000000000000000") + err = giveBalance(ctx, platform, multiAddr.Address(), fiveTRUF.String()) require.NoError(t, err, "failed to give balance") // Get initial balance initialBalance, err := getBalance(ctx, platform, multiAddr.Address()) require.NoError(t, err, "failed to get initial balance") - require.Equal(t, fortyTwoTRUF, initialBalance, "Initial balance should be 42 TRUF") + require.Equal(t, fiveTRUF, initialBalance, "Initial balance should be 5 TRUF") - // Create streams (costs 6 + 18 = 24 TRUF total) + // Create streams (costs 1 + 3 = 4 TRUF total) composedStreamId := util.GenerateStreamId("taxonomy_multi_composed") child1StreamId := util.GenerateStreamId("taxonomy_multi_child1") child2StreamId := util.GenerateStreamId("taxonomy_multi_child2") child3StreamId := util.GenerateStreamId("taxonomy_multi_child3") - // Create composed stream (costs 6 TRUF) + // Create composed stream (costs 1 TRUF) err = createStream(ctx, platform, multiAddr, composedStreamId.String(), "composed") require.NoError(t, err, "failed to create composed stream") - // Create 3 child streams (costs 18 TRUF total) + // Create 3 child streams (costs 3 TRUF total, one per create_stream call) for _, childId := range []util.StreamId{child1StreamId, child2StreamId, child3StreamId} { err = createStream(ctx, platform, multiAddr, childId.String(), "primitive") require.NoError(t, err, "failed to create child stream") } - // Balance after stream creation should be 18 TRUF (42 - 24) + // Balance after stream creation should be 1 TRUF (5 - 4) balanceAfterStreams, err := getBalance(ctx, platform, multiAddr.Address()) require.NoError(t, err, "failed to get balance after stream creation") - eighteenTRUF := mustParseBigInt("18000000000000000000") - require.Equal(t, eighteenTRUF, balanceAfterStreams, "Balance should be 18 TRUF after creating streams") + require.Equal(t, oneTRUFTaxonomy, balanceAfterStreams, "Balance should be 1 TRUF after creating streams") - // Insert taxonomy with 3 children (should charge 18 TRUF total) + // Insert taxonomy with 3 children — must still charge exactly 1 TRUF. err = insertTaxonomy(ctx, platform, multiAddr, multiAddr.Address(), composedStreamId.String(), []string{multiAddr.Address(), multiAddr.Address(), multiAddr.Address()}, @@ -268,11 +274,11 @@ func testTaxonomyMultipleChildrenFee(t *testing.T) func(ctx context.Context, pla nil) require.NoError(t, err, "taxonomy insertion should succeed") - // Verify balance is now 0 (18 TRUF taxonomy fee charged) + // Verify balance is now 0 — 3-child taxonomy charged only 1 TRUF (flat). finalBalance, err := getBalance(ctx, platform, multiAddr.Address()) require.NoError(t, err, "failed to get final balance") - require.Equal(t, big.NewInt(0), finalBalance, "Final balance should be 0 after paying all fees") + require.Equal(t, big.NewInt(0), finalBalance, "Final balance should be 0 — taxonomy fee is flat 1 TRUF regardless of child count") return nil } diff --git a/tests/streams/transaction_events_ledger_test.go b/tests/streams/transaction_events_ledger_test.go index 839529d4..5355c8d6 100644 --- a/tests/streams/transaction_events_ledger_test.go +++ b/tests/streams/transaction_events_ledger_test.go @@ -20,21 +20,26 @@ import ( "github.com/trufnetwork/node/internal/migrations" testutils "github.com/trufnetwork/node/tests/streams/utils" testerc20 "github.com/trufnetwork/node/tests/streams/utils/erc20" + "github.com/trufnetwork/node/tests/streams/utils/feefund" "github.com/trufnetwork/node/tests/streams/utils/setup" sdkTypes "github.com/trufnetwork/sdk-go/core/types" "github.com/trufnetwork/sdk-go/core/util" ) const ( + // The transfer/withdraw helpers (`sepolia_transfer`, + // `sepolia_bridge_tokens`) charge fees against the `sepolia_bridge` + // instance, so the test-local ledgerGiveBalance funds that one. The + // write-fee actions (create_streams / insert_records / insert_taxonomy / + // request_attestation) charge against `hoodi_tt` instead — that balance + // is topped up separately via `feefund.EnsureWalletFunded` below. ledgerChain = "sepolia" ledgerEscrow = "0x502430eD0BbE0f230215870c9C2853e126eE5Ae3" ledgerERC20 = "0x2222222222222222222222222222222222222222" ledgerExtensionAlias = "sepolia_bridge" + feeHalfTRUF = "500000000000000000" feeOneTRUF = "1000000000000000000" - feeThreeTRUF = "3000000000000000000" - feeSixTRUF = "6000000000000000000" - feeTwelveTRUF = "12000000000000000000" feeFortyTRUF = "40000000000000000000" transferAmount = "5000000000000000000" withdrawAmount = "10000000000000000000" @@ -84,6 +89,12 @@ func runTransactionEventsLedgerScenario(t *testing.T) func(ctx context.Context, actor := &actorVal require.NoError(t, setup.CreateDataProviderWithoutRole(ctx, platform, actor.Address())) require.NoError(t, ledgerGiveBalance(ctx, platform, actor.Address(), initialUserFunds)) + // The write-fee actions (create_streams / insert_records / + // insert_taxonomy / request_attestation) charge against `hoodi_tt`, + // not `sepolia_bridge`. Fund 100 TRUF there — covers 1+1+1 write + // fees plus the 40 TRUF attestation fee with headroom. + require.NoError(t, feefund.EnsureWalletFunded(ctx, platform, actor.Address(), "100000000000000000000"), + "fund actor on hoodi_tt for write fees") receiverVal := util.Unsafe_NewEthereumAddressFromString("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") receiver := &receiverVal @@ -141,9 +152,11 @@ func runTransactionEventsLedgerScenario(t *testing.T) func(ctx context.Context, UPDATE %s.transaction_event_distributions SET amount = $1::NUMERIC(78, 0) WHERE tx_id = $2 AND sequence = 1`, schemaName) + // Split the auto-recorded 1 TRUF distribution into two halves so the + // ledger test exercises multi-recipient bookkeeping for a single tx. _, err = platform.DB.Execute(ctx, updateSQL, - feeThreeTRUF, + feeHalfTRUF, insertTx, ) require.NoError(t, err) @@ -156,7 +169,7 @@ func runTransactionEventsLedgerScenario(t *testing.T) func(ctx context.Context, insertTx, 2, bonusRecipientLower, - feeThreeTRUF, + feeHalfTRUF, ) require.NoError(t, err) @@ -219,29 +232,29 @@ func runTransactionEventsLedgerScenario(t *testing.T) func(ctx context.Context, expected := map[string]ledgerExpectation{ createTx: { method: "deployStream", - fee: feeTwelveTRUF, + fee: feeOneTRUF, // flat 1 TRUF regardless of stream count feeRecipient: createLeaderAddr, feeDistributions: []string{ - buildDistribution(createLeaderAddr, feeTwelveTRUF), + buildDistribution(createLeaderAddr, feeOneTRUF), }, assertMetadata: assertNoMetadata, }, insertTx: { method: "insertRecords", - fee: feeSixTRUF, + fee: feeOneTRUF, // flat 1 TRUF regardless of record count feeRecipient: insertLeaderAddr, feeDistributions: []string{ - buildDistribution(insertLeaderAddr, feeThreeTRUF), - buildDistribution(bonusRecipientLower, feeThreeTRUF), + buildDistribution(insertLeaderAddr, feeHalfTRUF), + buildDistribution(bonusRecipientLower, feeHalfTRUF), }, assertMetadata: assertNoMetadata, }, taxTx: { method: "setTaxonomies", - fee: feeSixTRUF, + fee: feeOneTRUF, // flat 1 TRUF regardless of child count feeRecipient: taxLeaderAddr, feeDistributions: []string{ - buildDistribution(taxLeaderAddr, feeSixTRUF), + buildDistribution(taxLeaderAddr, feeOneTRUF), }, assertMetadata: assertNoMetadata, }, @@ -341,7 +354,7 @@ func runTransactionEventsLedgerScenario(t *testing.T) func(ctx context.Context, require.Equal(t, insertTx, insertLeaderReceivedRows[0].TxID) require.Equal(t, insertLeaderAddr, insertLeaderReceivedRows[0].FeeRecipient) require.Equal(t, insertLeaderAddr, insertLeaderReceivedRows[0].DistributionRecipient) - require.Equal(t, feeThreeTRUF, insertLeaderReceivedRows[0].DistributionAmount) + require.Equal(t, feeHalfTRUF, insertLeaderReceivedRows[0].DistributionAmount) bonusReceivedRows, err := fetchTransactionFees(ctx, platform, actor.Address(), bonusRecipientLower, "received") require.NoError(t, err) @@ -349,7 +362,7 @@ func runTransactionEventsLedgerScenario(t *testing.T) func(ctx context.Context, require.Equal(t, insertTx, bonusReceivedRows[0].TxID) require.Equal(t, insertLeaderAddr, bonusReceivedRows[0].FeeRecipient) require.Equal(t, bonusRecipientLower, bonusReceivedRows[0].DistributionRecipient) - require.Equal(t, feeThreeTRUF, bonusReceivedRows[0].DistributionAmount) + require.Equal(t, feeHalfTRUF, bonusReceivedRows[0].DistributionAmount) lastTxRows, err := fetchLastTransactions(ctx, platform, actor.Address(), userLower, int64(len(expected))) require.NoError(t, err) @@ -367,7 +380,7 @@ func runTransactionEventsLedgerScenario(t *testing.T) func(ctx context.Context, for _, row := range bonusHistoryRows { if row.DistributionRecipient == bonusRecipientLower { require.Equal(t, insertTx, row.TxID) - require.Equal(t, feeThreeTRUF, row.DistributionAmount) + require.Equal(t, feeHalfTRUF, row.DistributionAmount) foundBonus = true break } @@ -725,6 +738,9 @@ func runTransactionIDTrackingScenario(t *testing.T) func(ctx context.Context, pl actor := util.Unsafe_NewEthereumAddressFromString("0x9999999999999999999999999999999999999999") require.NoError(t, setup.CreateDataProviderWithoutRole(ctx, platform, actor.Address())) require.NoError(t, ledgerGiveBalance(ctx, platform, actor.Address(), initialUserFunds)) + // Write-fee actions charge against `hoodi_tt`; fund that bridge too. + require.NoError(t, feefund.EnsureWalletFunded(ctx, platform, actor.Address(), "100000000000000000000"), + "fund actor on hoodi_tt for write fees") userLower := strings.ToLower(actor.Address()) height := int64(10)