diff --git a/.changeset/brave-ads-end.md b/.changeset/brave-ads-end.md new file mode 100644 index 0000000..3984489 --- /dev/null +++ b/.changeset/brave-ads-end.md @@ -0,0 +1,5 @@ +--- +"@mangrovedao/mgv": patch +--- + +Fix density by using the same algorithm as from the chain diff --git a/src/lib/density.ts b/src/lib/density.ts index e3f9a28..3717b8a 100644 --- a/src/lib/density.ts +++ b/src/lib/density.ts @@ -48,6 +48,21 @@ export function formatDensity(density: number): bigint { return BigInt((exponent << 2) | mantissa) } +const SUBNORMAL_LIMIT = 0b111n + +export function rawDensityTo96X32(rawDensity: bigint): bigint { + if (rawDensity <= SUBNORMAL_LIMIT) { + return rawDensity & 0b11n + } + const shift = (rawDensity >> 2n) - 2n + return ((rawDensity & 0b11n) | 0b100n) << shift +} + +export function multiplyUpRawDensity(rawDensity: bigint, m: bigint): bigint { + const part = m * rawDensityTo96X32(rawDensity) + return (part >> 32n) + (part % (2n << 32n) === 0n ? 0n : 1n) +} + export function multiplyDensity(density: number, b: bigint, up = true): bigint { const roundMethod = up ? Math.ceil : Math.round return BigInt(roundMethod(Number(b) * density)) @@ -60,5 +75,5 @@ export function multiplyDensity(density: number, b: bigint, up = true): bigint { * @returns the minimum volume required to execute the offer. */ export function minVolume(config: LocalConfig, gasreq: bigint): bigint { - return multiplyDensity(config.density, gasreq + config.offer_gasbase) + return multiplyUpRawDensity(config.rawDensity, gasreq + config.offer_gasbase) } diff --git a/src/lib/local.test.ts b/src/lib/local.test.ts index 40139dd..7a82bcc 100644 --- a/src/lib/local.test.ts +++ b/src/lib/local.test.ts @@ -15,6 +15,7 @@ describe('local', () => { level1: 48n, root: 2n, offer_gasbase: 300_000n, + rawDensity: 273n, lock: false, last: 8698n, } diff --git a/src/lib/local.ts b/src/lib/local.ts index d1aa1d1..ae2c2f6 100644 --- a/src/lib/local.ts +++ b/src/lib/local.ts @@ -47,7 +47,8 @@ export function unpackLocalConfig(_config: bigint): LocalConfig { config >>= level3_bits const binPosInLeaf = config & mask(binPosInLeaf_bits) config >>= binPosInLeaf_bits - const density = parseDensity(config & mask(density_bits)) + const rawDensity = config & mask(density_bits) + const density = parseDensity(rawDensity) config >>= density_bits const fee = config & mask(fee_bits) config >>= fee_bits @@ -56,6 +57,7 @@ export function unpackLocalConfig(_config: bigint): LocalConfig { active: active === 1n, fee, density, + rawDensity, binPosInLeaf, level3, level2, diff --git a/src/types/lib.ts b/src/types/lib.ts index 9206574..d39ad99 100644 --- a/src/types/lib.ts +++ b/src/types/lib.ts @@ -26,6 +26,7 @@ export type LocalConfig = { active: boolean fee: bigint density: number + rawDensity: bigint binPosInLeaf: bigint level3: bigint level2: bigint