Skip to content
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
2a7d869
feat(platform)!: destroy a frozen identity's escrowed listings with i…
QuantumExplorer Oct 21, 2026
b0ad84b
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
be47ffe
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
086cbf0
fix(drive): delete a frozen identity's listings in one batch-aware op…
QuantumExplorer Oct 22, 2026
a1bdd65
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
afcfa47
fix(drive): build each operation of a protocol 15 batch against the b…
QuantumExplorer Oct 22, 2026
7e89edd
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
ca118a6
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
5429998
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
def042b
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
3dace61
fix(drive): protocol 15 batches drain shared index groups; grouped op…
QuantumExplorer Oct 22, 2026
c557b4f
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
56bd477
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
90b47d9
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
61023ba
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
2464e98
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
185ab58
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
9e14a54
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
df0bcd1
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
c832240
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
b313168
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 22, 2026
c8c9b65
fix(drive): the raw batch converter builds each operation against the…
QuantumExplorer Oct 22, 2026
9f5c02f
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 23, 2026
aaddedc
fix(drive): the shared token history builder records a destroy's list…
QuantumExplorer Oct 23, 2026
abb253f
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 23, 2026
ea6abc7
test(drive-abci): the shared-index destroy regression requires a posi…
QuantumExplorer Oct 23, 2026
4fb947d
test(drive-abci): a frozen identity's offer keeps its stored credit e…
QuantumExplorer Oct 23, 2026
e56eca7
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 23, 2026
d82f362
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 23, 2026
9f5cab6
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 23, 2026
0f79744
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 23, 2026
cabf5d9
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 23, 2026
c9db21e
test(drive-abci): a frozen destroy leaves other holders' and other to…
QuantumExplorer Oct 23, 2026
6190db2
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 23, 2026
a22dd93
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 23, 2026
1a31c9f
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 23, 2026
76c7c8b
fix(drive): contested and withdrawal inserts see the batch's earlier …
QuantumExplorer Oct 24, 2026
d40f57a
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 25, 2026
548512b
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 25, 2026
ab5f6d4
docs(platform-version): renumber the Frozen listings note after the m…
QuantumExplorer Oct 25, 2026
7e0b7ca
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 25, 2026
09dd130
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 25, 2026
414ab4c
refactor(drive): each destroyed-amount generation lives in its own mo…
QuantumExplorer Oct 25, 2026
741d996
docs(platform-version): indent the continuation of note 12
QuantumExplorer Oct 25, 2026
114fc75
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 25, 2026
55f462d
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 25, 2026
cbf4448
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 26, 2026
8355a63
fix(drive): the frozen-listing read fails closed before protocol vers…
QuantumExplorer Oct 26, 2026
74249a4
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 26, 2026
5b7c63b
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 26, 2026
0ef5022
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 26, 2026
dce4817
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 26, 2026
fdbbcc0
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 26, 2026
cdd288e
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 26, 2026
b79668c
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 26, 2026
71d3911
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 27, 2026
ec02ad6
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 27, 2026
348e12d
test(platform): frozen listing fixtures name no minimum fill or decimals
QuantumExplorer Oct 27, 2026
2729ce7
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 27, 2026
d35f57e
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 27, 2026
06ac436
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 27, 2026
ba04d79
docs(changelog): list the drive API changes of the frozen listings de…
QuantumExplorer Oct 27, 2026
47357f9
docs(changelog): list the platform-version fields of the frozen listi…
QuantumExplorer Oct 27, 2026
ca5e98f
test(drive-abci): a cancel between a group destroy's signatures only …
QuantumExplorer Oct 27, 2026
5d18348
fix(drive): the protocol 15 raw converter refuses repeated token writ…
QuantumExplorer Oct 27, 2026
3a04710
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 28, 2026
424a325
fix(drive)!: apply the frozen listings review: merged balance writes,…
QuantumExplorer Oct 28, 2026
080910f
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 29, 2026
e231e81
style(drive): sort the summable test imports
QuantumExplorer Oct 29, 2026
82a9136
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 29, 2026
929acaf
refactor(drive): copy only the frozen listings' ids in the destroy co…
QuantumExplorer Oct 29, 2026
61484c0
fix(drive): refuse a listing-bearing destroy at conversion generation 0
QuantumExplorer Oct 29, 2026
7e3ae81
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 30, 2026
cded6b8
fix(drive): build the read consume operations against their batch
QuantumExplorer Oct 30, 2026
036f9da
Merge claude/token-market-history into claude/token-market-frozen-escrow
QuantumExplorer Oct 30, 2026
a6ade36
Merge claude/token-market-history into claude/token-market-frozen-escrow
QuantumExplorer Oct 30, 2026
0d05bbf
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 30, 2026
91bae86
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 30, 2026
debbeea
Merge claude/token-market-history (decision proposals) into claude/to…
QuantumExplorer Oct 31, 2026
07a70dc
Merge branch 'claude/token-market-history' into claude/token-market-f…
QuantumExplorer Oct 31, 2026
fe2d450
Merge claude/token-market-history (private document types) into claud…
QuantumExplorer Oct 31, 2026
fee5083
Merge claude/token-market-history (EstimatedLayers, kind-aware pick) …
QuantumExplorer Oct 31, 2026
ca2be73
Merge claude/token-market-history (private document stores) into clau…
QuantumExplorer Nov 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions book/src/data-model/token-marketplace.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,22 @@ buyer pays the storage of the `bid` and gets it back when the offer closes. A `T
proven by its `bid` document, whose terms, untouched `remaining` and escrow (what the offer is
worth at its decimals) the client checks, and a `TokenFillBid` by the seller's token balance.

## Frozen accounts

A frozen account's open listings cannot be filled, and the tokens they hold sit in escrow, out of
the frozen balance. From protocol version 15 a `TokenDestroyFrozenFunds` destroys them with the
balance: it reads the frozen identity's open listings of the token, oldest first, at most
`max_frozen_listings_destroyed_per_transition` (16), destroys what they hold in escrow, deletes
their `ask` documents and records the whole amount destroyed in its `destroyFrozenFunds` history
document. A frozen identity with more listings needs one more destroy per 16. Its offers hold
credits, which are not the token's to destroy, and stay; it can still withdraw them.

```text
Frozen identity: balance 5,000, listings of 3,000 and 2,000
Before (protocol version 14 rules): the destroy burns 5,000; the 5,000 in escrow stays
From protocol version 15: the destroy burns all 10,000 and deletes both listings
```

## History

A token that keeps transfer history (`keepsHistory.keepsTransferHistory`, the default) also
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
//! batch state transition carries at most one document transition, and two
//! transitions in the same block become two separate GroveDB batches
//! (`execute_event` calls `apply_drive_operations` once per state transition).
//! The cases that expose the defect are therefore `#[ignore]`d rather than
//! deleted or weakened: they are the specification of one hazard raising that
//! cap would have to fix — not of the whole shape, since a real multi-transition
//! batch would also fold several writes to the same identity-contract nonce key
//! into one batch. The cases that run pin what the system relies on today — the
//! phantom is characterized as it actually is, the inverse shape fails loud,
//! and the sequential controls drain correctly.
//! From protocol version 15, `apply_drive_operations` 2 builds every operation
//! of a batch against the batch's operations built before it, so two deletes
//! that jointly empty a group see each other and the group is removed. The cases
//! that specify the drain run at the latest version; the phantom generation 1
//! leaves (protocol version 14 and earlier) stays characterized as it actually
//! is, the inverse shape fails loud, and the sequential controls drain
//! correctly. They specify one hazard raising the cap would have had to fix,
//! not the whole shape: a real multi-transition batch would also fold several
//! writes to the same identity-contract nonce key into one batch.
//!
//! The cap is not the only guard of its kind. `update_contract_keywords` builds
//! its own multi-document blind batch over one shared index group and is kept
Expand Down Expand Up @@ -214,13 +216,22 @@ fn update_op<'a>(
}

fn apply_batch(drive: &Drive, operations: Vec<DriveOperation>) {
apply_batch_at(drive, operations, platform_version());
}

/// Applies `operations` as one batch the way `platform_version` does.
fn apply_batch_at(
drive: &Drive,
operations: Vec<DriveOperation>,
platform_version: &PlatformVersion,
) {
drive
.apply_drive_operations(
operations,
true,
&BlockInfo::default(),
None,
platform_version(),
platform_version,
None,
)
.expect("the batch must apply");
Expand Down Expand Up @@ -570,21 +581,32 @@ fn assert_baseline(drive: &Drive, contract: &DataContract, axis: Axis) {
/// storage, grovedb's integrity sweep reports nothing, and the proved page
/// both equals the unproved one and reconstructs the live root hash.
///
/// It goes red the day the defect is fixed, or the day grovedb starts
/// detecting it. That is the intended signal, not a regression: delete this
/// test then, and un-ignore the cases below.
/// It applies the batch the way protocol version 14 does: generation 1 of
/// `apply_drive_operations`, which every released version runs. Generation 2
/// (protocol version 15) builds each operation against the batch's earlier
/// ones and removes the group; the cases below specify that.
#[test]
fn a_batched_drain_leaves_a_phantom_group_that_verifies_and_proves() {
let generation_1 = PlatformVersion::get(14).expect("expected protocol version 14");
assert_eq!(
generation_1
.drive
.methods
.batch_operations
.apply_drive_operations,
1
);
for axis in AXES {
let (drive, contract, docs) = setup_g_two_h_one(axis);
assert_baseline(&drive, &contract, axis);

apply_batch(
apply_batch_at(
&drive,
vec![
delete_op(&contract, axis.doctype, docs[1].id()),
delete_op(&contract, axis.doctype, docs[2].id()),
],
generation_1,
);

let path = indexed_property_name_tree_path(&contract, axis.doctype);
Expand Down Expand Up @@ -651,18 +673,18 @@ fn a_batched_drain_leaves_a_phantom_group_that_verifies_and_proves() {
}
}

/// **Known latent defect.** Both of `G`'s documents are deleted in one
/// **A latent defect before protocol version 15.** Both of `G`'s documents are deleted in one
/// `apply_drive_operations` call. Neither delete can see the other, so neither
/// removes `G`'s group tree: `G` stays in the ranked secondary with a zero
/// aggregate and no documents behind it, on all three axes, with
/// `verify_grovedb` clean and the proof reconstructing the live root hash.
///
/// Unreachable today because `max_transitions_in_documents_batch` is 1, which
/// keeps any two document operations out of a shared GroveDB batch. Raising
/// that cap arms this; see the documentation on
/// `SystemLimits::max_transitions_in_documents_batch`.
/// From protocol version 15 the second delete is built against the first and the
/// group is removed; this case runs at the latest version. Before 15 the defect
/// stands (see `a_batched_drain_leaves_a_phantom_group_that_verifies_and_proves`)
/// and is unreachable because `max_transitions_in_documents_batch` is 1; see the
/// documentation on `SystemLimits::max_transitions_in_documents_batch`.
#[test]
#[ignore = "documents a latent defect in shared write-path machinery that is unreachable while max_transitions_in_documents_batch is 1; un-ignore before raising that cap"]
fn deleting_a_groups_last_two_documents_in_one_batch_removes_the_group() {
for axis in AXES {
let (drive, contract, docs) = setup_g_two_h_one(axis);
Expand All @@ -687,14 +709,13 @@ fn deleting_a_groups_last_two_documents_in_one_batch_removes_the_group() {
}
}

/// **Known latent defect**, same as
/// **A latent defect before protocol version 15**, same as
/// [`deleting_a_groups_last_two_documents_in_one_batch_removes_the_group`],
/// with the two deletes in the opposite order — the group's emptiness is
/// mis-observed either way, so the defect is not an artefact of one ordering.
///
/// Unreachable while `max_transitions_in_documents_batch` is 1.
/// Removed from protocol version 15; this case runs at the latest version.
#[test]
#[ignore = "documents a latent defect in shared write-path machinery that is unreachable while max_transitions_in_documents_batch is 1; un-ignore before raising that cap"]
fn reverse_ordered_batched_deletes_remove_the_group_too() {
for axis in AXES {
let (drive, contract, docs) = setup_g_two_h_one(axis);
Expand All @@ -718,14 +739,13 @@ fn reverse_ordered_batched_deletes_remove_the_group_too() {
}
}

/// **Known latent defect**, same as
/// **A latent defect before protocol version 15**, same as
/// [`deleting_a_groups_last_two_documents_in_one_batch_removes_the_group`], on
/// a Drive configured the way a shipped node is — so it cannot be dismissed as
/// an artefact of the test harness's `batching_consistency_verification: true`.
///
/// Unreachable while `max_transitions_in_documents_batch` is 1.
/// Removed from protocol version 15; this case runs at the latest version.
#[test]
#[ignore = "documents a latent defect in shared write-path machinery that is unreachable while max_transitions_in_documents_batch is 1; un-ignore before raising that cap"]
fn batched_deletes_remove_the_group_under_the_shipped_batching_config() {
for axis in AXES {
let (drive, contract) = setup_restaurants_with_shipped_batching_config();
Expand Down Expand Up @@ -754,7 +774,7 @@ fn batched_deletes_remove_the_group_under_the_shipped_batching_config() {
}
}

/// **Known latent defect.** The batched drain and the identical drain applied
/// **A latent defect before protocol version 15.** The batched drain and the identical drain applied
/// one delete at a time must land the same logical index; they do not.
///
/// The comparison is over entries and primary aggregates rather than the root
Expand All @@ -764,9 +784,8 @@ fn batched_deletes_remove_the_group_under_the_shipped_batching_config() {
/// deterministic for nodes replaying identical history, so it is not itself a
/// consensus hazard — but it makes the app hash the wrong instrument here.
///
/// Unreachable while `max_transitions_in_documents_batch` is 1.
/// Removed from protocol version 15; this case runs at the latest version.
#[test]
#[ignore = "documents a latent defect in shared write-path machinery that is unreachable while max_transitions_in_documents_batch is 1; un-ignore before raising that cap"]
fn batched_and_sequential_drains_agree_on_the_logical_state() {
for axis in AXES {
let (batched, batched_contract, batched_docs) = setup_g_two_h_one(axis);
Expand Down Expand Up @@ -841,16 +860,15 @@ fn update_document_singly(drive: &Drive, contract: &DataContract, axis: Axis, do
.expect("the single-document update must succeed");
}

/// **Known latent defect**, reached through `UpdateDocument` rather than
/// **A latent defect before protocol version 15**, reached through `UpdateDocument` rather than
/// `DeleteDocument`: one batch moves both of `G`'s documents into `H`. `H`
/// correctly gains all three contributions, but `G` survives as a zero-valued
/// phantom, so the defect is not specific to deletes — any operation that
/// empties a group while a sibling operation in the same batch has not been
/// observed reproduces it.
///
/// Unreachable while `max_transitions_in_documents_batch` is 1.
/// Removed from protocol version 15; this case runs at the latest version.
#[test]
#[ignore = "documents a latent defect in shared write-path machinery that is unreachable while max_transitions_in_documents_batch is 1; un-ignore before raising that cap"]
fn moving_a_groups_last_two_documents_to_another_group_in_one_batch_drains_it() {
for axis in AXES {
let (drive, contract, docs) = setup_g_two_h_one(axis);
Expand Down
142 changes: 142 additions & 0 deletions packages/rs-drive/src/drive/tokens/order_escrow/fetch_order.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
use crate::drive::contract::DataContractFetchInfo;
use crate::drive::document::query::QueryDocumentsOutcomeV0Methods;
use crate::drive::Drive;
use crate::error::drive::DriveError;
use crate::error::Error;
use crate::query::ordering::OrderClause;
use crate::query::{DriveDocumentQuery, InternalClauses, WhereClause, WhereOperator};
use dpp::block::epoch::Epoch;
use dpp::data_contract::accessors::v0::DataContractV0Getters;
use dpp::data_contract::DataContract;
use dpp::document::Document;
use dpp::identifier::Identifier;
use dpp::platform_value::Value;
use dpp::tokens::token_order::TokenOrder;
use dpp::tokens::token_order_side::TokenOrderSide;
use dpp::version::PlatformVersion;
use grovedb::TransactionArg;
use grovedb_costs::OperationCost;
use indexmap::IndexMap;
use std::collections::BTreeMap;
use std::sync::Arc;

impl Drive {
Expand Down Expand Up @@ -82,4 +87,141 @@ impl Drive {
let cost = outcome.cost();
Ok((outcome.documents_owned().into_iter().next(), cost))
}

/// The open listings of `owner_id` for `token_id` that a `TokenDestroyFrozenFunds` destroys
/// with the frozen balance: the oldest first, at most
/// `max_frozen_listings_destroyed_per_transition`, read through the `ask` type's `byOwner`
/// index, with the processing cost of the read billed at `epoch`. None where
/// `fetch_frozen_listings` is `None`, which reads nothing: there the frozen balance alone is
/// destroyed, as before the marketplace.
pub fn fetch_frozen_token_listings(
&self,
token_id: Identifier,
owner_id: Identifier,
epoch: &Epoch,
transaction: TransactionArg,
platform_version: &PlatformVersion,
) -> Result<(Vec<TokenOrder>, u64), Error> {
match platform_version
.drive
.methods
.token
.order_escrow
.fetch_frozen_listings
{
None => Ok((vec![], 0)),
Some(0) => self.fetch_frozen_token_listings_v0(
token_id,
owner_id,
epoch,
transaction,
platform_version,
),
Some(version) => Err(Error::Drive(DriveError::UnknownVersionMismatch {
method: "fetch_frozen_token_listings".to_string(),
known_versions: vec![0],
received: version,
})),
}
}

fn fetch_frozen_token_listings_v0(
Comment thread
QuantumExplorer marked this conversation as resolved.
Resolved
&self,
token_id: Identifier,
owner_id: Identifier,
epoch: &Epoch,
transaction: TransactionArg,
platform_version: &PlatformVersion,
) -> Result<(Vec<TokenOrder>, u64), Error> {
let token_market_contract = self
.cache
.system_data_contracts
.load_token_market(platform_version)?;
let document_type = token_market_contract
.document_type_for_name(TokenOrderSide::Ask.document_type_name())?;
let equal = |field: &str, value: Identifier| {
(
field.to_string(),
WhereClause {
field: field.to_string(),
operator: WhereOperator::Equal,
value: Value::Identifier(value.to_buffer()),
},
)
};
let query = DriveDocumentQuery {
contract: &token_market_contract,
document_type,
internal_clauses: InternalClauses {
primary_key_in_clause: None,
primary_key_equal_clause: None,
in_clauses: Vec::new(),
range_clause: None,
equal_clauses: BTreeMap::from([
equal("$ownerId", owner_id),
equal("tokenId", token_id),
]),
},
offset: None,
limit: Some(
platform_version
.system_limits
.max_frozen_listings_destroyed_per_transition,
),
order_by: IndexMap::from([(
"$createdAt".to_string(),
OrderClause {
field: "$createdAt".to_string(),
ascending: true,
},
)]),
start_at: None,
start_at_included: false,
block_time_ms: None,
resolved_time_ranges: vec![],
sub_queries: vec![],
};
let outcome = self.query_documents(
query,
Some(epoch),
false,
transaction,
Some(platform_version.protocol_version),
)?;
let cost = outcome.cost();
let listings = outcome
.documents_owned()
.iter()
.map(|document| TokenOrder::from_document(document, TokenOrderSide::Ask))
.collect::<Result<Vec<_>, _>>()?;
Ok((listings, cost))
}
}

#[cfg(test)]
mod tests {
use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure;
use dpp::block::epoch::Epoch;
use dpp::identifier::Identifier;
use dpp::version::PlatformVersion;

/// Before protocol version 15 a destroy of frozen funds reads no listings: on a chain with no
/// marketplace state (no escrow trees, no token market contract) the read returns none and
/// costs nothing.
#[test]
fn should_read_no_frozen_listings_before_protocol_version_15() {
let platform_version = PlatformVersion::get(14).expect("expected protocol version 14");
let drive = setup_drive_with_initial_state_structure(Some(platform_version));
let (listings, cost) = drive
.fetch_frozen_token_listings(
Identifier::from([5; 32]),
Identifier::from([6; 32]),
&Epoch::new(0).expect("expected an epoch"),
None,
platform_version,
)
.expect("expected the read to be skipped");
assert!(listings.is_empty());
assert_eq!(cost, 0);
}
}
Loading
Loading