Entropy.t.sol 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948
  1. // SPDX-License-Identifier: Apache 2
  2. pragma solidity ^0.8.0;
  3. import "forge-std/Test.sol";
  4. import "@pythnetwork/entropy-sdk-solidity/EntropyStructs.sol";
  5. import "@pythnetwork/entropy-sdk-solidity/EntropyStructsV2.sol";
  6. import "@pythnetwork/entropy-sdk-solidity/EntropyEvents.sol";
  7. import "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol";
  8. import "@pythnetwork/entropy-sdk-solidity/IEntropy.sol";
  9. import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
  10. import "./utils/EntropyTestUtils.t.sol";
  11. import "../contracts/entropy/EntropyUpgradable.sol";
  12. import "@pythnetwork/entropy-sdk-solidity/EntropyStatusConstants.sol";
  13. import "@pythnetwork/entropy-sdk-solidity/EntropyEventsV2.sol";
  14. // TODO
  15. // - fuzz test?
  16. contract EntropyTest is Test, EntropyTestUtils, EntropyEvents, EntropyEventsV2 {
  17. ERC1967Proxy public proxy;
  18. EntropyUpgradable public random;
  19. uint128 pythFeeInWei = 7;
  20. address public provider1 = address(1);
  21. bytes32[] provider1Proofs;
  22. uint128 provider1FeeInWei = 8;
  23. uint64 provider1ChainLength = 1000;
  24. uint32 provider1MaxNumHashes = 500;
  25. bytes provider1Uri = bytes("https://foo.com");
  26. bytes provider1CommitmentMetadata = hex"0100";
  27. address public provider2 = address(2);
  28. bytes32[] provider2Proofs;
  29. uint128 provider2FeeInWei = 20;
  30. bytes provider2Uri = bytes("https://bar.com");
  31. address public user1 = address(3);
  32. address public user2 = address(4);
  33. address public unregisteredProvider = address(7);
  34. uint128 MAX_UINT128 = 2 ** 128 - 1;
  35. bytes32 ALL_ZEROS = bytes32(uint256(0));
  36. address public owner = address(8);
  37. address public admin = address(9);
  38. address public admin2 = address(10);
  39. function setUp() public {
  40. EntropyUpgradable _random = new EntropyUpgradable();
  41. // deploy proxy contract and point it to implementation
  42. proxy = new ERC1967Proxy(address(_random), "");
  43. // wrap in ABI to support easier calls
  44. random = EntropyUpgradable(address(proxy));
  45. random.initialize(owner, admin, pythFeeInWei, provider1, false);
  46. bytes32[] memory hashChain1 = generateHashChain(
  47. provider1,
  48. 0,
  49. provider1ChainLength
  50. );
  51. provider1Proofs = hashChain1;
  52. vm.prank(provider1);
  53. random.register(
  54. provider1FeeInWei,
  55. provider1Proofs[0],
  56. provider1CommitmentMetadata,
  57. provider1ChainLength,
  58. provider1Uri
  59. );
  60. vm.prank(provider1);
  61. random.setMaxNumHashes(provider1MaxNumHashes);
  62. bytes32[] memory hashChain2 = generateHashChain(provider2, 0, 100);
  63. provider2Proofs = hashChain2;
  64. vm.prank(provider2);
  65. random.register(
  66. provider2FeeInWei,
  67. provider2Proofs[0],
  68. hex"0200",
  69. 100,
  70. provider2Uri
  71. );
  72. }
  73. // Test helper method for requesting a random value as user from provider.
  74. function request(
  75. address user,
  76. address provider,
  77. uint randomNumber,
  78. bool useBlockhash
  79. ) public returns (uint64 sequenceNumber) {
  80. sequenceNumber = requestWithFee(
  81. user,
  82. random.getFee(provider),
  83. provider,
  84. randomNumber,
  85. useBlockhash
  86. );
  87. }
  88. function requestWithFee(
  89. address user,
  90. uint fee,
  91. address provider,
  92. uint randomNumber,
  93. bool useBlockhash
  94. ) public returns (uint64 sequenceNumber) {
  95. vm.deal(user, fee);
  96. vm.startPrank(user);
  97. sequenceNumber = random.request{value: fee}(
  98. provider,
  99. random.constructUserCommitment(bytes32(randomNumber)),
  100. useBlockhash
  101. );
  102. vm.stopPrank();
  103. }
  104. function assertRequestReverts(
  105. uint fee,
  106. address provider,
  107. uint randomNumber,
  108. bool useBlockhash,
  109. bytes4 revertReason
  110. ) public {
  111. bytes32 userCommitment = random.constructUserCommitment(
  112. bytes32(uint256(randomNumber))
  113. );
  114. vm.deal(address(this), fee);
  115. vm.expectRevert(revertReason);
  116. random.request{value: fee}(provider, userCommitment, useBlockhash);
  117. }
  118. function assertRevealSucceeds(
  119. address user,
  120. address provider,
  121. uint64 sequenceNumber,
  122. uint userRandom,
  123. bytes32 providerRevelation,
  124. bytes32 hash
  125. ) public {
  126. vm.prank(user);
  127. bytes32 randomNumber = random.reveal(
  128. provider,
  129. sequenceNumber,
  130. bytes32(userRandom),
  131. providerRevelation
  132. );
  133. assertEq(
  134. randomNumber,
  135. random.combineRandomValues(
  136. bytes32(userRandom),
  137. providerRevelation,
  138. hash
  139. )
  140. );
  141. }
  142. function assertRevealReverts(
  143. address user,
  144. address provider,
  145. uint64 sequenceNumber,
  146. uint userRandom,
  147. bytes32 providerRevelation
  148. ) public {
  149. vm.startPrank(user);
  150. vm.expectRevert();
  151. random.reveal(
  152. provider,
  153. sequenceNumber,
  154. bytes32(uint256(userRandom)),
  155. providerRevelation
  156. );
  157. vm.stopPrank();
  158. }
  159. function assertInvariants() public {
  160. uint expectedBalance = random
  161. .getProviderInfoV2(provider1)
  162. .accruedFeesInWei +
  163. random.getProviderInfoV2(provider2).accruedFeesInWei +
  164. random.getAccruedPythFees();
  165. assertEq(address(random).balance, expectedBalance);
  166. EntropyStructsV2.ProviderInfo memory info1 = random.getProviderInfoV2(
  167. provider1
  168. );
  169. assert(
  170. info1.originalCommitmentSequenceNumber <=
  171. info1.currentCommitmentSequenceNumber
  172. );
  173. assert(info1.currentCommitmentSequenceNumber < info1.sequenceNumber);
  174. assert(info1.sequenceNumber <= info1.endSequenceNumber);
  175. EntropyStructsV2.ProviderInfo memory info2 = random.getProviderInfoV2(
  176. provider2
  177. );
  178. assert(
  179. info2.originalCommitmentSequenceNumber <=
  180. info2.currentCommitmentSequenceNumber
  181. );
  182. assert(info2.sequenceNumber > info2.currentCommitmentSequenceNumber);
  183. assert(info2.sequenceNumber <= info2.endSequenceNumber);
  184. }
  185. function testBasicFlow() public {
  186. vm.roll(17);
  187. uint64 sequenceNumber = request(user2, provider1, 42, false);
  188. assertEq(
  189. random.getRequestV2(provider1, sequenceNumber).blockNumber,
  190. 17
  191. );
  192. assertEq(
  193. random.getRequestV2(provider1, sequenceNumber).useBlockhash,
  194. false
  195. );
  196. assertRevealSucceeds(
  197. user2,
  198. provider1,
  199. sequenceNumber,
  200. 42,
  201. provider1Proofs[sequenceNumber],
  202. ALL_ZEROS
  203. );
  204. EntropyStructsV2.Request memory reqAfterReveal = random.getRequestV2(
  205. provider1,
  206. sequenceNumber
  207. );
  208. assertEq(reqAfterReveal.sequenceNumber, 0);
  209. // You can only reveal the random number once. This isn't a feature of the contract per se, but it is
  210. // the expected behavior.
  211. assertRevealReverts(
  212. user2,
  213. provider1,
  214. sequenceNumber,
  215. 42,
  216. provider1Proofs[sequenceNumber]
  217. );
  218. }
  219. function testDefaultProvider() public {
  220. vm.roll(20);
  221. uint64 sequenceNumber = request(
  222. user2,
  223. random.getDefaultProvider(),
  224. 42,
  225. false
  226. );
  227. assertEq(
  228. random.getRequestV2(provider1, sequenceNumber).blockNumber,
  229. 20
  230. );
  231. assertEq(
  232. random.getRequestV2(provider1, sequenceNumber).useBlockhash,
  233. false
  234. );
  235. assertRevealReverts(
  236. user2,
  237. random.getDefaultProvider(),
  238. sequenceNumber,
  239. 42,
  240. provider2Proofs[sequenceNumber]
  241. );
  242. assertRevealSucceeds(
  243. user2,
  244. random.getDefaultProvider(),
  245. sequenceNumber,
  246. 42,
  247. provider1Proofs[sequenceNumber],
  248. ALL_ZEROS
  249. );
  250. }
  251. function testNoSuchProvider() public {
  252. assertRequestReverts(
  253. 10000000,
  254. unregisteredProvider,
  255. 42,
  256. false,
  257. EntropyErrors.NoSuchProvider.selector
  258. );
  259. }
  260. function testAuthorization() public {
  261. uint64 sequenceNumber = request(user2, provider1, 42, false);
  262. assertEq(
  263. random.getRequestV2(provider1, sequenceNumber).requester,
  264. user2
  265. );
  266. // user1 not authorized, must be user2.
  267. assertRevealReverts(
  268. user1,
  269. provider1,
  270. sequenceNumber,
  271. 42,
  272. provider1Proofs[sequenceNumber]
  273. );
  274. assertRevealSucceeds(
  275. user2,
  276. provider1,
  277. sequenceNumber,
  278. 42,
  279. provider1Proofs[sequenceNumber],
  280. ALL_ZEROS
  281. );
  282. }
  283. function testAdversarialReveal() public {
  284. uint64 sequenceNumber = request(user2, provider1, 42, false);
  285. // test revealing with the wrong hashes in the same chain
  286. for (uint256 i = 0; i < 10; i++) {
  287. if (i != sequenceNumber) {
  288. assertRevealReverts(
  289. user2,
  290. provider1,
  291. sequenceNumber,
  292. 42,
  293. provider1Proofs[i]
  294. );
  295. }
  296. }
  297. // test revealing with the wrong user revealed value.
  298. for (uint256 i = 0; i < 42; i++) {
  299. assertRevealReverts(
  300. user2,
  301. provider1,
  302. sequenceNumber,
  303. i,
  304. provider1Proofs[sequenceNumber]
  305. );
  306. }
  307. // test revealing sequence numbers that haven't been requested yet.
  308. for (uint64 i = sequenceNumber + 1; i < sequenceNumber + 3; i++) {
  309. assertRevealReverts(
  310. user2,
  311. provider1,
  312. i,
  313. 42,
  314. provider1Proofs[sequenceNumber]
  315. );
  316. assertRevealReverts(user2, provider1, i, 42, provider1Proofs[i]);
  317. }
  318. }
  319. function testConcurrentRequests() public {
  320. uint64 s1 = request(user1, provider1, 1, false);
  321. uint64 s2 = request(user2, provider1, 2, false);
  322. uint64 s3 = request(user1, provider1, 3, false);
  323. uint64 s4 = request(user1, provider1, 4, false);
  324. assertRevealSucceeds(
  325. user1,
  326. provider1,
  327. s3,
  328. 3,
  329. provider1Proofs[s3],
  330. ALL_ZEROS
  331. );
  332. assertInvariants();
  333. uint64 s5 = request(user1, provider1, 5, false);
  334. assertRevealSucceeds(
  335. user1,
  336. provider1,
  337. s4,
  338. 4,
  339. provider1Proofs[s4],
  340. ALL_ZEROS
  341. );
  342. assertInvariants();
  343. assertRevealSucceeds(
  344. user1,
  345. provider1,
  346. s1,
  347. 1,
  348. provider1Proofs[s1],
  349. ALL_ZEROS
  350. );
  351. assertInvariants();
  352. assertRevealSucceeds(
  353. user2,
  354. provider1,
  355. s2,
  356. 2,
  357. provider1Proofs[s2],
  358. ALL_ZEROS
  359. );
  360. assertInvariants();
  361. assertRevealSucceeds(
  362. user1,
  363. provider1,
  364. s5,
  365. 5,
  366. provider1Proofs[s5],
  367. ALL_ZEROS
  368. );
  369. assertInvariants();
  370. }
  371. function testBlockhash() public {
  372. vm.roll(1234);
  373. uint64 sequenceNumber = request(user2, provider1, 42, true);
  374. assertEq(
  375. random.getRequestV2(provider1, sequenceNumber).blockNumber,
  376. 1234
  377. );
  378. assertEq(
  379. random.getRequestV2(provider1, sequenceNumber).useBlockhash,
  380. true
  381. );
  382. vm.roll(1235);
  383. assertRevealSucceeds(
  384. user2,
  385. provider1,
  386. sequenceNumber,
  387. 42,
  388. provider1Proofs[sequenceNumber],
  389. blockhash(1234)
  390. );
  391. }
  392. function testNoCheckOnBlockNumberWhenNoBlockHashUsed() public {
  393. vm.roll(1234);
  394. uint64 sequenceNumber = request(user2, provider1, 42, false);
  395. vm.roll(1236);
  396. assertRevealSucceeds(
  397. user2,
  398. provider1,
  399. sequenceNumber,
  400. 42,
  401. provider1Proofs[sequenceNumber],
  402. ALL_ZEROS
  403. );
  404. vm.roll(1234);
  405. sequenceNumber = request(user2, provider1, 42, false);
  406. vm.roll(1234);
  407. assertRevealSucceeds(
  408. user2,
  409. provider1,
  410. sequenceNumber,
  411. 42,
  412. provider1Proofs[sequenceNumber],
  413. ALL_ZEROS
  414. );
  415. vm.roll(1234);
  416. sequenceNumber = request(user2, provider1, 42, false);
  417. vm.roll(1234 + 257);
  418. assertRevealSucceeds(
  419. user2,
  420. provider1,
  421. sequenceNumber,
  422. 42,
  423. provider1Proofs[sequenceNumber],
  424. ALL_ZEROS
  425. );
  426. }
  427. function testCheckOnBlockNumberWhenBlockHashUsed() public {
  428. vm.roll(1234);
  429. uint64 sequenceNumber = request(user2, provider1, 42, true);
  430. vm.roll(1234);
  431. assertRevealReverts(
  432. user2,
  433. provider1,
  434. sequenceNumber,
  435. 42,
  436. provider1Proofs[sequenceNumber]
  437. );
  438. vm.roll(1234 + 257);
  439. assertRevealReverts(
  440. user2,
  441. provider1,
  442. sequenceNumber,
  443. 42,
  444. provider1Proofs[sequenceNumber]
  445. );
  446. vm.roll(1235);
  447. assertRevealSucceeds(
  448. user2,
  449. provider1,
  450. sequenceNumber,
  451. 42,
  452. provider1Proofs[sequenceNumber],
  453. blockhash(1234)
  454. );
  455. }
  456. function testProviderCommitmentRotation() public {
  457. uint userRandom = 42;
  458. uint64 sequenceNumber1 = request(user2, provider1, userRandom, false);
  459. uint64 sequenceNumber2 = request(user2, provider1, userRandom, false);
  460. assertInvariants();
  461. uint64 newHashChainOffset = sequenceNumber2 + 1;
  462. bytes32[] memory newHashChain = generateHashChain(
  463. provider1,
  464. newHashChainOffset,
  465. 10
  466. );
  467. vm.prank(provider1);
  468. random.register(
  469. provider1FeeInWei,
  470. newHashChain[0],
  471. hex"0100",
  472. 10,
  473. provider1Uri
  474. );
  475. assertInvariants();
  476. EntropyStructsV2.ProviderInfo memory info1 = random.getProviderInfoV2(
  477. provider1
  478. );
  479. assertEq(info1.endSequenceNumber, newHashChainOffset + 10);
  480. uint64 sequenceNumber3 = request(user2, provider1, 42, false);
  481. // Rotating the provider key uses a sequence number
  482. assertEq(sequenceNumber3, sequenceNumber2 + 2);
  483. // Requests that were in-flight at the time of rotation use the commitment from the time of request
  484. for (uint256 i = 0; i < 10; i++) {
  485. assertRevealReverts(
  486. user2,
  487. provider1,
  488. sequenceNumber1,
  489. userRandom,
  490. newHashChain[i]
  491. );
  492. }
  493. assertRevealSucceeds(
  494. user2,
  495. provider1,
  496. sequenceNumber1,
  497. userRandom,
  498. provider1Proofs[sequenceNumber1],
  499. ALL_ZEROS
  500. );
  501. assertInvariants();
  502. // Requests after the rotation use the new commitment
  503. assertRevealReverts(
  504. user2,
  505. provider1,
  506. sequenceNumber3,
  507. userRandom,
  508. provider1Proofs[sequenceNumber3]
  509. );
  510. assertRevealSucceeds(
  511. user2,
  512. provider1,
  513. sequenceNumber3,
  514. userRandom,
  515. newHashChain[sequenceNumber3 - newHashChainOffset],
  516. ALL_ZEROS
  517. );
  518. assertInvariants();
  519. }
  520. function testOutOfRandomness() public {
  521. // Should be able to request chainLength - 1 random numbers successfully.
  522. for (uint64 i = 0; i < provider1ChainLength - 1; i++) {
  523. uint64 sequenceNumber = request(user2, provider1, 42, false);
  524. assertRevealSucceeds(
  525. user2,
  526. provider1,
  527. sequenceNumber,
  528. 42,
  529. provider1Proofs[sequenceNumber],
  530. ALL_ZEROS
  531. );
  532. }
  533. assertRequestReverts(
  534. random.getFee(provider1),
  535. provider1,
  536. provider1ChainLength - 1,
  537. false,
  538. EntropyErrors.OutOfRandomness.selector
  539. );
  540. }
  541. function testGetFee() public {
  542. assertEq(random.getFee(provider1), pythFeeInWei + provider1FeeInWei);
  543. assertEq(random.getFee(provider2), pythFeeInWei + provider2FeeInWei);
  544. // Requesting the fee for a nonexistent provider returns pythFeeInWei. This isn't necessarily desirable behavior,
  545. // but it's unlikely to cause a problem.
  546. assertEq(random.getFee(unregisteredProvider), pythFeeInWei);
  547. // Check that overflowing the fee arithmetic causes the transaction to revert.
  548. vm.prank(provider1);
  549. random.register(
  550. MAX_UINT128,
  551. provider1Proofs[0],
  552. hex"0100",
  553. 100,
  554. provider1Uri
  555. );
  556. vm.expectRevert();
  557. random.getFee(provider1);
  558. }
  559. function testOverflow() public {
  560. bytes32 userCommitment = random.constructUserCommitment(
  561. bytes32(uint256(42))
  562. );
  563. // msg.value overflows the uint128 fee variable
  564. uint fee = 2 ** 128;
  565. vm.deal(address(this), fee);
  566. vm.expectRevert("SafeCast: value doesn't fit in 128 bits");
  567. random.request{value: fee}(provider1, userCommitment, false);
  568. // block number is too large
  569. vm.roll(2 ** 96);
  570. vm.expectRevert("SafeCast: value doesn't fit in 64 bits");
  571. random.request{value: pythFeeInWei + provider1FeeInWei}(
  572. provider1,
  573. userCommitment,
  574. true
  575. );
  576. }
  577. function testFees() public {
  578. // Insufficient fees causes a revert
  579. assertRequestReverts(
  580. 0,
  581. provider1,
  582. 42,
  583. false,
  584. EntropyErrors.InsufficientFee.selector
  585. );
  586. assertRequestReverts(
  587. pythFeeInWei + provider1FeeInWei - 1,
  588. provider1,
  589. 42,
  590. false,
  591. EntropyErrors.InsufficientFee.selector
  592. );
  593. assertRequestReverts(
  594. 0,
  595. provider2,
  596. 42,
  597. false,
  598. EntropyErrors.InsufficientFee.selector
  599. );
  600. assertRequestReverts(
  601. pythFeeInWei + provider2FeeInWei - 1,
  602. provider2,
  603. 42,
  604. false,
  605. EntropyErrors.InsufficientFee.selector
  606. );
  607. // Accrue some fees for both providers
  608. for (uint i = 0; i < 3; i++) {
  609. request(user2, provider1, 42, false);
  610. }
  611. request(user2, provider2, 42, false);
  612. // this call overpays for the random number
  613. requestWithFee(
  614. user2,
  615. pythFeeInWei + provider2FeeInWei + 10000,
  616. provider2,
  617. 42,
  618. false
  619. );
  620. assertEq(
  621. random.getProviderInfoV2(provider1).accruedFeesInWei,
  622. provider1FeeInWei * 3
  623. );
  624. assertEq(
  625. random.getProviderInfoV2(provider2).accruedFeesInWei,
  626. provider2FeeInWei * 2
  627. );
  628. assertEq(random.getAccruedPythFees(), pythFeeInWei * 5 + 10000);
  629. assertInvariants();
  630. // Reregistering updates the required fees
  631. vm.prank(provider1);
  632. random.register(
  633. 12345,
  634. provider1Proofs[0],
  635. hex"0100",
  636. 100,
  637. provider1Uri
  638. );
  639. assertRequestReverts(
  640. pythFeeInWei + 12345 - 1,
  641. provider1,
  642. 42,
  643. false,
  644. EntropyErrors.InsufficientFee.selector
  645. );
  646. requestWithFee(user2, pythFeeInWei + 12345, provider1, 42, false);
  647. uint128 providerOneBalance = provider1FeeInWei * 3 + 12345;
  648. assertEq(
  649. random.getProviderInfoV2(provider1).accruedFeesInWei,
  650. providerOneBalance
  651. );
  652. assertInvariants();
  653. vm.prank(unregisteredProvider);
  654. vm.expectRevert();
  655. random.withdraw(1000);
  656. vm.prank(provider1);
  657. random.withdraw(1000);
  658. assertEq(
  659. random.getProviderInfoV2(provider1).accruedFeesInWei,
  660. providerOneBalance - 1000
  661. );
  662. assertInvariants();
  663. vm.prank(provider1);
  664. vm.expectRevert();
  665. random.withdraw(providerOneBalance);
  666. }
  667. function testGetProviderInfoV2() public {
  668. EntropyStructsV2.ProviderInfo memory providerInfo1 = random
  669. .getProviderInfoV2(provider1);
  670. // These two fields aren't used by the Entropy contract itself -- they're just convenient info to store
  671. // on-chain -- so they aren't tested in the other tests.
  672. assertEq(providerInfo1.uri, provider1Uri);
  673. assertEq(providerInfo1.commitmentMetadata, provider1CommitmentMetadata);
  674. }
  675. function testSetProviderFee() public {
  676. assertNotEq(random.getProviderInfoV2(provider1).feeInWei, 1);
  677. vm.prank(provider1);
  678. random.setProviderFee(1);
  679. assertEq(random.getProviderInfoV2(provider1).feeInWei, 1);
  680. }
  681. function testSetProviderFeeByUnregistered() public {
  682. vm.prank(unregisteredProvider);
  683. vm.expectRevert();
  684. random.setProviderFee(1);
  685. }
  686. function testSetProviderUri() public {
  687. bytes memory newUri = bytes("https://new.com");
  688. assertNotEq0(random.getProviderInfoV2(provider1).uri, newUri);
  689. vm.prank(provider1);
  690. random.setProviderUri(newUri);
  691. assertEq0(random.getProviderInfoV2(provider1).uri, newUri);
  692. }
  693. function testSetProviderUriByUnregistered() public {
  694. bytes memory newUri = bytes("https://new.com");
  695. vm.prank(unregisteredProvider);
  696. vm.expectRevert();
  697. random.setProviderUri(newUri);
  698. }
  699. function testRequestWithCallbackAndReveal() public {
  700. bytes32 userRandomNumber = bytes32(uint(42));
  701. uint fee = random.getFee(provider1);
  702. EntropyStructsV2.ProviderInfo memory providerInfo = random
  703. .getProviderInfoV2(provider1);
  704. vm.roll(1234);
  705. vm.deal(user1, fee);
  706. vm.startPrank(user1);
  707. vm.expectEmit(true, true, true, true, address(random));
  708. emit RequestedWithCallback(
  709. provider1,
  710. user1,
  711. providerInfo.sequenceNumber,
  712. userRandomNumber,
  713. EntropyStructs.Request({
  714. provider: provider1,
  715. sequenceNumber: providerInfo.sequenceNumber,
  716. numHashes: SafeCast.toUint32(
  717. providerInfo.sequenceNumber -
  718. providerInfo.currentCommitmentSequenceNumber
  719. ),
  720. commitment: keccak256(
  721. bytes.concat(
  722. random.constructUserCommitment(userRandomNumber),
  723. providerInfo.currentCommitment
  724. )
  725. ),
  726. blockNumber: 1234,
  727. requester: user1,
  728. useBlockhash: false,
  729. isRequestWithCallback: true
  730. })
  731. );
  732. vm.expectEmit(true, true, true, true, address(random));
  733. emit EntropyEventsV2.Requested(
  734. provider1,
  735. user1,
  736. providerInfo.sequenceNumber,
  737. userRandomNumber,
  738. bytes("")
  739. );
  740. vm.roll(1234);
  741. uint64 assignedSequenceNumber = random.requestWithCallback{value: fee}(
  742. provider1,
  743. userRandomNumber
  744. );
  745. assertEq(
  746. random.getRequestV2(provider1, assignedSequenceNumber).requester,
  747. user1
  748. );
  749. assertEq(
  750. random.getRequestV2(provider1, assignedSequenceNumber).provider,
  751. provider1
  752. );
  753. vm.expectRevert(EntropyErrors.InvalidRevealCall.selector);
  754. random.reveal(
  755. provider1,
  756. assignedSequenceNumber,
  757. userRandomNumber,
  758. provider1Proofs[assignedSequenceNumber]
  759. );
  760. vm.stopPrank();
  761. }
  762. function testRequestWithCallbackAndRevealWithCallbackByContract() public {
  763. bytes32 userRandomNumber = bytes32(uint(42));
  764. uint fee = random.getFee(provider1);
  765. EntropyConsumer consumer = new EntropyConsumer(address(random), false);
  766. vm.deal(user1, fee);
  767. vm.prank(user1);
  768. uint64 assignedSequenceNumber = consumer.requestEntropy{value: fee}(
  769. userRandomNumber
  770. );
  771. EntropyStructsV2.Request memory req = random.getRequestV2(
  772. provider1,
  773. assignedSequenceNumber
  774. );
  775. vm.expectEmit(true, true, true, true, address(random));
  776. emit RevealedWithCallback(
  777. EntropyStructConverter.toV1Request(req),
  778. userRandomNumber,
  779. provider1Proofs[assignedSequenceNumber],
  780. random.combineRandomValues(
  781. userRandomNumber,
  782. provider1Proofs[assignedSequenceNumber],
  783. 0
  784. )
  785. );
  786. vm.expectEmit(true, true, true, true, address(random));
  787. emit EntropyEventsV2.Revealed(
  788. provider1,
  789. req.requester,
  790. req.sequenceNumber,
  791. random.combineRandomValues(
  792. userRandomNumber,
  793. provider1Proofs[assignedSequenceNumber],
  794. 0
  795. ),
  796. false,
  797. bytes(""),
  798. bytes("")
  799. );
  800. vm.prank(user1);
  801. random.revealWithCallback(
  802. provider1,
  803. assignedSequenceNumber,
  804. userRandomNumber,
  805. provider1Proofs[assignedSequenceNumber]
  806. );
  807. assertEq(consumer.sequence(), assignedSequenceNumber);
  808. assertEq(consumer.provider(), provider1);
  809. assertEq(
  810. consumer.randomness(),
  811. random.combineRandomValues(
  812. userRandomNumber,
  813. provider1Proofs[assignedSequenceNumber],
  814. // No blockhash is being used in callback method. As it
  815. // is being depreceated. Passing 0 for it.
  816. 0
  817. )
  818. );
  819. EntropyStructsV2.Request memory reqAfterReveal = random.getRequestV2(
  820. provider1,
  821. assignedSequenceNumber
  822. );
  823. assertEq(reqAfterReveal.sequenceNumber, 0);
  824. }
  825. function testRequestWithCallbackAndRevealWithCallbackByEoa() public {
  826. bytes32 userRandomNumber = bytes32(uint(42));
  827. uint fee = random.getFee(provider1);
  828. vm.deal(user1, fee);
  829. vm.prank(user1);
  830. uint64 assignedSequenceNumber = random.requestWithCallback{value: fee}(
  831. provider1,
  832. userRandomNumber
  833. );
  834. EntropyStructsV2.Request memory req = random.getRequestV2(
  835. provider1,
  836. assignedSequenceNumber
  837. );
  838. vm.expectEmit(true, true, true, true, address(random));
  839. emit RevealedWithCallback(
  840. EntropyStructConverter.toV1Request(req),
  841. userRandomNumber,
  842. provider1Proofs[assignedSequenceNumber],
  843. random.combineRandomValues(
  844. userRandomNumber,
  845. provider1Proofs[assignedSequenceNumber],
  846. 0
  847. )
  848. );
  849. vm.expectEmit(true, true, true, true, address(random));
  850. emit EntropyEventsV2.Revealed(
  851. provider1,
  852. req.requester,
  853. req.sequenceNumber,
  854. random.combineRandomValues(
  855. userRandomNumber,
  856. provider1Proofs[assignedSequenceNumber],
  857. 0
  858. ),
  859. false,
  860. bytes(""),
  861. bytes("")
  862. );
  863. random.revealWithCallback(
  864. provider1,
  865. assignedSequenceNumber,
  866. userRandomNumber,
  867. provider1Proofs[assignedSequenceNumber]
  868. );
  869. EntropyStructsV2.Request memory reqAfterReveal = random.getRequestV2(
  870. provider1,
  871. assignedSequenceNumber
  872. );
  873. assertEq(reqAfterReveal.sequenceNumber, 0);
  874. }
  875. function testRequestAndRevealWithCallback() public {
  876. uint64 sequenceNumber = request(user2, provider1, 42, false);
  877. assertEq(
  878. random.getRequestV2(provider1, sequenceNumber).requester,
  879. user2
  880. );
  881. vm.expectRevert(EntropyErrors.InvalidRevealCall.selector);
  882. vm.prank(user2);
  883. random.revealWithCallback(
  884. provider1,
  885. sequenceNumber,
  886. bytes32(uint256(42)),
  887. provider1Proofs[sequenceNumber]
  888. );
  889. }
  890. function testRequestWithCallbackAndRevealWithCallbackFailing() public {
  891. bytes32 userRandomNumber = bytes32(uint(42));
  892. uint fee = random.getFee(provider1);
  893. EntropyConsumer consumer = new EntropyConsumer(address(random), true);
  894. vm.deal(address(consumer), fee);
  895. vm.startPrank(address(consumer));
  896. uint64 assignedSequenceNumber = random.requestWithCallback{value: fee}(
  897. provider1,
  898. userRandomNumber
  899. );
  900. vm.expectRevert();
  901. random.revealWithCallback(
  902. provider1,
  903. assignedSequenceNumber,
  904. userRandomNumber,
  905. provider1Proofs[assignedSequenceNumber]
  906. );
  907. }
  908. function testRequestWithCallbackGasLimit() public {
  909. uint32 defaultGasLimit = 100000;
  910. vm.prank(provider1);
  911. random.setDefaultGasLimit(defaultGasLimit);
  912. bytes32 userRandomNumber = bytes32(uint(42));
  913. uint fee = random.getFee(provider1);
  914. EntropyConsumer consumer = new EntropyConsumer(address(random), false);
  915. vm.deal(user1, fee);
  916. vm.prank(user1);
  917. uint64 assignedSequenceNumber = consumer.requestEntropy{value: fee}(
  918. userRandomNumber
  919. );
  920. EntropyStructsV2.Request memory req = random.getRequestV2(
  921. provider1,
  922. assignedSequenceNumber
  923. );
  924. // Verify the gas limit was set correctly
  925. assertEq(req.gasLimit10k, 10);
  926. vm.expectEmit(true, true, true, true, address(random));
  927. emit RevealedWithCallback(
  928. EntropyStructConverter.toV1Request(req),
  929. userRandomNumber,
  930. provider1Proofs[assignedSequenceNumber],
  931. random.combineRandomValues(
  932. userRandomNumber,
  933. provider1Proofs[assignedSequenceNumber],
  934. 0
  935. )
  936. );
  937. vm.expectEmit(true, true, true, true, address(random));
  938. emit EntropyEventsV2.Revealed(
  939. provider1,
  940. req.requester,
  941. req.sequenceNumber,
  942. random.combineRandomValues(
  943. userRandomNumber,
  944. provider1Proofs[assignedSequenceNumber],
  945. 0
  946. ),
  947. false,
  948. bytes(""),
  949. bytes("")
  950. );
  951. random.revealWithCallback(
  952. provider1,
  953. assignedSequenceNumber,
  954. userRandomNumber,
  955. provider1Proofs[assignedSequenceNumber]
  956. );
  957. assertEq(consumer.sequence(), assignedSequenceNumber);
  958. assertEq(consumer.provider(), provider1);
  959. assertEq(
  960. consumer.randomness(),
  961. random.combineRandomValues(
  962. userRandomNumber,
  963. provider1Proofs[assignedSequenceNumber],
  964. 0
  965. )
  966. );
  967. EntropyStructsV2.Request memory reqAfterReveal = random.getRequestV2(
  968. provider1,
  969. assignedSequenceNumber
  970. );
  971. assertEq(reqAfterReveal.sequenceNumber, 0);
  972. }
  973. function testRequestWithRevertingCallback() public {
  974. uint32 defaultGasLimit = 100000;
  975. vm.prank(provider1);
  976. random.setDefaultGasLimit(defaultGasLimit);
  977. bytes32 userRandomNumber = bytes32(uint(42));
  978. uint fee = random.getFee(provider1);
  979. EntropyConsumer consumer = new EntropyConsumer(address(random), true);
  980. vm.deal(user1, fee);
  981. vm.prank(user1);
  982. uint64 assignedSequenceNumber = consumer.requestEntropy{value: fee}(
  983. userRandomNumber
  984. );
  985. // On the first attempt, the transaction should succeed and emit CallbackFailed event.
  986. bytes memory revertReason = abi.encodeWithSelector(
  987. 0x08c379a0,
  988. "Callback failed"
  989. );
  990. vm.expectEmit(true, true, true, true, address(random));
  991. emit CallbackFailed(
  992. provider1,
  993. address(consumer),
  994. assignedSequenceNumber,
  995. userRandomNumber,
  996. provider1Proofs[assignedSequenceNumber],
  997. random.combineRandomValues(
  998. userRandomNumber,
  999. provider1Proofs[assignedSequenceNumber],
  1000. 0
  1001. ),
  1002. revertReason
  1003. );
  1004. vm.expectEmit(true, true, true, true, address(random));
  1005. emit EntropyEventsV2.Revealed(
  1006. provider1,
  1007. address(consumer),
  1008. assignedSequenceNumber,
  1009. random.combineRandomValues(
  1010. userRandomNumber,
  1011. provider1Proofs[assignedSequenceNumber],
  1012. 0
  1013. ),
  1014. true,
  1015. revertReason,
  1016. bytes("")
  1017. );
  1018. random.revealWithCallback(
  1019. provider1,
  1020. assignedSequenceNumber,
  1021. userRandomNumber,
  1022. provider1Proofs[assignedSequenceNumber]
  1023. );
  1024. // Verify request is still active after failure
  1025. EntropyStructsV2.Request memory reqAfterFailure = random.getRequestV2(
  1026. provider1,
  1027. assignedSequenceNumber
  1028. );
  1029. assertEq(reqAfterFailure.sequenceNumber, assignedSequenceNumber);
  1030. assertTrue(
  1031. reqAfterFailure.callbackStatus ==
  1032. EntropyStatusConstants.CALLBACK_FAILED
  1033. );
  1034. // On the second attempt, the transaction should directly revert
  1035. vm.expectRevert();
  1036. random.revealWithCallback(
  1037. provider1,
  1038. assignedSequenceNumber,
  1039. userRandomNumber,
  1040. provider1Proofs[assignedSequenceNumber]
  1041. );
  1042. // Again, request stays active after failure
  1043. reqAfterFailure = random.getRequestV2(
  1044. provider1,
  1045. assignedSequenceNumber
  1046. );
  1047. assertEq(reqAfterFailure.sequenceNumber, assignedSequenceNumber);
  1048. assertTrue(
  1049. reqAfterFailure.callbackStatus ==
  1050. EntropyStatusConstants.CALLBACK_FAILED
  1051. );
  1052. // If the callback starts succeeding, we can invoke it and it emits the usual RevealedWithCallback event.
  1053. consumer.setReverts(false);
  1054. vm.expectEmit(true, true, true, true, address(random));
  1055. emit RevealedWithCallback(
  1056. EntropyStructConverter.toV1Request(reqAfterFailure),
  1057. userRandomNumber,
  1058. provider1Proofs[assignedSequenceNumber],
  1059. random.combineRandomValues(
  1060. userRandomNumber,
  1061. provider1Proofs[assignedSequenceNumber],
  1062. 0
  1063. )
  1064. );
  1065. vm.expectEmit(true, true, true, true, address(random));
  1066. emit EntropyEventsV2.Revealed(
  1067. provider1,
  1068. reqAfterFailure.requester,
  1069. reqAfterFailure.sequenceNumber,
  1070. random.combineRandomValues(
  1071. userRandomNumber,
  1072. provider1Proofs[assignedSequenceNumber],
  1073. 0
  1074. ),
  1075. false,
  1076. bytes(""),
  1077. bytes("")
  1078. );
  1079. random.revealWithCallback(
  1080. provider1,
  1081. assignedSequenceNumber,
  1082. userRandomNumber,
  1083. provider1Proofs[assignedSequenceNumber]
  1084. );
  1085. // Verify request is cleared after successful reveal
  1086. EntropyStructsV2.Request memory reqAfterReveal = random.getRequestV2(
  1087. provider1,
  1088. assignedSequenceNumber
  1089. );
  1090. assertEq(reqAfterReveal.sequenceNumber, 0);
  1091. }
  1092. function testRequestWithCallbackUsingTooMuchGas() public {
  1093. uint32 defaultGasLimit = 100000;
  1094. vm.prank(provider1);
  1095. random.setDefaultGasLimit(defaultGasLimit);
  1096. bytes32 userRandomNumber = bytes32(uint(42));
  1097. uint fee = random.getFee(provider1);
  1098. EntropyConsumer consumer = new EntropyConsumer(address(random), false);
  1099. // Consumer callback uses ~10% more gas than the provider's default
  1100. consumer.setTargetGasUsage((defaultGasLimit * 110) / 100);
  1101. vm.deal(user1, fee);
  1102. vm.prank(user1);
  1103. uint64 assignedSequenceNumber = consumer.requestEntropy{value: fee}(
  1104. userRandomNumber
  1105. );
  1106. EntropyStructsV2.Request memory req = random.getRequestV2(
  1107. provider1,
  1108. assignedSequenceNumber
  1109. );
  1110. // Verify the gas limit was set correctly
  1111. assertEq(req.gasLimit10k, 10);
  1112. // The transaction reverts if the provider does not provide enough gas to forward
  1113. // the gasLimit to the callback transaction.
  1114. vm.expectRevert();
  1115. random.revealWithCallback{gas: defaultGasLimit - 10000}(
  1116. provider1,
  1117. assignedSequenceNumber,
  1118. userRandomNumber,
  1119. provider1Proofs[assignedSequenceNumber]
  1120. );
  1121. // If called with enough gas, the transaction should succeed, but the callback should fail because
  1122. // it uses too much gas.
  1123. vm.expectEmit(true, true, true, true, address(random));
  1124. emit CallbackFailed(
  1125. provider1,
  1126. address(consumer),
  1127. assignedSequenceNumber,
  1128. userRandomNumber,
  1129. provider1Proofs[assignedSequenceNumber],
  1130. random.combineRandomValues(
  1131. userRandomNumber,
  1132. provider1Proofs[assignedSequenceNumber],
  1133. 0
  1134. ),
  1135. // out-of-gas reverts have an empty bytes array as the return value.
  1136. ""
  1137. );
  1138. vm.expectEmit(true, true, true, true, address(random));
  1139. emit EntropyEventsV2.Revealed(
  1140. provider1,
  1141. address(consumer),
  1142. assignedSequenceNumber,
  1143. random.combineRandomValues(
  1144. userRandomNumber,
  1145. provider1Proofs[assignedSequenceNumber],
  1146. 0
  1147. ),
  1148. true,
  1149. "",
  1150. ""
  1151. );
  1152. random.revealWithCallback(
  1153. provider1,
  1154. assignedSequenceNumber,
  1155. userRandomNumber,
  1156. provider1Proofs[assignedSequenceNumber]
  1157. );
  1158. // Verify request is still active after failure
  1159. EntropyStructsV2.Request memory reqAfterFailure = random.getRequestV2(
  1160. provider1,
  1161. assignedSequenceNumber
  1162. );
  1163. assertEq(reqAfterFailure.sequenceNumber, assignedSequenceNumber);
  1164. assertEq(
  1165. reqAfterFailure.callbackStatus,
  1166. EntropyStatusConstants.CALLBACK_FAILED
  1167. );
  1168. // A subsequent attempt passing insufficient gas should also revert
  1169. vm.expectRevert();
  1170. random.revealWithCallback{gas: defaultGasLimit - 10000}(
  1171. provider1,
  1172. assignedSequenceNumber,
  1173. userRandomNumber,
  1174. provider1Proofs[assignedSequenceNumber]
  1175. );
  1176. // Again, request stays active after failure
  1177. reqAfterFailure = random.getRequestV2(
  1178. provider1,
  1179. assignedSequenceNumber
  1180. );
  1181. assertEq(reqAfterFailure.sequenceNumber, assignedSequenceNumber);
  1182. assertEq(
  1183. reqAfterFailure.callbackStatus,
  1184. EntropyStatusConstants.CALLBACK_FAILED
  1185. );
  1186. // Calling without a gas limit should succeed
  1187. vm.expectEmit(true, true, true, true, address(random));
  1188. emit RevealedWithCallback(
  1189. EntropyStructConverter.toV1Request(reqAfterFailure),
  1190. userRandomNumber,
  1191. provider1Proofs[assignedSequenceNumber],
  1192. random.combineRandomValues(
  1193. userRandomNumber,
  1194. provider1Proofs[assignedSequenceNumber],
  1195. 0
  1196. )
  1197. );
  1198. vm.expectEmit(true, true, true, true, address(random));
  1199. emit EntropyEventsV2.Revealed(
  1200. provider1,
  1201. address(consumer),
  1202. assignedSequenceNumber,
  1203. random.combineRandomValues(
  1204. userRandomNumber,
  1205. provider1Proofs[assignedSequenceNumber],
  1206. 0
  1207. ),
  1208. false,
  1209. "",
  1210. ""
  1211. );
  1212. random.revealWithCallback(
  1213. provider1,
  1214. assignedSequenceNumber,
  1215. userRandomNumber,
  1216. provider1Proofs[assignedSequenceNumber]
  1217. );
  1218. // Verify request is cleared after successful reveal
  1219. EntropyStructsV2.Request memory reqAfterReveal = random.getRequestV2(
  1220. provider1,
  1221. assignedSequenceNumber
  1222. );
  1223. assertEq(reqAfterReveal.sequenceNumber, 0);
  1224. }
  1225. // Test the corner case caused by the CALL opcode passing at most 63/64ths of the current gas
  1226. // to the sub-call.
  1227. function testRequestWithCallbackUsingTooMuchGas2() public {
  1228. // With a 64M gas limit, we will pass ~63M gas to the callback (which is insufficient), but still
  1229. // have ~1M gas to execute code within the revealWithCallback method, which should be enough to
  1230. // run all of the logic subsequent to the excessivelySafeCall.
  1231. uint32 defaultGasLimit = 64000000;
  1232. vm.prank(provider1);
  1233. random.setDefaultGasLimit(defaultGasLimit);
  1234. bytes32 userRandomNumber = bytes32(uint(42));
  1235. uint fee = random.getFee(provider1);
  1236. EntropyConsumer consumer = new EntropyConsumer(address(random), false);
  1237. consumer.setTargetGasUsage(defaultGasLimit);
  1238. vm.deal(user1, fee);
  1239. vm.prank(user1);
  1240. uint64 assignedSequenceNumber = consumer.requestEntropy{value: fee}(
  1241. userRandomNumber
  1242. );
  1243. // The transaction reverts if the provider does not provide enough gas to forward
  1244. // the gasLimit to the callback transaction.
  1245. vm.expectRevert(EntropyErrors.InsufficientGas.selector);
  1246. random.revealWithCallback{gas: defaultGasLimit - 10000}(
  1247. provider1,
  1248. assignedSequenceNumber,
  1249. userRandomNumber,
  1250. provider1Proofs[assignedSequenceNumber]
  1251. );
  1252. }
  1253. function testLastRevealedTooOld() public {
  1254. for (uint256 i = 0; i < provider1MaxNumHashes; i++) {
  1255. request(user1, provider1, 42, false);
  1256. }
  1257. assertRequestReverts(
  1258. random.getFee(provider1),
  1259. provider1,
  1260. 42,
  1261. false,
  1262. EntropyErrors.LastRevealedTooOld.selector
  1263. );
  1264. }
  1265. function testAdvanceProviderCommitment(
  1266. uint32 requestCount,
  1267. uint32 updateSeqNumber
  1268. ) public {
  1269. vm.assume(requestCount < provider1MaxNumHashes);
  1270. vm.assume(updateSeqNumber < requestCount);
  1271. vm.assume(0 < updateSeqNumber);
  1272. for (uint256 i = 0; i < requestCount; i++) {
  1273. request(user1, provider1, 42, false);
  1274. }
  1275. assertInvariants();
  1276. EntropyStructsV2.ProviderInfo memory info1 = random.getProviderInfoV2(
  1277. provider1
  1278. );
  1279. assertEq(info1.currentCommitmentSequenceNumber, 0);
  1280. assertEq(info1.sequenceNumber, requestCount + 1);
  1281. random.advanceProviderCommitment(
  1282. provider1,
  1283. updateSeqNumber,
  1284. provider1Proofs[updateSeqNumber]
  1285. );
  1286. info1 = random.getProviderInfoV2(provider1);
  1287. assertEq(info1.currentCommitmentSequenceNumber, updateSeqNumber);
  1288. assertEq(info1.currentCommitment, provider1Proofs[updateSeqNumber]);
  1289. assertEq(info1.sequenceNumber, requestCount + 1);
  1290. assertInvariants();
  1291. }
  1292. function testAdvanceProviderCommitmentTooOld(
  1293. uint32 requestCount,
  1294. uint32 updateSeqNumber
  1295. ) public {
  1296. vm.assume(requestCount < provider1MaxNumHashes);
  1297. vm.assume(updateSeqNumber < requestCount);
  1298. vm.assume(0 < updateSeqNumber);
  1299. for (uint256 i = 0; i < requestCount; i++) {
  1300. request(user1, provider1, 42, false);
  1301. }
  1302. assertRevealSucceeds(
  1303. user1,
  1304. provider1,
  1305. requestCount,
  1306. 42,
  1307. provider1Proofs[requestCount],
  1308. ALL_ZEROS
  1309. );
  1310. vm.expectRevert(EntropyErrors.UpdateTooOld.selector);
  1311. random.advanceProviderCommitment(
  1312. provider1,
  1313. updateSeqNumber,
  1314. provider1Proofs[updateSeqNumber]
  1315. );
  1316. }
  1317. function testAdvanceProviderCommitmentIncorrectRevelation(
  1318. uint32 seqNumber,
  1319. uint32 mismatchedProofNumber
  1320. ) public {
  1321. vm.assume(seqNumber < provider1ChainLength);
  1322. vm.assume(mismatchedProofNumber < provider1ChainLength);
  1323. vm.assume(seqNumber != mismatchedProofNumber);
  1324. vm.assume(seqNumber > 0);
  1325. vm.expectRevert(EntropyErrors.IncorrectRevelation.selector);
  1326. random.advanceProviderCommitment(
  1327. provider1,
  1328. seqNumber,
  1329. provider1Proofs[mismatchedProofNumber]
  1330. );
  1331. }
  1332. function testAdvanceProviderCommitmentUpdatesSequenceNumber(
  1333. uint32 seqNumber
  1334. ) public {
  1335. vm.assume(seqNumber < provider1ChainLength);
  1336. vm.assume(seqNumber > 0);
  1337. random.advanceProviderCommitment(
  1338. provider1,
  1339. seqNumber,
  1340. provider1Proofs[seqNumber]
  1341. );
  1342. EntropyStructsV2.ProviderInfo memory info1 = random.getProviderInfoV2(
  1343. provider1
  1344. );
  1345. assertEq(info1.sequenceNumber, seqNumber + 1);
  1346. }
  1347. function testAdvanceProviderCommitmentHigherThanChainLength(
  1348. uint32 seqNumber
  1349. ) public {
  1350. vm.assume(seqNumber >= provider1ChainLength);
  1351. vm.expectRevert(EntropyErrors.AssertionFailure.selector);
  1352. random.advanceProviderCommitment(
  1353. provider1,
  1354. seqNumber,
  1355. provider1Proofs[0]
  1356. );
  1357. }
  1358. function testSetMaxNumHashes(uint32 maxNumHashes) public {
  1359. vm.prank(provider1);
  1360. random.setMaxNumHashes(maxNumHashes);
  1361. EntropyStructsV2.ProviderInfo memory info1 = random.getProviderInfoV2(
  1362. provider1
  1363. );
  1364. assertEq(info1.maxNumHashes, maxNumHashes);
  1365. }
  1366. function testSetMaxNumHashesRevertIfNotFromProvider() public {
  1367. vm.expectRevert(EntropyErrors.NoSuchProvider.selector);
  1368. random.setMaxNumHashes(100);
  1369. }
  1370. function testZeroMaxNumHashesDisableChecks() public {
  1371. for (uint256 i = 0; i < provider1MaxNumHashes; i++) {
  1372. request(user1, provider1, 42, false);
  1373. }
  1374. assertRequestReverts(
  1375. random.getFee(provider1),
  1376. provider1,
  1377. 42,
  1378. false,
  1379. EntropyErrors.LastRevealedTooOld.selector
  1380. );
  1381. vm.prank(provider1);
  1382. random.setMaxNumHashes(0);
  1383. request(user1, provider1, 42, false);
  1384. }
  1385. function testFeeManager() public {
  1386. address manager = address(12);
  1387. // Make sure there are some fees for provider1
  1388. request(user1, provider1, 42, false);
  1389. // Manager isn't authorized, so can't withdraw or set fee.
  1390. vm.prank(manager);
  1391. vm.expectRevert();
  1392. random.withdrawAsFeeManager(provider1, provider1FeeInWei);
  1393. vm.prank(manager);
  1394. vm.expectRevert();
  1395. random.setProviderFeeAsFeeManager(provider1, 1000);
  1396. // You can't set a fee manager from an address that isn't a registered provider.
  1397. vm.expectRevert();
  1398. random.setFeeManager(address(manager));
  1399. // Authorizing the fee manager as the provider enables withdrawing and setting fees.
  1400. vm.prank(provider1);
  1401. random.setFeeManager(address(manager));
  1402. // Withdrawing decrements provider's accrued fees and sends balance to the fee manager.
  1403. uint startingBalance = manager.balance;
  1404. vm.prank(manager);
  1405. random.withdrawAsFeeManager(provider1, provider1FeeInWei);
  1406. assertEq(random.getProviderInfoV2(provider1).accruedFeesInWei, 0);
  1407. assertEq(manager.balance, startingBalance + provider1FeeInWei);
  1408. // Setting provider fee updates the fee in the ProviderInfo.
  1409. vm.prank(manager);
  1410. random.setProviderFeeAsFeeManager(provider1, 10101);
  1411. assertEq(random.getProviderInfoV2(provider1).feeInWei, 10101);
  1412. // Authorizing a different manager depermissions the previous one.
  1413. address manager2 = address(13);
  1414. vm.prank(provider1);
  1415. random.setFeeManager(address(manager2));
  1416. vm.prank(manager);
  1417. vm.expectRevert();
  1418. random.withdrawAsFeeManager(provider1, provider1FeeInWei);
  1419. vm.prank(manager);
  1420. vm.expectRevert();
  1421. random.setProviderFeeAsFeeManager(provider1, 1000);
  1422. }
  1423. function testSetDefaultGasLimit() public {
  1424. uint32 newGasLimit = 100000;
  1425. vm.prank(provider1);
  1426. vm.expectEmit(true, true, true, true, address(random));
  1427. emit ProviderDefaultGasLimitUpdated(provider1, 0, newGasLimit);
  1428. vm.expectEmit(true, true, true, true, address(random));
  1429. emit EntropyEventsV2.ProviderDefaultGasLimitUpdated(
  1430. provider1,
  1431. 0,
  1432. newGasLimit,
  1433. bytes("")
  1434. );
  1435. random.setDefaultGasLimit(newGasLimit);
  1436. EntropyStructsV2.ProviderInfo memory info = random.getProviderInfoV2(
  1437. provider1
  1438. );
  1439. assertEq(info.defaultGasLimit, newGasLimit);
  1440. // Can reset back to 0.
  1441. vm.prank(provider1);
  1442. random.setDefaultGasLimit(0);
  1443. info = random.getProviderInfoV2(provider1);
  1444. assertEq(info.defaultGasLimit, 0);
  1445. // Can set to maximum value.
  1446. uint32 maxLimit = random.MAX_GAS_LIMIT();
  1447. vm.prank(provider1);
  1448. random.setDefaultGasLimit(maxLimit);
  1449. info = random.getProviderInfoV2(provider1);
  1450. assertEq(info.defaultGasLimit, random.MAX_GAS_LIMIT());
  1451. // Reverts if max value is exceeded
  1452. uint32 exceedsGasLimit = random.MAX_GAS_LIMIT() + 1;
  1453. vm.prank(provider1);
  1454. vm.expectRevert(EntropyErrors.MaxGasLimitExceeded.selector);
  1455. random.setDefaultGasLimit(exceedsGasLimit);
  1456. }
  1457. function testSetDefaultGasLimitRevertIfNotFromProvider() public {
  1458. vm.expectRevert(EntropyErrors.NoSuchProvider.selector);
  1459. random.setDefaultGasLimit(100000);
  1460. }
  1461. function testRequestWithCallbackUsesDefaultGasLimit() public {
  1462. uint32 defaultGasLimit = 100000;
  1463. vm.prank(provider1);
  1464. random.setDefaultGasLimit(defaultGasLimit);
  1465. bytes32 userRandomNumber = bytes32(uint(42));
  1466. uint fee = random.getFee(provider1);
  1467. vm.deal(user1, fee);
  1468. vm.prank(user1);
  1469. uint64 sequenceNumber = random.requestWithCallback{value: fee}(
  1470. provider1,
  1471. userRandomNumber
  1472. );
  1473. EntropyStructsV2.Request memory req = random.getRequestV2(
  1474. provider1,
  1475. sequenceNumber
  1476. );
  1477. assertEq(req.gasLimit10k, 10);
  1478. }
  1479. function testGasLimitsAndFeeRounding() public {
  1480. vm.prank(provider1);
  1481. random.setDefaultGasLimit(20000);
  1482. vm.prank(provider1);
  1483. random.setProviderFee(1);
  1484. // Test exact multiples of 10,000
  1485. assertGasLimitAndFee(0, 2, 1);
  1486. assertGasLimitAndFee(10000, 2, 1);
  1487. assertGasLimitAndFee(20000, 2, 1);
  1488. assertGasLimitAndFee(100000, 10, 5);
  1489. // Test values just below multiples of 10,000
  1490. assertGasLimitAndFee(9999, 2, 1);
  1491. assertGasLimitAndFee(19999, 2, 1);
  1492. assertGasLimitAndFee(39999, 4, 2);
  1493. assertGasLimitAndFee(99999, 10, 5);
  1494. // Test values just above multiples of 10,000
  1495. assertGasLimitAndFee(10001, 2, 1);
  1496. assertGasLimitAndFee(20001, 3, 1);
  1497. assertGasLimitAndFee(100001, 11, 5);
  1498. assertGasLimitAndFee(110001, 12, 6);
  1499. // Test middle values
  1500. assertGasLimitAndFee(5000, 2, 1);
  1501. assertGasLimitAndFee(15000, 2, 1);
  1502. assertGasLimitAndFee(25000, 3, 1);
  1503. // Test maximum value
  1504. assertGasLimitAndFee(
  1505. uint32(type(uint16).max) * 10000,
  1506. type(uint16).max,
  1507. uint128(type(uint16).max) / 2
  1508. );
  1509. // Test larger than max value reverts with expected error
  1510. uint32 exceedsGasLimit = uint32(type(uint16).max) * 10000 + 1;
  1511. vm.expectRevert(EntropyErrors.MaxGasLimitExceeded.selector);
  1512. random.getFeeForGas(provider1, exceedsGasLimit);
  1513. vm.expectRevert(EntropyErrors.MaxGasLimitExceeded.selector);
  1514. random.requestWithCallbackAndGasLimit{value: 10000000000000}(
  1515. provider1,
  1516. bytes32(uint(42)),
  1517. exceedsGasLimit
  1518. );
  1519. // A provider with a 0 gas limit is opted-out of the failure state flow, indicated by
  1520. // a 0 gas limit on all requests.
  1521. vm.prank(provider1);
  1522. random.setDefaultGasLimit(0);
  1523. assertGasLimitAndFee(0, 0, 1);
  1524. assertGasLimitAndFee(10000, 0, 1);
  1525. assertGasLimitAndFee(20000, 0, 1);
  1526. assertGasLimitAndFee(100000, 0, 1);
  1527. }
  1528. // Helper method to create a request with a specific gas limit and check the gasLimit10k / provider fees
  1529. function assertGasLimitAndFee(
  1530. uint32 gasLimit,
  1531. uint16 expectedGasLimit10k,
  1532. uint128 expectedProviderFee
  1533. ) internal {
  1534. // Create a request with callback
  1535. bytes32 userRandomNumber = bytes32(uint(42));
  1536. uint fee = random.getFeeForGas(provider1, gasLimit);
  1537. assertEq(fee - random.getPythFee(), expectedProviderFee);
  1538. // Passing 1 wei less than the expected fee causes a revert.
  1539. vm.deal(user1, fee);
  1540. vm.prank(user1);
  1541. vm.expectRevert(EntropyErrors.InsufficientFee.selector);
  1542. random.requestWithCallbackAndGasLimit{value: fee - 1}(
  1543. provider1,
  1544. userRandomNumber,
  1545. gasLimit
  1546. );
  1547. uint128 startingAccruedProviderFee = random
  1548. .getProviderInfoV2(provider1)
  1549. .accruedFeesInWei;
  1550. vm.prank(user1);
  1551. uint64 sequenceNumber = random.requestWithCallbackAndGasLimit{
  1552. value: fee
  1553. }(provider1, userRandomNumber, gasLimit);
  1554. assertEq(
  1555. random.getProviderInfoV2(provider1).accruedFeesInWei -
  1556. startingAccruedProviderFee,
  1557. expectedProviderFee
  1558. );
  1559. // Check the gasLimit10k field in the request
  1560. EntropyStructsV2.Request memory req = random.getRequestV2(
  1561. provider1,
  1562. sequenceNumber
  1563. );
  1564. assertEq(req.gasLimit10k, expectedGasLimit10k);
  1565. }
  1566. function testCallbackProvidedGas() public {
  1567. vm.prank(provider1);
  1568. random.setDefaultGasLimit(200000);
  1569. assertCallbackResult(0, 190000, true);
  1570. assertCallbackResult(0, 210000, false);
  1571. assertCallbackResult(300000, 290000, true);
  1572. assertCallbackResult(300000, 310000, false);
  1573. // A provider that hasn't upgraded to the callback failure flow
  1574. // can never cause a callback to fail because it runs out of gas.
  1575. vm.prank(provider1);
  1576. random.setDefaultGasLimit(0);
  1577. assertCallbackResult(0, 190000, true);
  1578. assertCallbackResult(0, 210000, true);
  1579. assertCallbackResult(300000, 290000, true);
  1580. assertCallbackResult(300000, 310000, true);
  1581. }
  1582. // Helper method to assert whether a request with a specific gas limit / a callback with a specific gas cost
  1583. // should be successful or not.
  1584. function assertCallbackResult(
  1585. uint32 gasLimit,
  1586. uint32 callbackGasUsage,
  1587. bool expectSuccess
  1588. ) internal {
  1589. // Create a request with callback
  1590. bytes32 userRandomNumber = bytes32(uint(42));
  1591. uint fee = random.getFeeForGas(provider1, gasLimit);
  1592. vm.deal(user1, fee);
  1593. vm.prank(user1);
  1594. EntropyConsumer consumer = new EntropyConsumer(address(random), false);
  1595. uint64 sequenceNumber = consumer.requestEntropyWithGasLimit{value: fee}(
  1596. userRandomNumber,
  1597. gasLimit
  1598. );
  1599. consumer.setTargetGasUsage(callbackGasUsage);
  1600. EntropyStructsV2.Request memory req = random.getRequestV2(
  1601. provider1,
  1602. sequenceNumber
  1603. );
  1604. if (!expectSuccess) {
  1605. vm.expectEmit(true, true, true, true, address(random));
  1606. emit CallbackFailed(
  1607. provider1,
  1608. address(consumer),
  1609. sequenceNumber,
  1610. userRandomNumber,
  1611. provider1Proofs[sequenceNumber],
  1612. random.combineRandomValues(
  1613. userRandomNumber,
  1614. provider1Proofs[sequenceNumber],
  1615. 0
  1616. ),
  1617. // out-of-gas reverts have an empty bytes array as the return value.
  1618. ""
  1619. );
  1620. vm.expectEmit(true, true, true, true, address(random));
  1621. emit EntropyEventsV2.Revealed(
  1622. provider1,
  1623. address(consumer),
  1624. sequenceNumber,
  1625. random.combineRandomValues(
  1626. userRandomNumber,
  1627. provider1Proofs[sequenceNumber],
  1628. 0
  1629. ),
  1630. true,
  1631. bytes(""),
  1632. bytes("")
  1633. );
  1634. random.revealWithCallback(
  1635. provider1,
  1636. sequenceNumber,
  1637. userRandomNumber,
  1638. provider1Proofs[sequenceNumber]
  1639. );
  1640. // Verify request is still active after failure
  1641. EntropyStructsV2.Request memory reqAfterFailure = random
  1642. .getRequestV2(provider1, sequenceNumber);
  1643. assertEq(reqAfterFailure.sequenceNumber, sequenceNumber);
  1644. assertEq(
  1645. reqAfterFailure.callbackStatus,
  1646. EntropyStatusConstants.CALLBACK_FAILED
  1647. );
  1648. } else {
  1649. vm.expectEmit(true, true, true, true, address(random));
  1650. emit RevealedWithCallback(
  1651. EntropyStructConverter.toV1Request(req),
  1652. userRandomNumber,
  1653. provider1Proofs[sequenceNumber],
  1654. random.combineRandomValues(
  1655. userRandomNumber,
  1656. provider1Proofs[sequenceNumber],
  1657. 0
  1658. )
  1659. );
  1660. vm.expectEmit(true, true, true, true, address(random));
  1661. emit EntropyEventsV2.Revealed(
  1662. provider1,
  1663. req.requester,
  1664. req.sequenceNumber,
  1665. random.combineRandomValues(
  1666. userRandomNumber,
  1667. provider1Proofs[sequenceNumber],
  1668. 0
  1669. ),
  1670. false,
  1671. bytes(""),
  1672. bytes("")
  1673. );
  1674. random.revealWithCallback(
  1675. provider1,
  1676. sequenceNumber,
  1677. userRandomNumber,
  1678. provider1Proofs[sequenceNumber]
  1679. );
  1680. // Verify request is cleared after successful callback
  1681. EntropyStructsV2.Request memory reqAfterSuccess = random
  1682. .getRequestV2(provider1, sequenceNumber);
  1683. assertEq(reqAfterSuccess.sequenceNumber, 0);
  1684. }
  1685. }
  1686. }
  1687. contract EntropyConsumer is IEntropyConsumer {
  1688. uint64 public sequence;
  1689. bytes32 public randomness;
  1690. address public provider;
  1691. address public entropy;
  1692. bool public reverts;
  1693. uint256 public targetGasUsage;
  1694. constructor(address _entropy, bool _reverts) {
  1695. entropy = _entropy;
  1696. reverts = _reverts;
  1697. targetGasUsage = 0; // Default target
  1698. }
  1699. function requestEntropy(
  1700. bytes32 randomNumber
  1701. ) public payable returns (uint64 sequenceNumber) {
  1702. address _provider = IEntropy(entropy).getDefaultProvider();
  1703. sequenceNumber = IEntropy(entropy).requestWithCallback{
  1704. value: msg.value
  1705. }(_provider, randomNumber);
  1706. }
  1707. function requestEntropyWithGasLimit(
  1708. bytes32 randomNumber,
  1709. uint32 gasLimit
  1710. ) public payable returns (uint64 sequenceNumber) {
  1711. address _provider = IEntropy(entropy).getDefaultProvider();
  1712. sequenceNumber = IEntropy(entropy).requestWithCallbackAndGasLimit{
  1713. value: msg.value
  1714. }(_provider, randomNumber, gasLimit);
  1715. }
  1716. function getEntropy() internal view override returns (address) {
  1717. return entropy;
  1718. }
  1719. function setReverts(bool _reverts) public {
  1720. reverts = _reverts;
  1721. }
  1722. function setTargetGasUsage(uint256 _targetGasUsage) public {
  1723. require(
  1724. _targetGasUsage > 60000,
  1725. "Target gas usage cannot be below 60k (~the cost of storing callback results)"
  1726. );
  1727. targetGasUsage = _targetGasUsage;
  1728. }
  1729. function entropyCallback(
  1730. uint64 _sequence,
  1731. address _provider,
  1732. bytes32 _randomness
  1733. ) internal override {
  1734. uint256 startGas = gasleft();
  1735. // These seemingly innocuous instructions are actually quite expensive
  1736. // (~60k gas) because they're writes to contract storage.
  1737. sequence = _sequence;
  1738. provider = _provider;
  1739. randomness = _randomness;
  1740. // Keep consuming gas until we reach our target
  1741. uint256 currentGasUsed = startGas - gasleft();
  1742. while (currentGasUsed < targetGasUsage) {
  1743. // Consume gas with a hash operation
  1744. keccak256(abi.encodePacked(currentGasUsed, _randomness));
  1745. currentGasUsed = startGas - gasleft();
  1746. }
  1747. if (reverts) {
  1748. revert("Callback failed");
  1749. }
  1750. }
  1751. }