93: Add a minimum EVE burn amount and retained reserve to the Evelyn IOU burner
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
## Purpose
|
||||
|
||||
Defines the Evelyn-specific service that safely converts prioritized wallet assets into Evelyn IOU, burns the complete visible EVE balance, and announces only finalized burns without automatically repeating transactions whose outcomes may be unknown.
|
||||
Defines the Evelyn-specific service that safely converts prioritized wallet assets into Evelyn IOU, accumulates EVE for burns above a configured minimum while retaining an EVE reserve, and announces only finalized burns without automatically repeating transactions whose outcomes may be unknown.
|
||||
## Requirements
|
||||
### Requirement: Evelyn-specific public service boundary
|
||||
The system SHALL expose an empty lifecycle-free `EvelynIOUBurnerService` under `com.fanitas.evelyn.service.burner` as the typed domain service and Registry view until external domain operations exist, and SHALL keep its reference implementation under `com.fanitas.evelyn.service.burner.impl.ref`. The same reference implementation object SHALL implement both `EvelynIOUBurnerService` and `NenjimProcess`; the Hub SHALL start it only through its `NenjimProcess` view. Neither the service interface nor the implementation SHALL expose a general stop, restart, worker-control, or other lifecycle operation. The service SHALL remain specific to Evelyn IOU and SHALL NOT introduce a generic token-burner abstraction, burner-specific input interfaces, records, or class hierarchies.
|
||||
@@ -161,40 +161,56 @@ A structured definitive on-chain swap failure SHALL be logged without suspending
|
||||
- **THEN** the burner performs no additional confirmation wait and reloads the wallet instead of deriving its burn amount only from the returned output amount
|
||||
|
||||
### Requirement: Complete visible EVE balance is eligible
|
||||
After the optional swap attempt, the service SHALL detect the fixed EVE mint's supported token program internally and reload the wallet's complete available EVE balance. A missing EVE mint account, unsupported program, absent wallet token account, zero balance, or negative/invalid balance SHALL cause no burn or notification in that iteration. Every positive complete balance SHALL be eligible without a minimum threshold, including EVE deposited before the iteration or visible after a failed or absent swap.
|
||||
After the optional swap attempt, the service SHALL detect the fixed EVE mint's supported token program internally and reload the wallet's complete available EVE balance. A missing EVE mint account, unsupported program, absent wallet token account, zero balance, or negative/invalid balance SHALL cause no burn or notification in that iteration. The service SHALL subtract its configured EVE reserve, clamp negative available amounts to zero and round down to validated EVE mint precision using the detected token program. It SHALL submit a new burn only when the actual rounded amount is positive and at least the configured minimum burn amount; equality qualifies. It SHALL burn the entire eligible amount above reserve, without a maximum or fixed batch size, including EVE deposited before the iteration or visible after a failed or absent swap. Below threshold or with unusable mint precision it SHALL retain the EVE and send no burn notification. This threshold SHALL NOT suppress independent buybacks.
|
||||
|
||||
#### Scenario: Existing EVE without buyback
|
||||
- **WHEN** no swap is performed but the wallet contains a positive EVE balance
|
||||
- **THEN** the service evaluates that complete balance for burning
|
||||
- **THEN** the service evaluates that complete balance under the EVE reserve, precision and burn-minimum rules
|
||||
|
||||
#### Scenario: EVE account is absent or empty
|
||||
- **WHEN** the wallet has no EVE token account or its complete balance is zero
|
||||
- **THEN** the iteration submits no burn and sends no notification
|
||||
|
||||
#### Scenario: Issue example threshold and reserve
|
||||
- **WHEN** minimum is 1 EVE and reserve is 0.1 EVE
|
||||
- **THEN** balances 0, 0.05, 0.1, 1.05 and 1.099999 produce no burn; balance 1.1 burns 1 and balance 1.35 burns 1.25, retaining 0.1 after success
|
||||
|
||||
#### Scenario: Accumulation across small buybacks
|
||||
- **WHEN** individually eligible small buybacks accumulate EVE over multiple iterations
|
||||
- **THEN** each below-threshold iteration still permits its buyback and sends no burn message; the first qualifying iteration burns all eligible EVE and subsequent accumulation starts with the retained reserve
|
||||
|
||||
#### Scenario: Exact configuration exceeds mint precision
|
||||
- **WHEN** six-decimal mint precision rounds available 1.0000009 to 1.000000 while minimum is 1.0000001
|
||||
- **THEN** no burn occurs; no amount is rounded upward and the reserve is never consumed to reach the minimum
|
||||
|
||||
### Requirement: Fresh EVE value is required before submission
|
||||
Immediately before a new burn, the service SHALL obtain the latest canonical EVE/USDT observation and require a positive price, non-null observation timestamp, and age no greater than `maximumPriceAge` milliseconds. USDT SHALL be treated as USD for notification value, calculated as the complete EVE amount multiplied by that fresh price. If the pair is unsupported or the observation is missing, invalid, or stale, the service SHALL warn, postpone the burn, send no notification, and retry only by re-evaluating state in a later scheduled iteration.
|
||||
Immediately before a new burn, the service SHALL obtain the latest canonical EVE/USDT observation and require a positive price, non-null observation timestamp, and age no greater than `maximumPriceAge` milliseconds. USDT SHALL be treated as USD for notification value, calculated as the actual rounded eligible EVE amount above reserve multiplied by that fresh price. If the pair is unsupported or the observation is missing, invalid, or stale, the service SHALL warn, postpone the burn, send no notification, and retry only by re-evaluating state in a later scheduled iteration.
|
||||
|
||||
#### Scenario: Fresh EVE price exists
|
||||
- **WHEN** a complete positive EVE balance and sufficiently fresh positive EVE/USDT observation are available
|
||||
- **THEN** the service calculates the notification's USD value from that complete balance before submitting the burn
|
||||
- **WHEN** a positive rounded EVE amount at or above the burn minimum and sufficiently fresh positive EVE/USDT observation are available
|
||||
- **THEN** the service calculates the notification's USD value from that actual eligible burn amount, excluding reserve before submitting the burn
|
||||
|
||||
#### Scenario: EVE price is stale
|
||||
- **WHEN** EVE is present but its observation is older than the configured age limit
|
||||
- **THEN** the service leaves EVE unburned and sends no notification in that iteration
|
||||
|
||||
### Requirement: Single complete-balance burn submission and pending state
|
||||
For a positive EVE balance with a usable price, the service SHALL call the wallet burn operation exactly once with the fixed EVE mint and complete observed balance. It SHALL NOT automatically retry, rebuild, re-sign, or resubmit within or across iterations. Immediately after a non-blank signature is returned, it SHALL retain process-local pending data containing that signature, submitted EVE amount, and its calculated notification value or complete notification text before awaiting the signature.
|
||||
For a positive rounded EVE amount at or above the minimum with a usable price, the service SHALL call the wallet burn operation exactly once with the fixed EVE mint and entire eligible rounded amount above reserve. It SHALL NOT automatically retry, rebuild, re-sign, or resubmit within or across iterations. Immediately after a non-blank signature is returned, it SHALL retain process-local pending data containing that signature, actual submitted EVE amount excluding reserve, and its calculated notification value or complete notification text before awaiting the signature.
|
||||
|
||||
If burn submission fails without a usable signature and its outcome may be unknown, including an I/O or interruption path whose contract permits post-submission uncertainty, the service SHALL conservatively suspend further burn submissions for the current process. It MAY continue ordinary iteration work that does not submit another burn. Recovery SHALL require external reconciliation followed by a complete process restart, not a Burner service stop/start operation.
|
||||
|
||||
#### Scenario: Burn returns a signature
|
||||
- **WHEN** the wallet submits the complete observed EVE balance and returns a non-blank signature
|
||||
- **WHEN** the wallet submits the entire eligible rounded amount above reserve and returns a non-blank signature
|
||||
- **THEN** pending state is retained before the service begins finalization waiting
|
||||
|
||||
#### Scenario: Submission outcome may be unknown without a signature
|
||||
- **WHEN** burn submission fails or is interrupted without providing a usable signature and may already have reached Solana
|
||||
- **THEN** the service performs no further burn submission until external reconciliation and a complete process restart
|
||||
|
||||
#### Scenario: Pending burn bypasses new threshold evaluation
|
||||
- **WHEN** a retained burn signature remains pending while balance is now below the minimum or at the reserve
|
||||
- **THEN** only the original signature is awaited, its original submitted amount/value are preserved and it is never re-evaluated, rebuilt or resubmitted
|
||||
|
||||
### Requirement: Finalized burn outcome governs completion
|
||||
Every known burn signature SHALL be awaited through the Solana blockchain at `FINALIZED` with exactly the configured finalization timeout. `SUCCEEDED` SHALL authorize notification; `FAILED` SHALL log the slot and complete on-chain failure details, clear pending state, and send no notification; `TIMED_OUT` and `IOException` SHALL keep the pending signature because its result remains unknown; and `InterruptedException` SHALL preserve interruption and pending state. None of these outcomes SHALL cause automatic transaction resubmission.
|
||||
|
||||
@@ -231,7 +247,7 @@ The EVE amount SHALL use plain decimal notation without unnecessary trailing zer
|
||||
- **THEN** the service logs a non-secret failure, clears completed state, and never retries either notification or burn
|
||||
|
||||
### Requirement: Exact token-capped amount and per-currency reserve
|
||||
The service SHALL select the lesser of positive `balance - minimumReserve` and the input UUID's maximum token amount, then round downward to mint precision. It SHALL skip non-positive results and actual rounded amounts below that UUID's minimum, continuing to later inputs in the same iteration without counting a swap attempt. Equality SHALL qualify. It SHALL never round upward, top up from reserves or exceed either existing bound. Input selection SHALL require no input/USDC Ticker observation. Minima and maxima SHALL constrain buyback inputs only; EVE burns SHALL remain uncapped and unaffected. Native SOL reserves SHALL use observed balance without estimating future fees.
|
||||
The service SHALL select the lesser of positive `balance - minimumReserve` and the input UUID's maximum token amount, then round downward to mint precision. It SHALL skip non-positive results and actual rounded amounts below that UUID's minimum, continuing to later inputs in the same iteration without counting a swap attempt. Equality SHALL qualify. It SHALL never round upward, top up from reserves or exceed either existing bound. Input selection SHALL require no input/USDC Ticker observation. Minima and maxima SHALL constrain buyback inputs only; EVE burns SHALL remain uncapped and governed independently by their own EVE minimum and reserve. Native SOL reserves SHALL use observed balance without estimating future fees.
|
||||
|
||||
#### Scenario: SyrupUSDC maximum is lower than spendable balance
|
||||
- **WHEN** SyrupUSDC balance is 0.5, its reserve is 0.095, its minimum is 0.045 and its maximum is 0.2
|
||||
@@ -275,14 +291,18 @@ The service SHALL select the lesser of positive `balance - minimumReserve` and t
|
||||
|
||||
#### Scenario: Input minima do not suppress direct EVE burn
|
||||
- **WHEN** every configured input is below its minimum but the wallet contains EVE with a usable EVE/USDT price
|
||||
- **THEN** the complete EVE balance is still evaluated and burned by the existing rules
|
||||
- **THEN** the complete EVE balance is still evaluated and its rounded eligible amount above the EVE reserve is burned if it meets the EVE burn minimum
|
||||
|
||||
### Requirement: Production burner accepts USDT and SyrupUSDC
|
||||
The production Hub SHALL configure USDT first with reserve 0.1, minimum input 0.05 and maximum input 0.25 USDT, and SyrupUSDC second with reserve 0.095, minimum input 0.045 and maximum input 0.2 SyrupUSDC. These SHALL be token-denominated limits without a USD-value guarantee. The existing burner wallet, Jupiter route selection, registration, hourly interval, slippage, EVE/USDT freshness, confirmation settings and burn recovery behavior SHALL be preserved without new Ticker sources or history storage.
|
||||
The production Hub SHALL configure USDT first with reserve 0.1, minimum input 0.05 and maximum input 0.25 USDT, and SyrupUSDC second with reserve 0.095, minimum input 0.045 and maximum input 0.2 SyrupUSDC. These SHALL be token-denominated limits without a USD-value guarantee. The production EVE burn minimum SHALL be 0.1 EVE and its retained reserve SHALL be 0.01 EVE, as selected by the owner on 2026-10-06, configured as MoneyAmount values using the canonical EVE UUID. The existing burner wallet, Jupiter route selection, registration, hourly interval, slippage, EVE/USDT freshness, confirmation settings and burn recovery behavior SHALL be preserved without new Ticker sources or history storage.
|
||||
|
||||
#### Scenario: Production inputs and settings
|
||||
- **WHEN** the Hub constructs the production burner
|
||||
- **THEN** it supplies the exact reserves, minima and maxima as MoneyAmount values in USDT-then-SyrupUSDC priority and retains the other existing production arguments
|
||||
- **THEN** it supplies the exact reserves, minima and maxima as MoneyAmount values in USDT-then-SyrupUSDC priority, supplies minimum burn 0.1 EVE/reserve 0.01 EVE and retains the other existing production arguments
|
||||
|
||||
#### Scenario: Production burn threshold
|
||||
- **WHEN** production EVE balance is below 0.11, exactly 0.11, or 0.135 with usable mint precision and fresh price
|
||||
- **THEN** below 0.11 produces no burn, 0.11 burns 0.1 and 0.135 burns 0.125; successful burns retain 0.01 EVE
|
||||
|
||||
### Requirement: Pending swaps reconcile before new input selection
|
||||
After pending-burn priority, a retained swap SHALL be checked read-only by its original signature at CONFIRMED or stronger in a bounded operation. Success, on-chain failure or demonstrated non-executed expiry SHALL clear it and permit newly read balances to drive at most one new swap. Unknown, absent without expiry proof or I/O outcomes SHALL remain pending without a new swap while allowing existing EVE burns. Interruption SHALL propagate with pending state intact.
|
||||
@@ -305,3 +325,14 @@ Swap diagnostics SHALL identify canonical input symbol/UUID, attempted amount, k
|
||||
#### Scenario: Unknown outcome is diagnosed
|
||||
- **WHEN** a swap outcome remains unknown
|
||||
- **THEN** diagnostics identify whether its original signature will be checked next iteration or manual investigation is required, without exposing secret or payload data
|
||||
|
||||
### Requirement: Independent EVE burn policy configuration
|
||||
The constructor SHALL accept minimumBurnAmount and eveReserve as EVE-denominated MoneyAmount values identified by canonical EVE UUID regardless of supplied display metadata. Both values, their amounts, currencies and UUIDs SHALL be non-null; minimum SHALL be strictly positive and reserve non-negative. Zero reserve SHALL be valid. Invalid burn configuration SHALL fail before worker startup without changing existing input validation.
|
||||
|
||||
#### Scenario: Invalid burn configuration
|
||||
- **WHEN** either value, amount, currency or UUID is null, a UUID is not EVE, the minimum is zero/negative, or the reserve is negative
|
||||
- **THEN** construction fails before creating a worker or transaction
|
||||
|
||||
#### Scenario: Stale EVE metadata and zero reserve
|
||||
- **WHEN** both values carry the EVE UUID with stale names/symbols and the reserve is zero
|
||||
- **THEN** construction succeeds and uses canonical EVE identity with the configured exact numeric amounts
|
||||
|
||||
Reference in New Issue
Block a user