Last active
July 12, 2021 01:57
-
-
Save alexroan/55c1263fcfc710f834aa38b7bbd21dc1 to your computer and use it in GitHub Desktop.
Game of Thrones 20 Sided Dice
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity 0.6.6; | |
import "https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/VRFConsumerBase.sol"; | |
import "https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/Owned.sol"; | |
/** | |
* @notice A Chainlink VRF consumer which uses randomness to mimic the rolling | |
* of a 20 sided die | |
* @dev This is only an example implementation and not necessarily suitable for mainnet. | |
*/ | |
contract VRFD20 is VRFConsumerBase, Owned { | |
using SafeMathChainlink for uint256; | |
uint256 private constant ROLL_IN_PROGRESS = 42; | |
bytes32 private s_keyHash; | |
uint256 private s_fee; | |
mapping(bytes32 => address) private s_rollers; | |
mapping(address => uint256) private s_results; | |
event DiceRolled(bytes32 indexed requestId, address indexed roller); | |
event DiceLanded(bytes32 indexed requestId, uint256 indexed result); | |
/** | |
* @notice Constructor inherits VRFConsumerBase | |
* | |
* @dev NETWORK: KOVAN | |
* @dev Chainlink VRF Coordinator address: 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9 | |
* @dev LINK token address: 0xa36085F69e2889c224210F603D836748e7dC0088 | |
* @dev Key Hash: 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4 | |
* @dev Fee: 0.1 LINK (100000000000000000) | |
* | |
* @param vrfCoordinator address of the VRF Coordinator | |
* @param link address of the LINK token | |
* @param keyHash bytes32 representing the hash of the VRF job | |
* @param fee uint256 fee to pay the VRF oracle | |
*/ | |
constructor(address vrfCoordinator, address link, bytes32 keyHash, uint256 fee) | |
public | |
VRFConsumerBase(vrfCoordinator, link) | |
{ | |
s_keyHash = keyHash; | |
s_fee = fee; | |
} | |
/** | |
* @notice Requests randomness from a user-provided seed | |
* @dev Warning: if the VRF response is delayed, avoid calling requestRandomness repeatedly | |
* as that would give miners/VRF operators latitude about which VRF response arrives first. | |
* @dev You must review your implementation details with extreme care. | |
* | |
* @param userProvidedSeed uint256 unpredictable seed | |
* @param roller address of the roller | |
*/ | |
function rollDice(uint256 userProvidedSeed, address roller) public onlyOwner returns (bytes32 requestId) { | |
require(LINK.balanceOf(address(this)) >= s_fee, "Not enough LINK to pay fee"); | |
require(s_results[roller] == 0, "Already rolled"); | |
requestId = requestRandomness(s_keyHash, s_fee, userProvidedSeed); | |
s_rollers[requestId] = roller; | |
s_results[roller] = ROLL_IN_PROGRESS; | |
emit DiceRolled(requestId, roller); | |
} | |
/** | |
* @notice Callback function used by VRF Coordinator to return the random number | |
* to this contract. | |
* @dev Some action on the contract state should be taken here, like storing the result. | |
* @dev WARNING: take care to avoid having multiple VRF requests in flight if their order of arrival would result | |
* in contract states with different outcomes. Otherwise miners or the VRF operator would could take advantage | |
* by controlling the order. | |
* @dev The VRF Coordinator will only send this function verified responses, and the parent VRFConsumerBase | |
* contract ensures that this method only receives randomness from the designated VRFCoordinator. | |
* | |
* @param requestId bytes32 | |
* @param randomness The random result returned by the oracle | |
*/ | |
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { | |
uint256 d20Value = randomness.mod(20).add(1); | |
s_results[s_rollers[requestId]] = d20Value; | |
emit DiceLanded(requestId, d20Value); | |
} | |
/** | |
* @notice Get the house assigned to the player once the address has rolled | |
* @param player address | |
* @return house as a string | |
*/ | |
function house(address player) public view returns (string memory) { | |
require(s_results[player] != 0, "Dice not rolled"); | |
require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress"); | |
return getHouseName(s_results[player]); | |
} | |
/** | |
* @notice Withdraw LINK from this contract. | |
* @dev this is an example only, and in a real contract withdrawals should | |
* happen according to the established withdrawal pattern: | |
* https://docs.soliditylang.org/en/v0.4.24/common-patterns.html#withdrawal-from-contracts | |
* @param to the address to withdraw LINK to | |
* @param value the amount of LINK to withdraw | |
*/ | |
function withdrawLINK(address to, uint256 value) public onlyOwner { | |
require(LINK.transfer(to, value), "Not enough LINK"); | |
} | |
/** | |
* @notice Set the key hash for the oracle | |
* | |
* @param keyHash bytes32 | |
*/ | |
function setKeyHash(bytes32 keyHash) public onlyOwner { | |
s_keyHash = keyHash; | |
} | |
/** | |
* @notice Get the current key hash | |
* | |
* @return bytes32 | |
*/ | |
function keyHash() public view returns (bytes32) { | |
return s_keyHash; | |
} | |
/** | |
* @notice Set the oracle fee for requesting randomness | |
* | |
* @param fee uint256 | |
*/ | |
function setFee(uint256 fee) public onlyOwner { | |
s_fee = fee; | |
} | |
/** | |
* @notice Get the current fee | |
* | |
* @return uint256 | |
*/ | |
function fee() public view returns (uint256) { | |
return s_fee; | |
} | |
/** | |
* @notice Get the house namne from the id | |
* @param id uint256 | |
* @return house name string | |
*/ | |
function getHouseName(uint256 id) private pure returns (string memory) { | |
string[20] memory houseNames = [ | |
"Targaryen", | |
"Lannister", | |
"Stark", | |
"Tyrell", | |
"Baratheon", | |
"Martell", | |
"Tully", | |
"Bolton", | |
"Greyjoy", | |
"Arryn", | |
"Frey", | |
"Mormont", | |
"Tarley", | |
"Dayne", | |
"Umber", | |
"Valeryon", | |
"Manderly", | |
"Clegane", | |
"Glover", | |
"Karstark" | |
]; | |
return houseNames[id.sub(1)]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment