Skip to content

Commit 2ea20ee

Browse files
Merge pull request #1 from rainlanguage/2025-06-10-literal-intorastring
2025 06 10 literal intorastring
2 parents 7bac044 + a27458c commit 2ea20ee

File tree

7 files changed

+134
-47
lines changed

7 files changed

+134
-47
lines changed

lib/pyth-crosschain

src/generated/PythWords.pointers.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
pragma solidity =0.8.25;
1111

1212
/// @dev Hash of the known bytecode.
13-
bytes32 constant BYTECODE_HASH = bytes32(0x61435eb0bae1f17f1ebf3d9837981995cc7a957fa80469edbb87a69cf964909e);
13+
bytes32 constant BYTECODE_HASH = bytes32(0xd05bd0f45f2b111e5bf80debd87ef42e2fdd9ff22a158a80bec0079d5c8e4c52);
1414

1515
/// @dev The hash of the meta that describes the contract.
1616
bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0x59a6ebb4b3b0730014b2424184427e3c39407d6f0ef38a9baf68f6bb395303d5);
@@ -47,10 +47,10 @@ bytes constant SUB_PARSER_WORD_PARSERS = hex"0782";
4747
/// @dev Every two bytes is a function pointer for an operand handler.
4848
/// These positional indexes all map to the same indexes looked up in the parse
4949
/// meta.
50-
bytes constant OPERAND_HANDLER_FUNCTION_POINTERS = hex"08c0";
50+
bytes constant OPERAND_HANDLER_FUNCTION_POINTERS = hex"087c";
5151

5252
/// @dev The function pointers for the integrity check fns.
53-
bytes constant INTEGRITY_FUNCTION_POINTERS = hex"08b3";
53+
bytes constant INTEGRITY_FUNCTION_POINTERS = hex"086f";
5454

5555
/// @dev The function pointers known to the interpreter for dynamic dispatch.
5656
/// By setting these as a constant they can be inlined into the interpreter

src/lib/op/LibOpPythPrice.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ library LibOpPythPrice {
2525
staleAfter := mload(add(inputs, 0x40))
2626
}
2727

28-
uint256 price18 = LibPyth.getPriceNoOlderThan(symbol.toString(), staleAfter);
28+
uint256 price18 = LibPyth.getPriceNoOlderThan(symbol, staleAfter);
2929

3030
uint256[] memory outputs;
3131
assembly ("memory-safe") {

src/lib/pyth/LibPyth.sol

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pragma solidity ^0.8.25;
55
import {IPyth} from "pyth-sdk/IPyth.sol";
66
import {PythStructs} from "pyth-sdk/PythStructs.sol";
77
import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol";
8+
import {IntOrAString} from "rain.intorastring/lib/LibIntOrAString.sol";
89

910
error UnsupportedChainId();
1011

@@ -23,31 +24,38 @@ library LibPyth {
2324
/// Google.
2425
bytes32 constant PRICE_FEED_ID_EQUITY_US_GOOG_USD =
2526
0xe65ff435be42630439c96396653a342829e877e2aafaeaf1a10d0ee5fd2cf3f2;
26-
bytes32 constant PRICE_FEED_SYMBOL_HASH_EQUITY_US_GOOG_USD = keccak256("Equity.US.GOOG/USD");
27+
uint256 constant PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_GOOG_USD =
28+
66160371403383253599282426833944855373143809818294373840007959174479400140800;
2729
/// Amazon.
2830
bytes32 constant PRICE_FEED_ID_EQUITY_US_AMZN_USD =
2931
0xb5d0e0fa58a1f8b81498ae670ce93c872d14434b72c364885d4fa1b257cbb07a;
30-
bytes32 constant PRICE_FEED_SYMBOL_HASH_EQUITY_US_AMZN_USD = keccak256("Equity.US.AMZN/USD");
32+
uint256 constant PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_AMZN_USD =
33+
66160371403383253599282426825164673485599929989200081975222960745157943623680;
3134
/// Apple.
3235
bytes32 constant PRICE_FEED_ID_EQUITY_US_AAPL_USD =
3336
0x49f6b65cb1de6b10eaf75e7c03ca029c306d0357e91b5311b175084a5ad55688;
34-
bytes32 constant PRICE_FEED_SYMBOL_HASH_EQUITY_US_AAPL_USD = keccak256("Equity.US.AAPL/USD");
37+
uint256 constant PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_AAPL_USD =
38+
66160371403383253599282426825095942414673486745157375598258859489931187716096;
3539
/// Microsoft.
3640
bytes32 constant PRICE_FEED_ID_EQUITY_US_MSFT_USD =
3741
0xd0ca23c1cc005e004ccf1db5bf76aeb6a49218f43dac3d4b275e92de12ded4d1;
38-
bytes32 constant PRICE_FEED_SYMBOL_HASH_EQUITY_US_MSFT_USD = keccak256("Equity.US.MSFT/USD");
42+
uint256 constant PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_MSFT_USD =
43+
66160371403383253599282426842736501585965453022888347996463088912268173246464;
3944
/// Tesla.
4045
bytes32 constant PRICE_FEED_ID_EQUITY_US_TSLA_USD =
4146
0x16dad506d7db8da01c87581c87ca897a012a153557d4d578c3b9c9e1bc0632f1;
42-
bytes32 constant PRICE_FEED_SYMBOL_HASH_EQUITY_US_TSLA_USD = keccak256("Equity.US.TSLA/USD");
47+
uint256 constant PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_TSLA_USD =
48+
66160371403383253599282426852967145196619531930608304753932615391908156407808;
4349
/// Nvidia.
4450
bytes32 constant PRICE_FEED_ID_EQUITY_US_NVDA_USD =
4551
0xb1073854ed24cbc755dc527418f52b7d271f6cc967bbf8d8129112b18860a593;
46-
bytes32 constant PRICE_FEED_SYMBOL_HASH_EQUITY_US_NVDA_USD = keccak256("Equity.US.NVDA/USD");
52+
uint256 constant PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_NVDA_USD =
53+
66160371403383253599282426844215083938984997694973762903522130028717106266112;
4754
/// Meta Platforms (Facebook).
4855
bytes32 constant PRICE_FEED_ID_EQUITY_US_META_USD =
4956
0x78a3e3b8e676a8f73c439f5d749737034b139bbbe899ba5775216fba596607fe;
50-
bytes32 constant PRICE_FEED_SYMBOL_HASH_EQUITY_US_META_USD = keccak256("Equity.US.META/USD");
57+
uint256 constant PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_META_USD =
58+
66160371403383253599282426842656886270473265994828379196375643713571242639360;
5159

5260
/// TODO replace with O(1) lookup table.
5361
function getPriceFeedContract(uint256 chainId) internal pure returns (IPyth) {
@@ -61,28 +69,28 @@ library LibPyth {
6169
}
6270

6371
/// TODO replace with O(1) lookup table.
64-
function getPriceFeedId(string memory feedSymbol) internal pure returns (bytes32) {
65-
bytes32 feedSymbolHash = keccak256(bytes(feedSymbol));
66-
if (feedSymbolHash == PRICE_FEED_SYMBOL_HASH_EQUITY_US_GOOG_USD) {
72+
function getPriceFeedId(IntOrAString feedSymbolIntOrAString) internal pure returns (bytes32) {
73+
uint256 feedSymbol = IntOrAString.unwrap(feedSymbolIntOrAString);
74+
if (feedSymbol == PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_GOOG_USD) {
6775
return PRICE_FEED_ID_EQUITY_US_GOOG_USD;
68-
} else if (feedSymbolHash == PRICE_FEED_SYMBOL_HASH_EQUITY_US_AMZN_USD) {
76+
} else if (feedSymbol == PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_AMZN_USD) {
6977
return PRICE_FEED_ID_EQUITY_US_AMZN_USD;
70-
} else if (feedSymbolHash == PRICE_FEED_SYMBOL_HASH_EQUITY_US_AAPL_USD) {
78+
} else if (feedSymbol == PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_AAPL_USD) {
7179
return PRICE_FEED_ID_EQUITY_US_AAPL_USD;
72-
} else if (feedSymbolHash == PRICE_FEED_SYMBOL_HASH_EQUITY_US_MSFT_USD) {
80+
} else if (feedSymbol == PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_MSFT_USD) {
7381
return PRICE_FEED_ID_EQUITY_US_MSFT_USD;
74-
} else if (feedSymbolHash == PRICE_FEED_SYMBOL_HASH_EQUITY_US_TSLA_USD) {
82+
} else if (feedSymbol == PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_TSLA_USD) {
7583
return PRICE_FEED_ID_EQUITY_US_TSLA_USD;
76-
} else if (feedSymbolHash == PRICE_FEED_SYMBOL_HASH_EQUITY_US_NVDA_USD) {
84+
} else if (feedSymbol == PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_NVDA_USD) {
7785
return PRICE_FEED_ID_EQUITY_US_NVDA_USD;
78-
} else if (feedSymbolHash == PRICE_FEED_SYMBOL_HASH_EQUITY_US_META_USD) {
86+
} else if (feedSymbol == PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_META_USD) {
7987
return PRICE_FEED_ID_EQUITY_US_META_USD;
8088
} else {
8189
revert UnsupportedFeedSymbol();
8290
}
8391
}
8492

85-
function getPriceNoOlderThan(string memory feedSymbol, uint256 staleAfter) internal view returns (uint256) {
93+
function getPriceNoOlderThan(IntOrAString feedSymbol, uint256 staleAfter) internal view returns (uint256) {
8694
bytes32 feedId = getPriceFeedId(feedSymbol);
8795
IPyth priceFeedContract = getPriceFeedContract(block.chainid);
8896

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// SPDX-License-Identifier: LicenseRef-DCL-1.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd
3+
pragma solidity =0.8.25;
4+
5+
import {Test} from "forge-std/Test.sol";
6+
import {LibIntOrAString, IntOrAString} from "rain.intorastring/lib/LibIntOrAString.sol";
7+
import {LibPyth} from "src/lib/pyth/LibPyth.sol";
8+
9+
contract LibPythConstantsTest is Test {
10+
function testChainIdConstants() external pure {
11+
assertEq(LibPyth.CHAIN_ID_ARBITRUM, 42161);
12+
assertEq(LibPyth.CHAIN_ID_BASE, 8453);
13+
}
14+
15+
function testIntorastringConstants() external pure {
16+
assertEq(
17+
LibPyth.PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_GOOG_USD,
18+
IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.GOOG/USD"))
19+
);
20+
assertEq(
21+
LibPyth.PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_AMZN_USD,
22+
IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.AMZN/USD"))
23+
);
24+
assertEq(
25+
LibPyth.PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_AAPL_USD,
26+
IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.AAPL/USD"))
27+
);
28+
assertEq(
29+
LibPyth.PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_MSFT_USD,
30+
IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.MSFT/USD"))
31+
);
32+
assertEq(
33+
LibPyth.PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_TSLA_USD,
34+
IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.TSLA/USD"))
35+
);
36+
assertEq(
37+
LibPyth.PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_NVDA_USD,
38+
IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.NVDA/USD"))
39+
);
40+
assertEq(
41+
LibPyth.PRICE_FEED_SYMBOL_INTORASTRING_EQUITY_US_META_USD,
42+
IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.META/USD"))
43+
);
44+
}
45+
}

test/src/lib/pyth/LibPyth.getPriceFeedId.t.sol

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,55 @@ pragma solidity =0.8.25;
44

55
import {Test} from "forge-std/Test.sol";
66
import {LibPyth, UnsupportedFeedSymbol} from "src/lib/pyth/LibPyth.sol";
7+
import {IntOrAString, LibIntOrAString} from "rain.intorastring/lib/LibIntOrAString.sol";
78

89
contract LibPythGetPriceFeedIdTest is Test {
9-
function getPriceFeedIdExternal(string memory symbol) external pure returns (bytes32) {
10+
function getPriceFeedIdExternal(IntOrAString symbol) external pure returns (bytes32) {
1011
return LibPyth.getPriceFeedId(symbol);
1112
}
1213

1314
function testPriceFeedIdKnownMappings() external pure {
1415
// Test known price feed IDs.
15-
assertEq(LibPyth.PRICE_FEED_ID_EQUITY_US_GOOG_USD, LibPyth.getPriceFeedId("Equity.US.GOOG/USD"));
16-
assertEq(LibPyth.PRICE_FEED_ID_EQUITY_US_AMZN_USD, LibPyth.getPriceFeedId("Equity.US.AMZN/USD"));
17-
assertEq(LibPyth.PRICE_FEED_ID_EQUITY_US_AAPL_USD, LibPyth.getPriceFeedId("Equity.US.AAPL/USD"));
18-
assertEq(LibPyth.PRICE_FEED_ID_EQUITY_US_MSFT_USD, LibPyth.getPriceFeedId("Equity.US.MSFT/USD"));
19-
assertEq(LibPyth.PRICE_FEED_ID_EQUITY_US_TSLA_USD, LibPyth.getPriceFeedId("Equity.US.TSLA/USD"));
20-
assertEq(LibPyth.PRICE_FEED_ID_EQUITY_US_NVDA_USD, LibPyth.getPriceFeedId("Equity.US.NVDA/USD"));
21-
assertEq(LibPyth.PRICE_FEED_ID_EQUITY_US_META_USD, LibPyth.getPriceFeedId("Equity.US.META/USD"));
16+
assertEq(
17+
LibPyth.PRICE_FEED_ID_EQUITY_US_GOOG_USD,
18+
LibPyth.getPriceFeedId(LibIntOrAString.fromString2("Equity.US.GOOG/USD"))
19+
);
20+
assertEq(
21+
LibPyth.PRICE_FEED_ID_EQUITY_US_AMZN_USD,
22+
LibPyth.getPriceFeedId(LibIntOrAString.fromString2("Equity.US.AMZN/USD"))
23+
);
24+
assertEq(
25+
LibPyth.PRICE_FEED_ID_EQUITY_US_AAPL_USD,
26+
LibPyth.getPriceFeedId(LibIntOrAString.fromString2("Equity.US.AAPL/USD"))
27+
);
28+
assertEq(
29+
LibPyth.PRICE_FEED_ID_EQUITY_US_MSFT_USD,
30+
LibPyth.getPriceFeedId(LibIntOrAString.fromString2("Equity.US.MSFT/USD"))
31+
);
32+
assertEq(
33+
LibPyth.PRICE_FEED_ID_EQUITY_US_TSLA_USD,
34+
LibPyth.getPriceFeedId(LibIntOrAString.fromString2("Equity.US.TSLA/USD"))
35+
);
36+
assertEq(
37+
LibPyth.PRICE_FEED_ID_EQUITY_US_NVDA_USD,
38+
LibPyth.getPriceFeedId(LibIntOrAString.fromString2("Equity.US.NVDA/USD"))
39+
);
40+
assertEq(
41+
LibPyth.PRICE_FEED_ID_EQUITY_US_META_USD,
42+
LibPyth.getPriceFeedId(LibIntOrAString.fromString2("Equity.US.META/USD"))
43+
);
2244
}
2345

24-
function testPriceFeedIdUnknownMappings(string memory symbol) external {
46+
function testPriceFeedIdUnknownMappings(IntOrAString symbol) external {
47+
vm.assume(
48+
IntOrAString.unwrap(symbol) != IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.GOOG/USD"))
49+
&& IntOrAString.unwrap(symbol) != IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.AMZN/USD"))
50+
&& IntOrAString.unwrap(symbol) != IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.AAPL/USD"))
51+
&& IntOrAString.unwrap(symbol) != IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.MSFT/USD"))
52+
&& IntOrAString.unwrap(symbol) != IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.TSLA/USD"))
53+
&& IntOrAString.unwrap(symbol) != IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.NVDA/USD"))
54+
&& IntOrAString.unwrap(symbol) != IntOrAString.unwrap(LibIntOrAString.fromString2("Equity.US.META/USD"))
55+
);
2556
vm.expectRevert(UnsupportedFeedSymbol.selector);
2657
this.getPriceFeedIdExternal(symbol);
2758
}

test/src/lib/pyth/LibPyth.getPriceNoOlderThan.t.sol

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,35 @@ pragma solidity ^0.8.25;
55
import {Test} from "forge-std/Test.sol";
66
import {LibPyth} from "src/lib/pyth/LibPyth.sol";
77
import {FORK_RPC_URL_ARBITRUM, FORK_RPC_URL_BASE, FORK_BLOCK_ARBITRUM, FORK_BLOCK_BASE} from "test/lib/LibFork.sol";
8+
import {IntOrAString, LibIntOrAString} from "rain.intorastring/lib/LibIntOrAString.sol";
89

910
contract LibPythGetPriceNoOlderThanTest is Test {
10-
function getPriceNoOlderThanExternal(string memory symbol, uint256 maxAge) external view returns (uint256) {
11+
using LibIntOrAString for string;
12+
13+
function getPriceNoOlderThanExternal(IntOrAString symbol, uint256 maxAge) external view returns (uint256) {
1114
return LibPyth.getPriceNoOlderThan(symbol, maxAge);
1215
}
1316

14-
function checkPriceNoOlderThan(string memory symbol, uint256 maxAge, uint256 expectedPrice) internal view {
17+
function checkPriceNoOlderThan(IntOrAString symbol, uint256 maxAge, uint256 expectedPrice) internal view {
1518
assertEq(LibPyth.getPriceNoOlderThan(symbol, maxAge), expectedPrice);
1619
}
1720

1821
function testPriceNoOlderThanArbitrum() external {
1922
vm.createSelectFork(FORK_RPC_URL_ARBITRUM, FORK_BLOCK_ARBITRUM);
20-
checkPriceNoOlderThan("Equity.US.GOOG/USD", 72 hours, 172.3176e18);
21-
checkPriceNoOlderThan("Equity.US.AMZN/USD", 500 hours, 205.06198e18);
22-
checkPriceNoOlderThan("Equity.US.AAPL/USD", 72 hours, 202.86002e18);
23-
checkPriceNoOlderThan("Equity.US.MSFT/USD", 72 hours, 469.8035e18);
24-
checkPriceNoOlderThan("Equity.US.TSLA/USD", 300 hours, 360.02978e18);
25-
checkPriceNoOlderThan("Equity.US.NVDA/USD", 1000 hours, 104.5623e18);
26-
checkPriceNoOlderThan("Equity.US.META/USD", 8000 hours, 448.73e18);
23+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.GOOG/USD"), 72 hours, 172.3176e18);
24+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.AMZN/USD"), 500 hours, 205.06198e18);
25+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.AAPL/USD"), 72 hours, 202.86002e18);
26+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.MSFT/USD"), 72 hours, 469.8035e18);
27+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.TSLA/USD"), 300 hours, 360.02978e18);
28+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.NVDA/USD"), 1000 hours, 104.5623e18);
29+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.META/USD"), 8000 hours, 448.73e18);
2730
vm.createSelectFork(FORK_RPC_URL_BASE, FORK_BLOCK_BASE);
28-
checkPriceNoOlderThan("Equity.US.GOOG/USD", 72 hours, 174.93179e18);
29-
checkPriceNoOlderThan("Equity.US.AMZN/USD", 500 hours, 207.372e18);
30-
checkPriceNoOlderThan("Equity.US.AAPL/USD", 72 hours, 205.12e18);
31-
checkPriceNoOlderThan("Equity.US.MSFT/USD", 300 hours, 458.35309e18);
32-
checkPriceNoOlderThan("Equity.US.TSLA/USD", 72 hours, 301.47341e18);
33-
checkPriceNoOlderThan("Equity.US.NVDA/USD", 72 hours, 141.66994e18);
34-
checkPriceNoOlderThan("Equity.US.META/USD", 72 hours, 693.349e18);
31+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.GOOG/USD"), 72 hours, 174.93179e18);
32+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.AMZN/USD"), 500 hours, 207.372e18);
33+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.AAPL/USD"), 72 hours, 205.12e18);
34+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.MSFT/USD"), 300 hours, 458.35309e18);
35+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.TSLA/USD"), 72 hours, 301.47341e18);
36+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.NVDA/USD"), 72 hours, 141.66994e18);
37+
checkPriceNoOlderThan(LibIntOrAString.fromString2("Equity.US.META/USD"), 72 hours, 693.349e18);
3538
}
3639
}

0 commit comments

Comments
 (0)