Skip to content

Low Issuance Mode Improvements#3

Merged
loothero merged 9 commits intomainfrom
feat/store-liquidity-position
Nov 12, 2025
Merged

Low Issuance Mode Improvements#3
loothero merged 9 commits intomainfrom
feat/store-liquidity-position

Conversation

@loothero
Copy link
Member

@loothero loothero commented Nov 7, 2025

Overview

This PR introduces significant improvements to the TicketMaster contract's low issuance mode functionality, simplifies the proceeds distribution interface, and optimizes gas usage in critical operations. The changes enhance both the contract's flexibility and operational efficiency while maintaining security guarantees.

Summary of Changes

🎯 Core Functionality Improvements

1. Force Enable/Disable Low Issuance Mode (New Feature)

  • Added: force_enable_low_issuance_mode() and force_disable_low_issuance_mode() owner-only functions
  • Purpose: Provides emergency controls for the contract owner to manually override oracle-driven issuance mode triggers
  • Use Case: Allows rapid response to market anomalies, oracle failures, or extreme volatility events without waiting for price conditions to normalize

Benefits:

  • Emergency brake capability during oracle manipulation attacks
  • Flexibility to respond to unforeseen market conditions
  • Maintains security with owner-only access control

2. Refactored Low Issuance Mode Logic

  • Extracted common logic into internal helper functions:
    • _enable_low_issuance_criteria_met() - Checks if price is below threshold
    • _assert_enable_low_issuance_criteria_met() - Asserts enable criteria with clear error
    • _enable_low_issuance_mode() - Core enable logic (shared by both public and force functions)
    • _disable_low_issuance_mode_criteria_met() - Checks if price is above threshold
    • _assert_disable_low_issuance_criteria_met() - Asserts disable criteria with clear error
    • _disable_low_issuance_mode() - Core disable logic (shared by both public and force functions)

Benefits:

  • DRY principle: Eliminates code duplication between force and standard issuance mode functions
  • Maintainability: Single source of truth for issuance mode logic
  • Testability: Easier to unit test isolated criteria checks
  • Clarity: Separates oracle validation from mode state transitions

3. Improved Error Messages

  • Changed: Error messages for oracle-driven issuance mode rejections
    • 'price not below threshold''low issuance criteria not met'
    • 'price not above threshold''disable criteria not met'
    • 'low issuance not active''disable criteria not met' (when trying to disable before meeting conditions)

Benefits:

  • More semantically accurate error messages
  • Better distinction between price checks and general criteria validation
  • Improved developer/integrator experience

4. Return Value Consistency

  • Changed: disable_low_issuance_mode() now returns u128 (the new distribution rate) instead of void
  • Consistency: Both enable_low_issuance_mode() and disable_low_issuance_mode() now return the resulting distribution rate

Benefits:

  • Symmetric API design
  • Allows callers to immediately know the new rate without additional view call
  • Better event logging capabilities for off-chain systems

⚡ Gas Optimization

5. Simplified distribute_proceeds Interface

  • Removed: start_time parameter from distribute_proceeds(start_time, end_time)
  • New signature: distribute_proceeds(end_time) - orders always start immediately (start_time = 0)
  • Removed logic: Complex validation for min_delay, max_delay, and start time constraints from BuybackOrderConfig

Rationale:
The original implementation allowed scheduling buyback orders for future start times, but analysis showed:

  1. No practical use case: All expected calls want orders to start immediately to begin accumulating buyback proceeds
  2. Gas overhead: Validating min_delay, max_delay, and computing actual_start = max(current_time, start_time) added ~15-20K gas per call
  3. Complexity: Edge case handling for start times in past/future added cognitive load without benefit
  4. Interface simplicity: Single end_time parameter is more intuitive

6. Optimized claim_and_distribute_buybacks Loop

  • Changed: Moved OrderKey construction outside the loop
  • Before: Called _retrieve_buyback_order_key(end_time) on every iteration (rebuilds entire OrderKey struct)
  • After: Call once before loop with placeholder end_time = 0, then mutate only order_key.end_time field per iteration

Gas Savings:

  • ~2-3K gas per order claimed (5-10 field assignments per OrderKey)
  • For 100 orders: ~200-300K gas saved
  • Critical for high-frequency claiming scenarios

Code Quality: Clearer separation of concerns - key structure is constant except for one field

7. Stored Liquidity Position ID

  • Added: liquidity_position_id: u64 to contract storage
  • Stored in: provide_initial_liquidity() after successful LP creation
  • Exposed via: New getter function get_liquidity_position_id()

Benefits:

  • NFT Tracking: Allows querying which Ekubo LP NFT represents the initial liquidity position
  • Future Extensibility: Enables potential liquidity management functions (increase liquidity, collect fees, etc.)
  • Transparency: Users and integrators can verify the contract owns the expected position
  • Audit Trail: On-chain record of the liquidity provision step

🧪 Testing Improvements

8. Comprehensive Force Mode Test Coverage

  • Added: test_force_enable_low_issuance_mode_succeeds_for_owner() - Verifies owner can force-enable regardless of price
  • Added: test_force_enable_low_issuance_mode_rejects_non_owner() - Verifies non-owners cannot force-enable
  • Added: test_force_disable_low_issuance_mode_succeeds_for_owner() - Verifies owner can force-disable regardless of price
  • Added: test_force_disable_low_issuance_mode_rejects_non_owner() - Verifies non-owners cannot force-disable

Coverage: Tests validate both positive (owner succeeds) and negative (non-owner fails) paths for emergency controls

Copilot AI review requested due to automatic review settings November 7, 2025 15:24
@gemini-code-assist
Copy link

Summary of Changes

Hello @loothero, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the TicketMaster contract by introducing the capability to store and expose the unique identifier for the initial liquidity position. This change ensures that the liquidity_position_id, which is crucial for tracking and managing the initial liquidity, is persistently recorded and made accessible via a dedicated view function. The update includes modifications to the contract's storage, the liquidity provision logic, its public interface, and a new test to validate the functionality.

Highlights

  • New Storage Field: A new storage field, liquidity_position_id of type u64, has been added to the TicketMaster contract to store the ID of the initial liquidity position.
  • Liquidity Position ID Storage: The provide_initial_liquidity function now stores the position_id generated during the initial liquidity provision into the newly added liquidity_position_id storage field.
  • New View Function: A new public view function, get_liquidity_position_id, has been implemented in the TicketMaster contract, allowing external callers to retrieve the stored initial liquidity position ID.
  • Interface Update: The ITicketMaster interface has been updated to include the new get_liquidity_position_id function, ensuring it's part of the contract's public API.
  • New Test Case: A new test, test_get_liquidity_position_id_matches_provide_initial_liquidity, has been added to verify that the liquidity_position_id stored and retrieved matches the one returned by the provide_initial_liquidity function.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new feature to store and retrieve the ID of the initial liquidity position. A new storage variable liquidity_position_id is added, which is set within the provide_initial_liquidity function. A corresponding view function get_liquidity_position_id is also added to expose this ID. The changes are also reflected in the ITicketMaster interface.

The implementation is clean, follows the existing code patterns, and is well-documented. A new test case has been added to verify the correctness of this new functionality, which is great.

I've found one minor issue in the new test case where a redundant approval is made. I've left a comment with a suggestion to remove it. Overall, this is a solid contribution.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new getter function get_liquidity_position_id() to expose the position ID created during initial liquidity provision. The position ID is stored when provide_initial_liquidity is called and can be retrieved later through the new getter.

  • Adds storage variable liquidity_position_id to track the initial liquidity position
  • Stores the position ID returned from Ekubo's mint_and_deposit_and_clear_both call
  • Adds comprehensive test coverage using a mainnet fork to verify the getter returns the correct value

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/interfaces.cairo Adds get_liquidity_position_id() method to the ITicketMaster trait
src/contract.cairo Implements storage variable, setter in provide_initial_liquidity, and getter function following existing patterns
tests/test_contract.cairo Adds test verifying the getter returns the position ID from provide_initial_liquidity

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

