From e5e8693a7051726914a38a0c423469e6bdab8a94 Mon Sep 17 00:00:00 2001 From: Michael Buntarman Date: Mon, 9 Feb 2026 16:46:00 +0700 Subject: [PATCH 1/3] chore: prevent trading after event completion --- .../migrations/032-order-book-actions.sql | 45 ++++++++++++-- .../040-binary-attestation-actions.sql | 20 ++++++ .../streams/order_book/binary_actions_test.go | 62 +++++++++++++++++++ tests/streams/order_book/buy_order_test.go | 38 ++++++++++++ 4 files changed, 160 insertions(+), 5 deletions(-) diff --git a/internal/migrations/032-order-book-actions.sql b/internal/migrations/032-order-book-actions.sql index 9fca6b147..b85f75192 100644 --- a/internal/migrations/032-order-book-actions.sql +++ b/internal/migrations/032-order-book-actions.sql @@ -1053,10 +1053,12 @@ CREATE OR REPLACE ACTION place_buy_order( -- 1.4 Validate market exists and is not settled $settled BOOL; + $settle_time INT8; $market_found BOOL := false; - for $row in SELECT settled FROM ob_queries WHERE id = $query_id { + for $row in SELECT settled, settle_time FROM ob_queries WHERE id = $query_id { $settled := $row.settled; + $settle_time := $row.settle_time; $market_found := true; } @@ -1072,6 +1074,11 @@ CREATE OR REPLACE ACTION place_buy_order( ERROR('Market has already settled (no trading allowed)'); } + -- Trading Cutoff: Prevent new orders after settlement time + if @block_timestamp >= $settle_time { + ERROR('Trading is closed. Market has passed its settlement time.'); + } + -- ========================================================================== -- SECTION 2: CALCULATE COLLATERAL NEEDED -- ========================================================================== @@ -1244,10 +1251,12 @@ CREATE OR REPLACE ACTION place_sell_order( -- 1.3 Validate market exists and is not settled $settled BOOL; + $settle_time INT8; $market_found BOOL := false; - for $row in SELECT settled FROM ob_queries WHERE id = $query_id { + for $row in SELECT settled, settle_time FROM ob_queries WHERE id = $query_id { $settled := $row.settled; + $settle_time := $row.settle_time; $market_found := true; } @@ -1263,6 +1272,11 @@ CREATE OR REPLACE ACTION place_sell_order( ERROR('Market has already settled (no trading allowed)'); } + -- Trading Cutoff: Prevent new orders after settlement time + if @block_timestamp >= $settle_time { + ERROR('Trading is closed. Market has passed its settlement time.'); + } + -- ========================================================================== -- SECTION 2: GET PARTICIPANT (NO AUTO-CREATE FOR SELLS) -- ========================================================================== @@ -1440,10 +1454,12 @@ CREATE OR REPLACE ACTION place_split_limit_order( -- 1.4 Validate market exists and is not settled $settled BOOL; + $settle_time INT8; $market_found BOOL := false; - for $row in SELECT settled FROM ob_queries WHERE id = $query_id { + for $row in SELECT settled, settle_time FROM ob_queries WHERE id = $query_id { $settled := $row.settled; + $settle_time := $row.settle_time; $market_found := true; } @@ -1459,6 +1475,11 @@ CREATE OR REPLACE ACTION place_split_limit_order( ERROR('Market has already settled (no trading allowed)'); } + -- Trading Cutoff: Prevent new orders after settlement time + if @block_timestamp >= $settle_time { + ERROR('Trading is closed. Market has passed its settlement time.'); + } + -- ========================================================================== -- SECTION 2: CALCULATE COLLATERAL NEEDED -- ========================================================================== @@ -1897,8 +1918,10 @@ CREATE OR REPLACE ACTION change_bid( -- ========================================================================== $settled BOOL; - for $row in SELECT settled FROM ob_queries WHERE id = $query_id { + $settle_time INT8; + for $row in SELECT settled, settle_time FROM ob_queries WHERE id = $query_id { $settled := $row.settled; + $settle_time := $row.settle_time; } if $settled IS NULL { @@ -1909,6 +1932,11 @@ CREATE OR REPLACE ACTION change_bid( ERROR('Cannot modify orders on settled market'); } + -- Trading Cutoff: Prevent modifying orders after settlement time + if @block_timestamp >= $settle_time { + ERROR('Trading is closed. Market has passed its settlement time.'); + } + -- ========================================================================== -- SECTION 4: GET OLD ORDER DETAILS -- ========================================================================== @@ -2142,8 +2170,10 @@ CREATE OR REPLACE ACTION change_ask( -- ========================================================================== $settled BOOL; - for $row in SELECT settled FROM ob_queries WHERE id = $query_id { + $settle_time INT8; + for $row in SELECT settled, settle_time FROM ob_queries WHERE id = $query_id { $settled := $row.settled; + $settle_time := $row.settle_time; } if $settled IS NULL { @@ -2154,6 +2184,11 @@ CREATE OR REPLACE ACTION change_ask( ERROR('Cannot modify orders on settled market'); } + -- Trading Cutoff: Prevent modifying orders after settlement time + if @block_timestamp >= $settle_time { + ERROR('Trading is closed. Market has passed its settlement time.'); + } + -- ========================================================================== -- SECTION 4: GET OLD ORDER DETAILS -- ========================================================================== diff --git a/internal/migrations/040-binary-attestation-actions.sql b/internal/migrations/040-binary-attestation-actions.sql index b1ac6d0e2..f238db5d4 100644 --- a/internal/migrations/040-binary-attestation-actions.sql +++ b/internal/migrations/040-binary-attestation-actions.sql @@ -54,6 +54,11 @@ CREATE OR REPLACE ACTION price_above_threshold( if $timestamp IS NULL { ERROR('timestamp is required'); } + + -- Prevent premature resolution + if @block_timestamp < $timestamp { + ERROR('Cannot resolve market before target timestamp. Current: ' || @block_timestamp::TEXT || ', Target: ' || $timestamp::TEXT); + } if $threshold IS NULL { ERROR('threshold is required'); } @@ -124,6 +129,11 @@ CREATE OR REPLACE ACTION price_below_threshold( if $timestamp IS NULL { ERROR('timestamp is required'); } + + -- Prevent premature resolution + if @block_timestamp < $timestamp { + ERROR('Cannot resolve market before target timestamp. Current: ' || @block_timestamp::TEXT || ', Target: ' || $timestamp::TEXT); + } if $threshold IS NULL { ERROR('threshold is required'); } @@ -192,6 +202,11 @@ CREATE OR REPLACE ACTION value_in_range( if $timestamp IS NULL { ERROR('timestamp is required'); } + + -- Prevent premature resolution + if @block_timestamp < $timestamp { + ERROR('Cannot resolve market before target timestamp. Current: ' || @block_timestamp::TEXT || ', Target: ' || $timestamp::TEXT); + } if $min_value IS NULL { ERROR('min_value is required'); } @@ -268,6 +283,11 @@ CREATE OR REPLACE ACTION value_equals( if $timestamp IS NULL { ERROR('timestamp is required'); } + + -- Prevent premature resolution + if @block_timestamp < $timestamp { + ERROR('Cannot resolve market before target timestamp. Current: ' || @block_timestamp::TEXT || ', Target: ' || $timestamp::TEXT); + } if $target IS NULL { ERROR('target is required'); } diff --git a/tests/streams/order_book/binary_actions_test.go b/tests/streams/order_book/binary_actions_test.go index 4b249409a..96d3254fd 100644 --- a/tests/streams/order_book/binary_actions_test.go +++ b/tests/streams/order_book/binary_actions_test.go @@ -5,6 +5,7 @@ package order_book import ( "context" "testing" + "time" "github.com/stretchr/testify/require" "github.com/trufnetwork/kwil-db/common" @@ -51,6 +52,7 @@ func TestBinaryActions(t *testing.T) { // Error cases testBinaryActionNoData(t), testValueInRangeInvalidRange(t), + testBinaryActionFutureTimestamp(t), }, }, testutils.GetTestOptionsWithCache()) } @@ -74,6 +76,9 @@ func setupBinaryActionTest(t *testing.T, ctx context.Context, platform *kwilTest // Use attestation helper for engine context after data provider is created helper := attestationTests.NewAttestationTestHelper(t, ctx, platform) engineCtx := helper.NewEngineContext() + // Set block timestamp to be after the event time so "past" queries work + // If eventTime is 1000, block time 2000 allows querying 1000 + engineCtx.TxContext.BlockContext.Timestamp = eventTime + 1000 t.Logf("Setup: Creating stream %s", streamID) @@ -614,6 +619,7 @@ func testBinaryActionNoData(t *testing.T) func(context.Context, *kwilTesting.Pla helper := attestationTests.NewAttestationTestHelper(t, ctx, platform) engineCtx := helper.NewEngineContext() + engineCtx.TxContext.BlockContext.Timestamp = 2000 // Ensure query is in the past // Create stream but DON'T insert any data _, err = platform.Engine.Call(engineCtx, platform.DB, "", "create_stream", @@ -649,6 +655,7 @@ func testValueInRangeInvalidRange(t *testing.T) func(context.Context, *kwilTesti eventTime := int64(1000) engineCtx, dataProvider := setupBinaryActionTest(t, ctx, platform, streamID, eventTime, "100.000000000000000000") + engineCtx.TxContext.BlockContext.Timestamp = 2000 // Ensure query is in the past // min > max is invalid minDecimal, err := kwilTypes.ParseDecimalExplicit("200.000000000000000000", 36, 18) @@ -674,3 +681,58 @@ func testValueInRangeInvalidRange(t *testing.T) func(context.Context, *kwilTesti return nil } } + +func testBinaryActionFutureTimestamp(t *testing.T) func(context.Context, *kwilTesting.Platform) error { + return func(ctx context.Context, platform *kwilTesting.Platform) error { + deployer := util.Unsafe_NewEthereumAddressFromString("0x1111111111111111111111111111111111111111") + platform.Deployer = deployer.Bytes() + + streamID := "stbinaryfuture000000000000000001" + dataProvider := deployer.Address() + + // Create data provider using setup helper + err := setup.CreateDataProvider(ctx, platform, dataProvider) + require.NoError(t, err) + + helper := attestationTests.NewAttestationTestHelper(t, ctx, platform) + engineCtx := helper.NewEngineContext() + + // Create stream + _, err = platform.Engine.Call(engineCtx, platform.DB, "", "create_stream", + []any{streamID, "primitive"}, nil) + require.NoError(t, err) + + // Insert some data for now + eventTime := time.Now().Unix() + valueDecimal, _ := kwilTypes.ParseDecimalExplicit("50000.000000000000000000", 36, 18) + _, err = platform.Engine.Call(engineCtx, platform.DB, "", "insert_records", + []any{ + []string{dataProvider}, + []string{streamID}, + []int64{eventTime}, + []*kwilTypes.Decimal{valueDecimal}, + }, nil) + require.NoError(t, err) + + // Try to query for FUTURE timestamp (1 hour later) + futureTime := eventTime + 3600 + thresholdDecimal, _ := kwilTypes.ParseDecimalExplicit("40000.000000000000000000", 36, 18) + + res, err := platform.Engine.Call(engineCtx, platform.DB, "", "price_above_threshold", + []any{ + dataProvider, + streamID, + futureTime, + thresholdDecimal, + nil, + }, nil) + require.NoError(t, err) + + // Should error due to premature resolution safeguard + require.NotNil(t, res.Error, "should error when querying future timestamp") + require.Contains(t, res.Error.Error(), "Cannot resolve market before target timestamp", "error should mention target timestamp") + t.Log("price_above_threshold with future timestamp: correctly returned error") + + return nil + } +} diff --git a/tests/streams/order_book/buy_order_test.go b/tests/streams/order_book/buy_order_test.go index ced61ad27..fade6e824 100644 --- a/tests/streams/order_book/buy_order_test.go +++ b/tests/streams/order_book/buy_order_test.go @@ -64,6 +64,7 @@ func TestPlaceBuyOrder(t *testing.T) { testBuyOrderMultipleOrdersDifferentPrices(t), testBuyOrderMultipleOrdersSamePrice(t), testBuyOrderBalanceChanges(t), + testBuyOrderTradingClosed(t), }, }, testutils.GetTestOptionsWithCache()) } @@ -636,3 +637,40 @@ func getUSDCBalance(ctx context.Context, platform *kwilTesting.Platform, wallet return balance, nil } + +// testBuyOrderTradingClosed tests that orders cannot be placed after settlement time +func testBuyOrderTradingClosed(t *testing.T) func(ctx context.Context, platform *kwilTesting.Platform) error { + return func(ctx context.Context, platform *kwilTesting.Platform) error { + userAddr := util.Unsafe_NewEthereumAddressFromString("0x9999999999999999999999999999999999999999") + + err := giveBalance(ctx, platform, userAddr.Address(), "100000000000000000000") + require.NoError(t, err) + + err = erc20bridge.ForTestingInitializeExtension(ctx, platform) + require.NoError(t, err) + + // Create market with settlement time 2 seconds in the future + // Note: We need a slight delay to ensure we can create it before it expires + settleTime := time.Now().Add(2 * time.Second).Unix() + + queryComponents, err := encodeQueryComponentsForTests(userAddr.Address(), "sttest00000000000000000000000008", "get_record", []byte{0x01}) + require.NoError(t, err) + + var marketID int64 + err = callCreateMarket(ctx, platform, &userAddr, queryComponents, settleTime, 5, 20, func(row *common.Row) error { + marketID = row.Values[0].(int64) + return nil + }) + require.NoError(t, err) + + // Wait for settlement time to pass + time.Sleep(3 * time.Second) + + // Try to place buy order - should fail + err = callPlaceBuyOrder(ctx, platform, &userAddr, int(marketID), true, 50, 10) + require.Error(t, err, "place_buy_order should fail after settle_time") + require.Contains(t, err.Error(), "Trading is closed", "error should mention trading closed") + + return nil + } +} From c87fec32c0beaaa5372f773782c9da409620e55c Mon Sep 17 00:00:00 2001 From: Michael Buntarman Date: Tue, 10 Feb 2026 06:04:42 +0700 Subject: [PATCH 2/3] chore: patch CI --- tests/streams/order_book/settlement_payout_test.go | 5 +++-- tests/streams/order_book/settlement_test.go | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/streams/order_book/settlement_payout_test.go b/tests/streams/order_book/settlement_payout_test.go index a002fa099..88df3055e 100644 --- a/tests/streams/order_book/settlement_payout_test.go +++ b/tests/streams/order_book/settlement_payout_test.go @@ -6,6 +6,7 @@ import ( "context" "math/big" "testing" + "time" "github.com/stretchr/testify/require" "github.com/trufnetwork/kwil-db/common" @@ -175,14 +176,14 @@ func testWinnerReceivesFullPayout(t *testing.T) func(context.Context, *kwilTesti require.NoError(t, err) // Create market using query_components - settleTime := int64(100) // Future timestamp + settleTime := time.Now().Add(1 * time.Hour).Unix() // Future timestamp maxSpread := int64(5) minOrderSize := int64(1) var queryID int // Use timestamp 50 for market creation (before settleTime) engineCtx = helper.NewEngineContext() - engineCtx.TxContext.BlockContext.Timestamp = 50 + engineCtx.TxContext.BlockContext.Timestamp = time.Now().Unix() createMarketRes, err := platform.Engine.Call(engineCtx, platform.DB, "", "create_market", []any{testExtensionName, queryComponents, settleTime, maxSpread, minOrderSize}, func(row *common.Row) error { diff --git a/tests/streams/order_book/settlement_test.go b/tests/streams/order_book/settlement_test.go index eb900cfca..489c807d6 100644 --- a/tests/streams/order_book/settlement_test.go +++ b/tests/streams/order_book/settlement_test.go @@ -177,14 +177,14 @@ func testSettleMarketHappyPath(t *testing.T) func(context.Context, *kwilTesting. require.NoError(t, err) // Create market using query_components - settleTime := int64(100) // Future timestamp + settleTime := time.Now().Add(1 * time.Hour).Unix() maxSpread := int64(5) minOrderSize := int64(1) var queryID int // Use timestamp 50 for market creation (before settleTime) engineCtx = helper.NewEngineContext() - engineCtx.TxContext.BlockContext.Timestamp = 50 + engineCtx.TxContext.BlockContext.Timestamp = time.Now().Unix() createRes, err := platform.Engine.Call(engineCtx, platform.DB, "", "create_market", []any{testExtensionName, queryComponents, settleTime, maxSpread, minOrderSize}, func(row *common.Row) error { From e64836a6b1bf9fde026b96a3db9b1681ef08584c Mon Sep 17 00:00:00 2001 From: Michael Buntarman Date: Tue, 10 Feb 2026 06:39:09 +0700 Subject: [PATCH 3/3] chore: apply suggestion --- .../migrations/032-order-book-actions.sql | 24 +++++----- .../040-binary-attestation-actions.sql | 48 +++++++------------ .../order_book/settlement_payout_test.go | 6 +-- tests/streams/order_book/settlement_test.go | 13 ++--- 4 files changed, 38 insertions(+), 53 deletions(-) diff --git a/internal/migrations/032-order-book-actions.sql b/internal/migrations/032-order-book-actions.sql index b85f75192..b3d25a767 100644 --- a/internal/migrations/032-order-book-actions.sql +++ b/internal/migrations/032-order-book-actions.sql @@ -1066,10 +1066,10 @@ CREATE OR REPLACE ACTION place_buy_order( ERROR('Market does not exist (query_id: ' || $query_id::TEXT || ')'); } - -- Note: Markets remain tradable until explicitly settled (settled=true). - -- The settle_time is metadata indicating when settlement CAN occur, not when it MUST. - -- Users can continue trading past settle_time until the settlement action is triggered. - -- This two-phase design allows flexibility in settlement timing. + -- Note: Markets remain tradable until settlement time is reached or explicitly settled (settled=true). + -- The settle_time is metadata indicating when settlement CAN occur, and now serves as a hard cutoff for trading. + -- Users cannot continue trading past settle_time. + -- This two-phase design allows flexibility in settlement timing while ensuring a fixed trading window. if $settled { ERROR('Market has already settled (no trading allowed)'); } @@ -1264,10 +1264,10 @@ CREATE OR REPLACE ACTION place_sell_order( ERROR('Market does not exist (query_id: ' || $query_id::TEXT || ')'); } - -- Note: Markets remain tradable until explicitly settled (settled=true). - -- The settle_time is metadata indicating when settlement CAN occur, not when it MUST. - -- Users can continue trading past settle_time until the settlement action is triggered. - -- This two-phase design allows flexibility in settlement timing. + -- Note: Markets remain tradable until settlement time is reached or explicitly settled (settled=true). + -- The settle_time is metadata indicating when settlement CAN occur, and now serves as a hard cutoff for trading. + -- Users cannot continue trading past settle_time. + -- This two-phase design allows flexibility in settlement timing while ensuring a fixed trading window. if $settled { ERROR('Market has already settled (no trading allowed)'); } @@ -1467,10 +1467,10 @@ CREATE OR REPLACE ACTION place_split_limit_order( ERROR('Market does not exist (query_id: ' || $query_id::TEXT || ')'); } - -- Note: Markets remain tradable until explicitly settled (settled=true). - -- The settle_time is metadata indicating when settlement CAN occur, not when it MUST. - -- Users can continue trading past settle_time until the settlement action is triggered. - -- This two-phase design allows flexibility in settlement timing. + -- Note: Markets remain tradable until settlement time is reached or explicitly settled (settled=true). + -- The settle_time is metadata indicating when settlement CAN occur, and now serves as a hard cutoff for trading. + -- Users cannot continue trading past settle_time. + -- This two-phase design allows flexibility in settlement timing while ensuring a fixed trading window. if $settled { ERROR('Market has already settled (no trading allowed)'); } diff --git a/internal/migrations/040-binary-attestation-actions.sql b/internal/migrations/040-binary-attestation-actions.sql index f238db5d4..c91453ae0 100644 --- a/internal/migrations/040-binary-attestation-actions.sql +++ b/internal/migrations/040-binary-attestation-actions.sql @@ -22,6 +22,18 @@ INSERT INTO attestation_actions (action_name, action_id) VALUES ('value_equals', 9) ON CONFLICT (action_name) DO NOTHING; +-- ============================================================================= +-- Helper: Validate timestamp is not in the future +-- ============================================================================= +CREATE OR REPLACE ACTION validate_not_before_timestamp($timestamp INT8) PRIVATE { + if $timestamp IS NULL { + ERROR('timestamp is required'); + } + if @block_timestamp < $timestamp { + ERROR('Cannot resolve market before target timestamp. Current: ' || @block_timestamp::TEXT || ', Target: ' || $timestamp::TEXT); + } +}; + -- ============================================================================= -- price_above_threshold: Returns TRUE if value > threshold at timestamp -- ============================================================================= @@ -51,14 +63,7 @@ CREATE OR REPLACE ACTION price_above_threshold( $effective_frozen_at INT8 := COALESCE($frozen_at, $max_int8); -- Validate inputs - if $timestamp IS NULL { - ERROR('timestamp is required'); - } - - -- Prevent premature resolution - if @block_timestamp < $timestamp { - ERROR('Cannot resolve market before target timestamp. Current: ' || @block_timestamp::TEXT || ', Target: ' || $timestamp::TEXT); - } + validate_not_before_timestamp($timestamp); if $threshold IS NULL { ERROR('threshold is required'); } @@ -126,14 +131,7 @@ CREATE OR REPLACE ACTION price_below_threshold( $effective_frozen_at INT8 := COALESCE($frozen_at, $max_int8); -- Validate inputs - if $timestamp IS NULL { - ERROR('timestamp is required'); - } - - -- Prevent premature resolution - if @block_timestamp < $timestamp { - ERROR('Cannot resolve market before target timestamp. Current: ' || @block_timestamp::TEXT || ', Target: ' || $timestamp::TEXT); - } + validate_not_before_timestamp($timestamp); if $threshold IS NULL { ERROR('threshold is required'); } @@ -199,14 +197,7 @@ CREATE OR REPLACE ACTION value_in_range( $effective_frozen_at INT8 := COALESCE($frozen_at, $max_int8); -- Validate inputs - if $timestamp IS NULL { - ERROR('timestamp is required'); - } - - -- Prevent premature resolution - if @block_timestamp < $timestamp { - ERROR('Cannot resolve market before target timestamp. Current: ' || @block_timestamp::TEXT || ', Target: ' || $timestamp::TEXT); - } + validate_not_before_timestamp($timestamp); if $min_value IS NULL { ERROR('min_value is required'); } @@ -280,14 +271,7 @@ CREATE OR REPLACE ACTION value_equals( $effective_tolerance NUMERIC(36, 18) := COALESCE($tolerance, 0::NUMERIC(36, 18)); -- Validate inputs - if $timestamp IS NULL { - ERROR('timestamp is required'); - } - - -- Prevent premature resolution - if @block_timestamp < $timestamp { - ERROR('Cannot resolve market before target timestamp. Current: ' || @block_timestamp::TEXT || ', Target: ' || $timestamp::TEXT); - } + validate_not_before_timestamp($timestamp); if $target IS NULL { ERROR('target is required'); } diff --git a/tests/streams/order_book/settlement_payout_test.go b/tests/streams/order_book/settlement_payout_test.go index 88df3055e..fe051f00b 100644 --- a/tests/streams/order_book/settlement_payout_test.go +++ b/tests/streams/order_book/settlement_payout_test.go @@ -181,7 +181,7 @@ func testWinnerReceivesFullPayout(t *testing.T) func(context.Context, *kwilTesti minOrderSize := int64(1) var queryID int - // Use timestamp 50 for market creation (before settleTime) + // Use current time for market creation (before settleTime) engineCtx = helper.NewEngineContext() engineCtx.TxContext.BlockContext.Timestamp = time.Now().Unix() createMarketRes, err := platform.Engine.Call(engineCtx, platform.DB, "", "create_market", @@ -217,9 +217,9 @@ func testWinnerReceivesFullPayout(t *testing.T) func(context.Context, *kwilTesti require.Equal(t, int64(100), yesHoldings.Amount) t.Logf("User has %d YES holdings before settlement", yesHoldings.Amount) - // Settle the market with timestamp 200 (after settleTime) + // Settle the market with timestamp after settleTime engineCtx = helper.NewEngineContext() - engineCtx.TxContext.BlockContext.Timestamp = 200 + engineCtx.TxContext.BlockContext.Timestamp = settleTime + 1 settleRes, err := platform.Engine.Call(engineCtx, platform.DB, "", "settle_market", []any{queryID}, nil) diff --git a/tests/streams/order_book/settlement_test.go b/tests/streams/order_book/settlement_test.go index 489c807d6..6aec20ae4 100644 --- a/tests/streams/order_book/settlement_test.go +++ b/tests/streams/order_book/settlement_test.go @@ -182,7 +182,7 @@ func testSettleMarketHappyPath(t *testing.T) func(context.Context, *kwilTesting. minOrderSize := int64(1) var queryID int - // Use timestamp 50 for market creation (before settleTime) + // Use current time for market creation (before settleTime) engineCtx = helper.NewEngineContext() engineCtx.TxContext.BlockContext.Timestamp = time.Now().Unix() createRes, err := platform.Engine.Call(engineCtx, platform.DB, "", "create_market", @@ -198,9 +198,9 @@ func testSettleMarketHappyPath(t *testing.T) func(context.Context, *kwilTesting. } require.Greater(t, queryID, 0, "queryID should be positive") - // Settle the market with timestamp 200 (after settleTime) + // Settle the market with timestamp after settleTime engineCtx = helper.NewEngineContext() - engineCtx.TxContext.BlockContext.Timestamp = 200 + engineCtx.TxContext.BlockContext.Timestamp = settleTime + 1 settleRes, err := platform.Engine.Call(engineCtx, platform.DB, "", "settle_market", []any{queryID}, nil) @@ -1005,11 +1005,12 @@ func testSettleMarketBlockedByBinaryParityViolation(t *testing.T) func(context.C require.NoError(t, err) // Create market + settleTime := time.Now().Add(1 * time.Hour).Unix() var queryID int engineCtx = helper.NewEngineContext() - engineCtx.TxContext.BlockContext.Timestamp = 50 + engineCtx.TxContext.BlockContext.Timestamp = time.Now().Unix() _, err = platform.Engine.Call(engineCtx, platform.DB, "", "create_market", - []any{testExtensionName, queryComponents, int64(100), int64(5), int64(1)}, + []any{testExtensionName, queryComponents, settleTime, int64(5), int64(1)}, func(row *common.Row) error { queryID = int(row.Values[0].(int64)) return nil @@ -1072,7 +1073,7 @@ func testSettleMarketBlockedByBinaryParityViolation(t *testing.T) func(context.C // Try to settle (should fail with binary parity violation) engineCtx = helper.NewEngineContext() - engineCtx.TxContext.BlockContext.Timestamp = 200 + engineCtx.TxContext.BlockContext.Timestamp = settleTime + 1 settleRes, err := platform.Engine.Call(engineCtx, platform.DB, "", "settle_market", []any{queryID}, nil) require.NoError(t, err)