ido: categories in display/UI byte order, drop hardcoded PLP limits
libriften moved encodeVmTokenCategory/decodeVmTokenCategory (which reverse the 32 category bytes, display<->VM) into the ido announcement and ORB IdoParams serialize/deserialize layer. Net wire effects the indexer sees: - preinit announcement delphiCategory[44..76] and xTokenCategory[126..158] are now VM/little-endian (were display order); - the IdoParams commitment stays VM on-wire, but the derived on-chain postlaunch orbPoolParamsCategory push flips display->VM (decode now returns display, the unchanged bake re-wraps it in encodeVmTokenCategory). Keep the three categories (delphiCategory, xTokenCategory, orbPoolParamsCategory) in display/UI byte order in-memory and over RPC: reverse at every parse site (announcement + IdoParams NFT commitment) and restore the .rev() on the output#0 delphi-NFT to_blob() compare. The build_*_bytecode helpers keep reversing display->VM when baking, so the output#7 P2SH32 rebuild matches the new on-chain layout. Also drop the now-unused hardcoded MAX_PLP_SHARE / MAX_PLP_ANNUAL_DISCOUNT / MIN_PLP_ANNUAL_DISCOUNT statics and dead checks; the min-PLP limits are NFT-pinned (minPlpShare / minPlpAfterDiscount) and the discount/max-discount checks now just guard against negatives. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4677cc955e
commit
c1952142de
1 changed files with 17 additions and 29 deletions
|
|
@ -70,9 +70,6 @@ const OFFERING_ENTRY_FLAG_XWNT: u8 = 0x20; // exchange with native token (legacy
|
|||
static PERMANENT_LIQUIDITY_SHARE_DENOMINATOR: LazyLock<Integer> =
|
||||
LazyLock::new(|| Integer::from(100_000_000i64));
|
||||
|
||||
static MAX_PLP_SHARE: LazyLock<Integer> = LazyLock::new(|| Integer::from(80_000_000i64)); // 80%
|
||||
static MAX_PLP_ANNUAL_DISCOUNT: LazyLock<Integer> = LazyLock::new(|| Integer::from(10_000_000i64)); // 10%
|
||||
static MIN_PLP_ANNUAL_DISCOUNT: LazyLock<Integer> = LazyLock::new(|| Integer::from(0i64)); // 0%
|
||||
// The minimum PLP share and minimum PLP-after-discount are no longer hardcoded:
|
||||
// they are pinned per-IdoParams NFT (minPlpShare / minPlpAfterDiscount, numerators
|
||||
// over PERMANENT_LIQUIDITY_SHARE_DENOMINATOR) and enforced against the offering.
|
||||
|
|
@ -155,8 +152,10 @@ static REBUILD_IPFS_PLACEHOLDER_BCMR_FOR_GENESIS_WITH_AUTHGUARD_CONTRACT: LazyLo
|
|||
/// [117..121] entryExecutionFee (pIntLE, sats)
|
||||
/// [121..125] createExecutionFee (pIntLE, sats)
|
||||
/// [125..127] paramsUseFee (pIntLE, sats/100 — not parsed here)
|
||||
/// Categories and the nfth are stored in the same byte order the announcement
|
||||
/// uses, so equality checks against announced parameters are direct compares.
|
||||
/// Categories are carried on-chain in VM (little-endian) byte order and are
|
||||
/// reversed to display/UI order on parse (matching the announcement parse), so
|
||||
/// equality checks against announced parameters remain direct compares. The
|
||||
/// nfth is a hash and is kept in its on-chain order.
|
||||
const IDO_PARAMS_COMMITMENT_SIZE: usize = 127;
|
||||
|
||||
/// The only ORB IdoParams NFT commitment version this indexer understands
|
||||
|
|
@ -188,8 +187,10 @@ fn parse_ido_params_nft_commitment(commitment: &[u8]) -> Result<IdoParamsNftComm
|
|||
}
|
||||
Ok(IdoParamsNftCommitment {
|
||||
version: commitment[0],
|
||||
orbPoolParamsCategory: commitment[1..33].to_vec(),
|
||||
delphiCategory: commitment[33..65].to_vec(),
|
||||
// Categories are stored on-chain in VM (little-endian) byte order; the
|
||||
// indexer keeps them in display/UI order, so reverse on parse.
|
||||
orbPoolParamsCategory: commitment[1..33].iter().copied().rev().collect(),
|
||||
delphiCategory: commitment[33..65].iter().copied().rev().collect(),
|
||||
platformFeeNfth: commitment[65..97].to_vec(),
|
||||
platformFee: vm_number_to_bigint(&commitment[97..101]),
|
||||
minExpireDuration: vm_number_to_bigint(&commitment[101..105]),
|
||||
|
|
@ -1475,7 +1476,8 @@ fn parse_ido_preinit_tx_params(
|
|||
offering: IdoParametersOffering {
|
||||
platformFeeNFTH: data[8..40].to_vec(),
|
||||
platformFeeNumerator: vm_number_to_bigint(&data[40..44]),
|
||||
delphiCategory: data[44..76].to_vec(),
|
||||
// On-chain in VM order; kept in display/UI order.
|
||||
delphiCategory: data[44..76].iter().copied().rev().collect(),
|
||||
launchConditions: IdoParametersOfferingLaunchConditions {
|
||||
expiresAt: vm_number_to_bigint(&data[76..82]),
|
||||
deployThreshold: vm_number_to_bigint(&data[82..90]),
|
||||
|
|
@ -1486,7 +1488,8 @@ fn parse_ido_preinit_tx_params(
|
|||
discountAnnualRateNumerator: vm_number_to_bigint(&data[102..106]),
|
||||
priceNumerator: vm_number_to_bigint(&data[106..122]),
|
||||
minOffer: vm_number_to_bigint(&data[122..126]),
|
||||
xTokenCategory: data[126..158].to_vec(),
|
||||
// On-chain in VM order; kept in display/UI order.
|
||||
xTokenCategory: data[126..158].iter().copied().rev().collect(),
|
||||
},
|
||||
executionFee: vm_number_to_bigint(&data[158..162]),
|
||||
},
|
||||
|
|
@ -1526,33 +1529,18 @@ fn parse_ido_preinit_tx_params(
|
|||
}
|
||||
}
|
||||
|
||||
if preinit_parameters.permanentLiquidityShareNumerator > *MAX_PLP_SHARE {
|
||||
invalid_ido_reasons.push(anyhow::anyhow!(
|
||||
"preinit_parameters.permanentLiquidityShareNumerator > *MAX_PLP_SHARE"
|
||||
));
|
||||
is_valid_ido = false;
|
||||
}
|
||||
if preinit_parameters
|
||||
.offering
|
||||
.offer
|
||||
.discountAnnualRateNumerator
|
||||
< *MIN_PLP_ANNUAL_DISCOUNT
|
||||
< 0
|
||||
{
|
||||
invalid_ido_reasons.push(anyhow::anyhow!("preinit_parameters.offering.offer.discountAnnualRateNumerator > *MAX_PLP_ANNUAL_DISCOUNT"));
|
||||
is_valid_ido = false;
|
||||
}
|
||||
if preinit_parameters
|
||||
.offering
|
||||
.offer
|
||||
.discountAnnualRateNumerator
|
||||
> *MAX_PLP_ANNUAL_DISCOUNT
|
||||
{
|
||||
invalid_ido_reasons.push(anyhow::anyhow!("preinit_parameters.offering.offer.discountAnnualRateNumerator > *MAX_PLP_ANNUAL_DISCOUNT"));
|
||||
invalid_ido_reasons.push(anyhow::anyhow!("preinit_parameters.offering.offer.discountAnnualRateNumerator < 0"));
|
||||
is_valid_ido = false;
|
||||
}
|
||||
|
||||
if preinit_parameters.offering.offer.maxDiscountRateNumerator < 0 {
|
||||
invalid_ido_reasons.push(anyhow::anyhow!("preinit_parameters.offering.offer.maxDiscountRateNumerator < Integer::from(0)"));
|
||||
invalid_ido_reasons.push(anyhow::anyhow!("preinit_parameters.offering.offer.maxDiscountRateNumerator < 0"));
|
||||
is_valid_ido = false;
|
||||
}
|
||||
if preinit_parameters.offeredTokenAmount <= 0 {
|
||||
|
|
@ -1639,9 +1627,9 @@ fn parse_ido_preinit_tx_params(
|
|||
match tx.output.first() {
|
||||
Some(delphiOut) => match delphiOut.token.as_ref() {
|
||||
Some(delphiToken) if delphiToken.has_nft() => {
|
||||
let delphiTokenId: Vec<u8> =
|
||||
let delphiTokenCategory: Vec<u8> =
|
||||
delphiToken.id.to_blob().iter().copied().rev().collect();
|
||||
if delphiTokenId != preinit_parameters.offering.delphiCategory {
|
||||
if delphiTokenCategory != preinit_parameters.offering.delphiCategory {
|
||||
invalid_ido_reasons.push(anyhow::anyhow!("delphi nft category in first output != offering.delphiCategory"));
|
||||
is_valid_ido = false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue