Skip to content

Commit 44a0225

Browse files
committed
feat(target_chains/ethereum/sdk/solidity): add convertToUint method to the sdk (#1390)
* Moving convertToUint to utils * pre-commit fix * reversing OracleSwap example * pre-commit] * added test * abi-gen * Added solc to sdk * resolved comments
1 parent 267f8e0 commit 44a0225

File tree

5 files changed

+173
-4
lines changed

5 files changed

+173
-4
lines changed

package-lock.json

Lines changed: 72 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

target_chains/ethereum/contracts/forge-test/utils/PythTestUtils.t.sol

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
1212
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
1313
import "@pythnetwork/pyth-sdk-solidity/IPythEvents.sol";
1414
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
15+
import "@pythnetwork/pyth-sdk-solidity/PythUtils.sol";
1516

1617
import "forge-std/Test.sol";
1718
import "./WormholeTestUtils.t.sol";
@@ -275,3 +276,35 @@ abstract contract PythTestUtils is Test, WormholeTestUtils, RandTestUtils {
275276
}
276277
}
277278
}
279+
280+
contract PythUtilsTest is Test, WormholeTestUtils, PythTestUtils, IPythEvents {
281+
function testConvertToUnit() public {
282+
// Price can't be negative
283+
vm.expectRevert();
284+
PythUtils.convertToUint(-100, -5, 18);
285+
286+
// Exponent can't be positive
287+
vm.expectRevert();
288+
PythUtils.convertToUint(100, 5, 18);
289+
290+
// Price with 18 decimals and exponent -5
291+
assertEq(
292+
PythUtils.convertToUint(100, -5, 18),
293+
1000000000000000 // 100 * 10^13
294+
);
295+
296+
// Price with 9 decimals and exponent -2
297+
assertEq(
298+
PythUtils.convertToUint(100, -2, 9),
299+
1000000000 // 100 * 10^7
300+
);
301+
302+
// Price with 4 decimals and exponent -5
303+
assertEq(PythUtils.convertToUint(100, -5, 4), 10);
304+
305+
// Price with 5 decimals and exponent -2
306+
// @note: We will lose precision here as price is
307+
// 0.00001 and we are targetDecimals is 2.
308+
assertEq(PythUtils.convertToUint(100, -5, 2), 0);
309+
}
310+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.0;
3+
4+
library PythUtils {
5+
/// @notice Converts a Pyth price to a uint256 with a target number of decimals
6+
/// @param price The Pyth price
7+
/// @param expo The Pyth price exponent
8+
/// @param targetDecimals The target number of decimals
9+
/// @return The price as a uint256
10+
/// @dev Function will lose precision if targetDecimals is less than the Pyth price decimals.
11+
/// This method will truncate any digits that cannot be represented by the targetDecimals.
12+
/// e.g. If the price is 0.000123 and the targetDecimals is 2, the result will be 0
13+
function convertToUint(
14+
int64 price,
15+
int32 expo,
16+
uint8 targetDecimals
17+
) public pure returns (uint256) {
18+
if (price < 0 || expo > 0 || expo < -255) {
19+
revert();
20+
}
21+
22+
uint8 priceDecimals = uint8(uint32(-1 * expo));
23+
24+
if (targetDecimals >= priceDecimals) {
25+
return
26+
uint(uint64(price)) *
27+
10 ** uint32(targetDecimals - priceDecimals);
28+
} else {
29+
return
30+
uint(uint64(price)) /
31+
10 ** uint32(priceDecimals - targetDecimals);
32+
}
33+
}
34+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[
2+
{
3+
"inputs": [
4+
{
5+
"internalType": "int64",
6+
"name": "price",
7+
"type": "int64"
8+
},
9+
{
10+
"internalType": "int32",
11+
"name": "expo",
12+
"type": "int32"
13+
},
14+
{
15+
"internalType": "uint8",
16+
"name": "targetDecimals",
17+
"type": "uint8"
18+
}
19+
],
20+
"name": "convertToUint",
21+
"outputs": [
22+
{
23+
"internalType": "uint256",
24+
"name": "",
25+
"type": "uint256"
26+
}
27+
],
28+
"stateMutability": "pure",
29+
"type": "function"
30+
}
31+
]

target_chains/ethereum/sdk/solidity/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
"scripts": {
1111
"format": "npx prettier --write .",
12-
"generate-abi": "npx generate-abis IPyth IPythEvents AbstractPyth MockPyth PythErrors",
12+
"generate-abi": "npx generate-abis IPyth IPythEvents AbstractPyth MockPyth PythErrors PythUtils",
1313
"check-abi": "git diff --exit-code abis",
1414
"build": "solcjs --bin MockPyth.sol --base-path . -o build/"
1515
},
@@ -25,8 +25,9 @@
2525
},
2626
"homepage": "https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity",
2727
"devDependencies": {
28+
"abi_generator": "*",
2829
"prettier": "^2.7.1",
2930
"prettier-plugin-solidity": "^1.0.0-rc.1",
30-
"abi_generator": "*"
31+
"solc": "^0.8.25"
3132
}
3233
}

0 commit comments

Comments
 (0)