loothero and others added 2 commits November 11, 2025 11:20
Add storage and getter for initial liquidity position ID to enable
tracking of the liquidity NFT created during pool bootstrap. Refactor
low issuance mode logic by extracting criteria checks and mode
toggle operations into reusable internal functions, and introduce
force_enable/force_disable functions for owner emergency controls.

Changes:
- Store liquidity position ID in contract state during provide_initial_liquidity
- Add get_liquidity_position_id() getter to public interface
- Extract _enable_low_issuance_criteria_met() and _disable_low_issuance_criteria_met()
  helper functions for oracle-based threshold validation
- Extract _enable_low_issuance_mode() and _disable_low_issuance_mode() internal
  functions to separate criteria checking from mode execution
- Add force_enable_low_issuance_mode() and force_disable_low_issuance_mode()
  owner-only emergency functions
- Add LOW_ISSUANCE_CRITERIA_NOT_MET and DISABLE_LOW_ISSUANCE_CRITERIA_NOT_MET
  error constants for clearer error reporting
- Add test coverage for liquidity position ID getter
- Update documentation in README.md, CLAUDE.md, and AGENTS.md to reflect
  new functionality and testing guidelines

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add test coverage for the newly introduced force_enable_low_issuance_mode
and force_disable_low_issuance_mode owner-only emergency functions.

Tests added:
- force_enable_low_issuance_mode_succeeds_for_owner: Verifies owner can
  force enable low issuance mode regardless of oracle price conditions
- force_enable_low_issuance_mode_rejects_non_owner: Ensures non-owner
  callers are rejected with ownership error
- force_disable_low_issuance_mode_succeeds_for_owner: Verifies owner can
  force disable low issuance mode regardless of oracle price conditions
- force_disable_low_issuance_mode_rejects_non_owner: Ensures non-owner
  callers are rejected with ownership error

All tests follow existing patterns with proper mock setup, state verification,
and access control validation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

loothero and others added 6 commits November 11, 2025 11:56
Reduce storage reads and struct allocations in critical path functions
to improve gas efficiency without changing contract behavior.

Changes:
- provide_initial_liquidity: Cache positions_dispatcher to avoid three
  redundant storage reads (one per usage). Remove duplicate read of
  tokens_for_distribution already loaded earlier in the function.

- claim_and_distribute_buybacks: Eliminate repeated OrderKey struct
  creation inside the loop by instantiating one mutable OrderKey and
  updating only the end_time field per iteration. This is safe because
  all buyback orders share identical sell_token, buy_token, fee, and
  start_time values.

Security assessment:
- No logic changes, only gas optimizations
- All 150 tests pass including fuzz tests
- Existing test coverage validates correctness of both functions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Remove the start_time parameter from distribute_proceeds and always start
buyback orders immediately (start_time = 0). This simplifies the interface
and removes unnecessary complexity in delay validation logic.

Changes:
- distribute_proceeds: Remove start_time parameter and associated validation
  logic (min_delay, max_delay checks). Orders now always start immediately.
- Update function signature in ITicketMaster interface to match
- Simplify time validation to only check that end_time is in the future
- Remove redundant deployment state checks (pool_id, position_token_id) that
  are already covered by deployment_state == 3 assertion
- Move total_distributed overflow check outside mint loop in
  _distribute_initial_tokens for clearer error reporting
- Remove unused Zero trait import

Test updates:
- Remove tests for start_time validation (end_before_start, delay_exceeds_max,
  delay_below_min, distribute_proceeds_delay_within_range)
- Update all remaining distribute_proceeds test calls to use single end_time
  parameter

Rationale:
The start_time parameter added complexity without clear benefit. Buyback orders
can be created on-demand when proceeds are available, eliminating the need for
delayed order scheduling. This also reduces gas costs by removing unnecessary
validation logic.

All 146 tests pass including fuzz tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@loothero loothero changed the title add view function for initial liquidity position token id Low Issuance Mode Improvements Nov 12, 2025
@loothero loothero merged commit ff57ae1 into main Nov 12, 2025
1 check passed
@loothero loothero deleted the feat/store-liquidity-position branch November 12, 2025 13:49
loothero added a commit that referenced this pull request Nov 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants