Skip to content

Commit ebfef91

Browse files
authored
Use saturating_sub instead of overflowing sub (#54)
* Use saturating_sub instead of overflowing sub Also adds tests
1 parent 2114b36 commit ebfef91

File tree

7 files changed

+35
-17
lines changed

7 files changed

+35
-17
lines changed

.github/workflows/pyth-sdk-solana.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
steps:
1919
- uses: actions/checkout@v2
2020
- name: Install dependencies
21-
run: sudo apt-get install libudev-dev
21+
run: sudo apt-get update && sudo apt-get install libudev-dev
2222
- name: Build
2323
run: cargo build --verbose
2424
- name: Run tests
@@ -31,7 +31,7 @@ jobs:
3131
steps:
3232
- uses: actions/checkout@v2
3333
- name: Install dependencies
34-
run: sudo apt-get install libudev-dev
34+
run: sudo apt-get update && sudo apt-get install libudev-dev
3535
- name: Install Solana Binaries
3636
run: |
3737
sh -c "$(curl -sSfL https://release.solana.com/v1.8.14/install)"

.github/workflows/pyth-sdk-terra.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
steps:
1919
- uses: actions/checkout@v2
2020
- name: Install dependencies
21-
run: sudo apt-get install libudev-dev
21+
run: sudo apt-get update && sudo apt-get install libudev-dev
2222
- name: Build
2323
run: cargo build --verbose
2424
- name: Run tests

.github/workflows/pyth-sdk.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
steps:
2121
- uses: actions/checkout@v2
2222
- name: Install dependencies
23-
run: sudo apt-get install libudev-dev
23+
run: sudo apt-get update && sudo apt-get install libudev-dev
2424
- name: Build
2525
run: cargo build --verbose
2626
- name: Run tests

pyth-sdk-solana/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pyth-sdk-solana"
3-
version = "0.4.0"
3+
version = "0.4.1"
44
authors = ["Pyth Data Foundation"]
55
edition = "2018"
66
license = "Apache-2.0"

pyth-sdk-solana/src/state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ impl PriceAccount {
350350

351351
#[cfg(target_arch = "bpf")]
352352
if matches!(status, PriceStatus::Trading)
353-
&& Clock::get().unwrap().slot - self.agg.pub_slot > VALID_SLOT_PERIOD
353+
&& Clock::get().unwrap().slot.saturating_sub(self.agg.pub_slot) > VALID_SLOT_PERIOD
354354
{
355355
status = PriceStatus::Unknown;
356356
}

pyth-sdk-solana/test-contract/tests/common.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@ use test_contract::processor::process_instruction;
77

88
// Panics if running instruction fails
99
pub async fn test_instr_exec_ok(instr: Instruction) {
10-
let (mut banks_client, payer, recent_blockhash) =
11-
ProgramTest::new("test_contract", id(), processor!(process_instruction))
12-
.start()
13-
.await;
14-
let mut transaction = Transaction::new_with_payer(&[instr], Some(&payer.pubkey()));
15-
transaction.sign(&[&payer], recent_blockhash);
16-
banks_client.process_transaction(transaction).await.unwrap()
10+
let mut context = ProgramTest::new("test_contract", id(), processor!(process_instruction))
11+
.start_with_context()
12+
.await;
13+
14+
context.warp_to_slot(1000).unwrap();
15+
16+
let mut transaction = Transaction::new_with_payer(&[instr], Some(&context.payer.pubkey()));
17+
transaction.sign(&[&context.payer], context.last_blockhash);
18+
context
19+
.banks_client
20+
.process_transaction(transaction)
21+
.await
22+
.unwrap()
1723
}

pyth-sdk-solana/test-contract/tests/stale_price.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use pyth_sdk_solana::state::{
55
MAGIC,
66
VERSION_2,
77
};
8+
use pyth_sdk_solana::VALID_SLOT_PERIOD;
89
use solana_program_test::*;
910
use test_contract::instruction;
1011

@@ -25,6 +26,20 @@ fn price_account_all_zero() -> PriceAccount {
2526
#[tokio::test]
2627
async fn test_price_not_stale() {
2728
let mut price = price_account_all_zero();
29+
price.agg.pub_slot = 1000 - 10;
30+
price.agg.status = PriceStatus::Trading;
31+
test_instr_exec_ok(instruction::price_status_check(
32+
&price,
33+
PriceStatus::Trading,
34+
))
35+
.await;
36+
}
37+
38+
39+
#[tokio::test]
40+
async fn test_price_not_stale_future() {
41+
let mut price = price_account_all_zero();
42+
price.agg.pub_slot = 1000 + 10;
2843
price.agg.status = PriceStatus::Trading;
2944
test_instr_exec_ok(instruction::price_status_check(
3045
&price,
@@ -38,10 +53,7 @@ async fn test_price_not_stale() {
3853
async fn test_price_stale() {
3954
let mut price = price_account_all_zero();
4055
price.agg.status = PriceStatus::Trading;
41-
// Value 100 will cause an overflow because this is bigger than Solana slot in the test suite
42-
// (its ~1-5). As the check will be 5u - 100u ~= 1e18 > MAX_SLOT_DIFFERENCE. It can only
43-
// break when Solana slot in the test suite becomes between 100 and 100+MAX_SLOT_DIFFERENCE.
44-
price.agg.pub_slot = 100;
56+
price.agg.pub_slot = 1000 - VALID_SLOT_PERIOD - 1;
4557

4658
#[cfg(feature = "test-bpf")] // Only in BPF the clock check is performed
4759
let expected_status = PriceStatus::Unknown;

0 commit comments

Comments
 (0)