/** * Migration Test Harness Utilities * * These utilities help verify that BigInt implementations produce identical * results to the original BigNumber implementations during the ethers v6 migration. */ /** * Compares two numeric values for equality * Handles BigInt, string, and number comparisons */ export function assertEqual( actual: bigint | string | number, expected: bigint | string | number, message?: string, ): void { const actualStr = actual.toString(); const expectedStr = expected.toString(); if (actualStr !== expectedStr) { throw new Error(message || `Expected ${expectedStr} but got ${actualStr}`); } } /** * Converts various types to BigInt for comparison */ export function toBigInt(value: bigint | string | number): bigint { if (typeof value === 'bigint') return value; return BigInt(value); } /** * Converts various types to string for comparison */ export function toString(value: bigint | string | number): string { return value.toString(); } /** * X128 math utilities for testing * X128 = 2^128 precision fixed-point arithmetic */ export const X128 = BigInt(2) ** BigInt(128); /** * Test fixture for X128 calculations */ export interface X128TestCase { sqrtPriceX96: string; desiredRatio: { numerator: string; denominator: string }; expectedToken1PerToken0X128: string; } /** * Standard test fixtures for verifying calculation accuracy */ export const testFixtures = { // Basic arithmetic test cases arithmetic: { addition: [ { a: '1000000000000000000', b: '500000000000000000', expected: '1500000000000000000', }, { a: '0', b: '0', expected: '0' }, { a: '999999999999999999', b: '1', expected: '1000000000000000000' }, ], subtraction: [ { a: '1500000000000000000', b: '500000000000000000', expected: '1000000000000000000', }, { a: '1000', b: '1000', expected: '0' }, ], multiplication: [ { a: '1000000000000000000', b: '2', expected: '2000000000000000000' }, { a: '500000000000000000', b: '3', expected: '1500000000000000000' }, ], division: [ { a: '2000000000000000000', b: '2', expected: '1000000000000000000' }, { a: '1000000000000000000', b: '3', expected: '333333333333333333' }, // floor division ], power: [ { a: '2', b: '128', expected: '340282366920938463463374607431768211456' }, // 2^128 { a: '10', b: '18', expected: '1000000000000000000' }, ], }, // X128 precision test cases x128: { sqrtPriceX96: [ { value: '79228162514264337593543950336', description: '1.0 price (2^96)', }, { value: '112045541949572279837463876454', description: '2.0 price' }, { value: '56022770974786139918731938227', description: '0.5 price' }, ], tokenRatios: [ { numerator: '1', denominator: '1', expected: '340282366920938463463374607431768211456', }, // 1:1 = X128 { numerator: '2', denominator: '1', expected: '680564733841876926926749214863536422912', }, // 2:1 { numerator: '1', denominator: '2', expected: '170141183460469231731687303715884105728', }, // 1:2 ], }, // Slippage calculation test cases slippage: { basisPoints: [ { slippagePercent: 0.5, expected: '9950' }, // 0.5% slippage = 9950 bps { slippagePercent: 1.0, expected: '9900' }, // 1% slippage { slippagePercent: 0.1, expected: '9990' }, // 0.1% slippage ], }, // Edge cases edgeCases: { zero: ['0', '0x0', '0x00'], maxUint256: '115792089237316195423570985008687907853269984665640564039457584007913129639935', largeNumbers: [ '1000000000000000000000000', // 1e24 '999999999999999999999999', '123456789012345678901234567890', ], }, }; /** * Helper to run BigInt arithmetic operations and compare with expected values */ export function testBigIntOperation( operation: () => bigint, expected: string, testName: string, ): void { const result = operation(); assertEqual( result, expected, `${testName}: expected ${expected} but got ${result.toString()}`, ); } /** * Validates that BigInt division matches expected floor behavior */ export function testDivision( numerator: string, denominator: string, expected: string, ): void { const result = BigInt(numerator) / BigInt(denominator); assertEqual(result, expected); } /** * Validates X128 math operations */ export function testX128Math( sqrtPriceX96: string, token1PerToken0X128: string, ): void { const sqrtPrice = BigInt(sqrtPriceX96); const priceX128 = (sqrtPrice * sqrtPrice) / BigInt(2) ** BigInt(64); assertEqual(priceX128, token1PerToken0X128); }