@@ -370,6 +370,17 @@ abstract contract PythTestUtils is Test, WormholeTestUtils, RandTestUtils {
370370}
371371
372372contract PythUtilsTest is Test , WormholeTestUtils , PythTestUtils , IPythEvents {
373+ function successTest (int64 price1 , int32 expo1 , int64 price2 , int32 expo2 , int64 expectedPrice , int32 expectedExpo ) internal pure {
374+ (int64 price , int32 expo ) = PythUtils.deriveCrossRate (price1, expo1, price2, expo2);
375+ assertEq (price, expectedPrice);
376+ assertEq (expo, expectedExpo);
377+ }
378+
379+ function revertTest (int64 price1 , int32 expo1 , int64 price2 , int32 expo2 ) internal {
380+ vm.expectRevert ();
381+ PythUtils.deriveCrossRate (price1, expo1, price2, expo2);
382+ }
383+
373384 function testConvertToUnit () public {
374385 // Price can't be negative
375386 vm.expectRevert ();
@@ -401,64 +412,42 @@ contract PythUtilsTest is Test, WormholeTestUtils, PythTestUtils, IPythEvents {
401412 }
402413
403414 function testCombinePrices () public {
404- // Test case 1: Basic price combination (StEth/Eth / Eth/USD = ETH/BTC)
405- PythStructs.Price memory stEthEth = PythStructs.Price ({
406- price: 206487956502 ,
407- conf: 10 ,
408- expo: - 8 ,
409- publishTime: block .timestamp
410- });
415+
416+ // Basic Tests
417+ successTest (100 , - 2 , 100 , - 2 , 100 , - 2 );
418+ successTest (10000 , - 2 , 100 , - 2 , 10000 , - 2 );
419+ successTest (1_000_000 , - 2 , 10_000 , - 2 , 10_000 , - 2 );
420+
421+ // Negative Price Tests
422+ revertTest (- 100 , - 2 , 100 , - 2 );
423+ revertTest (100 , - 2 , - 100 , - 2 );
424+ revertTest (- 100 , - 2 , - 100 , - 2 );
425+
426+ // Positive Exponent Tests
427+ revertTest (100 , 2 , 100 , - 2 );
428+ revertTest (100 , - 2 , 100 , 2 );
429+ revertTest (100 , 2 , 100 , 2 );
430+
431+ // Different Exponent Tests
432+ successTest (10_000 , - 2 , 100 , - 4 , 100_000_000 , - 4 );
433+ successTest (10_000 , - 2 , 10_000 , 0 , 1 , - 2 );
434+ successTest (10_000 , 0 , 10_000 , 0 , 1 , 0 );
435+
436+ // End Range Tests
437+ successTest (int64 (type (int64 ).max), 0 , int64 (type (int64 ).max), 0 , 1 , 0 );
438+ successTest (int64 (type (int64 ).max), 0 , 1 , 0 , int64 (type (int64 ).max), 0 );
439+ successTest (1 , 0 , int64 (type (int64 ).max), 0 , 1 / int64 (type (int64 ).max), 0 );
440+ revertTest (10_000 , - 2 , 10_000 , - 256 );
411441
412- PythStructs.Price memory ethUsd = PythStructs.Price ({
413- price: 206741615681 ,
414- conf: 100 ,
415- expo: - 8 ,
416- publishTime: block .timestamp
417- });
418-
419- (int64 price , int32 expo ) = PythUtils.combinePrices (stEthEth.price, stEthEth.expo, ethUsd.price, ethUsd.expo);
442+ // More Realistic Tests
443+ // Test case 1: (StEth/Eth / Eth/USD = ETH/BTC)
444+ (int64 price , int32 expo ) = PythUtils.deriveCrossRate (206487956502 , - 8 , 206741615681 , - 8 );
420445 assertApproxEqRel (price, 100000000 , 9e17 ); // $1
421446 assertEq (expo, - 8 );
422-
423- // Test case 2: Different exponents
424- PythStructs.Price memory smallPrice = PythStructs.Price ({
425- price: 100 , // $0.01
426- conf: 1 ,
427- expo: - 4 , // 4 decimals
428- publishTime: block .timestamp
429- });
430-
431- PythStructs.Price memory largePrice = PythStructs.Price ({
432- price: 1000 , // $10
433- conf: 10 ,
434- expo: - 2 , // 2 decimals
435- publishTime: block .timestamp
436- });
437-
438- (price, expo) = PythUtils.combinePrices (smallPrice.price, smallPrice.expo, largePrice.price, largePrice.expo);
439- assertEq (price, 10 ); // 0.001
440- assertEq (expo, - 4 );
441-
442- // Test case 3: Revert on negative prices
443- PythStructs.Price memory negativePrice = PythStructs.Price ({
444- price: - 100 ,
445- conf: 10 ,
446- expo: - 2 ,
447- publishTime: block .timestamp
448- });
449-
450- vm.expectRevert ();
451- PythUtils.combinePrices (negativePrice.price, negativePrice.expo, ethUsd.price, ethUsd.expo);
452447
453- // Test case 4: Revert on positive exponents
454- PythStructs.Price memory invalidExpo = PythStructs.Price ({
455- price: 100 ,
456- conf: 10 ,
457- expo: 2 ,
458- publishTime: block .timestamp
459- });
460-
461- vm.expectRevert ();
462- PythUtils.combinePrices (ethUsd.price, ethUsd.expo, invalidExpo.price, invalidExpo.expo);
448+ // Test case 2:
449+ (price, expo) = PythUtils.deriveCrossRate (520010 , - 8 , 38591 , - 8 );
450+ assertApproxEqRel (price, 1347490347 , 9e17 ); // $1
451+ assertEq (expo, - 8 );
463452 }
464453}
0 commit comments