Skip to content

Commit e6768c8

Browse files
committed
Merge branch 'main' of github.com:pyth-network/pyth-crosschain into mike/agent-jrpc-id
2 parents 299481e + dde5629 commit e6768c8

File tree

9 files changed

+433
-16
lines changed

9 files changed

+433
-16
lines changed

Cargo.lock

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

lazer/contracts/solana/programs/pyth-lazer-solana-contract/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ no-log-ix-name = []
1919
idl-build = ["anchor-lang/idl-build"]
2020

2121
[dependencies]
22-
pyth-lazer-protocol = { path = "../../../../sdk/rust/protocol", version = "0.18.0" }
22+
pyth-lazer-protocol = { path = "../../../../sdk/rust/protocol", version = "0.18.1" }
2323

2424
anchor-lang = "0.31.1"
2525
bytemuck = { version = "1.20.0", features = ["derive"] }

lazer/publisher_sdk/rust/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
[package]
22
name = "pyth-lazer-publisher-sdk"
3-
version = "0.16.0"
3+
version = "0.16.1"
44
edition = "2021"
55
description = "Pyth Lazer Publisher SDK types."
66
license = "Apache-2.0"
77
repository = "https://github.com/pyth-network/pyth-crosschain"
88

99
[dependencies]
10-
pyth-lazer-protocol = { version = "0.18.0", path = "../../sdk/rust/protocol" }
10+
pyth-lazer-protocol = { version = "0.18.1", path = "../../sdk/rust/protocol" }
1111
anyhow = "1.0.98"
1212
protobuf = "3.7.2"
1313
serde_json = "1.0.140"

lazer/sdk/rust/client/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[package]
22
name = "pyth-lazer-client"
3-
version = "8.4.0"
3+
version = "8.4.1"
44
edition = "2021"
55
description = "A Rust client for Pyth Lazer"
66
license = "Apache-2.0"
77

88
[dependencies]
9-
pyth-lazer-protocol = { path = "../protocol", version = "0.18.0" }
9+
pyth-lazer-protocol = { path = "../protocol", version = "0.18.1" }
1010
tokio = { version = "1", features = ["full"] }
1111
tokio-tungstenite = { version = "0.20", features = ["native-tls"] }
1212
futures-util = "0.3"

lazer/sdk/rust/protocol/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-lazer-protocol"
3-
version = "0.18.0"
3+
version = "0.18.1"
44
edition = "2021"
55
description = "Pyth Lazer SDK - protocol types."
66
license = "Apache-2.0"

lazer/sdk/rust/protocol/src/jrpc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{api::Channel, price::Price};
66
use serde::{Deserialize, Serialize};
77
use std::time::Duration;
88

9-
#[derive(Serialize, Deserialize, Debug, Default, Eq, PartialEq)]
9+
#[derive(Serialize, Deserialize, Clone, Debug, Default, Eq, PartialEq)]
1010
#[serde(untagged)]
1111
pub enum JrpcId {
1212
String(String),
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// SPDX-License-Identifier: Apache 2
2+
pragma solidity ^0.8.0;
3+
4+
import "forge-std/Test.sol";
5+
import "@pythnetwork/entropy-sdk-solidity/MockEntropy.sol";
6+
import "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol";
7+
import "@pythnetwork/entropy-sdk-solidity/EntropyStructsV2.sol";
8+
9+
contract MockEntropyConsumer is IEntropyConsumer {
10+
address public entropy;
11+
bytes32 public lastRandomNumber;
12+
uint64 public lastSequenceNumber;
13+
address public lastProvider;
14+
uint256 public callbackCount;
15+
16+
constructor(address _entropy) {
17+
entropy = _entropy;
18+
}
19+
20+
function requestRandomNumber() external payable returns (uint64) {
21+
return MockEntropy(entropy).requestV2{value: msg.value}();
22+
}
23+
24+
function requestRandomNumberWithGasLimit(
25+
uint32 gasLimit
26+
) external payable returns (uint64) {
27+
return MockEntropy(entropy).requestV2{value: msg.value}(gasLimit);
28+
}
29+
30+
function requestRandomNumberFromProvider(
31+
address provider,
32+
uint32 gasLimit
33+
) external payable returns (uint64) {
34+
return
35+
MockEntropy(entropy).requestV2{value: msg.value}(
36+
provider,
37+
gasLimit
38+
);
39+
}
40+
41+
function getEntropy() internal view override returns (address) {
42+
return entropy;
43+
}
44+
45+
function entropyCallback(
46+
uint64 sequenceNumber,
47+
address provider,
48+
bytes32 randomNumber
49+
) internal override {
50+
lastSequenceNumber = sequenceNumber;
51+
lastProvider = provider;
52+
lastRandomNumber = randomNumber;
53+
callbackCount += 1;
54+
}
55+
}
56+
57+
contract MockEntropyTest is Test {
58+
MockEntropy public entropy;
59+
MockEntropyConsumer public consumer;
60+
address public provider;
61+
62+
function setUp() public {
63+
provider = address(0x1234);
64+
entropy = new MockEntropy(provider);
65+
consumer = new MockEntropyConsumer(address(entropy));
66+
}
67+
68+
function testBasicRequestAndReveal() public {
69+
uint64 seq = consumer.requestRandomNumber();
70+
assertEq(seq, 1, "Sequence number should be 1");
71+
72+
bytes32 randomNumber = bytes32(uint256(42));
73+
entropy.mockReveal(provider, seq, randomNumber);
74+
75+
assertEq(
76+
consumer.lastSequenceNumber(),
77+
seq,
78+
"Callback sequence number mismatch"
79+
);
80+
assertEq(
81+
consumer.lastProvider(),
82+
provider,
83+
"Callback provider mismatch"
84+
);
85+
assertEq(
86+
consumer.lastRandomNumber(),
87+
randomNumber,
88+
"Random number mismatch"
89+
);
90+
assertEq(consumer.callbackCount(), 1, "Callback should be called once");
91+
}
92+
93+
function testDifferentInterleavings() public {
94+
uint64 seq1 = consumer.requestRandomNumber();
95+
uint64 seq2 = consumer.requestRandomNumber();
96+
uint64 seq3 = consumer.requestRandomNumber();
97+
98+
assertEq(seq1, 1, "First sequence should be 1");
99+
assertEq(seq2, 2, "Second sequence should be 2");
100+
assertEq(seq3, 3, "Third sequence should be 3");
101+
102+
bytes32 random2 = bytes32(uint256(200));
103+
bytes32 random3 = bytes32(uint256(300));
104+
bytes32 random1 = bytes32(uint256(100));
105+
106+
entropy.mockReveal(provider, seq2, random2);
107+
assertEq(
108+
consumer.lastRandomNumber(),
109+
random2,
110+
"Should reveal seq2 first"
111+
);
112+
assertEq(consumer.lastSequenceNumber(), seq2, "Sequence should be 2");
113+
114+
entropy.mockReveal(provider, seq3, random3);
115+
assertEq(
116+
consumer.lastRandomNumber(),
117+
random3,
118+
"Should reveal seq3 second"
119+
);
120+
assertEq(consumer.lastSequenceNumber(), seq3, "Sequence should be 3");
121+
122+
entropy.mockReveal(provider, seq1, random1);
123+
assertEq(
124+
consumer.lastRandomNumber(),
125+
random1,
126+
"Should reveal seq1 last"
127+
);
128+
assertEq(consumer.lastSequenceNumber(), seq1, "Sequence should be 1");
129+
130+
assertEq(
131+
consumer.callbackCount(),
132+
3,
133+
"All three callbacks should be called"
134+
);
135+
}
136+
137+
function testDifferentProviders() public {
138+
address provider2 = address(0x5678);
139+
140+
uint64 seq1 = consumer.requestRandomNumberFromProvider(
141+
provider,
142+
100000
143+
);
144+
uint64 seq2 = consumer.requestRandomNumberFromProvider(
145+
provider2,
146+
100000
147+
);
148+
149+
assertEq(seq1, 1, "Provider 1 first sequence should be 1");
150+
assertEq(seq2, 1, "Provider 2 first sequence should be 1");
151+
152+
bytes32 random1 = bytes32(uint256(111));
153+
bytes32 random2 = bytes32(uint256(222));
154+
155+
entropy.mockReveal(provider, seq1, random1);
156+
assertEq(
157+
consumer.lastRandomNumber(),
158+
random1,
159+
"First provider random number"
160+
);
161+
162+
entropy.mockReveal(provider2, seq2, random2);
163+
assertEq(
164+
consumer.lastRandomNumber(),
165+
random2,
166+
"Second provider random number"
167+
);
168+
}
169+
170+
function testRequestWithGasLimit() public {
171+
uint64 seq = consumer.requestRandomNumberWithGasLimit(200000);
172+
173+
assertEq(seq, 1, "Sequence should be 1");
174+
175+
EntropyStructsV2.Request memory req = entropy.getRequestV2(
176+
provider,
177+
seq
178+
);
179+
assertEq(req.gasLimit10k, 20, "Gas limit should be 20 (200k / 10k)");
180+
181+
bytes32 randomNumber = bytes32(uint256(999));
182+
entropy.mockReveal(provider, seq, randomNumber);
183+
184+
assertEq(
185+
consumer.lastRandomNumber(),
186+
randomNumber,
187+
"Random number should match"
188+
);
189+
}
190+
191+
function testGetProviderInfo() public {
192+
EntropyStructsV2.ProviderInfo memory info = entropy.getProviderInfoV2(
193+
provider
194+
);
195+
assertEq(info.feeInWei, 1, "Fee should be 1");
196+
assertEq(
197+
info.defaultGasLimit,
198+
100000,
199+
"Default gas limit should be 100000"
200+
);
201+
assertEq(info.sequenceNumber, 1, "Sequence number should start at 1");
202+
}
203+
204+
function testGetDefaultProvider() public {
205+
assertEq(
206+
entropy.getDefaultProvider(),
207+
provider,
208+
"Default provider should match"
209+
);
210+
}
211+
212+
function testFeesReturnZero() public {
213+
assertEq(entropy.getFeeV2(), 0, "getFeeV2() should return 0");
214+
assertEq(
215+
entropy.getFeeV2(100000),
216+
0,
217+
"getFeeV2(gasLimit) should return 0"
218+
);
219+
assertEq(
220+
entropy.getFeeV2(provider, 100000),
221+
0,
222+
"getFeeV2(provider, gasLimit) should return 0"
223+
);
224+
}
225+
226+
function testCustomRandomNumbers() public {
227+
uint64 seq = consumer.requestRandomNumber();
228+
229+
bytes32[] memory randomNumbers = new bytes32[](3);
230+
randomNumbers[0] = bytes32(uint256(0));
231+
randomNumbers[1] = bytes32(type(uint256).max);
232+
randomNumbers[2] = keccak256("custom random value");
233+
234+
for (uint i = 0; i < randomNumbers.length; i++) {
235+
if (i > 0) {
236+
seq = consumer.requestRandomNumber();
237+
}
238+
entropy.mockReveal(provider, seq, randomNumbers[i]);
239+
assertEq(
240+
consumer.lastRandomNumber(),
241+
randomNumbers[i],
242+
"Custom random number should match"
243+
);
244+
}
245+
}
246+
}

0 commit comments

Comments
 (0)