MockEntropy.t.sol 7.3 KB

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