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
This commit is contained in:
parent
9328b73284
commit
77db9ee53b
|
@ -59453,7 +59453,47 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"abi_generator": "*",
|
"abi_generator": "*",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"prettier-plugin-solidity": "^1.0.0-rc.1"
|
"prettier-plugin-solidity": "^1.0.0-rc.1",
|
||||||
|
"solc": "^0.8.25"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"target_chains/ethereum/sdk/solidity/node_modules/commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"target_chains/ethereum/sdk/solidity/node_modules/semver": {
|
||||||
|
"version": "5.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"target_chains/ethereum/sdk/solidity/node_modules/solc": {
|
||||||
|
"version": "0.8.25",
|
||||||
|
"resolved": "https://registry.npmjs.org/solc/-/solc-0.8.25.tgz",
|
||||||
|
"integrity": "sha512-7P0TF8gPeudl1Ko3RGkyY6XVCxe2SdD/qQhtns1vl3yAbK/PDifKDLHGtx1t7mX3LgR7ojV7Fg/Kc6Q9D2T8UQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"command-exists": "^1.2.8",
|
||||||
|
"commander": "^8.1.0",
|
||||||
|
"follow-redirects": "^1.12.1",
|
||||||
|
"js-sha3": "0.8.0",
|
||||||
|
"memorystream": "^0.3.1",
|
||||||
|
"semver": "^5.5.0",
|
||||||
|
"tmp": "0.0.33"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"solcjs": "solc.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"target_chains/solana/sdk/js/pyth_solana_receiver": {
|
"target_chains/solana/sdk/js/pyth_solana_receiver": {
|
||||||
|
@ -71066,7 +71106,37 @@
|
||||||
"requires": {
|
"requires": {
|
||||||
"abi_generator": "*",
|
"abi_generator": "*",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"prettier-plugin-solidity": "^1.0.0-rc.1"
|
"prettier-plugin-solidity": "^1.0.0-rc.1",
|
||||||
|
"solc": "*"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"solc": {
|
||||||
|
"version": "0.8.25",
|
||||||
|
"resolved": "https://registry.npmjs.org/solc/-/solc-0.8.25.tgz",
|
||||||
|
"integrity": "sha512-7P0TF8gPeudl1Ko3RGkyY6XVCxe2SdD/qQhtns1vl3yAbK/PDifKDLHGtx1t7mX3LgR7ojV7Fg/Kc6Q9D2T8UQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"command-exists": "^1.2.8",
|
||||||
|
"commander": "^8.1.0",
|
||||||
|
"follow-redirects": "^1.12.1",
|
||||||
|
"js-sha3": "0.8.0",
|
||||||
|
"memorystream": "^0.3.1",
|
||||||
|
"semver": "^5.5.0",
|
||||||
|
"tmp": "0.0.33"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@pythnetwork/pyth-solana-receiver": {
|
"@pythnetwork/pyth-solana-receiver": {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
|
||||||
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
|
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
|
||||||
import "@pythnetwork/pyth-sdk-solidity/IPythEvents.sol";
|
import "@pythnetwork/pyth-sdk-solidity/IPythEvents.sol";
|
||||||
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
|
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
|
||||||
|
import "@pythnetwork/pyth-sdk-solidity/PythUtils.sol";
|
||||||
|
|
||||||
import "forge-std/Test.sol";
|
import "forge-std/Test.sol";
|
||||||
import "./WormholeTestUtils.t.sol";
|
import "./WormholeTestUtils.t.sol";
|
||||||
|
@ -275,3 +276,35 @@ abstract contract PythTestUtils is Test, WormholeTestUtils, RandTestUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contract PythUtilsTest is Test, WormholeTestUtils, PythTestUtils, IPythEvents {
|
||||||
|
function testConvertToUnit() public {
|
||||||
|
// Price can't be negative
|
||||||
|
vm.expectRevert();
|
||||||
|
PythUtils.convertToUint(-100, -5, 18);
|
||||||
|
|
||||||
|
// Exponent can't be positive
|
||||||
|
vm.expectRevert();
|
||||||
|
PythUtils.convertToUint(100, 5, 18);
|
||||||
|
|
||||||
|
// Price with 18 decimals and exponent -5
|
||||||
|
assertEq(
|
||||||
|
PythUtils.convertToUint(100, -5, 18),
|
||||||
|
1000000000000000 // 100 * 10^13
|
||||||
|
);
|
||||||
|
|
||||||
|
// Price with 9 decimals and exponent -2
|
||||||
|
assertEq(
|
||||||
|
PythUtils.convertToUint(100, -2, 9),
|
||||||
|
1000000000 // 100 * 10^7
|
||||||
|
);
|
||||||
|
|
||||||
|
// Price with 4 decimals and exponent -5
|
||||||
|
assertEq(PythUtils.convertToUint(100, -5, 4), 10);
|
||||||
|
|
||||||
|
// Price with 5 decimals and exponent -2
|
||||||
|
// @note: We will lose precision here as price is
|
||||||
|
// 0.00001 and we are targetDecimals is 2.
|
||||||
|
assertEq(PythUtils.convertToUint(100, -5, 2), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
pragma solidity ^0.8.0;
|
||||||
|
|
||||||
|
library PythUtils {
|
||||||
|
/// @notice Converts a Pyth price to a uint256 with a target number of decimals
|
||||||
|
/// @param price The Pyth price
|
||||||
|
/// @param expo The Pyth price exponent
|
||||||
|
/// @param targetDecimals The target number of decimals
|
||||||
|
/// @return The price as a uint256
|
||||||
|
/// @dev Function will lose precision if targetDecimals is less than the Pyth price decimals.
|
||||||
|
/// This method will truncate any digits that cannot be represented by the targetDecimals.
|
||||||
|
/// e.g. If the price is 0.000123 and the targetDecimals is 2, the result will be 0
|
||||||
|
function convertToUint(
|
||||||
|
int64 price,
|
||||||
|
int32 expo,
|
||||||
|
uint8 targetDecimals
|
||||||
|
) public pure returns (uint256) {
|
||||||
|
if (price < 0 || expo > 0 || expo < -255) {
|
||||||
|
revert();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 priceDecimals = uint8(uint32(-1 * expo));
|
||||||
|
|
||||||
|
if (targetDecimals >= priceDecimals) {
|
||||||
|
return
|
||||||
|
uint(uint64(price)) *
|
||||||
|
10 ** uint32(targetDecimals - priceDecimals);
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
uint(uint64(price)) /
|
||||||
|
10 ** uint32(priceDecimals - targetDecimals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "int64",
|
||||||
|
"name": "price",
|
||||||
|
"type": "int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "int32",
|
||||||
|
"name": "expo",
|
||||||
|
"type": "int32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint8",
|
||||||
|
"name": "targetDecimals",
|
||||||
|
"type": "uint8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "convertToUint",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
]
|
|
@ -9,7 +9,7 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"format": "npx prettier --write .",
|
"format": "npx prettier --write .",
|
||||||
"generate-abi": "npx generate-abis IPyth IPythEvents AbstractPyth MockPyth PythErrors",
|
"generate-abi": "npx generate-abis IPyth IPythEvents AbstractPyth MockPyth PythErrors PythUtils",
|
||||||
"check-abi": "git diff --exit-code abis",
|
"check-abi": "git diff --exit-code abis",
|
||||||
"build": "solcjs --bin MockPyth.sol --base-path . -o build/"
|
"build": "solcjs --bin MockPyth.sol --base-path . -o build/"
|
||||||
},
|
},
|
||||||
|
@ -25,8 +25,9 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity",
|
"homepage": "https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"abi_generator": "*",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"prettier-plugin-solidity": "^1.0.0-rc.1",
|
"prettier-plugin-solidity": "^1.0.0-rc.1",
|
||||||
"abi_generator": "*"
|
"solc": "^0.8.25"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue