Skip to content

Instantly share code, notes, and snippets.

@alexroan
Last active July 12, 2021 01:57
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save alexroan/55c1263fcfc710f834aa38b7bbd21dc1 to your computer and use it in GitHub Desktop.
Save alexroan/55c1263fcfc710f834aa38b7bbd21dc1 to your computer and use it in GitHub Desktop.
Game of Thrones 20 Sided Dice
// 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