{"id":18738566,"url":"https://github.com/lancelot-c/rng-audit","last_synced_at":"2026-04-26T08:38:03.957Z","repository":{"id":224413272,"uuid":"763153435","full_name":"lancelot-c/rng-audit","owner":"lancelot-c","description":"Make your own audit of Random.win","archived":false,"fork":false,"pushed_at":"2024-04-08T20:26:30.000Z","size":83798,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-11T03:15:33.185Z","etag":null,"topics":["ethereum","foundry","randomness","randomness-testing","rng","smart-contracts","testing","testing-tool"],"latest_commit_sha":null,"homepage":"https://random.win","language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lancelot-c.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-25T17:40:48.000Z","updated_at":"2024-05-28T09:05:39.000Z","dependencies_parsed_at":"2024-11-07T15:37:39.944Z","dependency_job_id":"8d40636e-7f09-43fc-9c4e-4948653694a7","html_url":"https://github.com/lancelot-c/rng-audit","commit_stats":null,"previous_names":["lancelot-c/rng-audit"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lancelot-c/rng-audit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lancelot-c%2Frng-audit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lancelot-c%2Frng-audit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lancelot-c%2Frng-audit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lancelot-c%2Frng-audit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lancelot-c","download_url":"https://codeload.github.com/lancelot-c/rng-audit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lancelot-c%2Frng-audit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32291265,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T08:29:33.829Z","status":"ssl_error","status_checked_at":"2026-04-26T08:29:18.366Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ethereum","foundry","randomness","randomness-testing","rng","smart-contracts","testing","testing-tool"],"created_at":"2024-11-07T15:29:35.120Z","updated_at":"2026-04-26T08:38:03.940Z","avatar_url":"https://github.com/lancelot-c.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RNG Audit\n\nThis repository contains scripts enabling anyone to quickly audit the random number generator (RNG) used in the [Verifiable Draws](https://github.com/lancelot-c/verifiable-draws) project.\n\nIt is separated in 2 parts:\n- [Audit of the Chainlink VRF random numbers](https://github.com/lancelot-c/rng-audit?tab=readme-ov-file#empirical-testing-on-chainlink-vrf) that Verifiable Draws uses as a source of randomness\n- [Audit of the observed drawing outcomes](https://github.com/lancelot-c/rng-audit?tab=readme-ov-file#empirical-testing-on-observed-drawing-outcomes)\n\nFor each part we collect a huge sample of randomness which can then be manually analyzed by simply looking at the data and realizing that it looks random. Alternatively, you can perform a more in-depth analysis by using the collected data as inputs for the [Diehard tests](https://en.wikipedia.org/wiki/Diehard_tests) to precisely measure the quality of the random number generator.\n\n## Setup\n\nClone this repository on your local machine:\n```shell\ngit clone https://github.com/lancelot-c/rng-audit.git\n```\n\n## Empirical testing on Chainlink VRF\n\nThis is the testing of the raw randomness received from Chainlink VRF requests.\n\nA smart contract is needed to generate VRF randomness on-demand and make it available for export.\nSuch a contract is available at `src/OnlyRaw.sol` and is deployed for your convenience at [0xBBCD0c8DBdC112dd29af8c57Ee8740bD9feE084B](https://sepolia.arbiscan.io/address/0xBBCD0c8DBdC112dd29af8c57Ee8740bD9feE084B#code). The variable [wordsCounter](https://sepolia.arbiscan.io/address/0xbbcd0c8dbdc112dd29af8c57ee8740bd9fee084b#readContract#F4) is the number of random values that the contract has already generated. At the time of writing, the contract holds a total of 3,125,210 random words, which we consider enough to perform a relevant analysis.\n\n### [Optional] - Generate additional VRF randomness\n\nIf you need more randomness, the easiest way is to [registrer a time-based Upkeep](https://automation.chain.link/arbitrum-sepolia) for this contract on the function `makeVrfRequest(110)` with the CRON expression `*/1 * * * *` for an execution every minute. Make sure [the VRF subscription](https://vrf.chain.link/arbitrum-sepolia/88) for this contract is sufficiently funded, otherwise add funds to the subscription with your own wallet: `Connect Wallet \u003e Actions dropdown \u003e Fund subscription`.\n\nℹ️ Even though Chainlink says you can generate a maximum number of 500 random words per VRF request, it turns out in practice that 110 is the maximum you can ask for (at least on Arbitrum Sepolia), any value greater than that will return an error.\n\n### Export the VRF randomness\n\nNow we want to export all this raw randomness out of the smart contract.\n\nThe `OnlyRaw` script is doing precisely that:\n```shell\ncd scripts/OnlyRaw\n```\n\nSet the variables in the `.env` depending on what values you want to export, for example if you want the first 1,000,000 values:\n```shell\nSTART_AT=1\nHOW_MANY=1000000\n```\n\nThen run the script:\n```shell\nnpm install\nnode OnlyRaw.js\n```\n\nThe output file is located at `script-outputs/OnlyRaw-\u003cSTART_AT\u003e-\u003cHOW_MANY\u003e.txt`.\n\nIf you need additionnal values, let's say 5,000,000 more values, you can run the same script again but this time by ignoring the values that you've already exported:\n```shell\nSTART_AT=1000001\nHOW_MANY=5000000\n```\n\nℹ️ Verifiable Draws is using 64-bit numbers as a source of randomness, however each random word received from Chainlink is 256-bit so each random word is splitted into 4 numbers of 64-bit each and these 64-bit numbers are the ones being exported. This means that when you are exporting 1,000,000 values with this script, you are actually only exporting 250,000 random words from Chainlink. It is important to know this when setting the value for the `HOW_MANY` variable. The maximum value of `HOW_MANY` is therefore the value of [wordsCounter](https://sepolia.arbiscan.io/address/0xbbcd0c8dbdc112dd29af8c57ee8740bd9fee084b#readContract#F4) multiplied by 4.\n\n### Parallelization\n\nFor faster execution, you can run several instances of this script in parallel with different `.env` values.\n\n\n\n## Empirical testing on observed drawing outcomes\n\nWe would like to collect the following 20 datasets:\n\n| **Range** | **Positions** | **Replacement** | **Draws**      |\n|-----------|---------------|-----------------|----------------|\n| 2         | 1             | N/A             |      1,000,000 |\n| 17        | 5             | No              |    20,000,000  |\n| 31        | 12            | No              |    50,000,000  |\n| 57        | 20            | No              |    50,000,000  |\n| 105       | 7             | No              |   100,000,000  |\n| 194       | 30            | No              |   100,000,000  |\n| 358       | 20            | No              |   100,000,000  |\n| 660       | 40            | No              |    50,000,000  |\n| 1,217     | 50            | No              |    50,000,000  |\n| 2,243     | 10            | No              |   200,000,000  |\n| 4,135     | 12            | No              |   200,000,000  |\n| 7,622     | 4             | No              |   500,000,000  |\n| 14,050    | 9             | No              |   200,000,000  |\n| 25,899    | 75            | No              |    20,000,000  |\n| 47,742    | 10            | No              |   200,000,000  |\n| 65,536    | 5             | No              |   500,000,000  |\n| 72,859    | 10            | No              |   200,000,000  |\n| 80,989    | 25            | No              |    50,000,000  |\n| 90,007    | 15            | No              |   100,000,000  |\n| 100,000   | 100           | No              |    10,000,000  |\n\nThis is roughly 32 billion samples total. Now, this is quite a lot of data to collect so instead of using Chainlink VRF as a source of randomness we can use fuzz testing which is a built-in feature of Foundry.\n\nInstall Foundry by running the following command in your terminal, then follow the onscreen instructions:\n```shell\ncurl -L https://foundry.paradigm.xyz | bash\n```\n\nInstall the project dependencies:\n```shell\ncd rng-audit\nforge install lancelot-c/verifiable-draws\nforge install smartcontractkit/chainlink\nforge install OpenZeppelin/openzeppelin-contracts\n```\nWe will run the test file `OnlyOutcomes.t.sol` which contains an equivalent of the [checkDrawWinners](https://sepolia.arbiscan.io/address/0xea8f563fe11c87cd90186433ff6ebe1f7ccf3d1e#code#F9#L379) function of the Verifiable Draws smart contract adapted for fuzz testing.\n\nMake sure your `.env` has the desired dataset parameters, for example if you want to collect dataset #2 your `.env` should have:\n```\nRANGE=17\nPOSITIONS=5\nFOUNDRY_FUZZ_RUNS=20000000\n```\n\nThen run:\n```shell\nforge test\n```\nThe output file is located at `script-outputs/OnlyOutcomes-\u003cRANGE\u003e-\u003cPOSITIONS\u003e-\u003cFOUNDRY_FUZZ_RUNS\u003e.txt`.\n\nOn a regular consumer laptop the dataset #1 should take approximatively 90 seconds to generate.\n\n### Parallelization\n\nFor faster execution, each dataset can be generated in parallel if you launch several instances of this test on different machines with different `.env` values.\n\n\n## Getting Help\n\nOur [Discord](https://discord.gg/UTcNWAZ9) is the best place to ask for help.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flancelot-c%2Frng-audit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flancelot-c%2Frng-audit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flancelot-c%2Frng-audit/lists"}