Skip to content

feat: secondary market trade history, treasury management, and issuer verification contracts - #676

Merged
TS-mfon merged 3 commits into
StellarState:devfrom
Mawuli-tech:feat/secondary-trade-history-treasury-management-issuer-verification
Oct 26, 2026
Merged

TS-mfon merged 3 commits into
StellarState:devfrom
Mawuli-tech:feat/secondary-trade-history-treasury-management-issuer-verification

Conversation

@Mawuli-tech

Copy link
Copy Markdown
Contributor

Summary

Three new independent Soroban contracts, each implementing one assigned issue end to end with its own storage, errors, events, and test module, matching the workspace's existing accreditation-registry contract's modular structure.

closes #642
closes #644
closes #645

Changes

#642: contracts/secondary-trade-history, a new contract recording executed secondary market trade prices for invoice fractions. record_trade(invoice_id, price, amount, timestamp), get_price_history(invoice_id, limit) (newest first), get_last_price(invoice_id). Storage is pruned to the most recent 100 trades per invoice. record_trade is gated to a single authorized recorder address (set at initialize, changeable by the admin), since an unrestricted writer would let anyone inject fabricated prices into on-chain price discovery data. Confirmed this is genuinely new functionality by auditing the existing secondary-market and secondary-market-oracle contracts first: secondary-market has no trade-price recording at all, and secondary-market-oracle's existing get_price_history/record_listing_price tracks ask/listing prices (pre-sale), not executed trades, a different concept from what this issue asks for.

#644: contracts/treasury-management, a new contract consolidating protocol fee inflows. receive_fee(source, amount) attributes incoming fees per source; allocate(destination, amount, purpose) is admin-only and records a paginated allocation log; get_treasury_balance() returns the total plus a per-source breakdown (tracked via an explicit known-sources list, since Soroban storage has no key enumeration); get_allocation_history(offset, limit) paginates the log. Confirmed the existing fee-treasury contract is a different, epoch-based batch-distribution design (collect_fee/distribute/get_distribution by epoch) rather than this issue's ad hoc per-source/per-allocation model, so this is genuinely separate functionality, not a duplicate.

#645: contracts/invoice-issuer-verification, a new contract for admin-granted issuer verification badges. grant_verification(admin, issuer_wallet, tier, expiry_timestamp) with three tiers (BasicVerified, EnhancedVerified, Institutional); revoke_verification(admin, issuer_wallet) immediately removes the record so is_verified reflects the revocation in the same transaction; is_verified(issuer_wallet) returns verified/tier/expiry, with an expired verification read-time-evaluated as not verified rather than needing a separate expiry sweep. No existing contract in the workspace implements anything like this.

Test plan

Each contract has its own src/test.rs covering the happy path, every admin/unauthorized-caller boundary, every documented error condition, and the events each mutating function emits (decoded from their raw XDR topics/data, matching the existing accreditation-registry test's pattern).

Ran the real test suite for all three (cargo test -p <crate>, single-job to accommodate limited local memory): 15/15 passing for invoice-issuer-verification, 12/12 for secondary-trade-history, 13/13 for treasury-management. Also ran a combined cargo check across all three together with zero errors, and cargo fmt to match the workspace's formatting.

One real bug was found and fixed during this work, not just a passed-on assumption: VerificationStatus's initial design used Option<VerificationTier> for the no-verification case, which failed to compile under #[contracttype] (the trait bound ScVal: TryFrom<&Option<VerificationTier>> is not satisfied), since a custom #[repr(u32)] enum doesn't currently round-trip through Option in this soroban-sdk version. Restructured to a non-optional tier with a documented sentinel value for the unverified case instead, confirmed working by the full test suite.

@TS-mfon

TS-mfon commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

✅ PR Ready for Review

Due to a recent malware incident affecting our repositories, all PRs are required to pass automated security checks before being reviewed for merging.

This PR has passed all automated checks:

  • ✅ Security scan — no malicious code detected
  • ✅ No merge conflicts

A maintainer will review and merge this PR shortly.

@TS-mfon
TS-mfon merged commit b6be678 into StellarState:dev Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants