feat: reset bonding curve to canonical 18-decimal integer protocol#1922
feat: reset bonding curve to canonical 18-decimal integer protocol#1922umwelt wants to merge 5 commits intodevelopmentfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Resets the bonding-curve path toward a canonical 18-decimal, integer-only protocol by centralizing tokenomics constants in lib-types, introducing fixed-layout bonding-curve transaction/receipt types, and widening bonding-curve/pricing-related amounts to u128 across consensus + tests.
Changes:
- Added
lib-types::tokenomicsand re-exported canonical token supply/decimal constants (u128, 18-decimal scale). - Introduced canonical fixed-layout bonding-curve tx/receipt structs in
lib-typesand a canonical band table + helpers inlib-blockchain. - Migrated many bonding-curve/pricing structs and transaction fields from
u64→u128, removed/disabled the legacy bonding-curve mutation path, and updated tests/docs accordingly.
Reviewed changes
Copilot reviewed 40 out of 40 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| lib-types/src/tokenomics.rs | Adds canonical 18-decimal tokenomics constants (scale, decimals, max supply). |
| lib-types/src/lib.rs | Exposes new bonding_curve + tokenomics modules and re-exports protocol types/constants. |
| lib-types/src/economy.rs | Wires SOV total supply constant through lib-types::tokenomics and widens to u128. |
| lib-types/src/bonding_curve.rs | Adds fixed-layout bonding-curve tx/receipt structs with fixed bincode-size tests. |
| lib-client/src/bonding_curve_tx.rs | Widens client-side bonding-curve builder amounts to u128. |
| lib-blockchain/tests/unified_pricing_tests.rs | Updates pricing test inputs to u128. |
| lib-blockchain/tests/sov_unit_tests.rs | Switches tests to shared tokenomics constants and 18-decimal expectations. |
| lib-blockchain/tests/phase4_api_completeness_tests.rs | Updates expectations for seeded wallet allocations in fresh genesis. |
| lib-blockchain/tests/phase3c_fee_distribution_tests.rs | Aligns fee tests with executor fee model v2 and adjusted genesis/funding setup. |
| lib-blockchain/tests/oracle_executor_tests.rs | Widens bonding-curve token test fixture fields to u128 and 18 decimals. |
| lib-blockchain/tests/oracle_cbe_integration_tests.rs | Widens bonding-curve token test fixture fields to u128 and 18 decimals. |
| lib-blockchain/tests/dao_voting_power_tests.rs | Updates voting power tests for identity-mode floor + allows deprecated round-trip tests. |
| lib-blockchain/tests/dao_hybrid_tests.rs | Updates default hybrid governance parameters + allows deprecated persistence test. |
| lib-blockchain/tests/cbe_lifecycle_integration_tests.rs | Updates bonding-curve lifecycle tests toward u128 amounts and revised split handling. |
| lib-blockchain/tests/bonding_curve_tx_integration_tests.rs | Reworks tests to assert legacy non-executor path rejects bonding-curve txs. |
| lib-blockchain/tests/bonding_curve_integration_tests.rs | Adjusts integration tests to match widened supply type and minor API changes. |
| lib-blockchain/src/validation/block_validate.rs | Removes unused TransactionType import in tests. |
| lib-blockchain/src/utils/nondeterminism_tests.rs | Serializes nondeterminism tests via a global lock and adds deterministic reset helper usage. |
| lib-blockchain/src/utils.rs | Adds reset_consensus_validation_for_tests() for test-only global state reset. |
| lib-blockchain/src/types/sov.rs | Re-exports SOV_MAX_SUPPLY from lib-types (atomic, u128). |
| lib-blockchain/src/transaction/core.rs | Widens bonding-curve tx data fields (u64 → u128). |
| lib-blockchain/src/pricing/mod.rs | Widens price-related fields and helpers (u64 → u128). |
| lib-blockchain/src/integration/economic_integration.rs | Updates memo string expectation from “ZHTP” to “SOV”. |
| lib-blockchain/src/genesis/mod.rs | Widens bonding-curve graduation threshold stored in genesis to u128. |
| lib-blockchain/src/execution/tx_apply.rs | Updates disabled bonding-curve apply stubs to u128 parameters. |
| lib-blockchain/src/execution/executor.rs | Widens executor outcomes and deploy parameter conversions to u128; updates tests for block funding flow. |
| lib-blockchain/src/contracts/tokens/mod.rs | Re-exports canonical protocol constants (SOV + CBE) alongside legacy runtime constants. |
| lib-blockchain/src/contracts/tokens/constants.rs | Splits “protocol” (lib-types) vs legacy runtime (u64) SOV constants. |
| lib-blockchain/src/contracts/tokens/cbe_token.rs | Aligns legacy runtime CBE constants with canonical whole-token supply target. |
| lib-blockchain/src/contracts/bonding_curve/types.rs | Widens curve/threshold/stats fields to u128 and ties token scale to canonical scale. |
| lib-blockchain/src/contracts/bonding_curve/token.rs | Migrates bonding-curve token state to u128 and sets decimals to 18. |
| lib-blockchain/src/contracts/bonding_curve/mod.rs | Adds canonical module and re-exports canonical band/tx/receipt items. |
| lib-blockchain/src/contracts/bonding_curve/events.rs | Widens bonding-curve event amount fields to u128. |
| lib-blockchain/src/contracts/bonding_curve/event_indexer.rs | Removes unused ReserveUpdateReason import in tests. |
| lib-blockchain/src/contracts/bonding_curve/canonical.rs | Introduces canonical constants/band table + deterministic integer math helpers. |
| lib-blockchain/src/contracts/bonding_curve/amm_pool.rs | Widens AMM/POL pool creation result fields to u128 and updates price continuity calculations. |
| lib-blockchain/src/blockchain.rs | Disables legacy bonding-curve mutation path; various governance/treasury/reorg guard tweaks; widens CBE price getter return type. |
| lib-blockchain/src/block/core.rs | Marks PoW fields as legacy and adds serde skipping/defaulting for some header fields. |
| BONDING_CURVE_TECHNICAL_SPEC.md | Adds canonical bonding-curve protocol spec for reset. |
| BONDING_CURVE_MIGRATION_PLAN.md | Adds migration plan and merge gates checklist. |
Comments suppressed due to low confidence (1)
lib-blockchain/tests/cbe_lifecycle_integration_tests.rs:273
- The test output still hard-codes 20%/80% labels and divides by
1e8for “SOV”/“CBE” display, but the split is now driven byRESERVE_SPLIT_*and the protocol is moving to 18-decimal atomic units. Update the labels and formatting to derive percentages from the constants and to use the correct scale so the test output matches the actual protocol semantics.
println!("✓ Reserve/treasury split verified on purchase");
println!(" Buy amount: {} SOV", buy_amount as f64 / 100_000_000.0);
println!(" To reserve (20%): {} SOV", reserve_increase as f64 / 100_000_000.0);
println!(" To treasury (80%): {} SOV", treasury_increase as f64 / 100_000_000.0);
println!(" CBE received: {} CBE", cbe_received as f64 / 100_000_000.0);
You can also share your feedback on Copilot code review. Take the survey.
| } | ||
| CurveType::PiecewiseLinear(curve) => { | ||
| curve.price_at(supply).min(u64::MAX as u128) as u64 | ||
| curve.price_at(u64::try_from(supply).unwrap_or(u64::MAX)) |
| /// Minimum liquidity required for AMM pool creation. | ||
| /// Prevents division by zero attacks and ensures meaningful liquidity. | ||
| pub const MINIMUM_AMM_LIQUIDITY: u64 = 1_000_000; // 0.01 SOV or equivalent | ||
| pub const MINIMUM_AMM_LIQUIDITY: u128 = 1_000_000; // 0.01 SOV or equivalent |
| // Calculate max tokens we can sell with remaining reserve | ||
| let max_tokens = (remaining_reserve as u128 * 100_000_000 / current_price.max(1) as u128) as u64; | ||
| let max_tokens = remaining_reserve | ||
| .saturating_mul(100_000_000) |
| let to_reserve = stable_amount | ||
| .checked_mul(RESERVE_SPLIT_NUMERATOR) | ||
| .ok_or(CurveError::Overflow)? | ||
| .checked_div(RESERVE_SPLIT_DENOMINATOR as u128) | ||
| .ok_or(CurveError::Overflow)?, | ||
| ) | ||
| .map_err(|_| CurveError::Overflow)?; | ||
| .checked_div(RESERVE_SPLIT_DENOMINATOR) | ||
| .ok_or(CurveError::Overflow)?; | ||
| let to_treasury = stable_amount - to_reserve; |
| /// Issue #1844: Reserve/treasury split — 40% reserve / 60% treasury. | ||
| pub const RESERVE_SPLIT_NUMERATOR: u64 = 2; | ||
| pub const RESERVE_SPLIT_DENOMINATOR: u64 = 5; | ||
| pub const RESERVE_SPLIT_NUMERATOR: u128 = 2; | ||
| pub const RESERVE_SPLIT_DENOMINATOR: u128 = 5; |
| /// Retained in-memory for compatibility helpers only. BFT serialization | ||
| /// drops this field and restores `Difficulty::default()` on decode. | ||
| #[serde(skip, default)] |
| /// Retained in-memory for compatibility helpers only. BFT serialization | ||
| /// drops this field and restores `0` on decode. | ||
| #[serde(skip, default)] |
| CurveType::PiecewiseLinear(curve) => { | ||
| curve.quote_buy(current_supply, stable_amount) | ||
| curve.quote_buy( | ||
| u64::try_from(current_supply).unwrap_or(u64::MAX), | ||
| u64::try_from(stable_amount).unwrap_or(u64::MAX), | ||
| ) as u128 |
| let slope_component = band | ||
| .slope_num | ||
| .checked_mul(supply) | ||
| .and_then(|v| v.checked_div(band.slope_den)) | ||
| .expect("canonical price slope component overflow"); |
|
Security & Blockchain Correctness ReviewCRITICAL — Blockers1. Buy/Sell permanently disabled ( 2. Slippage protection never enforced 3. HIGH — Must Fix Before Merge4. 40/60 split truncation accumulates loss ( 5. Buy/sell round-trip symmetry untested 6. Oracle staleness can cycle and manipulate graduation ( 7. Graduation threshold not re-checked at apply time ( MEDIUM8. Bincode field order fragile ( 9. Confirmation bypass via 10. USD price scale cross-module assumption ( What's Good
The mathematical foundation is well-designed. The blockers are all in the execution/validation layer, not the curve math itself. All CRITICAL and HIGH items must be addressed before merge. |



Summary
Testing
Closes #1921