Skip to content

Commit

Permalink
Merge pull request #348 from MerlinEgalite/feat/chainlink-rng
Browse files Browse the repository at this point in the history
feat(ChainlinkRNG): Add Chainlink RNG contract
  • Loading branch information
MerlinEgalite authored Jun 7, 2021
2 parents 54df464 + 8b33dae commit d570e96
Show file tree
Hide file tree
Showing 4 changed files with 1,532 additions and 12 deletions.
133 changes: 133 additions & 0 deletions contracts/standard/rng/ChainlinkRNG.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/**
* @authors: [@MerlinEgalite]
* @reviewers: []
* @auditors: []
* @bounties: []
* @deployments: []
*/
pragma solidity ^0.6.6;

import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
import "./RNG.sol";


interface IKlerosLiquid {
function passPhase() external;
}


/**
* @title Random Number Generator using Chainlink Verifiable Randomness Mechanism on Polygon
* @author Merlin Egalite - <[email protected]>
*
* @dev This contract implements the RNG standard and inherits from VRFConsumerBase to use Chainlink Verifiable Randomness Mechanism.
* @dev It allows to store the random number associated to the requests made.
* @dev Note that to make requests to Chainlink, the contract needs to be funded with some LINK.
* @dev Chainlink documentation: https://docs.chain.link/docs/chainlink-vrf/
* @dev For SECURITY CONSIDERATIONS, you might also have look to: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/VRFConsumerBase.sol
*/
contract ChainlinkRNG is RNG, VRFConsumerBase {

/* Storage */

IKlerosLiquid public kleros; // The address of Kleros Liquid.
bytes32 internal keyHash; // The key hash for the VRF Coordinator.
uint256 internal fee; // The amount of LINK to send with a request.
mapping(bytes32 => uint256) public randomNumber; // randomNumber[requestId] is the random number for the requestId, 0 otherwise.

/* Modifier */

modifier onlyByKleros() {
require(msg.sender == address(kleros), "ChainlinkRNG: not called by Kleros");
_;
}

/* Constructor */

/**
* @dev Constructs the ChainlinkRNG contract.
* @param _vrfCoordinator The address of VRFCoordinator contract.
* @param _link The address of LINK token contract.
* @param _kleros The address of Kleros Liquid's contract.
* @param _keyHash The key hash for the VRF Coordinator.
* @param _fee The amount of LINK to send with a request.
*
* @dev https://docs.chain.link/docs/link-token-contracts
*/
constructor(
address _vrfCoordinator,
address _link,
IKlerosLiquid _kleros,
bytes32 _keyHash,
uint256 _fee
)
VRFConsumerBase(_vrfCoordinator, _link)
public
{
keyHash = _keyHash;
kleros = _kleros;
fee = _fee;
}

/* External */

/**
* @dev Withdraws all LINK tokens locked in this contract.
*/
function withdrawLink() external onlyByKleros {
require(LINK.transfer(msg.sender, LINK.balanceOf(address(this))), "ChainlinkRNG: unable to transfer LINK tokens");
}

/**
* @dev Changes the `fee` storage variable.
* @param _newFee The new value for the `fee` storage variable.
*/
function changeFee(uint256 _newFee) external onlyByKleros {
fee = _newFee;
}

/**
* @dev Changes the `kleros` storage variable.
* @param _newKleros The new value for the `kleros` storage variable.
*/
function changeKleros(IKlerosLiquid _newKleros) external onlyByKleros {
kleros = _newKleros;
}

/**
* @dev Requests a random number.
* @dev The _seed parameter is vestigial, and is kept only for API
* @dev compatibility with older versions. It can't *hurt* to mix in some of
* @dev your own randomness, here, but it's not necessary because the VRF
* @dev oracle will mix the hash of the block containing your request into the
* @dev VRF seed it ultimately uses.
* @param _seed seed mixed into the input of the VRF.
* @return requestId unique ID for this request.
*/
function requestRN(uint _seed) external onlyByKleros returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "ChainlinkRNG: not enough LINK to pay the fee");
return requestRandomness(keyHash, fee, _seed);
}

/**
* @dev Gets the random number associated to a `_requestId`.
* @param _requestId The request Id initially returned by requestRN.
* @return RN Random Number. If the number is not ready or has not been required it returns 0.
*/
function getRN(bytes32 _requestId) external view returns (uint256 RN) {
return randomNumber[_requestId];
}

/* Internal */

/**
* @dev Stores the random number given by the VRF Coordinator and calls passPhase function on Kleros Liquid.
* @dev This is the callback function used by the VRF Coordinator.
* @param _requestId The request Id initially returned by requestRN.
* @param _randomness the VRF output.
*/
function fulfillRandomness(bytes32 _requestId, uint256 _randomness) internal override {
randomNumber[_requestId] = _randomness;
IKlerosLiquid(kleros).passPhase();
}
}
4 changes: 3 additions & 1 deletion contracts/standard/rng/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ BlockhashRNGFallback.sol does the same as the previous contract but fallback to

TrustedRNG.sol implements a random number generator based on a trusted third party.

ConstantNG.sol implements a contracts always returning a specified number to ease testing.
ConstantNG.sol implements a contract always returning a specified number to ease testing.

Chainlink.sol implements the RNG standard using Chainlink's Verifiable Randomness Mechanism
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"dependencies": {
"@kleros/kleros": "^0.1.2",
"@realitio/realitio-contracts": "^2.0.5",
"@chainlink/contracts": "^0.1.7",
"minimetoken": "^0.2.0",
"openzeppelin-solidity": "^1.12.0",
"web3-utils": "^1.2.1"
Expand Down
Loading

0 comments on commit d570e96

Please sign in to comment.