diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2ed207e..3842e6a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,6 +32,6 @@ jobs: - uses: actions/setup-node@main with: node-version: ${{ matrix.node }} - - run: yarn install + - run: yarn - run: yarn deploy - run: yarn test diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..cc0e65f --- /dev/null +++ b/.npmignore @@ -0,0 +1,39 @@ +node_modules +.env +.env.* +coverage +coverage.json +.vscode +.openzeppelin +.github +.husky +.git + +.eslintignore +.gitignore +.gitmodules +.prettierignore +.prettierrc +.solcover.js +.solhint.json +.solhintignore +tsconfig.json +tslint.json + +# fix for coverage with 0.8.19 +/modules + +#Hardhat files +/cache +/artifacts +/.openzeppelin +/scripts +hardhat.config.ts +resolutions.json +mythril.solc.json +slither.config.json +.solcx-lock* + +/contracts/test +/test +/constants \ No newline at end of file diff --git a/README.md b/README.md index 6da960e..0be234b 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,105 @@ [![Continuous integration](https://github.com/PaintSwap/samwitch-vrf/actions/workflows/main.yml/badge.svg)](https://github.com/PaintSwap/samwitch-vrf/actions/workflows/main.yml) ![swvrf](https://github.com/PaintSwap/samwitch-vrf/assets/84033732/4caebec8-7e8d-4416-9f59-91e827ecbdd3) + This is a Verifiable Random Function smart contract handler, which requests random numbers from an oracle, and has a callback called once the random numbers are ready. There are no costs in requesting a number, but there needs to be enough native gas (FTM) on the oracle signer to be able to call the callbacks. -To start copy the `.env.sample` file to `.env` and fill in `PRIVATE_KEY` at a minimum (starts with `0x`). +## Consume Random Numbers + +### Install via NPM + +Install using `yarn` or `npm`. ```shell -yarn install +npm install -D @samwitch/vrf +``` + +```shell +yarn add -D @samwitch/vrf +``` + +### Include in Solidity Contracts + +To request a random number in your contract you must implement `ISamWitchVRFConsumer.fulfillRandomWords(bytes32 requestId, uint256[] calldata randomWords)` to recieve the response to your request. The service can be called using the `ISamWitchVRF` interface, and ensuring +that the results are only provided by the randomness service contract. + +```ts +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import { ISamWitchVRFConsumer } from "@samwitch/vrf/contracts/interfaces/ISamWitchVRFConsumer.sol"; +import { ISamWitchVRF } from "@samwitch/vrf/contracts/interfaces/ISamWitchVRF.sol"; + +contract TestVRFConsumer is ISamWitchVRFConsumer { + ISamWitchVRF public samWitchVRF; + mapping(bytes32 requestId => uint256[] randomWords) public allRandomWords; + + error OnlySamWitchVRF(); + + modifier onlySamWitchVRF() { + if (msg.sender != address(samWitchVRF)) { + revert OnlySamWitchVRF(); + } + _; + } + + constructor(ISamWitchVRF _samWitchVRF) { + samWitchVRF = _samWitchVRF; + } + + function requestRandomWords( + uint256 numWords, + uint256 callbackGasLimit + ) external onlyOwner returns (bytes32 requestId) { + requestId = samWitchVRF.requestRandomWords(numWords, callbackGasLimit); + } + // Called by the VRF contract to fulfill a random number request + function fulfillRandomWords( + bytes32 requestId, + uint256[] calldata randomWords + ) external override onlySamWitchVRF { + allRandomWords[requestId] = randomWords; + } +} +``` + +## Remote Deployment + +If you want to deploy your own randomness service and manage it from another project, you must first import it into your Solidity contracts. This can be done by creating a file such as `./Imports.sol` with the contents: + +```ts +// SPDX-License-Identifier: MIT +pragma solidity ^0.8; + +import {SamWitchVRF} from "@samwitch/vrf/contracts/SamWitchVRF.sol"; + +``` + +You can then reference this artifact name in TypeScript files, like in this `ethers-v6` and `hardhat` proxy example. + +```ts +import { SamWitchVRF } from "@samwitch/vrf"; + +async function deployContractsFixture() { + const [owner] = await ethers.getSigners(); + const SamWitchVRF = await ethers.getContractFactory("SamWitchVRF"); + const samWitchVRF = (await upgrades.deployProxy( + SamWitchVRF, + [owner.address], + { + kind: "uups", + }, + )) as unknown as SamWitchVRF; + console.log("SamWitchVRF deployed at", await samWitchVRF.getAddress()); +} +``` + +## Development & Testing + +To start copy the `.env.sample` file to `.env` and fill in `PRIVATE_KEY` at a minimum (starts with `0x`). + +```shell # To compile the contracts yarn compile diff --git a/contracts/libraries/EllipticCurve.sol b/contracts/libraries/EllipticCurve.sol index 0847fff..7b05cc8 100644 --- a/contracts/libraries/EllipticCurve.sol +++ b/contracts/libraries/EllipticCurve.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity ^0.8.0; /** ** @title Elliptic Curve Library diff --git a/contracts/libraries/VRF.sol b/contracts/libraries/VRF.sol index 0b9d977..6db50db 100644 --- a/contracts/libraries/VRF.sol +++ b/contracts/libraries/VRF.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity ^0.8.0; import {EllipticCurve} from "./EllipticCurve.sol"; diff --git a/contracts/test/TestVRFConsumer.sol b/contracts/test/TestVRFConsumer.sol index e59cdfb..e9d91f7 100644 --- a/contracts/test/TestVRFConsumer.sol +++ b/contracts/test/TestVRFConsumer.sol @@ -32,7 +32,7 @@ contract TestVRFConsumer is ISamWitchVRFConsumer, Ownable { } // Called by the VRF contract to fulfill a random number request - function fulfillRandomWords(bytes32 requestId, uint256[] calldata randomWords) external onlySamWitchVRF { + function fulfillRandomWords(bytes32 requestId, uint256[] calldata randomWords) external override onlySamWitchVRF { allRandomWords[requestId] = randomWords; if (shouldRevert) { revert ShouldRevertTrue(); diff --git a/package.json b/package.json index fbe2384..a54d554 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,12 @@ { - "name": "samwitch-vrf", - "version": "1.0.0", - "main": "index.js", + "name": "@samwitch/vrf", + "version": "0.0.1", "author": "0xSamWitch ", + "contributors": [ + "0xDoubleSharp" + ], "license": "MIT", + "types": "typechain-types/contracts/index.ts", "devDependencies": { "@nomicfoundation/hardhat-chai-matchers": "^2.0.6", "@nomicfoundation/hardhat-ethers": "^3.0.5", @@ -57,6 +60,7 @@ "abi": "npx hardhat export-abi", "prettier": "npx prettier --write contracts/**/*.sol", "precommit": "npx pretty-quick --staged", - "prepare": "npx husky install .husky" + "prepare": "npx husky .husky", + "prepublish": "npx hardhat typechain" } }