Skip to content

Commit c0c0394

Browse files
authored
Update price evm Oracle Example (#1411)
1 parent c2fde0f commit c0c0394

File tree

6 files changed

+83
-35
lines changed

6 files changed

+83
-35
lines changed

target_chains/ethereum/examples/oracle_swap/README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,20 @@ All of the commands in this section expect to be run from the `contract` directo
1717
### Building
1818

1919
You need to have [Foundry](https://getfoundry.sh/) and `node` installed to run this example.
20-
Once you have installed these tools, run the following commands from the [`contract`](./contract) directory:
20+
Once you have installed these tools, run the following commands from the [`contract`](./contract) directory to install openzeppelin and forge dependencies:
2121

2222
```
23-
forge install foundry-rs/forge-std@2c7cbfc6fbede6d7c9e6b17afe997e3fdfe22fef --no-git --no-commit
24-
forge install pyth-network/[email protected] --no-git --no-commit
23+
forge install foundry-rs/[email protected] --no-git --no-commit
2524
forge install OpenZeppelin/[email protected] --no-git --no-commit
2625
```
2726

27+
After installing the above dependencies, you need to install pyth-sdk-solidity.
28+
29+
```
30+
npm init -y
31+
npm install @pythnetwork/pyth-sdk-solidity
32+
```
33+
2834
### Testing
2935

3036
Simply run `forge test` in the [`contract`](./contract) directory. This command will run the

target_chains/ethereum/examples/oracle_swap/contract/package-lock.json

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "contract",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"directories": {
7+
"lib": "lib",
8+
"test": "test"
9+
},
10+
"scripts": {
11+
"test": "echo \"Error: no test specified\" && exit 1"
12+
},
13+
"keywords": [],
14+
"author": "",
15+
"license": "ISC",
16+
"dependencies": {
17+
"@pythnetwork/pyth-sdk-solidity": "^3.0.0"
18+
}
19+
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
ds-test/=lib/forge-std/lib/ds-test/src/
1+
ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/
2+
erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/
23
forge-std/=lib/forge-std/src/
3-
pyth-sdk-solidity/=lib/pyth-sdk-solidity/
44
openzeppelin-contracts/=lib/openzeppelin-contracts/
5+
@pythnetwork=node_modules/@pythnetwork

target_chains/ethereum/examples/oracle_swap/contract/src/OracleSwap.sol

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// SPDX-License-Identifier: UNLICENSED
22
pragma solidity ^0.8.0;
33

4-
import "pyth-sdk-solidity/IPyth.sol";
5-
import "pyth-sdk-solidity/PythStructs.sol";
4+
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
5+
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
6+
import "@pythnetwork/pyth-sdk-solidity/PythUtils.sol";
67
import "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
78

89
// Example oracle AMM powered by Pyth price feeds.
@@ -17,7 +18,12 @@ import "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
1718
// some quantity of both the base and quote token in order to function properly (using the ERC20 transfer function to
1819
// the contract's address).
1920
contract OracleSwap {
20-
event Transfer(address from, address to, uint amountUsd, uint amountWei);
21+
event Transfer(
22+
address from,
23+
address to,
24+
uint256 amountUsd,
25+
uint256 amountWei
26+
);
2127

2228
IPyth pyth;
2329

@@ -53,10 +59,10 @@ contract OracleSwap {
5359
// See the frontend code for an example of how to retrieve this data and pass it to this function.
5460
function swap(
5561
bool isBuy,
56-
uint size,
62+
uint256 size,
5763
bytes[] calldata pythUpdateData
5864
) external payable {
59-
uint updateFee = pyth.getUpdateFee(pythUpdateData);
65+
uint256 updateFee = pyth.getUpdateFee(pythUpdateData);
6066
pyth.updatePriceFeeds{value: updateFee}(pythUpdateData);
6167

6268
PythStructs.Price memory currentBasePrice = pyth.getPrice(
@@ -69,8 +75,16 @@ contract OracleSwap {
6975
// Note: this code does all arithmetic with 18 decimal points. This approach should be fine for most
7076
// price feeds, which typically have ~8 decimals. You can check the exponent on the price feed to ensure
7177
// this doesn't lose precision.
72-
uint256 basePrice = convertToUint(currentBasePrice, 18);
73-
uint256 quotePrice = convertToUint(currentQuotePrice, 18);
78+
uint256 basePrice = PythUtils.convertToUint(
79+
currentBasePrice.price,
80+
currentBasePrice.expo,
81+
18
82+
);
83+
uint256 quotePrice = PythUtils.convertToUint(
84+
currentQuotePrice.price,
85+
currentQuotePrice.expo,
86+
18
87+
);
7488

7589
// This computation loses precision. The infinite-precision result is between [quoteSize, quoteSize + 1]
7690
// We need to round this result in favor of the contract.
@@ -90,28 +104,6 @@ contract OracleSwap {
90104
}
91105
}
92106

93-
// TODO: we should probably move something like this into the solidity sdk
94-
function convertToUint(
95-
PythStructs.Price memory price,
96-
uint8 targetDecimals
97-
) private pure returns (uint256) {
98-
if (price.price < 0 || price.expo > 0 || price.expo < -255) {
99-
revert();
100-
}
101-
102-
uint8 priceDecimals = uint8(uint32(-1 * price.expo));
103-
104-
if (targetDecimals >= priceDecimals) {
105-
return
106-
uint(uint64(price.price)) *
107-
10 ** uint32(targetDecimals - priceDecimals);
108-
} else {
109-
return
110-
uint(uint64(price.price)) /
111-
10 ** uint32(priceDecimals - targetDecimals);
112-
}
113-
}
114-
115107
// Get the number of base tokens in the pool
116108
function baseBalance() public view returns (uint256) {
117109
return baseToken.balanceOf(address(this));

target_chains/ethereum/examples/oracle_swap/contract/test/OracleSwap.t.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pragma solidity ^0.8.0;
33

44
import "forge-std/Test.sol";
55
import "../src/OracleSwap.sol";
6-
import "pyth-sdk-solidity/MockPyth.sol";
6+
import "@pythnetwork/pyth-sdk-solidity/MockPyth.sol";
77
import "openzeppelin-contracts/contracts/mocks/ERC20Mock.sol";
88

99
contract OracleSwapTest is Test {
@@ -84,6 +84,7 @@ contract OracleSwapTest is Test {
8484
-5,
8585
basePrice * 100000,
8686
10 * 100000,
87+
uint64(block.timestamp),
8788
uint64(block.timestamp)
8889
);
8990
updateData[1] = mockPyth.createPriceFeedUpdateData(
@@ -93,6 +94,7 @@ contract OracleSwapTest is Test {
9394
-5,
9495
quotePrice * 100000,
9596
10 * 100000,
97+
uint64(block.timestamp),
9698
uint64(block.timestamp)
9799
);
98100

0 commit comments

Comments
 (0)