├── .env.example ├── .gitignore ├── .solhint.json ├── LICENSE ├── README.md ├── chainlink-node └── job_specs │ ├── password_api.json │ └── weather_update.json ├── contracts ├── Consensus2021ChainlinkWeatherNFT.sol ├── Migrations.sol ├── WeatherFeed.sol ├── interfaces │ └── IWeatherFeed.sol └── test │ └── MockOracle.sol ├── flatWeatherNFT.txt ├── migrations ├── 1_initial_migration.js ├── 2_deploy_weather_feed.js ├── 3_deploy_weatherNFT.js ├── 4_mint.js ├── 5_fund.js └── 6_get_weather.js ├── package.json ├── scripts ├── attempt-password.js ├── helper-scripts.js ├── read-weather.js └── request-weather.js ├── test └── weatherTest.js ├── truffle-config.js ├── weather-ipfs ├── img │ ├── cloud-chainlink.gif │ ├── rain-chainlink.gif │ ├── snow-chainlink.gif │ └── sun-chainlink.gif └── metadata │ ├── cloud-chainlink.json │ ├── rain-chainlink.json │ ├── snow-chainlink.json │ └── sun-chainlink.json └── yarn.lock /.env.example: -------------------------------------------------------------------------------- 1 | MNEMONIC="..." 2 | RPC_URL="https://kovan.infura.io/v3/..." 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .notes 2 | node_modules 3 | .DS* 4 | build 5 | .env 6 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "rules": { 4 | "compiler-version": ["error","^0.6.12"] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 SmartContract ChainLink, Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Weather-NFTs 2 | 3 |
4 |

5 | 6 | Chainlink Cloud 7 | Chainlink Rain 8 | Chainlink Sun 9 | Chainlink Snow 10 | 11 |

12 |
13 | 14 | [Weather Condition Codes](https://openweathermap.org/weather-conditions) 15 | 16 | ## Requirements 17 | 18 | - NPM 19 | 20 | ## Installation 21 | 22 | 1. Install truffle 23 | 24 | ```bash 25 | yarn global add truffle 26 | ``` 27 | 28 | 2. Setup repo 29 | 30 | ```bash 31 | git clone https://github.com/PatrickAlphaC/weather-nft 32 | cd weather-nft 33 | yarn 34 | ``` 35 | 36 | sdfasdfasf 37 | 3. Deploy 38 | 39 | ``` 40 | truffle migrate --network XXXX 41 | ``` 42 | 43 | ### Verify 44 | 45 | 46 | ``` 47 | yarn add truffle-plugin-verify 48 | truffle run verify WeatherNFT --network rinkeby --license MIT 49 | truffle run verify WeatherFeed --network rinkeby --license MIT 50 | ``` 51 | 52 | ## password_cl_ea 53 | 54 | https://github.com/PatrickAlphaC/password_cl_ea 55 | 56 | 57 | -------------------------------------------------------------------------------- /chainlink-node/job_specs/password_api.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "password-api-job", 3 | "initiators": [ 4 | { 5 | "type": "runlog", 6 | "params": { 7 | "address": "CONTRACT_ADDRESS" 8 | } 9 | } 10 | ], 11 | "tasks": [ 12 | { 13 | "type": "password_cl_ea" 14 | }, 15 | { 16 | "type": "copy", 17 | "params": { 18 | "copyPath": [ 19 | "result" 20 | ] 21 | } 22 | }, 23 | { 24 | "type": "ethuint256" 25 | }, 26 | { 27 | "type": "ethtx" 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /chainlink-node/job_specs/weather_update.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weather_update", 3 | "initiators": [ 4 | { 5 | "type": "RunLog", 6 | "params": { 7 | "address": "" 8 | } 9 | } 10 | ], 11 | "tasks": [ 12 | { 13 | "type": "weather_cl_ea" 14 | }, 15 | { 16 | "type": "copy" 17 | }, 18 | { 19 | "type": "ethbytes32" 20 | }, 21 | { 22 | "type": "EthTx" 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /contracts/Consensus2021ChainlinkWeatherNFT.sol: -------------------------------------------------------------------------------- 1 | // 2 | // SPDX-License-Identifier: MIT 3 | 4 | pragma solidity ^0.6.6; 5 | 6 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 7 | import "@openzeppelin/contracts/access/Ownable.sol"; 8 | import "@openzeppelin/contracts/utils/Strings.sol"; 9 | import "./interfaces/IWeatherFeed.sol"; 10 | import "@chainlink/contracts/src/v0.6/ChainlinkClient.sol"; 11 | import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; 12 | 13 | contract Consensus2021ChainlinkWeatherNFT is ERC721, Ownable, ChainlinkClient { 14 | using Strings for string; 15 | bool public overRide; 16 | string public overRideWeather; 17 | uint256 public tokenCounter; 18 | address public weatherFeedAddress; 19 | uint256 public response; 20 | 21 | bytes32 public jobId; 22 | address public oracle; 23 | uint256 public fee; 24 | 25 | mapping(bytes32 => address) public requestIdToAttemptee; 26 | mapping(string => string) public weatherToWeatherURI; 27 | mapping(uint256 => string) public overRideTokenIdToWeatherURI; 28 | mapping(uint256 => bool) public tokenIdTaken; 29 | event attemptedPassword(bytes32 requestId); 30 | 31 | constructor(address _link, address _weatherFeed, address _oracle, bytes32 _jobId, uint256 _fee) public 32 | ERC721("Consensus2021ChainlinkWeatherNFT", "wNFT") 33 | { 34 | if (_link == address(0)) { 35 | setPublicChainlinkToken(); 36 | } else { 37 | setChainlinkToken(_link); 38 | } 39 | weatherFeedAddress = _weatherFeed; 40 | weatherToWeatherURI["Thunderstorm"] = "https://ipfs.io/ipfs/QmP3TpPig2St3nTwvi9TFAGdv6YTew5k4pmC1yFtaLwFFo"; 41 | weatherToWeatherURI["Drizzle"] = "https://ipfs.io/ipfs/QmP3TpPig2St3nTwvi9TFAGdv6YTew5k4pmC1yFtaLwFFo"; 42 | weatherToWeatherURI["Rain"] = "https://ipfs.io/ipfs/QmP3TpPig2St3nTwvi9TFAGdv6YTew5k4pmC1yFtaLwFFo"; 43 | weatherToWeatherURI["Snow"] = "https://ipfs.io/ipfs/QmaeYdJ8EydzUGdGQGkPNkSBEQUmwRmAv2QWq1VTfsfrdk"; 44 | weatherToWeatherURI["Atmosphere"] = "https://ipfs.io/ipfs/QmbNEeSa8pZrepYhGnnhSCmABZXymvc7YR5JKFT7TuYuYY"; 45 | weatherToWeatherURI["Clear"] = "https://ipfs.io/ipfs/QmcKEV1xJQ3ZCyPsDPJHsuEZnF95hNZf8S3rBEvzCKwjof"; 46 | weatherToWeatherURI["Clouds"] = "https://ipfs.io/ipfs/QmbNEeSa8pZrepYhGnnhSCmABZXymvc7YR5JKFT7TuYuYY"; 47 | overRide = true; 48 | overRideTokenIdToWeatherURI[0] = weatherToWeatherURI["Rain"]; 49 | overRideTokenIdToWeatherURI[1] = weatherToWeatherURI["Clear"]; 50 | overRideTokenIdToWeatherURI[2] = weatherToWeatherURI["Clouds"]; 51 | overRideTokenIdToWeatherURI[3] = weatherToWeatherURI["Snow"]; 52 | oracle = _oracle; 53 | jobId = _jobId; 54 | fee = _fee; 55 | } 56 | 57 | function mintWeatherNFT() public onlyOwner{ 58 | _safeMint(msg.sender, tokenCounter); 59 | tokenCounter = tokenCounter + 1; 60 | } 61 | 62 | function setOverRide(uint256 _overRide) public onlyOwner { 63 | if (_overRide == 0){ 64 | overRide = false; 65 | } 66 | if (_overRide == 1){ 67 | overRide = true; 68 | } 69 | } 70 | 71 | function setWeatherURI(string memory weather, string memory tokenUri, uint256 tokenId) public onlyOwner { 72 | weatherToWeatherURI[weather] = tokenUri; 73 | overRideTokenIdToWeatherURI[tokenId] = tokenUri; 74 | } 75 | 76 | function tokenURI(uint256 tokenId) public view override (ERC721) returns (string memory) { 77 | require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); 78 | if(overRide == true){ 79 | return overRideTokenIdToWeatherURI[tokenId % 4]; 80 | } 81 | return weatherToWeatherURI[IWeatherFeed(weatherFeedAddress).weather()]; 82 | // snow 83 | // rain 84 | // sun 85 | // clouds 86 | } 87 | 88 | function attemptPassword(string memory password) public returns (bytes32 requestId){ 89 | Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfill.selector); 90 | req.add("password", password); 91 | requestId = sendChainlinkRequestTo(oracle, req, fee); 92 | requestIdToAttemptee[requestId] = msg.sender; 93 | emit attemptedPassword(requestId); 94 | } 95 | 96 | function fulfill(bytes32 _requestId, uint256 _data) public recordChainlinkFulfillment(_requestId) 97 | { 98 | response = _data; 99 | if(response == 0){ 100 | require(tokenIdTaken[0] == false, "This token is taken!"); 101 | safeTransferFrom(ownerOf(0), requestIdToAttemptee[_requestId], 0); 102 | tokenIdTaken[0] = true; 103 | } 104 | if (response == 1){ 105 | require(tokenIdTaken[1] == false, "This token is taken!"); 106 | safeTransferFrom(ownerOf(1), requestIdToAttemptee[_requestId], 1); 107 | tokenIdTaken[1] = true; 108 | } 109 | if (response == 2){ 110 | require(tokenIdTaken[2] == false, "This token is taken!"); 111 | safeTransferFrom(ownerOf(2), requestIdToAttemptee[_requestId], 2); 112 | tokenIdTaken[2] = true; 113 | } 114 | if (response == 3){ 115 | require(tokenIdTaken[3] == false, "This token is taken!"); 116 | safeTransferFrom(ownerOf(3), requestIdToAttemptee[_requestId], 3); 117 | tokenIdTaken[3] = true; 118 | } 119 | } 120 | 121 | function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) { 122 | uint8 i = 0; 123 | while(i < 32 && _bytes32[i] != 0) { 124 | i++; 125 | } 126 | bytes memory bytesArray = new bytes(i); 127 | for (i = 0; i < 32 && _bytes32[i] != 0; i++) { 128 | bytesArray[i] = _bytes32[i]; 129 | } 130 | return string(bytesArray); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.6; 3 | 4 | contract Migrations { 5 | address public owner; 6 | uint256 public lastCompletedMigration; 7 | 8 | modifier restricted() { 9 | if (msg.sender == owner) _; 10 | } 11 | 12 | constructor() public { 13 | owner = msg.sender; 14 | } 15 | 16 | function setCompleted(uint256 completed) public restricted { 17 | lastCompletedMigration = completed; 18 | } 19 | 20 | function upgrade(address newAddress) public restricted { 21 | Migrations upgraded = Migrations(newAddress); 22 | upgraded.setCompleted(lastCompletedMigration); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/WeatherFeed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.6; 3 | 4 | import "@chainlink/contracts/src/v0.6/ChainlinkClient.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | import "@openzeppelin/contracts/utils/Strings.sol"; 7 | 8 | /** 9 | * @title MyContract is an example contract which requests data from 10 | * the Chainlink network 11 | * @dev This contract is designed to work on multiple networks, including 12 | * local test networks 13 | */ 14 | contract WeatherFeed is ChainlinkClient, Ownable { 15 | using Strings for string; 16 | string public weather; 17 | bytes32 public jobid; 18 | address public oracle; 19 | uint256 public fee; 20 | 21 | /** 22 | * @notice Deploy the contract with a specified address for the LINK 23 | * and Oracle contract addresses 24 | * @dev Sets the storage for the specified addresses 25 | * @param _link The address of the LINK token contract 26 | */ 27 | // web3.utils.toHex(jobId) 28 | constructor(address _link, bytes32 _jobid, address _oracle, uint256 _fee) public { 29 | if (_link == address(0)) { 30 | setPublicChainlinkToken(); 31 | } else { 32 | setChainlinkToken(_link); 33 | } 34 | jobid = _jobid; 35 | oracle = _oracle; 36 | fee = _fee; 37 | weather = "Clear"; 38 | } 39 | 40 | /** 41 | * @notice Returns the address of the LINK token 42 | * @dev This is the public implementation for chainlinkTokenAddress, which is 43 | * an internal method of the ChainlinkClient contract 44 | */ 45 | function getChainlinkToken() public view returns (address) { 46 | return chainlinkTokenAddress(); 47 | } 48 | 49 | function setWeather(string memory _weather) public onlyOwner { 50 | weather = _weather; 51 | } 52 | 53 | function getWeather() public onlyOwner 54 | returns (bytes32 requestId) 55 | { 56 | Chainlink.Request memory req = buildChainlinkRequest(jobid, address(this), this.fulfill.selector); 57 | req.add("city", "boston"); 58 | req.add("copyPath", "weather.0.main"); 59 | requestId = sendChainlinkRequestTo(oracle, req, fee); 60 | } 61 | 62 | /** 63 | * @notice The fulfill method from requests created by this contract 64 | * @dev The recordChainlinkFulfillment protects this function from being called 65 | * by anyone other than the oracle address that the request was sent to 66 | * @param _requestId The ID that was generated for the request 67 | * @param _data The answer provided by the oracle 68 | */ 69 | function fulfill(bytes32 _requestId, bytes32 _data) 70 | public 71 | recordChainlinkFulfillment(_requestId) 72 | { 73 | weather = bytes32ToString(_data); 74 | } 75 | 76 | /** 77 | * @notice Allows the owner to withdraw any LINK balance on the contract 78 | */ 79 | function withdrawLink() public onlyOwner { 80 | LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); 81 | require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer"); 82 | } 83 | 84 | 85 | function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) { 86 | uint8 i = 0; 87 | while(i < 32 && _bytes32[i] != 0) { 88 | i++; 89 | } 90 | bytes memory bytesArray = new bytes(i); 91 | for (i = 0; i < 32 && _bytes32[i] != 0; i++) { 92 | bytesArray[i] = _bytes32[i]; 93 | } 94 | return string(bytesArray); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /contracts/interfaces/IWeatherFeed.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.6; 2 | 3 | interface IWeatherFeed { 4 | function weather() external view returns (string memory); 5 | } 6 | -------------------------------------------------------------------------------- /contracts/test/MockOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.6.6; 3 | 4 | import "@chainlink/contracts/src/v0.6/LinkTokenReceiver.sol"; 5 | import "@chainlink/contracts/src/v0.6/interfaces/ChainlinkRequestInterface.sol"; 6 | import "@chainlink/contracts/src/v0.6/interfaces/LinkTokenInterface.sol"; 7 | import "@chainlink/contracts/src/v0.6/vendor/SafeMathChainlink.sol"; 8 | 9 | /** 10 | * @title The Chainlink Mock Oracle contract 11 | * @notice Chainlink smart contract developers can use this to test their contracts 12 | */ 13 | contract MockOracle is ChainlinkRequestInterface, LinkTokenReceiver { 14 | using SafeMathChainlink for uint256; 15 | bytes32 public bigRequestId; 16 | 17 | uint256 constant public EXPIRY_TIME = 5 minutes; 18 | uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000; 19 | 20 | struct Request { 21 | address callbackAddr; 22 | bytes4 callbackFunctionId; 23 | } 24 | 25 | LinkTokenInterface internal LinkToken; 26 | mapping(bytes32 => Request) public commitments; 27 | 28 | event OracleRequest( 29 | bytes32 indexed specId, 30 | address requester, 31 | bytes32 requestId, 32 | uint256 payment, 33 | address callbackAddr, 34 | bytes4 callbackFunctionId, 35 | uint256 cancelExpiration, 36 | uint256 dataVersion, 37 | bytes data 38 | ); 39 | 40 | event CancelOracleRequest( 41 | bytes32 indexed requestId 42 | ); 43 | 44 | /** 45 | * @notice Deploy with the address of the LINK token 46 | * @dev Sets the LinkToken address for the imported LinkTokenInterface 47 | * @param _link The address of the LINK token 48 | */ 49 | constructor(address _link) 50 | public 51 | { 52 | LinkToken = LinkTokenInterface(_link); // external but already deployed and unalterable 53 | } 54 | 55 | /** 56 | * @notice Creates the Chainlink request 57 | * @dev Stores the hash of the params as the on-chain commitment for the request. 58 | * Emits OracleRequest event for the Chainlink node to detect. 59 | * @param _sender The sender of the request 60 | * @param _payment The amount of payment given (specified in wei) 61 | * @param _specId The Job Specification ID 62 | * @param _callbackAddress The callback address for the response 63 | * @param _callbackFunctionId The callback function ID for the response 64 | * @param _nonce The nonce sent by the requester 65 | * @param _dataVersion The specified data version 66 | * @param _data The CBOR payload of the request 67 | */ 68 | function oracleRequest( 69 | address _sender, 70 | uint256 _payment, 71 | bytes32 _specId, 72 | address _callbackAddress, 73 | bytes4 _callbackFunctionId, 74 | uint256 _nonce, 75 | uint256 _dataVersion, 76 | bytes calldata _data 77 | ) 78 | external 79 | override 80 | onlyLINK() 81 | checkCallbackAddress(_callbackAddress) 82 | { 83 | bytes32 requestId = keccak256(abi.encodePacked(_sender, _nonce)); 84 | require(commitments[requestId].callbackAddr == address(0), "Must use a unique ID"); 85 | // solhint-disable-next-line not-rely-on-time 86 | uint256 expiration = now.add(EXPIRY_TIME); 87 | 88 | commitments[requestId] = Request( 89 | _callbackAddress, 90 | _callbackFunctionId 91 | ); 92 | bigRequestId = requestId; 93 | 94 | emit OracleRequest( 95 | _specId, 96 | _sender, 97 | requestId, 98 | _payment, 99 | _callbackAddress, 100 | _callbackFunctionId, 101 | expiration, 102 | _dataVersion, 103 | _data); 104 | } 105 | 106 | /** 107 | * @notice Called by the Chainlink node to fulfill requests 108 | * @dev Given params must hash back to the commitment stored from `oracleRequest`. 109 | * Will call the callback address' callback function without bubbling up error 110 | * checking in a `require` so that the node can get paid. 111 | * @param _requestId The fulfillment request ID that must match the requester's 112 | * @param _data The data to return to the consuming contract 113 | * @return Status if the external call was successful 114 | */ 115 | function fulfillOracleRequest( 116 | bytes32 _requestId, 117 | bytes32 _data 118 | ) 119 | external 120 | isValidRequest(_requestId) 121 | returns (bool) 122 | { 123 | Request memory req = commitments[_requestId]; 124 | delete commitments[_requestId]; 125 | require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas"); 126 | // All updates to the oracle's fulfillment should come before calling the 127 | // callback(addr+functionId) as it is untrusted. 128 | // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern 129 | (bool success, ) = req.callbackAddr.call(abi.encodeWithSelector(req.callbackFunctionId, _requestId, _data)); // solhint-disable-line avoid-low-level-calls 130 | return success; 131 | } 132 | 133 | /** 134 | * @notice Allows requesters to cancel requests sent to this oracle contract. Will transfer the LINK 135 | * sent for the request back to the requester's address. 136 | * @dev Given params must hash to a commitment stored on the contract in order for the request to be valid 137 | * Emits CancelOracleRequest event. 138 | * @param _requestId The request ID 139 | * @param _payment The amount of payment given (specified in wei) 140 | * @param _expiration The time of the expiration for the request 141 | */ 142 | function cancelOracleRequest( 143 | bytes32 _requestId, 144 | uint256 _payment, 145 | bytes4, 146 | uint256 _expiration 147 | ) 148 | external 149 | override 150 | { 151 | require(commitments[_requestId].callbackAddr != address(0), "Must use a unique ID"); 152 | // solhint-disable-next-line not-rely-on-time 153 | require(_expiration <= now, "Request is not expired"); 154 | 155 | delete commitments[_requestId]; 156 | emit CancelOracleRequest(_requestId); 157 | 158 | assert(LinkToken.transfer(msg.sender, _payment)); 159 | } 160 | 161 | /** 162 | * @notice Returns the address of the LINK token 163 | * @dev This is the public implementation for chainlinkTokenAddress, which is 164 | * an internal method of the ChainlinkClient contract 165 | */ 166 | function getChainlinkToken() 167 | public 168 | view 169 | override 170 | returns (address) 171 | { 172 | return address(LinkToken); 173 | } 174 | 175 | // MODIFIERS 176 | 177 | /** 178 | * @dev Reverts if request ID does not exist 179 | * @param _requestId The given request ID to check in stored `commitments` 180 | */ 181 | modifier isValidRequest(bytes32 _requestId) { 182 | require(commitments[_requestId].callbackAddr != address(0), "Must have a valid requestId"); 183 | _; 184 | } 185 | 186 | 187 | /** 188 | * @dev Reverts if the callback address is the LINK token 189 | * @param _to The callback address 190 | */ 191 | modifier checkCallbackAddress(address _to) { 192 | require(_to != address(LinkToken), "Cannot callback to LINK"); 193 | _; 194 | } 195 | 196 | } 197 | -------------------------------------------------------------------------------- /flatWeatherNFT.txt: -------------------------------------------------------------------------------- 1 | // File: @openzeppelin/contracts/utils/Context.sol 2 | 3 | // SPDX-License-Identifier: MIT 4 | 5 | pragma solidity >=0.6.0 <0.8.0; 6 | 7 | /* 8 | * @dev Provides information about the current execution context, including the 9 | * sender of the transaction and its data. While these are generally available 10 | * via msg.sender and msg.data, they should not be accessed in such a direct 11 | * manner, since when dealing with GSN meta-transactions the account sending and 12 | * paying for execution may not be the actual sender (as far as an application 13 | * is concerned). 14 | * 15 | * This contract is only required for intermediate, library-like contracts. 16 | */ 17 | abstract contract Context { 18 | function _msgSender() internal view virtual returns (address payable) { 19 | return msg.sender; 20 | } 21 | 22 | function _msgData() internal view virtual returns (bytes memory) { 23 | this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 24 | return msg.data; 25 | } 26 | } 27 | 28 | // File: @openzeppelin/contracts/introspection/IERC165.sol 29 | 30 | // SPDX-License-Identifier: MIT 31 | 32 | pragma solidity >=0.6.0 <0.8.0; 33 | 34 | /** 35 | * @dev Interface of the ERC165 standard, as defined in the 36 | * https://eips.ethereum.org/EIPS/eip-165[EIP]. 37 | * 38 | * Implementers can declare support of contract interfaces, which can then be 39 | * queried by others ({ERC165Checker}). 40 | * 41 | * For an implementation, see {ERC165}. 42 | */ 43 | interface IERC165 { 44 | /** 45 | * @dev Returns true if this contract implements the interface defined by 46 | * `interfaceId`. See the corresponding 47 | * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] 48 | * to learn more about how these ids are created. 49 | * 50 | * This function call must use less than 30 000 gas. 51 | */ 52 | function supportsInterface(bytes4 interfaceId) external view returns (bool); 53 | } 54 | 55 | // File: @openzeppelin/contracts/token/ERC721/IERC721.sol 56 | 57 | // SPDX-License-Identifier: MIT 58 | 59 | pragma solidity >=0.6.2 <0.8.0; 60 | 61 | 62 | /** 63 | * @dev Required interface of an ERC721 compliant contract. 64 | */ 65 | interface IERC721 is IERC165 { 66 | /** 67 | * @dev Emitted when `tokenId` token is transferred from `from` to `to`. 68 | */ 69 | event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); 70 | 71 | /** 72 | * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. 73 | */ 74 | event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); 75 | 76 | /** 77 | * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. 78 | */ 79 | event ApprovalForAll(address indexed owner, address indexed operator, bool approved); 80 | 81 | /** 82 | * @dev Returns the number of tokens in ``owner``'s account. 83 | */ 84 | function balanceOf(address owner) external view returns (uint256 balance); 85 | 86 | /** 87 | * @dev Returns the owner of the `tokenId` token. 88 | * 89 | * Requirements: 90 | * 91 | * - `tokenId` must exist. 92 | */ 93 | function ownerOf(uint256 tokenId) external view returns (address owner); 94 | 95 | /** 96 | * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients 97 | * are aware of the ERC721 protocol to prevent tokens from being forever locked. 98 | * 99 | * Requirements: 100 | * 101 | * - `from` cannot be the zero address. 102 | * - `to` cannot be the zero address. 103 | * - `tokenId` token must exist and be owned by `from`. 104 | * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. 105 | * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. 106 | * 107 | * Emits a {Transfer} event. 108 | */ 109 | function safeTransferFrom(address from, address to, uint256 tokenId) external; 110 | 111 | /** 112 | * @dev Transfers `tokenId` token from `from` to `to`. 113 | * 114 | * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. 115 | * 116 | * Requirements: 117 | * 118 | * - `from` cannot be the zero address. 119 | * - `to` cannot be the zero address. 120 | * - `tokenId` token must be owned by `from`. 121 | * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. 122 | * 123 | * Emits a {Transfer} event. 124 | */ 125 | function transferFrom(address from, address to, uint256 tokenId) external; 126 | 127 | /** 128 | * @dev Gives permission to `to` to transfer `tokenId` token to another account. 129 | * The approval is cleared when the token is transferred. 130 | * 131 | * Only a single account can be approved at a time, so approving the zero address clears previous approvals. 132 | * 133 | * Requirements: 134 | * 135 | * - The caller must own the token or be an approved operator. 136 | * - `tokenId` must exist. 137 | * 138 | * Emits an {Approval} event. 139 | */ 140 | function approve(address to, uint256 tokenId) external; 141 | 142 | /** 143 | * @dev Returns the account approved for `tokenId` token. 144 | * 145 | * Requirements: 146 | * 147 | * - `tokenId` must exist. 148 | */ 149 | function getApproved(uint256 tokenId) external view returns (address operator); 150 | 151 | /** 152 | * @dev Approve or remove `operator` as an operator for the caller. 153 | * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. 154 | * 155 | * Requirements: 156 | * 157 | * - The `operator` cannot be the caller. 158 | * 159 | * Emits an {ApprovalForAll} event. 160 | */ 161 | function setApprovalForAll(address operator, bool _approved) external; 162 | 163 | /** 164 | * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. 165 | * 166 | * See {setApprovalForAll} 167 | */ 168 | function isApprovedForAll(address owner, address operator) external view returns (bool); 169 | 170 | /** 171 | * @dev Safely transfers `tokenId` token from `from` to `to`. 172 | * 173 | * Requirements: 174 | * 175 | * - `from` cannot be the zero address. 176 | * - `to` cannot be the zero address. 177 | * - `tokenId` token must exist and be owned by `from`. 178 | * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. 179 | * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. 180 | * 181 | * Emits a {Transfer} event. 182 | */ 183 | function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; 184 | } 185 | 186 | // File: @openzeppelin/contracts/token/ERC721/IERC721Metadata.sol 187 | 188 | // SPDX-License-Identifier: MIT 189 | 190 | pragma solidity >=0.6.2 <0.8.0; 191 | 192 | 193 | /** 194 | * @title ERC-721 Non-Fungible Token Standard, optional metadata extension 195 | * @dev See https://eips.ethereum.org/EIPS/eip-721 196 | */ 197 | interface IERC721Metadata is IERC721 { 198 | 199 | /** 200 | * @dev Returns the token collection name. 201 | */ 202 | function name() external view returns (string memory); 203 | 204 | /** 205 | * @dev Returns the token collection symbol. 206 | */ 207 | function symbol() external view returns (string memory); 208 | 209 | /** 210 | * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. 211 | */ 212 | function tokenURI(uint256 tokenId) external view returns (string memory); 213 | } 214 | 215 | // File: @openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol 216 | 217 | // SPDX-License-Identifier: MIT 218 | 219 | pragma solidity >=0.6.2 <0.8.0; 220 | 221 | 222 | /** 223 | * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension 224 | * @dev See https://eips.ethereum.org/EIPS/eip-721 225 | */ 226 | interface IERC721Enumerable is IERC721 { 227 | 228 | /** 229 | * @dev Returns the total amount of tokens stored by the contract. 230 | */ 231 | function totalSupply() external view returns (uint256); 232 | 233 | /** 234 | * @dev Returns a token ID owned by `owner` at a given `index` of its token list. 235 | * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. 236 | */ 237 | function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); 238 | 239 | /** 240 | * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. 241 | * Use along with {totalSupply} to enumerate all tokens. 242 | */ 243 | function tokenByIndex(uint256 index) external view returns (uint256); 244 | } 245 | 246 | // File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol 247 | 248 | // SPDX-License-Identifier: MIT 249 | 250 | pragma solidity >=0.6.0 <0.8.0; 251 | 252 | /** 253 | * @title ERC721 token receiver interface 254 | * @dev Interface for any contract that wants to support safeTransfers 255 | * from ERC721 asset contracts. 256 | */ 257 | interface IERC721Receiver { 258 | /** 259 | * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} 260 | * by `operator` from `from`, this function is called. 261 | * 262 | * It must return its Solidity selector to confirm the token transfer. 263 | * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. 264 | * 265 | * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. 266 | */ 267 | function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4); 268 | } 269 | 270 | // File: @openzeppelin/contracts/introspection/ERC165.sol 271 | 272 | // SPDX-License-Identifier: MIT 273 | 274 | pragma solidity >=0.6.0 <0.8.0; 275 | 276 | 277 | /** 278 | * @dev Implementation of the {IERC165} interface. 279 | * 280 | * Contracts may inherit from this and call {_registerInterface} to declare 281 | * their support of an interface. 282 | */ 283 | abstract contract ERC165 is IERC165 { 284 | /* 285 | * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 286 | */ 287 | bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; 288 | 289 | /** 290 | * @dev Mapping of interface ids to whether or not it's supported. 291 | */ 292 | mapping(bytes4 => bool) private _supportedInterfaces; 293 | 294 | constructor () internal { 295 | // Derived contracts need only register support for their own interfaces, 296 | // we register support for ERC165 itself here 297 | _registerInterface(_INTERFACE_ID_ERC165); 298 | } 299 | 300 | /** 301 | * @dev See {IERC165-supportsInterface}. 302 | * 303 | * Time complexity O(1), guaranteed to always use less than 30 000 gas. 304 | */ 305 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 306 | return _supportedInterfaces[interfaceId]; 307 | } 308 | 309 | /** 310 | * @dev Registers the contract as an implementer of the interface defined by 311 | * `interfaceId`. Support of the actual ERC165 interface is automatic and 312 | * registering its interface id is not required. 313 | * 314 | * See {IERC165-supportsInterface}. 315 | * 316 | * Requirements: 317 | * 318 | * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). 319 | */ 320 | function _registerInterface(bytes4 interfaceId) internal virtual { 321 | require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); 322 | _supportedInterfaces[interfaceId] = true; 323 | } 324 | } 325 | 326 | // File: @openzeppelin/contracts/math/SafeMath.sol 327 | 328 | // SPDX-License-Identifier: MIT 329 | 330 | pragma solidity >=0.6.0 <0.8.0; 331 | 332 | /** 333 | * @dev Wrappers over Solidity's arithmetic operations with added overflow 334 | * checks. 335 | * 336 | * Arithmetic operations in Solidity wrap on overflow. This can easily result 337 | * in bugs, because programmers usually assume that an overflow raises an 338 | * error, which is the standard behavior in high level programming languages. 339 | * `SafeMath` restores this intuition by reverting the transaction when an 340 | * operation overflows. 341 | * 342 | * Using this library instead of the unchecked operations eliminates an entire 343 | * class of bugs, so it's recommended to use it always. 344 | */ 345 | library SafeMath { 346 | /** 347 | * @dev Returns the addition of two unsigned integers, with an overflow flag. 348 | * 349 | * _Available since v3.4._ 350 | */ 351 | function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { 352 | uint256 c = a + b; 353 | if (c < a) return (false, 0); 354 | return (true, c); 355 | } 356 | 357 | /** 358 | * @dev Returns the substraction of two unsigned integers, with an overflow flag. 359 | * 360 | * _Available since v3.4._ 361 | */ 362 | function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { 363 | if (b > a) return (false, 0); 364 | return (true, a - b); 365 | } 366 | 367 | /** 368 | * @dev Returns the multiplication of two unsigned integers, with an overflow flag. 369 | * 370 | * _Available since v3.4._ 371 | */ 372 | function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { 373 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 374 | // benefit is lost if 'b' is also tested. 375 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 376 | if (a == 0) return (true, 0); 377 | uint256 c = a * b; 378 | if (c / a != b) return (false, 0); 379 | return (true, c); 380 | } 381 | 382 | /** 383 | * @dev Returns the division of two unsigned integers, with a division by zero flag. 384 | * 385 | * _Available since v3.4._ 386 | */ 387 | function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { 388 | if (b == 0) return (false, 0); 389 | return (true, a / b); 390 | } 391 | 392 | /** 393 | * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. 394 | * 395 | * _Available since v3.4._ 396 | */ 397 | function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { 398 | if (b == 0) return (false, 0); 399 | return (true, a % b); 400 | } 401 | 402 | /** 403 | * @dev Returns the addition of two unsigned integers, reverting on 404 | * overflow. 405 | * 406 | * Counterpart to Solidity's `+` operator. 407 | * 408 | * Requirements: 409 | * 410 | * - Addition cannot overflow. 411 | */ 412 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 413 | uint256 c = a + b; 414 | require(c >= a, "SafeMath: addition overflow"); 415 | return c; 416 | } 417 | 418 | /** 419 | * @dev Returns the subtraction of two unsigned integers, reverting on 420 | * overflow (when the result is negative). 421 | * 422 | * Counterpart to Solidity's `-` operator. 423 | * 424 | * Requirements: 425 | * 426 | * - Subtraction cannot overflow. 427 | */ 428 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 429 | require(b <= a, "SafeMath: subtraction overflow"); 430 | return a - b; 431 | } 432 | 433 | /** 434 | * @dev Returns the multiplication of two unsigned integers, reverting on 435 | * overflow. 436 | * 437 | * Counterpart to Solidity's `*` operator. 438 | * 439 | * Requirements: 440 | * 441 | * - Multiplication cannot overflow. 442 | */ 443 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 444 | if (a == 0) return 0; 445 | uint256 c = a * b; 446 | require(c / a == b, "SafeMath: multiplication overflow"); 447 | return c; 448 | } 449 | 450 | /** 451 | * @dev Returns the integer division of two unsigned integers, reverting on 452 | * division by zero. The result is rounded towards zero. 453 | * 454 | * Counterpart to Solidity's `/` operator. Note: this function uses a 455 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 456 | * uses an invalid opcode to revert (consuming all remaining gas). 457 | * 458 | * Requirements: 459 | * 460 | * - The divisor cannot be zero. 461 | */ 462 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 463 | require(b > 0, "SafeMath: division by zero"); 464 | return a / b; 465 | } 466 | 467 | /** 468 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 469 | * reverting when dividing by zero. 470 | * 471 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 472 | * opcode (which leaves remaining gas untouched) while Solidity uses an 473 | * invalid opcode to revert (consuming all remaining gas). 474 | * 475 | * Requirements: 476 | * 477 | * - The divisor cannot be zero. 478 | */ 479 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 480 | require(b > 0, "SafeMath: modulo by zero"); 481 | return a % b; 482 | } 483 | 484 | /** 485 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 486 | * overflow (when the result is negative). 487 | * 488 | * CAUTION: This function is deprecated because it requires allocating memory for the error 489 | * message unnecessarily. For custom revert reasons use {trySub}. 490 | * 491 | * Counterpart to Solidity's `-` operator. 492 | * 493 | * Requirements: 494 | * 495 | * - Subtraction cannot overflow. 496 | */ 497 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 498 | require(b <= a, errorMessage); 499 | return a - b; 500 | } 501 | 502 | /** 503 | * @dev Returns the integer division of two unsigned integers, reverting with custom message on 504 | * division by zero. The result is rounded towards zero. 505 | * 506 | * CAUTION: This function is deprecated because it requires allocating memory for the error 507 | * message unnecessarily. For custom revert reasons use {tryDiv}. 508 | * 509 | * Counterpart to Solidity's `/` operator. Note: this function uses a 510 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 511 | * uses an invalid opcode to revert (consuming all remaining gas). 512 | * 513 | * Requirements: 514 | * 515 | * - The divisor cannot be zero. 516 | */ 517 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 518 | require(b > 0, errorMessage); 519 | return a / b; 520 | } 521 | 522 | /** 523 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 524 | * reverting with custom message when dividing by zero. 525 | * 526 | * CAUTION: This function is deprecated because it requires allocating memory for the error 527 | * message unnecessarily. For custom revert reasons use {tryMod}. 528 | * 529 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 530 | * opcode (which leaves remaining gas untouched) while Solidity uses an 531 | * invalid opcode to revert (consuming all remaining gas). 532 | * 533 | * Requirements: 534 | * 535 | * - The divisor cannot be zero. 536 | */ 537 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 538 | require(b > 0, errorMessage); 539 | return a % b; 540 | } 541 | } 542 | 543 | // File: @openzeppelin/contracts/utils/Address.sol 544 | 545 | // SPDX-License-Identifier: MIT 546 | 547 | pragma solidity >=0.6.2 <0.8.0; 548 | 549 | /** 550 | * @dev Collection of functions related to the address type 551 | */ 552 | library Address { 553 | /** 554 | * @dev Returns true if `account` is a contract. 555 | * 556 | * [IMPORTANT] 557 | * ==== 558 | * It is unsafe to assume that an address for which this function returns 559 | * false is an externally-owned account (EOA) and not a contract. 560 | * 561 | * Among others, `isContract` will return false for the following 562 | * types of addresses: 563 | * 564 | * - an externally-owned account 565 | * - a contract in construction 566 | * - an address where a contract will be created 567 | * - an address where a contract lived, but was destroyed 568 | * ==== 569 | */ 570 | function isContract(address account) internal view returns (bool) { 571 | // This method relies on extcodesize, which returns 0 for contracts in 572 | // construction, since the code is only stored at the end of the 573 | // constructor execution. 574 | 575 | uint256 size; 576 | // solhint-disable-next-line no-inline-assembly 577 | assembly { size := extcodesize(account) } 578 | return size > 0; 579 | } 580 | 581 | /** 582 | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 583 | * `recipient`, forwarding all available gas and reverting on errors. 584 | * 585 | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 586 | * of certain opcodes, possibly making contracts go over the 2300 gas limit 587 | * imposed by `transfer`, making them unable to receive funds via 588 | * `transfer`. {sendValue} removes this limitation. 589 | * 590 | * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 591 | * 592 | * IMPORTANT: because control is transferred to `recipient`, care must be 593 | * taken to not create reentrancy vulnerabilities. Consider using 594 | * {ReentrancyGuard} or the 595 | * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 596 | */ 597 | function sendValue(address payable recipient, uint256 amount) internal { 598 | require(address(this).balance >= amount, "Address: insufficient balance"); 599 | 600 | // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 601 | (bool success, ) = recipient.call{ value: amount }(""); 602 | require(success, "Address: unable to send value, recipient may have reverted"); 603 | } 604 | 605 | /** 606 | * @dev Performs a Solidity function call using a low level `call`. A 607 | * plain`call` is an unsafe replacement for a function call: use this 608 | * function instead. 609 | * 610 | * If `target` reverts with a revert reason, it is bubbled up by this 611 | * function (like regular Solidity function calls). 612 | * 613 | * Returns the raw returned data. To convert to the expected return value, 614 | * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 615 | * 616 | * Requirements: 617 | * 618 | * - `target` must be a contract. 619 | * - calling `target` with `data` must not revert. 620 | * 621 | * _Available since v3.1._ 622 | */ 623 | function functionCall(address target, bytes memory data) internal returns (bytes memory) { 624 | return functionCall(target, data, "Address: low-level call failed"); 625 | } 626 | 627 | /** 628 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 629 | * `errorMessage` as a fallback revert reason when `target` reverts. 630 | * 631 | * _Available since v3.1._ 632 | */ 633 | function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 634 | return functionCallWithValue(target, data, 0, errorMessage); 635 | } 636 | 637 | /** 638 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 639 | * but also transferring `value` wei to `target`. 640 | * 641 | * Requirements: 642 | * 643 | * - the calling contract must have an ETH balance of at least `value`. 644 | * - the called Solidity function must be `payable`. 645 | * 646 | * _Available since v3.1._ 647 | */ 648 | function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 649 | return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 650 | } 651 | 652 | /** 653 | * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 654 | * with `errorMessage` as a fallback revert reason when `target` reverts. 655 | * 656 | * _Available since v3.1._ 657 | */ 658 | function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 659 | require(address(this).balance >= value, "Address: insufficient balance for call"); 660 | require(isContract(target), "Address: call to non-contract"); 661 | 662 | // solhint-disable-next-line avoid-low-level-calls 663 | (bool success, bytes memory returndata) = target.call{ value: value }(data); 664 | return _verifyCallResult(success, returndata, errorMessage); 665 | } 666 | 667 | /** 668 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 669 | * but performing a static call. 670 | * 671 | * _Available since v3.3._ 672 | */ 673 | function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { 674 | return functionStaticCall(target, data, "Address: low-level static call failed"); 675 | } 676 | 677 | /** 678 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 679 | * but performing a static call. 680 | * 681 | * _Available since v3.3._ 682 | */ 683 | function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { 684 | require(isContract(target), "Address: static call to non-contract"); 685 | 686 | // solhint-disable-next-line avoid-low-level-calls 687 | (bool success, bytes memory returndata) = target.staticcall(data); 688 | return _verifyCallResult(success, returndata, errorMessage); 689 | } 690 | 691 | /** 692 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 693 | * but performing a delegate call. 694 | * 695 | * _Available since v3.4._ 696 | */ 697 | function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { 698 | return functionDelegateCall(target, data, "Address: low-level delegate call failed"); 699 | } 700 | 701 | /** 702 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 703 | * but performing a delegate call. 704 | * 705 | * _Available since v3.4._ 706 | */ 707 | function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 708 | require(isContract(target), "Address: delegate call to non-contract"); 709 | 710 | // solhint-disable-next-line avoid-low-level-calls 711 | (bool success, bytes memory returndata) = target.delegatecall(data); 712 | return _verifyCallResult(success, returndata, errorMessage); 713 | } 714 | 715 | function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { 716 | if (success) { 717 | return returndata; 718 | } else { 719 | // Look for revert reason and bubble it up if present 720 | if (returndata.length > 0) { 721 | // The easiest way to bubble the revert reason is using memory via assembly 722 | 723 | // solhint-disable-next-line no-inline-assembly 724 | assembly { 725 | let returndata_size := mload(returndata) 726 | revert(add(32, returndata), returndata_size) 727 | } 728 | } else { 729 | revert(errorMessage); 730 | } 731 | } 732 | } 733 | } 734 | 735 | // File: @openzeppelin/contracts/utils/EnumerableSet.sol 736 | 737 | // SPDX-License-Identifier: MIT 738 | 739 | pragma solidity >=0.6.0 <0.8.0; 740 | 741 | /** 742 | * @dev Library for managing 743 | * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive 744 | * types. 745 | * 746 | * Sets have the following properties: 747 | * 748 | * - Elements are added, removed, and checked for existence in constant time 749 | * (O(1)). 750 | * - Elements are enumerated in O(n). No guarantees are made on the ordering. 751 | * 752 | * ``` 753 | * contract Example { 754 | * // Add the library methods 755 | * using EnumerableSet for EnumerableSet.AddressSet; 756 | * 757 | * // Declare a set state variable 758 | * EnumerableSet.AddressSet private mySet; 759 | * } 760 | * ``` 761 | * 762 | * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) 763 | * and `uint256` (`UintSet`) are supported. 764 | */ 765 | library EnumerableSet { 766 | // To implement this library for multiple types with as little code 767 | // repetition as possible, we write it in terms of a generic Set type with 768 | // bytes32 values. 769 | // The Set implementation uses private functions, and user-facing 770 | // implementations (such as AddressSet) are just wrappers around the 771 | // underlying Set. 772 | // This means that we can only create new EnumerableSets for types that fit 773 | // in bytes32. 774 | 775 | struct Set { 776 | // Storage of set values 777 | bytes32[] _values; 778 | 779 | // Position of the value in the `values` array, plus 1 because index 0 780 | // means a value is not in the set. 781 | mapping (bytes32 => uint256) _indexes; 782 | } 783 | 784 | /** 785 | * @dev Add a value to a set. O(1). 786 | * 787 | * Returns true if the value was added to the set, that is if it was not 788 | * already present. 789 | */ 790 | function _add(Set storage set, bytes32 value) private returns (bool) { 791 | if (!_contains(set, value)) { 792 | set._values.push(value); 793 | // The value is stored at length-1, but we add 1 to all indexes 794 | // and use 0 as a sentinel value 795 | set._indexes[value] = set._values.length; 796 | return true; 797 | } else { 798 | return false; 799 | } 800 | } 801 | 802 | /** 803 | * @dev Removes a value from a set. O(1). 804 | * 805 | * Returns true if the value was removed from the set, that is if it was 806 | * present. 807 | */ 808 | function _remove(Set storage set, bytes32 value) private returns (bool) { 809 | // We read and store the value's index to prevent multiple reads from the same storage slot 810 | uint256 valueIndex = set._indexes[value]; 811 | 812 | if (valueIndex != 0) { // Equivalent to contains(set, value) 813 | // To delete an element from the _values array in O(1), we swap the element to delete with the last one in 814 | // the array, and then remove the last element (sometimes called as 'swap and pop'). 815 | // This modifies the order of the array, as noted in {at}. 816 | 817 | uint256 toDeleteIndex = valueIndex - 1; 818 | uint256 lastIndex = set._values.length - 1; 819 | 820 | // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs 821 | // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. 822 | 823 | bytes32 lastvalue = set._values[lastIndex]; 824 | 825 | // Move the last value to the index where the value to delete is 826 | set._values[toDeleteIndex] = lastvalue; 827 | // Update the index for the moved value 828 | set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based 829 | 830 | // Delete the slot where the moved value was stored 831 | set._values.pop(); 832 | 833 | // Delete the index for the deleted slot 834 | delete set._indexes[value]; 835 | 836 | return true; 837 | } else { 838 | return false; 839 | } 840 | } 841 | 842 | /** 843 | * @dev Returns true if the value is in the set. O(1). 844 | */ 845 | function _contains(Set storage set, bytes32 value) private view returns (bool) { 846 | return set._indexes[value] != 0; 847 | } 848 | 849 | /** 850 | * @dev Returns the number of values on the set. O(1). 851 | */ 852 | function _length(Set storage set) private view returns (uint256) { 853 | return set._values.length; 854 | } 855 | 856 | /** 857 | * @dev Returns the value stored at position `index` in the set. O(1). 858 | * 859 | * Note that there are no guarantees on the ordering of values inside the 860 | * array, and it may change when more values are added or removed. 861 | * 862 | * Requirements: 863 | * 864 | * - `index` must be strictly less than {length}. 865 | */ 866 | function _at(Set storage set, uint256 index) private view returns (bytes32) { 867 | require(set._values.length > index, "EnumerableSet: index out of bounds"); 868 | return set._values[index]; 869 | } 870 | 871 | // Bytes32Set 872 | 873 | struct Bytes32Set { 874 | Set _inner; 875 | } 876 | 877 | /** 878 | * @dev Add a value to a set. O(1). 879 | * 880 | * Returns true if the value was added to the set, that is if it was not 881 | * already present. 882 | */ 883 | function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { 884 | return _add(set._inner, value); 885 | } 886 | 887 | /** 888 | * @dev Removes a value from a set. O(1). 889 | * 890 | * Returns true if the value was removed from the set, that is if it was 891 | * present. 892 | */ 893 | function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { 894 | return _remove(set._inner, value); 895 | } 896 | 897 | /** 898 | * @dev Returns true if the value is in the set. O(1). 899 | */ 900 | function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { 901 | return _contains(set._inner, value); 902 | } 903 | 904 | /** 905 | * @dev Returns the number of values in the set. O(1). 906 | */ 907 | function length(Bytes32Set storage set) internal view returns (uint256) { 908 | return _length(set._inner); 909 | } 910 | 911 | /** 912 | * @dev Returns the value stored at position `index` in the set. O(1). 913 | * 914 | * Note that there are no guarantees on the ordering of values inside the 915 | * array, and it may change when more values are added or removed. 916 | * 917 | * Requirements: 918 | * 919 | * - `index` must be strictly less than {length}. 920 | */ 921 | function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { 922 | return _at(set._inner, index); 923 | } 924 | 925 | // AddressSet 926 | 927 | struct AddressSet { 928 | Set _inner; 929 | } 930 | 931 | /** 932 | * @dev Add a value to a set. O(1). 933 | * 934 | * Returns true if the value was added to the set, that is if it was not 935 | * already present. 936 | */ 937 | function add(AddressSet storage set, address value) internal returns (bool) { 938 | return _add(set._inner, bytes32(uint256(uint160(value)))); 939 | } 940 | 941 | /** 942 | * @dev Removes a value from a set. O(1). 943 | * 944 | * Returns true if the value was removed from the set, that is if it was 945 | * present. 946 | */ 947 | function remove(AddressSet storage set, address value) internal returns (bool) { 948 | return _remove(set._inner, bytes32(uint256(uint160(value)))); 949 | } 950 | 951 | /** 952 | * @dev Returns true if the value is in the set. O(1). 953 | */ 954 | function contains(AddressSet storage set, address value) internal view returns (bool) { 955 | return _contains(set._inner, bytes32(uint256(uint160(value)))); 956 | } 957 | 958 | /** 959 | * @dev Returns the number of values in the set. O(1). 960 | */ 961 | function length(AddressSet storage set) internal view returns (uint256) { 962 | return _length(set._inner); 963 | } 964 | 965 | /** 966 | * @dev Returns the value stored at position `index` in the set. O(1). 967 | * 968 | * Note that there are no guarantees on the ordering of values inside the 969 | * array, and it may change when more values are added or removed. 970 | * 971 | * Requirements: 972 | * 973 | * - `index` must be strictly less than {length}. 974 | */ 975 | function at(AddressSet storage set, uint256 index) internal view returns (address) { 976 | return address(uint160(uint256(_at(set._inner, index)))); 977 | } 978 | 979 | 980 | // UintSet 981 | 982 | struct UintSet { 983 | Set _inner; 984 | } 985 | 986 | /** 987 | * @dev Add a value to a set. O(1). 988 | * 989 | * Returns true if the value was added to the set, that is if it was not 990 | * already present. 991 | */ 992 | function add(UintSet storage set, uint256 value) internal returns (bool) { 993 | return _add(set._inner, bytes32(value)); 994 | } 995 | 996 | /** 997 | * @dev Removes a value from a set. O(1). 998 | * 999 | * Returns true if the value was removed from the set, that is if it was 1000 | * present. 1001 | */ 1002 | function remove(UintSet storage set, uint256 value) internal returns (bool) { 1003 | return _remove(set._inner, bytes32(value)); 1004 | } 1005 | 1006 | /** 1007 | * @dev Returns true if the value is in the set. O(1). 1008 | */ 1009 | function contains(UintSet storage set, uint256 value) internal view returns (bool) { 1010 | return _contains(set._inner, bytes32(value)); 1011 | } 1012 | 1013 | /** 1014 | * @dev Returns the number of values on the set. O(1). 1015 | */ 1016 | function length(UintSet storage set) internal view returns (uint256) { 1017 | return _length(set._inner); 1018 | } 1019 | 1020 | /** 1021 | * @dev Returns the value stored at position `index` in the set. O(1). 1022 | * 1023 | * Note that there are no guarantees on the ordering of values inside the 1024 | * array, and it may change when more values are added or removed. 1025 | * 1026 | * Requirements: 1027 | * 1028 | * - `index` must be strictly less than {length}. 1029 | */ 1030 | function at(UintSet storage set, uint256 index) internal view returns (uint256) { 1031 | return uint256(_at(set._inner, index)); 1032 | } 1033 | } 1034 | 1035 | // File: @openzeppelin/contracts/utils/EnumerableMap.sol 1036 | 1037 | // SPDX-License-Identifier: MIT 1038 | 1039 | pragma solidity >=0.6.0 <0.8.0; 1040 | 1041 | /** 1042 | * @dev Library for managing an enumerable variant of Solidity's 1043 | * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] 1044 | * type. 1045 | * 1046 | * Maps have the following properties: 1047 | * 1048 | * - Entries are added, removed, and checked for existence in constant time 1049 | * (O(1)). 1050 | * - Entries are enumerated in O(n). No guarantees are made on the ordering. 1051 | * 1052 | * ``` 1053 | * contract Example { 1054 | * // Add the library methods 1055 | * using EnumerableMap for EnumerableMap.UintToAddressMap; 1056 | * 1057 | * // Declare a set state variable 1058 | * EnumerableMap.UintToAddressMap private myMap; 1059 | * } 1060 | * ``` 1061 | * 1062 | * As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are 1063 | * supported. 1064 | */ 1065 | library EnumerableMap { 1066 | // To implement this library for multiple types with as little code 1067 | // repetition as possible, we write it in terms of a generic Map type with 1068 | // bytes32 keys and values. 1069 | // The Map implementation uses private functions, and user-facing 1070 | // implementations (such as Uint256ToAddressMap) are just wrappers around 1071 | // the underlying Map. 1072 | // This means that we can only create new EnumerableMaps for types that fit 1073 | // in bytes32. 1074 | 1075 | struct MapEntry { 1076 | bytes32 _key; 1077 | bytes32 _value; 1078 | } 1079 | 1080 | struct Map { 1081 | // Storage of map keys and values 1082 | MapEntry[] _entries; 1083 | 1084 | // Position of the entry defined by a key in the `entries` array, plus 1 1085 | // because index 0 means a key is not in the map. 1086 | mapping (bytes32 => uint256) _indexes; 1087 | } 1088 | 1089 | /** 1090 | * @dev Adds a key-value pair to a map, or updates the value for an existing 1091 | * key. O(1). 1092 | * 1093 | * Returns true if the key was added to the map, that is if it was not 1094 | * already present. 1095 | */ 1096 | function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) { 1097 | // We read and store the key's index to prevent multiple reads from the same storage slot 1098 | uint256 keyIndex = map._indexes[key]; 1099 | 1100 | if (keyIndex == 0) { // Equivalent to !contains(map, key) 1101 | map._entries.push(MapEntry({ _key: key, _value: value })); 1102 | // The entry is stored at length-1, but we add 1 to all indexes 1103 | // and use 0 as a sentinel value 1104 | map._indexes[key] = map._entries.length; 1105 | return true; 1106 | } else { 1107 | map._entries[keyIndex - 1]._value = value; 1108 | return false; 1109 | } 1110 | } 1111 | 1112 | /** 1113 | * @dev Removes a key-value pair from a map. O(1). 1114 | * 1115 | * Returns true if the key was removed from the map, that is if it was present. 1116 | */ 1117 | function _remove(Map storage map, bytes32 key) private returns (bool) { 1118 | // We read and store the key's index to prevent multiple reads from the same storage slot 1119 | uint256 keyIndex = map._indexes[key]; 1120 | 1121 | if (keyIndex != 0) { // Equivalent to contains(map, key) 1122 | // To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one 1123 | // in the array, and then remove the last entry (sometimes called as 'swap and pop'). 1124 | // This modifies the order of the array, as noted in {at}. 1125 | 1126 | uint256 toDeleteIndex = keyIndex - 1; 1127 | uint256 lastIndex = map._entries.length - 1; 1128 | 1129 | // When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs 1130 | // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. 1131 | 1132 | MapEntry storage lastEntry = map._entries[lastIndex]; 1133 | 1134 | // Move the last entry to the index where the entry to delete is 1135 | map._entries[toDeleteIndex] = lastEntry; 1136 | // Update the index for the moved entry 1137 | map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based 1138 | 1139 | // Delete the slot where the moved entry was stored 1140 | map._entries.pop(); 1141 | 1142 | // Delete the index for the deleted slot 1143 | delete map._indexes[key]; 1144 | 1145 | return true; 1146 | } else { 1147 | return false; 1148 | } 1149 | } 1150 | 1151 | /** 1152 | * @dev Returns true if the key is in the map. O(1). 1153 | */ 1154 | function _contains(Map storage map, bytes32 key) private view returns (bool) { 1155 | return map._indexes[key] != 0; 1156 | } 1157 | 1158 | /** 1159 | * @dev Returns the number of key-value pairs in the map. O(1). 1160 | */ 1161 | function _length(Map storage map) private view returns (uint256) { 1162 | return map._entries.length; 1163 | } 1164 | 1165 | /** 1166 | * @dev Returns the key-value pair stored at position `index` in the map. O(1). 1167 | * 1168 | * Note that there are no guarantees on the ordering of entries inside the 1169 | * array, and it may change when more entries are added or removed. 1170 | * 1171 | * Requirements: 1172 | * 1173 | * - `index` must be strictly less than {length}. 1174 | */ 1175 | function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) { 1176 | require(map._entries.length > index, "EnumerableMap: index out of bounds"); 1177 | 1178 | MapEntry storage entry = map._entries[index]; 1179 | return (entry._key, entry._value); 1180 | } 1181 | 1182 | /** 1183 | * @dev Tries to returns the value associated with `key`. O(1). 1184 | * Does not revert if `key` is not in the map. 1185 | */ 1186 | function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) { 1187 | uint256 keyIndex = map._indexes[key]; 1188 | if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key) 1189 | return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based 1190 | } 1191 | 1192 | /** 1193 | * @dev Returns the value associated with `key`. O(1). 1194 | * 1195 | * Requirements: 1196 | * 1197 | * - `key` must be in the map. 1198 | */ 1199 | function _get(Map storage map, bytes32 key) private view returns (bytes32) { 1200 | uint256 keyIndex = map._indexes[key]; 1201 | require(keyIndex != 0, "EnumerableMap: nonexistent key"); // Equivalent to contains(map, key) 1202 | return map._entries[keyIndex - 1]._value; // All indexes are 1-based 1203 | } 1204 | 1205 | /** 1206 | * @dev Same as {_get}, with a custom error message when `key` is not in the map. 1207 | * 1208 | * CAUTION: This function is deprecated because it requires allocating memory for the error 1209 | * message unnecessarily. For custom revert reasons use {_tryGet}. 1210 | */ 1211 | function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) { 1212 | uint256 keyIndex = map._indexes[key]; 1213 | require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key) 1214 | return map._entries[keyIndex - 1]._value; // All indexes are 1-based 1215 | } 1216 | 1217 | // UintToAddressMap 1218 | 1219 | struct UintToAddressMap { 1220 | Map _inner; 1221 | } 1222 | 1223 | /** 1224 | * @dev Adds a key-value pair to a map, or updates the value for an existing 1225 | * key. O(1). 1226 | * 1227 | * Returns true if the key was added to the map, that is if it was not 1228 | * already present. 1229 | */ 1230 | function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { 1231 | return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); 1232 | } 1233 | 1234 | /** 1235 | * @dev Removes a value from a set. O(1). 1236 | * 1237 | * Returns true if the key was removed from the map, that is if it was present. 1238 | */ 1239 | function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { 1240 | return _remove(map._inner, bytes32(key)); 1241 | } 1242 | 1243 | /** 1244 | * @dev Returns true if the key is in the map. O(1). 1245 | */ 1246 | function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { 1247 | return _contains(map._inner, bytes32(key)); 1248 | } 1249 | 1250 | /** 1251 | * @dev Returns the number of elements in the map. O(1). 1252 | */ 1253 | function length(UintToAddressMap storage map) internal view returns (uint256) { 1254 | return _length(map._inner); 1255 | } 1256 | 1257 | /** 1258 | * @dev Returns the element stored at position `index` in the set. O(1). 1259 | * Note that there are no guarantees on the ordering of values inside the 1260 | * array, and it may change when more values are added or removed. 1261 | * 1262 | * Requirements: 1263 | * 1264 | * - `index` must be strictly less than {length}. 1265 | */ 1266 | function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { 1267 | (bytes32 key, bytes32 value) = _at(map._inner, index); 1268 | return (uint256(key), address(uint160(uint256(value)))); 1269 | } 1270 | 1271 | /** 1272 | * @dev Tries to returns the value associated with `key`. O(1). 1273 | * Does not revert if `key` is not in the map. 1274 | * 1275 | * _Available since v3.4._ 1276 | */ 1277 | function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { 1278 | (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key)); 1279 | return (success, address(uint160(uint256(value)))); 1280 | } 1281 | 1282 | /** 1283 | * @dev Returns the value associated with `key`. O(1). 1284 | * 1285 | * Requirements: 1286 | * 1287 | * - `key` must be in the map. 1288 | */ 1289 | function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { 1290 | return address(uint160(uint256(_get(map._inner, bytes32(key))))); 1291 | } 1292 | 1293 | /** 1294 | * @dev Same as {get}, with a custom error message when `key` is not in the map. 1295 | * 1296 | * CAUTION: This function is deprecated because it requires allocating memory for the error 1297 | * message unnecessarily. For custom revert reasons use {tryGet}. 1298 | */ 1299 | function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) { 1300 | return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage)))); 1301 | } 1302 | } 1303 | 1304 | // File: @openzeppelin/contracts/utils/Strings.sol 1305 | 1306 | // SPDX-License-Identifier: MIT 1307 | 1308 | pragma solidity >=0.6.0 <0.8.0; 1309 | 1310 | /** 1311 | * @dev String operations. 1312 | */ 1313 | library Strings { 1314 | /** 1315 | * @dev Converts a `uint256` to its ASCII `string` representation. 1316 | */ 1317 | function toString(uint256 value) internal pure returns (string memory) { 1318 | // Inspired by OraclizeAPI's implementation - MIT licence 1319 | // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol 1320 | 1321 | if (value == 0) { 1322 | return "0"; 1323 | } 1324 | uint256 temp = value; 1325 | uint256 digits; 1326 | while (temp != 0) { 1327 | digits++; 1328 | temp /= 10; 1329 | } 1330 | bytes memory buffer = new bytes(digits); 1331 | uint256 index = digits - 1; 1332 | temp = value; 1333 | while (temp != 0) { 1334 | buffer[index--] = bytes1(uint8(48 + temp % 10)); 1335 | temp /= 10; 1336 | } 1337 | return string(buffer); 1338 | } 1339 | } 1340 | 1341 | // File: @openzeppelin/contracts/token/ERC721/ERC721.sol 1342 | 1343 | // SPDX-License-Identifier: MIT 1344 | 1345 | pragma solidity >=0.6.0 <0.8.0; 1346 | 1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | /** 1359 | * @title ERC721 Non-Fungible Token Standard basic implementation 1360 | * @dev see https://eips.ethereum.org/EIPS/eip-721 1361 | */ 1362 | contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable { 1363 | using SafeMath for uint256; 1364 | using Address for address; 1365 | using EnumerableSet for EnumerableSet.UintSet; 1366 | using EnumerableMap for EnumerableMap.UintToAddressMap; 1367 | using Strings for uint256; 1368 | 1369 | // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` 1370 | // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` 1371 | bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; 1372 | 1373 | // Mapping from holder address to their (enumerable) set of owned tokens 1374 | mapping (address => EnumerableSet.UintSet) private _holderTokens; 1375 | 1376 | // Enumerable mapping from token ids to their owners 1377 | EnumerableMap.UintToAddressMap private _tokenOwners; 1378 | 1379 | // Mapping from token ID to approved address 1380 | mapping (uint256 => address) private _tokenApprovals; 1381 | 1382 | // Mapping from owner to operator approvals 1383 | mapping (address => mapping (address => bool)) private _operatorApprovals; 1384 | 1385 | // Token name 1386 | string private _name; 1387 | 1388 | // Token symbol 1389 | string private _symbol; 1390 | 1391 | // Optional mapping for token URIs 1392 | mapping (uint256 => string) private _tokenURIs; 1393 | 1394 | // Base URI 1395 | string private _baseURI; 1396 | 1397 | /* 1398 | * bytes4(keccak256('balanceOf(address)')) == 0x70a08231 1399 | * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e 1400 | * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 1401 | * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc 1402 | * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 1403 | * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 1404 | * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd 1405 | * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e 1406 | * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde 1407 | * 1408 | * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ 1409 | * 0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd 1410 | */ 1411 | bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; 1412 | 1413 | /* 1414 | * bytes4(keccak256('name()')) == 0x06fdde03 1415 | * bytes4(keccak256('symbol()')) == 0x95d89b41 1416 | * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd 1417 | * 1418 | * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f 1419 | */ 1420 | bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; 1421 | 1422 | /* 1423 | * bytes4(keccak256('totalSupply()')) == 0x18160ddd 1424 | * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 1425 | * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 1426 | * 1427 | * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 1428 | */ 1429 | bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; 1430 | 1431 | /** 1432 | * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. 1433 | */ 1434 | constructor (string memory name_, string memory symbol_) public { 1435 | _name = name_; 1436 | _symbol = symbol_; 1437 | 1438 | // register the supported interfaces to conform to ERC721 via ERC165 1439 | _registerInterface(_INTERFACE_ID_ERC721); 1440 | _registerInterface(_INTERFACE_ID_ERC721_METADATA); 1441 | _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); 1442 | } 1443 | 1444 | /** 1445 | * @dev See {IERC721-balanceOf}. 1446 | */ 1447 | function balanceOf(address owner) public view virtual override returns (uint256) { 1448 | require(owner != address(0), "ERC721: balance query for the zero address"); 1449 | return _holderTokens[owner].length(); 1450 | } 1451 | 1452 | /** 1453 | * @dev See {IERC721-ownerOf}. 1454 | */ 1455 | function ownerOf(uint256 tokenId) public view virtual override returns (address) { 1456 | return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token"); 1457 | } 1458 | 1459 | /** 1460 | * @dev See {IERC721Metadata-name}. 1461 | */ 1462 | function name() public view virtual override returns (string memory) { 1463 | return _name; 1464 | } 1465 | 1466 | /** 1467 | * @dev See {IERC721Metadata-symbol}. 1468 | */ 1469 | function symbol() public view virtual override returns (string memory) { 1470 | return _symbol; 1471 | } 1472 | 1473 | /** 1474 | * @dev See {IERC721Metadata-tokenURI}. 1475 | */ 1476 | function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { 1477 | require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); 1478 | 1479 | string memory _tokenURI = _tokenURIs[tokenId]; 1480 | string memory base = baseURI(); 1481 | 1482 | // If there is no base URI, return the token URI. 1483 | if (bytes(base).length == 0) { 1484 | return _tokenURI; 1485 | } 1486 | // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked). 1487 | if (bytes(_tokenURI).length > 0) { 1488 | return string(abi.encodePacked(base, _tokenURI)); 1489 | } 1490 | // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI. 1491 | return string(abi.encodePacked(base, tokenId.toString())); 1492 | } 1493 | 1494 | /** 1495 | * @dev Returns the base URI set via {_setBaseURI}. This will be 1496 | * automatically added as a prefix in {tokenURI} to each token's URI, or 1497 | * to the token ID if no specific URI is set for that token ID. 1498 | */ 1499 | function baseURI() public view virtual returns (string memory) { 1500 | return _baseURI; 1501 | } 1502 | 1503 | /** 1504 | * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. 1505 | */ 1506 | function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { 1507 | return _holderTokens[owner].at(index); 1508 | } 1509 | 1510 | /** 1511 | * @dev See {IERC721Enumerable-totalSupply}. 1512 | */ 1513 | function totalSupply() public view virtual override returns (uint256) { 1514 | // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds 1515 | return _tokenOwners.length(); 1516 | } 1517 | 1518 | /** 1519 | * @dev See {IERC721Enumerable-tokenByIndex}. 1520 | */ 1521 | function tokenByIndex(uint256 index) public view virtual override returns (uint256) { 1522 | (uint256 tokenId, ) = _tokenOwners.at(index); 1523 | return tokenId; 1524 | } 1525 | 1526 | /** 1527 | * @dev See {IERC721-approve}. 1528 | */ 1529 | function approve(address to, uint256 tokenId) public virtual override { 1530 | address owner = ERC721.ownerOf(tokenId); 1531 | require(to != owner, "ERC721: approval to current owner"); 1532 | 1533 | require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()), 1534 | "ERC721: approve caller is not owner nor approved for all" 1535 | ); 1536 | 1537 | _approve(to, tokenId); 1538 | } 1539 | 1540 | /** 1541 | * @dev See {IERC721-getApproved}. 1542 | */ 1543 | function getApproved(uint256 tokenId) public view virtual override returns (address) { 1544 | require(_exists(tokenId), "ERC721: approved query for nonexistent token"); 1545 | 1546 | return _tokenApprovals[tokenId]; 1547 | } 1548 | 1549 | /** 1550 | * @dev See {IERC721-setApprovalForAll}. 1551 | */ 1552 | function setApprovalForAll(address operator, bool approved) public virtual override { 1553 | require(operator != _msgSender(), "ERC721: approve to caller"); 1554 | 1555 | _operatorApprovals[_msgSender()][operator] = approved; 1556 | emit ApprovalForAll(_msgSender(), operator, approved); 1557 | } 1558 | 1559 | /** 1560 | * @dev See {IERC721-isApprovedForAll}. 1561 | */ 1562 | function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { 1563 | return _operatorApprovals[owner][operator]; 1564 | } 1565 | 1566 | /** 1567 | * @dev See {IERC721-transferFrom}. 1568 | */ 1569 | function transferFrom(address from, address to, uint256 tokenId) public virtual override { 1570 | //solhint-disable-next-line max-line-length 1571 | require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); 1572 | 1573 | _transfer(from, to, tokenId); 1574 | } 1575 | 1576 | /** 1577 | * @dev See {IERC721-safeTransferFrom}. 1578 | */ 1579 | function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { 1580 | safeTransferFrom(from, to, tokenId, ""); 1581 | } 1582 | 1583 | /** 1584 | * @dev See {IERC721-safeTransferFrom}. 1585 | */ 1586 | function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override { 1587 | require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); 1588 | _safeTransfer(from, to, tokenId, _data); 1589 | } 1590 | 1591 | /** 1592 | * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients 1593 | * are aware of the ERC721 protocol to prevent tokens from being forever locked. 1594 | * 1595 | * `_data` is additional data, it has no specified format and it is sent in call to `to`. 1596 | * 1597 | * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. 1598 | * implement alternative mechanisms to perform token transfer, such as signature-based. 1599 | * 1600 | * Requirements: 1601 | * 1602 | * - `from` cannot be the zero address. 1603 | * - `to` cannot be the zero address. 1604 | * - `tokenId` token must exist and be owned by `from`. 1605 | * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. 1606 | * 1607 | * Emits a {Transfer} event. 1608 | */ 1609 | function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual { 1610 | _transfer(from, to, tokenId); 1611 | require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); 1612 | } 1613 | 1614 | /** 1615 | * @dev Returns whether `tokenId` exists. 1616 | * 1617 | * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. 1618 | * 1619 | * Tokens start existing when they are minted (`_mint`), 1620 | * and stop existing when they are burned (`_burn`). 1621 | */ 1622 | function _exists(uint256 tokenId) internal view virtual returns (bool) { 1623 | return _tokenOwners.contains(tokenId); 1624 | } 1625 | 1626 | /** 1627 | * @dev Returns whether `spender` is allowed to manage `tokenId`. 1628 | * 1629 | * Requirements: 1630 | * 1631 | * - `tokenId` must exist. 1632 | */ 1633 | function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { 1634 | require(_exists(tokenId), "ERC721: operator query for nonexistent token"); 1635 | address owner = ERC721.ownerOf(tokenId); 1636 | return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender)); 1637 | } 1638 | 1639 | /** 1640 | * @dev Safely mints `tokenId` and transfers it to `to`. 1641 | * 1642 | * Requirements: 1643 | d* 1644 | * - `tokenId` must not exist. 1645 | * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. 1646 | * 1647 | * Emits a {Transfer} event. 1648 | */ 1649 | function _safeMint(address to, uint256 tokenId) internal virtual { 1650 | _safeMint(to, tokenId, ""); 1651 | } 1652 | 1653 | /** 1654 | * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is 1655 | * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. 1656 | */ 1657 | function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual { 1658 | _mint(to, tokenId); 1659 | require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); 1660 | } 1661 | 1662 | /** 1663 | * @dev Mints `tokenId` and transfers it to `to`. 1664 | * 1665 | * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible 1666 | * 1667 | * Requirements: 1668 | * 1669 | * - `tokenId` must not exist. 1670 | * - `to` cannot be the zero address. 1671 | * 1672 | * Emits a {Transfer} event. 1673 | */ 1674 | function _mint(address to, uint256 tokenId) internal virtual { 1675 | require(to != address(0), "ERC721: mint to the zero address"); 1676 | require(!_exists(tokenId), "ERC721: token already minted"); 1677 | 1678 | _beforeTokenTransfer(address(0), to, tokenId); 1679 | 1680 | _holderTokens[to].add(tokenId); 1681 | 1682 | _tokenOwners.set(tokenId, to); 1683 | 1684 | emit Transfer(address(0), to, tokenId); 1685 | } 1686 | 1687 | /** 1688 | * @dev Destroys `tokenId`. 1689 | * The approval is cleared when the token is burned. 1690 | * 1691 | * Requirements: 1692 | * 1693 | * - `tokenId` must exist. 1694 | * 1695 | * Emits a {Transfer} event. 1696 | */ 1697 | function _burn(uint256 tokenId) internal virtual { 1698 | address owner = ERC721.ownerOf(tokenId); // internal owner 1699 | 1700 | _beforeTokenTransfer(owner, address(0), tokenId); 1701 | 1702 | // Clear approvals 1703 | _approve(address(0), tokenId); 1704 | 1705 | // Clear metadata (if any) 1706 | if (bytes(_tokenURIs[tokenId]).length != 0) { 1707 | delete _tokenURIs[tokenId]; 1708 | } 1709 | 1710 | _holderTokens[owner].remove(tokenId); 1711 | 1712 | _tokenOwners.remove(tokenId); 1713 | 1714 | emit Transfer(owner, address(0), tokenId); 1715 | } 1716 | 1717 | /** 1718 | * @dev Transfers `tokenId` from `from` to `to`. 1719 | * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. 1720 | * 1721 | * Requirements: 1722 | * 1723 | * - `to` cannot be the zero address. 1724 | * - `tokenId` token must be owned by `from`. 1725 | * 1726 | * Emits a {Transfer} event. 1727 | */ 1728 | function _transfer(address from, address to, uint256 tokenId) internal virtual { 1729 | require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal owner 1730 | require(to != address(0), "ERC721: transfer to the zero address"); 1731 | 1732 | _beforeTokenTransfer(from, to, tokenId); 1733 | 1734 | // Clear approvals from the previous owner 1735 | _approve(address(0), tokenId); 1736 | 1737 | _holderTokens[from].remove(tokenId); 1738 | _holderTokens[to].add(tokenId); 1739 | 1740 | _tokenOwners.set(tokenId, to); 1741 | 1742 | emit Transfer(from, to, tokenId); 1743 | } 1744 | 1745 | /** 1746 | * @dev Sets `_tokenURI` as the tokenURI of `tokenId`. 1747 | * 1748 | * Requirements: 1749 | * 1750 | * - `tokenId` must exist. 1751 | */ 1752 | function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual { 1753 | require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token"); 1754 | _tokenURIs[tokenId] = _tokenURI; 1755 | } 1756 | 1757 | /** 1758 | * @dev Internal function to set the base URI for all token IDs. It is 1759 | * automatically added as a prefix to the value returned in {tokenURI}, 1760 | * or to the token ID if {tokenURI} is empty. 1761 | */ 1762 | function _setBaseURI(string memory baseURI_) internal virtual { 1763 | _baseURI = baseURI_; 1764 | } 1765 | 1766 | /** 1767 | * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. 1768 | * The call is not executed if the target address is not a contract. 1769 | * 1770 | * @param from address representing the previous owner of the given token ID 1771 | * @param to target address that will receive the tokens 1772 | * @param tokenId uint256 ID of the token to be transferred 1773 | * @param _data bytes optional data to send along with the call 1774 | * @return bool whether the call correctly returned the expected magic value 1775 | */ 1776 | function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) 1777 | private returns (bool) 1778 | { 1779 | if (!to.isContract()) { 1780 | return true; 1781 | } 1782 | bytes memory returndata = to.functionCall(abi.encodeWithSelector( 1783 | IERC721Receiver(to).onERC721Received.selector, 1784 | _msgSender(), 1785 | from, 1786 | tokenId, 1787 | _data 1788 | ), "ERC721: transfer to non ERC721Receiver implementer"); 1789 | bytes4 retval = abi.decode(returndata, (bytes4)); 1790 | return (retval == _ERC721_RECEIVED); 1791 | } 1792 | 1793 | /** 1794 | * @dev Approve `to` to operate on `tokenId` 1795 | * 1796 | * Emits an {Approval} event. 1797 | */ 1798 | function _approve(address to, uint256 tokenId) internal virtual { 1799 | _tokenApprovals[tokenId] = to; 1800 | emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner 1801 | } 1802 | 1803 | /** 1804 | * @dev Hook that is called before any token transfer. This includes minting 1805 | * and burning. 1806 | * 1807 | * Calling conditions: 1808 | * 1809 | * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be 1810 | * transferred to `to`. 1811 | * - When `from` is zero, `tokenId` will be minted for `to`. 1812 | * - When `to` is zero, ``from``'s `tokenId` will be burned. 1813 | * - `from` cannot be the zero address. 1814 | * - `to` cannot be the zero address. 1815 | * 1816 | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 1817 | */ 1818 | function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { } 1819 | } 1820 | 1821 | // File: @openzeppelin/contracts/access/Ownable.sol 1822 | 1823 | // SPDX-License-Identifier: MIT 1824 | 1825 | pragma solidity >=0.6.0 <0.8.0; 1826 | 1827 | /** 1828 | * @dev Contract module which provides a basic access control mechanism, where 1829 | * there is an account (an owner) that can be granted exclusive access to 1830 | * specific functions. 1831 | * 1832 | * By default, the owner account will be the one that deploys the contract. This 1833 | * can later be changed with {transferOwnership}. 1834 | * 1835 | * This module is used through inheritance. It will make available the modifier 1836 | * `onlyOwner`, which can be applied to your functions to restrict their use to 1837 | * the owner. 1838 | */ 1839 | abstract contract Ownable is Context { 1840 | address private _owner; 1841 | 1842 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 1843 | 1844 | /** 1845 | * @dev Initializes the contract setting the deployer as the initial owner. 1846 | */ 1847 | constructor () internal { 1848 | address msgSender = _msgSender(); 1849 | _owner = msgSender; 1850 | emit OwnershipTransferred(address(0), msgSender); 1851 | } 1852 | 1853 | /** 1854 | * @dev Returns the address of the current owner. 1855 | */ 1856 | function owner() public view virtual returns (address) { 1857 | return _owner; 1858 | } 1859 | 1860 | /** 1861 | * @dev Throws if called by any account other than the owner. 1862 | */ 1863 | modifier onlyOwner() { 1864 | require(owner() == _msgSender(), "Ownable: caller is not the owner"); 1865 | _; 1866 | } 1867 | 1868 | /** 1869 | * @dev Leaves the contract without owner. It will not be possible to call 1870 | * `onlyOwner` functions anymore. Can only be called by the current owner. 1871 | * 1872 | * NOTE: Renouncing ownership will leave the contract without an owner, 1873 | * thereby removing any functionality that is only available to the owner. 1874 | */ 1875 | function renounceOwnership() public virtual onlyOwner { 1876 | emit OwnershipTransferred(_owner, address(0)); 1877 | _owner = address(0); 1878 | } 1879 | 1880 | /** 1881 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 1882 | * Can only be called by the current owner. 1883 | */ 1884 | function transferOwnership(address newOwner) public virtual onlyOwner { 1885 | require(newOwner != address(0), "Ownable: new owner is the zero address"); 1886 | emit OwnershipTransferred(_owner, newOwner); 1887 | _owner = newOwner; 1888 | } 1889 | } 1890 | 1891 | // File: contracts/interfaces/IWeatherFeed.sol 1892 | 1893 | pragma solidity ^0.6.6; 1894 | 1895 | interface IWeatherFeed { 1896 | function weather() external view returns (string memory); 1897 | } 1898 | 1899 | // File: @chainlink/contracts/src/v0.6/vendor/BufferChainlink.sol 1900 | 1901 | // SPDX-License-Identifier: MIT 1902 | pragma solidity ^0.6.0; 1903 | 1904 | /** 1905 | * @dev A library for working with mutable byte buffers in Solidity. 1906 | * 1907 | * Byte buffers are mutable and expandable, and provide a variety of primitives 1908 | * for writing to them. At any time you can fetch a bytes object containing the 1909 | * current contents of the buffer. The bytes object should not be stored between 1910 | * operations, as it may change due to resizing of the buffer. 1911 | */ 1912 | library BufferChainlink { 1913 | /** 1914 | * @dev Represents a mutable buffer. Buffers have a current value (buf) and 1915 | * a capacity. The capacity may be longer than the current value, in 1916 | * which case it can be extended without the need to allocate more memory. 1917 | */ 1918 | struct buffer { 1919 | bytes buf; 1920 | uint capacity; 1921 | } 1922 | 1923 | /** 1924 | * @dev Initializes a buffer with an initial capacity. 1925 | * @param buf The buffer to initialize. 1926 | * @param capacity The number of bytes of space to allocate the buffer. 1927 | * @return The buffer, for chaining. 1928 | */ 1929 | function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) { 1930 | if (capacity % 32 != 0) { 1931 | capacity += 32 - (capacity % 32); 1932 | } 1933 | // Allocate space for the buffer data 1934 | buf.capacity = capacity; 1935 | assembly { 1936 | let ptr := mload(0x40) 1937 | mstore(buf, ptr) 1938 | mstore(ptr, 0) 1939 | mstore(0x40, add(32, add(ptr, capacity))) 1940 | } 1941 | return buf; 1942 | } 1943 | 1944 | /** 1945 | * @dev Initializes a new buffer from an existing bytes object. 1946 | * Changes to the buffer may mutate the original value. 1947 | * @param b The bytes object to initialize the buffer with. 1948 | * @return A new buffer. 1949 | */ 1950 | function fromBytes(bytes memory b) internal pure returns(buffer memory) { 1951 | buffer memory buf; 1952 | buf.buf = b; 1953 | buf.capacity = b.length; 1954 | return buf; 1955 | } 1956 | 1957 | function resize(buffer memory buf, uint capacity) private pure { 1958 | bytes memory oldbuf = buf.buf; 1959 | init(buf, capacity); 1960 | append(buf, oldbuf); 1961 | } 1962 | 1963 | function max(uint a, uint b) private pure returns(uint) { 1964 | if (a > b) { 1965 | return a; 1966 | } 1967 | return b; 1968 | } 1969 | 1970 | /** 1971 | * @dev Sets buffer length to 0. 1972 | * @param buf The buffer to truncate. 1973 | * @return The original buffer, for chaining.. 1974 | */ 1975 | function truncate(buffer memory buf) internal pure returns (buffer memory) { 1976 | assembly { 1977 | let bufptr := mload(buf) 1978 | mstore(bufptr, 0) 1979 | } 1980 | return buf; 1981 | } 1982 | 1983 | /** 1984 | * @dev Writes a byte string to a buffer. Resizes if doing so would exceed 1985 | * the capacity of the buffer. 1986 | * @param buf The buffer to append to. 1987 | * @param off The start offset to write to. 1988 | * @param data The data to append. 1989 | * @param len The number of bytes to copy. 1990 | * @return The original buffer, for chaining. 1991 | */ 1992 | function write(buffer memory buf, uint off, bytes memory data, uint len) internal pure returns(buffer memory) { 1993 | require(len <= data.length); 1994 | 1995 | if (off + len > buf.capacity) { 1996 | resize(buf, max(buf.capacity, len + off) * 2); 1997 | } 1998 | 1999 | uint dest; 2000 | uint src; 2001 | assembly { 2002 | // Memory address of the buffer data 2003 | let bufptr := mload(buf) 2004 | // Length of existing buffer data 2005 | let buflen := mload(bufptr) 2006 | // Start address = buffer address + offset + sizeof(buffer length) 2007 | dest := add(add(bufptr, 32), off) 2008 | // Update buffer length if we're extending it 2009 | if gt(add(len, off), buflen) { 2010 | mstore(bufptr, add(len, off)) 2011 | } 2012 | src := add(data, 32) 2013 | } 2014 | 2015 | // Copy word-length chunks while possible 2016 | for (; len >= 32; len -= 32) { 2017 | assembly { 2018 | mstore(dest, mload(src)) 2019 | } 2020 | dest += 32; 2021 | src += 32; 2022 | } 2023 | 2024 | // Copy remaining bytes 2025 | uint mask = 256 ** (32 - len) - 1; 2026 | assembly { 2027 | let srcpart := and(mload(src), not(mask)) 2028 | let destpart := and(mload(dest), mask) 2029 | mstore(dest, or(destpart, srcpart)) 2030 | } 2031 | 2032 | return buf; 2033 | } 2034 | 2035 | /** 2036 | * @dev Appends a byte string to a buffer. Resizes if doing so would exceed 2037 | * the capacity of the buffer. 2038 | * @param buf The buffer to append to. 2039 | * @param data The data to append. 2040 | * @param len The number of bytes to copy. 2041 | * @return The original buffer, for chaining. 2042 | */ 2043 | function append(buffer memory buf, bytes memory data, uint len) internal pure returns (buffer memory) { 2044 | return write(buf, buf.buf.length, data, len); 2045 | } 2046 | 2047 | /** 2048 | * @dev Appends a byte string to a buffer. Resizes if doing so would exceed 2049 | * the capacity of the buffer. 2050 | * @param buf The buffer to append to. 2051 | * @param data The data to append. 2052 | * @return The original buffer, for chaining. 2053 | */ 2054 | function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { 2055 | return write(buf, buf.buf.length, data, data.length); 2056 | } 2057 | 2058 | /** 2059 | * @dev Writes a byte to the buffer. Resizes if doing so would exceed the 2060 | * capacity of the buffer. 2061 | * @param buf The buffer to append to. 2062 | * @param off The offset to write the byte at. 2063 | * @param data The data to append. 2064 | * @return The original buffer, for chaining. 2065 | */ 2066 | function writeUint8(buffer memory buf, uint off, uint8 data) internal pure returns(buffer memory) { 2067 | if (off >= buf.capacity) { 2068 | resize(buf, buf.capacity * 2); 2069 | } 2070 | 2071 | assembly { 2072 | // Memory address of the buffer data 2073 | let bufptr := mload(buf) 2074 | // Length of existing buffer data 2075 | let buflen := mload(bufptr) 2076 | // Address = buffer address + sizeof(buffer length) + off 2077 | let dest := add(add(bufptr, off), 32) 2078 | mstore8(dest, data) 2079 | // Update buffer length if we extended it 2080 | if eq(off, buflen) { 2081 | mstore(bufptr, add(buflen, 1)) 2082 | } 2083 | } 2084 | return buf; 2085 | } 2086 | 2087 | /** 2088 | * @dev Appends a byte to the buffer. Resizes if doing so would exceed the 2089 | * capacity of the buffer. 2090 | * @param buf The buffer to append to. 2091 | * @param data The data to append. 2092 | * @return The original buffer, for chaining. 2093 | */ 2094 | function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) { 2095 | return writeUint8(buf, buf.buf.length, data); 2096 | } 2097 | 2098 | /** 2099 | * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would 2100 | * exceed the capacity of the buffer. 2101 | * @param buf The buffer to append to. 2102 | * @param off The offset to write at. 2103 | * @param data The data to append. 2104 | * @param len The number of bytes to write (left-aligned). 2105 | * @return The original buffer, for chaining. 2106 | */ 2107 | function write(buffer memory buf, uint off, bytes32 data, uint len) private pure returns(buffer memory) { 2108 | if (len + off > buf.capacity) { 2109 | resize(buf, (len + off) * 2); 2110 | } 2111 | 2112 | uint mask = 256 ** len - 1; 2113 | // Right-align data 2114 | data = data >> (8 * (32 - len)); 2115 | assembly { 2116 | // Memory address of the buffer data 2117 | let bufptr := mload(buf) 2118 | // Address = buffer address + sizeof(buffer length) + off + len 2119 | let dest := add(add(bufptr, off), len) 2120 | mstore(dest, or(and(mload(dest), not(mask)), data)) 2121 | // Update buffer length if we extended it 2122 | if gt(add(off, len), mload(bufptr)) { 2123 | mstore(bufptr, add(off, len)) 2124 | } 2125 | } 2126 | return buf; 2127 | } 2128 | 2129 | /** 2130 | * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the 2131 | * capacity of the buffer. 2132 | * @param buf The buffer to append to. 2133 | * @param off The offset to write at. 2134 | * @param data The data to append. 2135 | * @return The original buffer, for chaining. 2136 | */ 2137 | function writeBytes20(buffer memory buf, uint off, bytes20 data) internal pure returns (buffer memory) { 2138 | return write(buf, off, bytes32(data), 20); 2139 | } 2140 | 2141 | /** 2142 | * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed 2143 | * the capacity of the buffer. 2144 | * @param buf The buffer to append to. 2145 | * @param data The data to append. 2146 | * @return The original buffer, for chhaining. 2147 | */ 2148 | function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { 2149 | return write(buf, buf.buf.length, bytes32(data), 20); 2150 | } 2151 | 2152 | /** 2153 | * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed 2154 | * the capacity of the buffer. 2155 | * @param buf The buffer to append to. 2156 | * @param data The data to append. 2157 | * @return The original buffer, for chaining. 2158 | */ 2159 | function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { 2160 | return write(buf, buf.buf.length, data, 32); 2161 | } 2162 | 2163 | /** 2164 | * @dev Writes an integer to the buffer. Resizes if doing so would exceed 2165 | * the capacity of the buffer. 2166 | * @param buf The buffer to append to. 2167 | * @param off The offset to write at. 2168 | * @param data The data to append. 2169 | * @param len The number of bytes to write (right-aligned). 2170 | * @return The original buffer, for chaining. 2171 | */ 2172 | function writeInt(buffer memory buf, uint off, uint data, uint len) private pure returns(buffer memory) { 2173 | if (len + off > buf.capacity) { 2174 | resize(buf, (len + off) * 2); 2175 | } 2176 | 2177 | uint mask = 256 ** len - 1; 2178 | assembly { 2179 | // Memory address of the buffer data 2180 | let bufptr := mload(buf) 2181 | // Address = buffer address + off + sizeof(buffer length) + len 2182 | let dest := add(add(bufptr, off), len) 2183 | mstore(dest, or(and(mload(dest), not(mask)), data)) 2184 | // Update buffer length if we extended it 2185 | if gt(add(off, len), mload(bufptr)) { 2186 | mstore(bufptr, add(off, len)) 2187 | } 2188 | } 2189 | return buf; 2190 | } 2191 | 2192 | /** 2193 | * @dev Appends a byte to the end of the buffer. Resizes if doing so would 2194 | * exceed the capacity of the buffer. 2195 | * @param buf The buffer to append to. 2196 | * @param data The data to append. 2197 | * @return The original buffer. 2198 | */ 2199 | function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) { 2200 | return writeInt(buf, buf.buf.length, data, len); 2201 | } 2202 | } 2203 | 2204 | // File: @chainlink/contracts/src/v0.6/vendor/CBORChainlink.sol 2205 | 2206 | // SPDX-License-Identifier: MIT 2207 | pragma solidity >= 0.4.19; 2208 | 2209 | 2210 | library CBORChainlink { 2211 | using BufferChainlink for BufferChainlink.buffer; 2212 | 2213 | uint8 private constant MAJOR_TYPE_INT = 0; 2214 | uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; 2215 | uint8 private constant MAJOR_TYPE_BYTES = 2; 2216 | uint8 private constant MAJOR_TYPE_STRING = 3; 2217 | uint8 private constant MAJOR_TYPE_ARRAY = 4; 2218 | uint8 private constant MAJOR_TYPE_MAP = 5; 2219 | uint8 private constant MAJOR_TYPE_TAG = 6; 2220 | uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; 2221 | 2222 | uint8 private constant TAG_TYPE_BIGNUM = 2; 2223 | uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3; 2224 | 2225 | function encodeType( 2226 | BufferChainlink.buffer memory buf, 2227 | uint8 major, 2228 | uint value 2229 | ) 2230 | private 2231 | pure 2232 | { 2233 | if(value <= 23) { 2234 | buf.appendUint8(uint8((major << 5) | value)); 2235 | } else if(value <= 0xFF) { 2236 | buf.appendUint8(uint8((major << 5) | 24)); 2237 | buf.appendInt(value, 1); 2238 | } else if(value <= 0xFFFF) { 2239 | buf.appendUint8(uint8((major << 5) | 25)); 2240 | buf.appendInt(value, 2); 2241 | } else if(value <= 0xFFFFFFFF) { 2242 | buf.appendUint8(uint8((major << 5) | 26)); 2243 | buf.appendInt(value, 4); 2244 | } else if(value <= 0xFFFFFFFFFFFFFFFF) { 2245 | buf.appendUint8(uint8((major << 5) | 27)); 2246 | buf.appendInt(value, 8); 2247 | } 2248 | } 2249 | 2250 | function encodeIndefiniteLengthType( 2251 | BufferChainlink.buffer memory buf, 2252 | uint8 major 2253 | ) 2254 | private 2255 | pure 2256 | { 2257 | buf.appendUint8(uint8((major << 5) | 31)); 2258 | } 2259 | 2260 | function encodeUInt( 2261 | BufferChainlink.buffer memory buf, 2262 | uint value 2263 | ) 2264 | internal 2265 | pure 2266 | { 2267 | encodeType(buf, MAJOR_TYPE_INT, value); 2268 | } 2269 | 2270 | function encodeInt( 2271 | BufferChainlink.buffer memory buf, 2272 | int value 2273 | ) 2274 | internal 2275 | pure 2276 | { 2277 | if(value < -0x10000000000000000) { 2278 | encodeSignedBigNum(buf, value); 2279 | } else if(value > 0xFFFFFFFFFFFFFFFF) { 2280 | encodeBigNum(buf, value); 2281 | } else if(value >= 0) { 2282 | encodeType(buf, MAJOR_TYPE_INT, uint(value)); 2283 | } else { 2284 | encodeType(buf, MAJOR_TYPE_NEGATIVE_INT, uint(-1 - value)); 2285 | } 2286 | } 2287 | 2288 | function encodeBytes( 2289 | BufferChainlink.buffer memory buf, 2290 | bytes memory value 2291 | ) 2292 | internal 2293 | pure 2294 | { 2295 | encodeType(buf, MAJOR_TYPE_BYTES, value.length); 2296 | buf.append(value); 2297 | } 2298 | 2299 | function encodeBigNum( 2300 | BufferChainlink.buffer memory buf, 2301 | int value 2302 | ) 2303 | internal 2304 | pure 2305 | { 2306 | buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM)); 2307 | encodeBytes(buf, abi.encode(uint(value))); 2308 | } 2309 | 2310 | function encodeSignedBigNum( 2311 | BufferChainlink.buffer memory buf, 2312 | int input 2313 | ) 2314 | internal 2315 | pure 2316 | { 2317 | buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM)); 2318 | encodeBytes(buf, abi.encode(uint(-1 - input))); 2319 | } 2320 | 2321 | function encodeString( 2322 | BufferChainlink.buffer memory buf, 2323 | string memory value 2324 | ) 2325 | internal 2326 | pure 2327 | { 2328 | encodeType(buf, MAJOR_TYPE_STRING, bytes(value).length); 2329 | buf.append(bytes(value)); 2330 | } 2331 | 2332 | function startArray( 2333 | BufferChainlink.buffer memory buf 2334 | ) 2335 | internal 2336 | pure 2337 | { 2338 | encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); 2339 | } 2340 | 2341 | function startMap( 2342 | BufferChainlink.buffer memory buf 2343 | ) 2344 | internal 2345 | pure 2346 | { 2347 | encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); 2348 | } 2349 | 2350 | function endSequence( 2351 | BufferChainlink.buffer memory buf 2352 | ) 2353 | internal 2354 | pure 2355 | { 2356 | encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); 2357 | } 2358 | } 2359 | 2360 | // File: @chainlink/contracts/src/v0.6/Chainlink.sol 2361 | 2362 | // SPDX-License-Identifier: MIT 2363 | pragma solidity ^0.6.0; 2364 | 2365 | 2366 | 2367 | /** 2368 | * @title Library for common Chainlink functions 2369 | * @dev Uses imported CBOR library for encoding to buffer 2370 | */ 2371 | library Chainlink { 2372 | uint256 internal constant defaultBufferSize = 256; // solhint-disable-line const-name-snakecase 2373 | 2374 | using CBORChainlink for BufferChainlink.buffer; 2375 | 2376 | struct Request { 2377 | bytes32 id; 2378 | address callbackAddress; 2379 | bytes4 callbackFunctionId; 2380 | uint256 nonce; 2381 | BufferChainlink.buffer buf; 2382 | } 2383 | 2384 | /** 2385 | * @notice Initializes a Chainlink request 2386 | * @dev Sets the ID, callback address, and callback function signature on the request 2387 | * @param self The uninitialized request 2388 | * @param _id The Job Specification ID 2389 | * @param _callbackAddress The callback address 2390 | * @param _callbackFunction The callback function signature 2391 | * @return The initialized request 2392 | */ 2393 | function initialize( 2394 | Request memory self, 2395 | bytes32 _id, 2396 | address _callbackAddress, 2397 | bytes4 _callbackFunction 2398 | ) internal pure returns (Chainlink.Request memory) { 2399 | BufferChainlink.init(self.buf, defaultBufferSize); 2400 | self.id = _id; 2401 | self.callbackAddress = _callbackAddress; 2402 | self.callbackFunctionId = _callbackFunction; 2403 | return self; 2404 | } 2405 | 2406 | /** 2407 | * @notice Sets the data for the buffer without encoding CBOR on-chain 2408 | * @dev CBOR can be closed with curly-brackets {} or they can be left off 2409 | * @param self The initialized request 2410 | * @param _data The CBOR data 2411 | */ 2412 | function setBuffer(Request memory self, bytes memory _data) 2413 | internal pure 2414 | { 2415 | BufferChainlink.init(self.buf, _data.length); 2416 | BufferChainlink.append(self.buf, _data); 2417 | } 2418 | 2419 | /** 2420 | * @notice Adds a string value to the request with a given key name 2421 | * @param self The initialized request 2422 | * @param _key The name of the key 2423 | * @param _value The string value to add 2424 | */ 2425 | function add(Request memory self, string memory _key, string memory _value) 2426 | internal pure 2427 | { 2428 | self.buf.encodeString(_key); 2429 | self.buf.encodeString(_value); 2430 | } 2431 | 2432 | /** 2433 | * @notice Adds a bytes value to the request with a given key name 2434 | * @param self The initialized request 2435 | * @param _key The name of the key 2436 | * @param _value The bytes value to add 2437 | */ 2438 | function addBytes(Request memory self, string memory _key, bytes memory _value) 2439 | internal pure 2440 | { 2441 | self.buf.encodeString(_key); 2442 | self.buf.encodeBytes(_value); 2443 | } 2444 | 2445 | /** 2446 | * @notice Adds a int256 value to the request with a given key name 2447 | * @param self The initialized request 2448 | * @param _key The name of the key 2449 | * @param _value The int256 value to add 2450 | */ 2451 | function addInt(Request memory self, string memory _key, int256 _value) 2452 | internal pure 2453 | { 2454 | self.buf.encodeString(_key); 2455 | self.buf.encodeInt(_value); 2456 | } 2457 | 2458 | /** 2459 | * @notice Adds a uint256 value to the request with a given key name 2460 | * @param self The initialized request 2461 | * @param _key The name of the key 2462 | * @param _value The uint256 value to add 2463 | */ 2464 | function addUint(Request memory self, string memory _key, uint256 _value) 2465 | internal pure 2466 | { 2467 | self.buf.encodeString(_key); 2468 | self.buf.encodeUInt(_value); 2469 | } 2470 | 2471 | /** 2472 | * @notice Adds an array of strings to the request with a given key name 2473 | * @param self The initialized request 2474 | * @param _key The name of the key 2475 | * @param _values The array of string values to add 2476 | */ 2477 | function addStringArray(Request memory self, string memory _key, string[] memory _values) 2478 | internal pure 2479 | { 2480 | self.buf.encodeString(_key); 2481 | self.buf.startArray(); 2482 | for (uint256 i = 0; i < _values.length; i++) { 2483 | self.buf.encodeString(_values[i]); 2484 | } 2485 | self.buf.endSequence(); 2486 | } 2487 | } 2488 | 2489 | // File: @chainlink/contracts/src/v0.6/interfaces/ENSInterface.sol 2490 | 2491 | // SPDX-License-Identifier: MIT 2492 | pragma solidity ^0.6.0; 2493 | 2494 | interface ENSInterface { 2495 | 2496 | // Logged when the owner of a node assigns a new owner to a subnode. 2497 | event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); 2498 | 2499 | // Logged when the owner of a node transfers ownership to a new account. 2500 | event Transfer(bytes32 indexed node, address owner); 2501 | 2502 | // Logged when the resolver for a node changes. 2503 | event NewResolver(bytes32 indexed node, address resolver); 2504 | 2505 | // Logged when the TTL of a node changes 2506 | event NewTTL(bytes32 indexed node, uint64 ttl); 2507 | 2508 | 2509 | function setSubnodeOwner(bytes32 node, bytes32 label, address _owner) external; 2510 | function setResolver(bytes32 node, address _resolver) external; 2511 | function setOwner(bytes32 node, address _owner) external; 2512 | function setTTL(bytes32 node, uint64 _ttl) external; 2513 | function owner(bytes32 node) external view returns (address); 2514 | function resolver(bytes32 node) external view returns (address); 2515 | function ttl(bytes32 node) external view returns (uint64); 2516 | 2517 | } 2518 | 2519 | // File: @chainlink/contracts/src/v0.6/interfaces/LinkTokenInterface.sol 2520 | 2521 | // SPDX-License-Identifier: MIT 2522 | pragma solidity ^0.6.0; 2523 | 2524 | interface LinkTokenInterface { 2525 | function allowance(address owner, address spender) external view returns (uint256 remaining); 2526 | function approve(address spender, uint256 value) external returns (bool success); 2527 | function balanceOf(address owner) external view returns (uint256 balance); 2528 | function decimals() external view returns (uint8 decimalPlaces); 2529 | function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); 2530 | function increaseApproval(address spender, uint256 subtractedValue) external; 2531 | function name() external view returns (string memory tokenName); 2532 | function symbol() external view returns (string memory tokenSymbol); 2533 | function totalSupply() external view returns (uint256 totalTokensIssued); 2534 | function transfer(address to, uint256 value) external returns (bool success); 2535 | function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success); 2536 | function transferFrom(address from, address to, uint256 value) external returns (bool success); 2537 | } 2538 | 2539 | // File: @chainlink/contracts/src/v0.6/interfaces/ChainlinkRequestInterface.sol 2540 | 2541 | // SPDX-License-Identifier: MIT 2542 | pragma solidity ^0.6.0; 2543 | 2544 | interface ChainlinkRequestInterface { 2545 | function oracleRequest( 2546 | address sender, 2547 | uint256 requestPrice, 2548 | bytes32 serviceAgreementID, 2549 | address callbackAddress, 2550 | bytes4 callbackFunctionId, 2551 | uint256 nonce, 2552 | uint256 dataVersion, 2553 | bytes calldata data 2554 | ) external; 2555 | 2556 | function cancelOracleRequest( 2557 | bytes32 requestId, 2558 | uint256 payment, 2559 | bytes4 callbackFunctionId, 2560 | uint256 expiration 2561 | ) external; 2562 | } 2563 | 2564 | // File: @chainlink/contracts/src/v0.6/interfaces/PointerInterface.sol 2565 | 2566 | // SPDX-License-Identifier: MIT 2567 | pragma solidity ^0.6.0; 2568 | 2569 | interface PointerInterface { 2570 | function getAddress() external view returns (address); 2571 | } 2572 | 2573 | // File: @chainlink/contracts/src/v0.6/vendor/ENSResolver.sol 2574 | 2575 | // SPDX-License-Identifier: MIT 2576 | pragma solidity ^0.6.0; 2577 | 2578 | abstract contract ENSResolver { 2579 | function addr(bytes32 node) public view virtual returns (address); 2580 | } 2581 | 2582 | // File: @chainlink/contracts/src/v0.6/ChainlinkClient.sol 2583 | 2584 | // SPDX-License-Identifier: MIT 2585 | pragma solidity ^0.6.0; 2586 | 2587 | 2588 | 2589 | 2590 | 2591 | 2592 | 2593 | /** 2594 | * @title The ChainlinkClient contract 2595 | * @notice Contract writers can inherit this contract in order to create requests for the 2596 | * Chainlink network 2597 | */ 2598 | contract ChainlinkClient { 2599 | using Chainlink for Chainlink.Request; 2600 | 2601 | uint256 constant internal LINK = 10**18; 2602 | uint256 constant private AMOUNT_OVERRIDE = 0; 2603 | address constant private SENDER_OVERRIDE = address(0); 2604 | uint256 constant private ARGS_VERSION = 1; 2605 | bytes32 constant private ENS_TOKEN_SUBNAME = keccak256("link"); 2606 | bytes32 constant private ENS_ORACLE_SUBNAME = keccak256("oracle"); 2607 | address constant private LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571; 2608 | 2609 | ENSInterface private ens; 2610 | bytes32 private ensNode; 2611 | LinkTokenInterface private link; 2612 | ChainlinkRequestInterface private oracle; 2613 | uint256 private requestCount = 1; 2614 | mapping(bytes32 => address) private pendingRequests; 2615 | 2616 | event ChainlinkRequested(bytes32 indexed id); 2617 | event ChainlinkFulfilled(bytes32 indexed id); 2618 | event ChainlinkCancelled(bytes32 indexed id); 2619 | 2620 | /** 2621 | * @notice Creates a request that can hold additional parameters 2622 | * @param _specId The Job Specification ID that the request will be created for 2623 | * @param _callbackAddress The callback address that the response will be sent to 2624 | * @param _callbackFunctionSignature The callback function signature to use for the callback address 2625 | * @return A Chainlink Request struct in memory 2626 | */ 2627 | function buildChainlinkRequest( 2628 | bytes32 _specId, 2629 | address _callbackAddress, 2630 | bytes4 _callbackFunctionSignature 2631 | ) internal pure returns (Chainlink.Request memory) { 2632 | Chainlink.Request memory req; 2633 | return req.initialize(_specId, _callbackAddress, _callbackFunctionSignature); 2634 | } 2635 | 2636 | /** 2637 | * @notice Creates a Chainlink request to the stored oracle address 2638 | * @dev Calls `chainlinkRequestTo` with the stored oracle address 2639 | * @param _req The initialized Chainlink Request 2640 | * @param _payment The amount of LINK to send for the request 2641 | * @return requestId The request ID 2642 | */ 2643 | function sendChainlinkRequest(Chainlink.Request memory _req, uint256 _payment) 2644 | internal 2645 | returns (bytes32) 2646 | { 2647 | return sendChainlinkRequestTo(address(oracle), _req, _payment); 2648 | } 2649 | 2650 | /** 2651 | * @notice Creates a Chainlink request to the specified oracle address 2652 | * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to 2653 | * send LINK which creates a request on the target oracle contract. 2654 | * Emits ChainlinkRequested event. 2655 | * @param _oracle The address of the oracle for the request 2656 | * @param _req The initialized Chainlink Request 2657 | * @param _payment The amount of LINK to send for the request 2658 | * @return requestId The request ID 2659 | */ 2660 | function sendChainlinkRequestTo(address _oracle, Chainlink.Request memory _req, uint256 _payment) 2661 | internal 2662 | returns (bytes32 requestId) 2663 | { 2664 | requestId = keccak256(abi.encodePacked(this, requestCount)); 2665 | _req.nonce = requestCount; 2666 | pendingRequests[requestId] = _oracle; 2667 | emit ChainlinkRequested(requestId); 2668 | require(link.transferAndCall(_oracle, _payment, encodeRequest(_req)), "unable to transferAndCall to oracle"); 2669 | requestCount += 1; 2670 | 2671 | return requestId; 2672 | } 2673 | 2674 | /** 2675 | * @notice Allows a request to be cancelled if it has not been fulfilled 2676 | * @dev Requires keeping track of the expiration value emitted from the oracle contract. 2677 | * Deletes the request from the `pendingRequests` mapping. 2678 | * Emits ChainlinkCancelled event. 2679 | * @param _requestId The request ID 2680 | * @param _payment The amount of LINK sent for the request 2681 | * @param _callbackFunc The callback function specified for the request 2682 | * @param _expiration The time of the expiration for the request 2683 | */ 2684 | function cancelChainlinkRequest( 2685 | bytes32 _requestId, 2686 | uint256 _payment, 2687 | bytes4 _callbackFunc, 2688 | uint256 _expiration 2689 | ) 2690 | internal 2691 | { 2692 | ChainlinkRequestInterface requested = ChainlinkRequestInterface(pendingRequests[_requestId]); 2693 | delete pendingRequests[_requestId]; 2694 | emit ChainlinkCancelled(_requestId); 2695 | requested.cancelOracleRequest(_requestId, _payment, _callbackFunc, _expiration); 2696 | } 2697 | 2698 | /** 2699 | * @notice Sets the stored oracle address 2700 | * @param _oracle The address of the oracle contract 2701 | */ 2702 | function setChainlinkOracle(address _oracle) internal { 2703 | oracle = ChainlinkRequestInterface(_oracle); 2704 | } 2705 | 2706 | /** 2707 | * @notice Sets the LINK token address 2708 | * @param _link The address of the LINK token contract 2709 | */ 2710 | function setChainlinkToken(address _link) internal { 2711 | link = LinkTokenInterface(_link); 2712 | } 2713 | 2714 | /** 2715 | * @notice Sets the Chainlink token address for the public 2716 | * network as given by the Pointer contract 2717 | */ 2718 | function setPublicChainlinkToken() internal { 2719 | setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress()); 2720 | } 2721 | 2722 | /** 2723 | * @notice Retrieves the stored address of the LINK token 2724 | * @return The address of the LINK token 2725 | */ 2726 | function chainlinkTokenAddress() 2727 | internal 2728 | view 2729 | returns (address) 2730 | { 2731 | return address(link); 2732 | } 2733 | 2734 | /** 2735 | * @notice Retrieves the stored address of the oracle contract 2736 | * @return The address of the oracle contract 2737 | */ 2738 | function chainlinkOracleAddress() 2739 | internal 2740 | view 2741 | returns (address) 2742 | { 2743 | return address(oracle); 2744 | } 2745 | 2746 | /** 2747 | * @notice Allows for a request which was created on another contract to be fulfilled 2748 | * on this contract 2749 | * @param _oracle The address of the oracle contract that will fulfill the request 2750 | * @param _requestId The request ID used for the response 2751 | */ 2752 | function addChainlinkExternalRequest(address _oracle, bytes32 _requestId) 2753 | internal 2754 | notPendingRequest(_requestId) 2755 | { 2756 | pendingRequests[_requestId] = _oracle; 2757 | } 2758 | 2759 | /** 2760 | * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS 2761 | * @dev Accounts for subnodes having different resolvers 2762 | * @param _ens The address of the ENS contract 2763 | * @param _node The ENS node hash 2764 | */ 2765 | function useChainlinkWithENS(address _ens, bytes32 _node) 2766 | internal 2767 | { 2768 | ens = ENSInterface(_ens); 2769 | ensNode = _node; 2770 | bytes32 linkSubnode = keccak256(abi.encodePacked(ensNode, ENS_TOKEN_SUBNAME)); 2771 | ENSResolver_Chainlink resolver = ENSResolver_Chainlink(ens.resolver(linkSubnode)); 2772 | setChainlinkToken(resolver.addr(linkSubnode)); 2773 | updateChainlinkOracleWithENS(); 2774 | } 2775 | 2776 | /** 2777 | * @notice Sets the stored oracle contract with the address resolved by ENS 2778 | * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously 2779 | */ 2780 | function updateChainlinkOracleWithENS() 2781 | internal 2782 | { 2783 | bytes32 oracleSubnode = keccak256(abi.encodePacked(ensNode, ENS_ORACLE_SUBNAME)); 2784 | ENSResolver_Chainlink resolver = ENSResolver_Chainlink(ens.resolver(oracleSubnode)); 2785 | setChainlinkOracle(resolver.addr(oracleSubnode)); 2786 | } 2787 | 2788 | /** 2789 | * @notice Encodes the request to be sent to the oracle contract 2790 | * @dev The Chainlink node expects values to be in order for the request to be picked up. Order of types 2791 | * will be validated in the oracle contract. 2792 | * @param _req The initialized Chainlink Request 2793 | * @return The bytes payload for the `transferAndCall` method 2794 | */ 2795 | function encodeRequest(Chainlink.Request memory _req) 2796 | private 2797 | view 2798 | returns (bytes memory) 2799 | { 2800 | return abi.encodeWithSelector( 2801 | oracle.oracleRequest.selector, 2802 | SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address 2803 | AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent 2804 | _req.id, 2805 | _req.callbackAddress, 2806 | _req.callbackFunctionId, 2807 | _req.nonce, 2808 | ARGS_VERSION, 2809 | _req.buf.buf); 2810 | } 2811 | 2812 | /** 2813 | * @notice Ensures that the fulfillment is valid for this contract 2814 | * @dev Use if the contract developer prefers methods instead of modifiers for validation 2815 | * @param _requestId The request ID for fulfillment 2816 | */ 2817 | function validateChainlinkCallback(bytes32 _requestId) 2818 | internal 2819 | recordChainlinkFulfillment(_requestId) 2820 | // solhint-disable-next-line no-empty-blocks 2821 | {} 2822 | 2823 | /** 2824 | * @dev Reverts if the sender is not the oracle of the request. 2825 | * Emits ChainlinkFulfilled event. 2826 | * @param _requestId The request ID for fulfillment 2827 | */ 2828 | modifier recordChainlinkFulfillment(bytes32 _requestId) { 2829 | require(msg.sender == pendingRequests[_requestId], 2830 | "Source must be the oracle of the request"); 2831 | delete pendingRequests[_requestId]; 2832 | emit ChainlinkFulfilled(_requestId); 2833 | _; 2834 | } 2835 | 2836 | /** 2837 | * @dev Reverts if the request is already pending 2838 | * @param _requestId The request ID for fulfillment 2839 | */ 2840 | modifier notPendingRequest(bytes32 _requestId) { 2841 | require(pendingRequests[_requestId] == address(0), "Request is already pending"); 2842 | _; 2843 | } 2844 | } 2845 | 2846 | // File: contracts/WeatherNFT.sol 2847 | 2848 | // 2849 | // SPDX-License-Identifier: MIT 2850 | 2851 | pragma solidity ^0.6.6; 2852 | 2853 | 2854 | 2855 | 2856 | 2857 | 2858 | 2859 | contract WeatherNFT is ERC721, Ownable, ChainlinkClient { 2860 | using Strings for string; 2861 | bool public overRide; 2862 | string public overRideWeather; 2863 | uint256 public tokenCounter; 2864 | address public weatherFeedAddress; 2865 | uint256 public response; 2866 | 2867 | bytes32 public jobId; 2868 | address public oracle; 2869 | uint256 public fee; 2870 | 2871 | mapping(bytes32 => address) public requestIdToAttemptee; 2872 | mapping(string => string) public weatherToWeatherURI; 2873 | mapping(uint256 => string) public overRideTokenIdToWeatherURI; 2874 | mapping(uint256 => bool) public tokenIdTaken; 2875 | event attemptedPassword(bytes32 requestId); 2876 | /** 2877 | * Constructor inherits VRFConsumerBase 2878 | * Network: Rinkeby 2879 | * LINK token address: 0x01BE23585060835E02B77ef475b0Cc51aA1e0709 2880 | */ 2881 | constructor(address _link, address _weatherFeed, address _oracle, bytes32 _jobId, uint256 _fee) public 2882 | ERC721("WeatherNFT", "wNFT") 2883 | { 2884 | if (_link == address(0)) { 2885 | setPublicChainlinkToken(); 2886 | } else { 2887 | setChainlinkToken(_link); 2888 | } 2889 | weatherFeedAddress = _weatherFeed; 2890 | weatherToWeatherURI["Thunderstorm"] = "https://ipfs.io/ipfs/QmP3TpPig2St3nTwvi9TFAGdv6YTew5k4pmC1yFtaLwFFo"; 2891 | weatherToWeatherURI["Drizzle"] = "https://ipfs.io/ipfs/QmP3TpPig2St3nTwvi9TFAGdv6YTew5k4pmC1yFtaLwFFo"; 2892 | weatherToWeatherURI["Rain"] = "https://ipfs.io/ipfs/QmP3TpPig2St3nTwvi9TFAGdv6YTew5k4pmC1yFtaLwFFo"; 2893 | weatherToWeatherURI["Snow"] = "https://ipfs.io/ipfs/QmaeYdJ8EydzUGdGQGkPNkSBEQUmwRmAv2QWq1VTfsfrdk"; 2894 | weatherToWeatherURI["Atmosphere"] = "https://ipfs.io/ipfs/QmbNEeSa8pZrepYhGnnhSCmABZXymvc7YR5JKFT7TuYuYY"; 2895 | weatherToWeatherURI["Clear"] = "https://ipfs.io/ipfs/QmcKEV1xJQ3ZCyPsDPJHsuEZnF95hNZf8S3rBEvzCKwjof"; 2896 | weatherToWeatherURI["Clouds"] = "https://ipfs.io/ipfs/QmbNEeSa8pZrepYhGnnhSCmABZXymvc7YR5JKFT7TuYuYY"; 2897 | overRide = false; 2898 | overRideTokenIdToWeatherURI[0] = weatherToWeatherURI["Rain"]; 2899 | overRideTokenIdToWeatherURI[1] = weatherToWeatherURI["Clear"]; 2900 | overRideTokenIdToWeatherURI[2] = weatherToWeatherURI["Clouds"]; 2901 | overRideTokenIdToWeatherURI[3] = weatherToWeatherURI["Snow"]; 2902 | oracle = _oracle; 2903 | jobId = _jobId; 2904 | fee = _fee; 2905 | } 2906 | 2907 | function mintWeatherNFT() public onlyOwner{ 2908 | _safeMint(msg.sender, tokenCounter); 2909 | tokenCounter = tokenCounter + 1; 2910 | } 2911 | 2912 | function setOverRide(uint256 _overRide) public onlyOwner { 2913 | if (_overRide == 0){ 2914 | overRide = false; 2915 | } 2916 | if (_overRide == 1){ 2917 | overRide = true; 2918 | } 2919 | } 2920 | 2921 | function setWeatherURI(string memory weather, string memory tokenUri, uint256 tokenId) public onlyOwner { 2922 | weatherToWeatherURI[weather] = tokenUri; 2923 | overRideTokenIdToWeatherURI[tokenId] = tokenUri; 2924 | } 2925 | 2926 | function tokenURI(uint256 tokenId) public view override (ERC721) returns (string memory) { 2927 | require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); 2928 | if(overRide == true){ 2929 | return overRideTokenIdToWeatherURI[tokenId % 4]; 2930 | } 2931 | return weatherToWeatherURI[IWeatherFeed(weatherFeedAddress).weather()]; 2932 | // snow 2933 | // rain 2934 | // sun 2935 | // clouds 2936 | } 2937 | 2938 | function attemptPassword(string memory password) public returns (bytes32 requestId){ 2939 | Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfill.selector); 2940 | req.add("password", password); 2941 | requestId = sendChainlinkRequestTo(oracle, req, fee); 2942 | requestIdToAttemptee[requestId] = msg.sender; 2943 | emit attemptedPassword(requestId); 2944 | } 2945 | 2946 | function fulfill(bytes32 _requestId, uint256 _data) public recordChainlinkFulfillment(_requestId) 2947 | { 2948 | require(tokenIdTaken[0] == false, "This token is taken!"); 2949 | response = _data; 2950 | if(response == 0){ 2951 | safeTransferFrom(ownerOf(0), requestIdToAttemptee[_requestId], 1); 2952 | tokenIdTaken[0] = true; 2953 | } 2954 | if (response == 1){ 2955 | safeTransferFrom(ownerOf(1), requestIdToAttemptee[_requestId], 1); 2956 | tokenIdTaken[1] = true; 2957 | } 2958 | if (response == 2){ 2959 | safeTransferFrom(ownerOf(2), requestIdToAttemptee[_requestId], 2); 2960 | tokenIdTaken[2] = true; 2961 | } 2962 | if (response == 3){ 2963 | safeTransferFrom(ownerOf(3), requestIdToAttemptee[_requestId], 3); 2964 | tokenIdTaken[3] = true; 2965 | } 2966 | } 2967 | 2968 | function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) { 2969 | uint8 i = 0; 2970 | while(i < 32 && _bytes32[i] != 0) { 2971 | i++; 2972 | } 2973 | bytes memory bytesArray = new bytes(i); 2974 | for (i = 0; i < 32 && _bytes32[i] != 0; i++) { 2975 | bytesArray[i] = _bytes32[i]; 2976 | } 2977 | return string(bytesArray); 2978 | } 2979 | } 2980 | -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('Migrations') 2 | const { LinkToken } = require('@chainlink/contracts/truffle/v0.4/LinkToken') 3 | const { Oracle } = require('@chainlink/contracts/truffle/v0.6/Oracle') 4 | 5 | 6 | module.exports = async (deployer, network, [defaultAccount]) => { 7 | deployer.deploy(Migrations, { from: defaultAccount }) 8 | if (!network.startsWith('kovan')) { 9 | LinkToken.setProvider(deployer.provider) 10 | Oracle.setProvider(deployer.provider) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /migrations/2_deploy_weather_feed.js: -------------------------------------------------------------------------------- 1 | const WeatherFeed = artifacts.require('WeatherFeed') 2 | const { networkConfig } = require('../scripts/helper-scripts.js') 3 | 4 | module.exports = async (deployer, network, [defaultAccount]) => { 5 | // Local (development) networks need their own deployment of the LINK 6 | // token and the Oracle contract 7 | if (!network.startsWith('rinkeby')) { 8 | console.log("We can deploy stuff... but that's it!") 9 | } 10 | 11 | await deployer.deploy(WeatherFeed, 12 | networkConfig[deployer.network_id]["linkToken"], 13 | web3.utils.toHex(networkConfig[deployer.network_id]["weatherJobId"]), 14 | networkConfig[deployer.network_id]["oracle"], 15 | networkConfig[deployer.network_id]["fee"], 16 | { from: defaultAccount }) 17 | } 18 | -------------------------------------------------------------------------------- /migrations/3_deploy_weatherNFT.js: -------------------------------------------------------------------------------- 1 | const WeatherFeed = artifacts.require('WeatherFeed') 2 | const Consensus2021ChainlinkWeatherNFT = artifacts.require('Consensus2021ChainlinkWeatherNFT') 3 | const { networkConfig } = require('../scripts/helper-scripts.js') 4 | 5 | module.exports = async (deployer, network, [defaultAccount]) => { 6 | // Local (development) networks need their own deployment of the LINK 7 | // token and the Oracle contract 8 | if (!network.startsWith('rinkeby')) { 9 | console.log("We can deploy stuff... but that's it!") 10 | } 11 | weatherFeed = await WeatherFeed.deployed() 12 | tx1 = await deployer.deploy(Consensus2021ChainlinkWeatherNFT, 13 | networkConfig[deployer.network_id]["linkToken"], 14 | WeatherFeed.address, 15 | networkConfig[deployer.network_id]["oracle"], 16 | web3.utils.toHex(networkConfig[deployer.network_id]["passwordJobId"]), 17 | networkConfig[deployer.network_id]["fee"], 18 | { from: defaultAccount }) 19 | } 20 | -------------------------------------------------------------------------------- /migrations/4_mint.js: -------------------------------------------------------------------------------- 1 | const WeatherFeed = artifacts.require('WeatherFeed') 2 | const Consensus2021ChainlinkWeatherNFT = artifacts.require('Consensus2021ChainlinkWeatherNFT') 3 | const { networkConfig } = require('../scripts/helper-scripts.js') 4 | 5 | module.exports = async (deployer, network, [defaultAccount]) => { 6 | // Local (development) networks need their own deployment of the LINK 7 | // token and the Oracle contract 8 | if (!network.startsWith('rinkeby')) { 9 | console.log("We can deploy stuff... but that's it!") 10 | } 11 | weatherNFT = await Consensus2021ChainlinkWeatherNFT.deployed() 12 | await weatherNFT.mintWeatherNFT({ from: defaultAccount }) 13 | await weatherNFT.mintWeatherNFT({ from: defaultAccount }) 14 | await weatherNFT.mintWeatherNFT({ from: defaultAccount }) 15 | await weatherNFT.mintWeatherNFT({ from: defaultAccount }) 16 | await weatherNFT.approve(networkConfig[deployer.network_id]["oracle"], 0, { from: defaultAccount }) 17 | await weatherNFT.approve(networkConfig[deployer.network_id]["oracle"], 1, { from: defaultAccount }) 18 | await weatherNFT.approve(networkConfig[deployer.network_id]["oracle"], 2, { from: defaultAccount }) 19 | await weatherNFT.approve(networkConfig[deployer.network_id]["oracle"], 3, { from: defaultAccount }) 20 | console.log("View your NFTs on Opensea!") 21 | console.log("https://opensea.io/assets/matic/" + weatherNFT.address + "/0") 22 | } 23 | -------------------------------------------------------------------------------- /migrations/5_fund.js: -------------------------------------------------------------------------------- 1 | const WeatherFeed = artifacts.require('WeatherFeed') 2 | const Consensus2021ChainlinkWeatherNFT = artifacts.require('Consensus2021ChainlinkWeatherNFT') 3 | const LinkTokenInterface = artifacts.require('LinkTokenInterface') 4 | const { networkConfig } = require('../scripts/helper-scripts.js') 5 | 6 | module.exports = async (deployer, network, [defaultAccount]) => { 7 | let amount = networkConfig[deployer.network_id]["fundAmount"] 8 | const weatherFeed = await WeatherFeed.deployed() 9 | const weatherNFT = await Consensus2021ChainlinkWeatherNFT.deployed() 10 | if (deployer.network_id != 4447) { 11 | const tokenAddress = networkConfig[deployer.network_id]["linkToken"] 12 | const token = await LinkTokenInterface.at(tokenAddress) 13 | console.log('Funding contract:', weatherFeed.address) 14 | let tx = await token.transfer(weatherFeed.address, amount, { from: defaultAccount }) 15 | console.log(tx.tx) 16 | console.log('Funding contract:', weatherNFT.address) 17 | let tx2 = await token.transfer(weatherNFT.address, amount, { from: defaultAccount }) 18 | console.log(tx2.tx) 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /migrations/6_get_weather.js: -------------------------------------------------------------------------------- 1 | const WeatherFeed = artifacts.require('WeatherFeed') 2 | const LinkTokenInterface = artifacts.require('LinkTokenInterface') 3 | const { networkConfig } = require('../scripts/helper-scripts.js') 4 | 5 | module.exports = async (deployer, network, [defaultAccount]) => { 6 | const weatherFeed = await WeatherFeed.deployed() 7 | const tx = await weatherFeed.getWeather() 8 | console.log('Got weather!', tx) 9 | } 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@chainlink/box", 3 | "version": "0.6.0", 4 | "description": "A Chainlink example in a Truffle box", 5 | "scripts": { 6 | "compile": "npx truffle compile", 7 | "console:dev": "npx truffle console --network cldev", 8 | "console:kovan": "npx truffle console --network kovan", 9 | "depcheck": "echo '@chainlink/box' && depcheck --ignore-dirs=build/contracts || true", 10 | "solhint": "solhint ./contracts/**/*.sol", 11 | "lint": "yarn solhint", 12 | "migrate:dev": "npx truffle migrate --reset --network cldev", 13 | "migrate:kovan": "npx truffle migrate --network kovan", 14 | "test": "npx truffle test" 15 | }, 16 | "license": "MIT", 17 | "dependencies": { 18 | "@chainlink/contracts": "^0.1.7", 19 | "@openzeppelin/contracts": "^3.4.0", 20 | "@truffle/hdwallet-provider": "^1.0.40", 21 | "dotenv": "^8.2.0", 22 | "truffle-plugin-verify": "^0.5.8" 23 | }, 24 | "devDependencies": { 25 | "@chainlink/belt": "^0.0.3", 26 | "@chainlink/test-helpers": "0.0.5", 27 | "@openzeppelin/test-helpers": "^0.5.10", 28 | "chai": "^4.3.0", 29 | "depcheck": "^1.3.1", 30 | "solhint": "^3.3.2", 31 | "truffle": "^5.3.1" 32 | }, 33 | "resolutions": { 34 | "**/minimist": "^0.2.1", 35 | "**/node-fetch": "^2.6.1", 36 | "**/yargs-parser": "^13.1.2", 37 | "**/mem": "^4.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /scripts/attempt-password.js: -------------------------------------------------------------------------------- 1 | // truffle console --network matic 2 | // const weatherNFT = await WeatherNFT.deployed() 3 | // await weatherNFT.attemptPassword("FreeBe") 4 | // Make sure it has some link ;) 5 | 6 | // Use the console! 7 | -------------------------------------------------------------------------------- /scripts/helper-scripts.js: -------------------------------------------------------------------------------- 1 | // const MyContract = artifacts.require('MyContract') 2 | const LinkTokenInterface = artifacts.require('LinkTokenInterface') 3 | 4 | // const linkIpfsImageURIs = { 5 | // "rain": "", 6 | // "sun": "", 7 | // "snow": "", 8 | // "cloud": "" 9 | // } 10 | 11 | // const linkIpfsTokenURI = { 12 | // "rain": "", 13 | // "sun": "", 14 | // "snow": "", 15 | // "cloud": "" 16 | // } 17 | 18 | const payment = process.env.TRUFFLE_CL_BOX_PAYMENT || '1000000000000000000' 19 | 20 | const fundContract = async (contractAddress, linkTokenAddress) => { 21 | const token = await LinkTokenInterface.at(linkTokenAddress) 22 | console.log('Funding contract:', contractAddress) 23 | const tx = await token.transfer(contractAddress, payment) 24 | } 25 | 26 | const networkConfig = { 27 | default: { 28 | name: 'ganache', 29 | linkToken: '0xa36085F69e2889c224210F603D836748e7dC0088', 30 | ethUsdPriceFeed: '0x9326BFA02ADD2366b30bacB125260Af641031331', 31 | keyHash: '0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4', 32 | vrfCoordinator: '0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9', 33 | oracle: '0xAA1DC356dc4B18f30C347798FD5379F3D77ABC5b', 34 | weatherJobId: '235f8b1eeb364efc83c26d0bef2d0c01', 35 | passwordJobId: '7dba1883480744b3a3a619aeb65b5d1f', 36 | fee: '100000000000000000', 37 | fundAmount: '400000000000000000', 38 | }, 39 | 4447: { 40 | name: 'ganache', 41 | linkToken: '0xa36085F69e2889c224210F603D836748e7dC0088', 42 | ethUsdPriceFeed: '0x9326BFA02ADD2366b30bacB125260Af641031331', 43 | keyHash: '0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4', 44 | vrfCoordinator: '0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9', 45 | oracle: '0xAA1DC356dc4B18f30C347798FD5379F3D77ABC5b', 46 | weatherJobId: '235f8b1eeb364efc83c26d0bef2d0c01', 47 | passwordJobId: '7dba1883480744b3a3a619aeb65b5d1f', 48 | fee: '100000000000000000', 49 | fundAmount: '400000000000000000', 50 | }, 51 | 31337: { 52 | name: 'localhost', 53 | fee: '100000000000000000', 54 | fundAmount: '400000000000000000', 55 | keyHash: '0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4', 56 | jobId: '29fa9aa13bf1468788b7cc4a500a45b8' 57 | }, 58 | 42: { 59 | name: 'kovan', 60 | linkToken: '0xa36085F69e2889c224210F603D836748e7dC0088', 61 | ethUsdPriceFeed: '0x9326BFA02ADD2366b30bacB125260Af641031331', 62 | keyHash: '0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4', 63 | vrfCoordinator: '0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9', 64 | oracle: '0xAA1DC356dc4B18f30C347798FD5379F3D77ABC5b', 65 | chainlinkNode: '0x1d1379d146a0Dc966BEb6042720ee018E70eeC72', 66 | weatherJobId: '57682b003f754195b60292006f1c3206', 67 | passwordJobId: '7dba1883480744b3a3a619aeb65b5d1f', 68 | fee: '100000000000000000', 69 | fundAmount: '400000000000000000', 70 | }, 71 | 4: { 72 | name: 'rinkeby', 73 | linkToken: '0x01be23585060835e02b77ef475b0cc51aa1e0709', 74 | ethUsdPriceFeed: '0x8A753747A1Fa494EC906cE90E9f37563A8AF630e', 75 | keyHash: '0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311', 76 | vrfCoordinator: '0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B', 77 | oracle: '0x8927c312d29d1bbef7bde10e8e9a2fa257efe8c7', 78 | weatherJobId: 'd8c92142857640a891b9434c72eed1e2', 79 | fee: '10000000000000000', 80 | fundAmount: '400000000000000000', 81 | // TODO - not done VVV 82 | passwordJobId: 'd8c92142857640a891b9434c72eed1e2', 83 | }, 84 | 1: { 85 | name: 'mainnet', 86 | linkToken: '0x514910771af9ca656af840dff83e8264ecf986ca' 87 | }, 88 | 5: { 89 | name: 'goerli', 90 | linkToken: '0x326c977e6efc84e512bb9c30f76e30c160ed06fb' 91 | }, 92 | 137: { 93 | name: 'matic', 94 | linkToken: '0xb0897686c545045afc77cf20ec7a532e3120e0f1', 95 | oracle: '0xce0bbe138dfd3a77bfafb5e4f71364c375d1726a', // Alpha Chain Matic 96 | weatherJobId: 'b577b21e91154a36bd216a8762e4bd76', 97 | passwordJobId: 'b210d5e836bb4c5faa6de7aa88c9be2c', 98 | fee: '10000000000000000', 99 | fundAmount: '40000000000000000' 100 | 101 | }, 102 | 80001: { 103 | name: 'mumbai', 104 | linkToken: '0xb0897686c545045afc77cf20ec7a532e3120e0f1', 105 | oracle: '', 106 | weatherJobId: '74873d17a942416586f812080c72fcdc', 107 | passwordJobId: '', 108 | fee: 10000000000000000, 109 | fundAmount: 40000000000000000, 110 | 111 | } 112 | } 113 | 114 | module.exports = { 115 | networkConfig, 116 | fundContract 117 | } 118 | -------------------------------------------------------------------------------- /scripts/read-weather.js: -------------------------------------------------------------------------------- 1 | const WeatherFeed = artifacts.require('WeatherFeed') 2 | const Consensus2021ChainlinkWeatherNFT = artifacts.require('Consensus2021ChainlinkWeatherNFT') 3 | 4 | module.exports = async (deployer, network, [defaultAccount]) => { 5 | // Local (development) networks need their own deployment of the LINK 6 | // token and the Oracle contract 7 | if (!network.startsWith('rinkeby')) { 8 | console.log("We can deploy stuff... but that's it!") 9 | } 10 | const weatherNFT = await Consensus2021ChainlinkWeatherNFT.deployed() 11 | const weatherFeed = await WeatherFeed.deployed() 12 | console.log(await weatherFeed.weather()) 13 | console.log(await weatherNFT.tokenURI(0)) 14 | } 15 | -------------------------------------------------------------------------------- /scripts/request-weather.js: -------------------------------------------------------------------------------- 1 | const WeatherFeed = artifacts.require('WeatherFeed') 2 | 3 | module.exports = async callback => { 4 | if (!network.startsWith('rinkeby')) { 5 | console.log("We can deploy stuff... but that's it!") 6 | } 7 | console.log("Requesting...") 8 | const weatherFeed = await WeatherFeed.deployed() 9 | const tx = await weatherFeed.getWeather() 10 | callback(tx.tx) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /test/weatherTest.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | const { oracle } = require('@chainlink/test-helpers') 3 | const { expectRevert, time } = require('@openzeppelin/test-helpers') 4 | const { networkConfig } = require('../scripts/helper-scripts.js') 5 | 6 | contract('MyContract', accounts => { 7 | const { LinkToken } = require('@chainlink/contracts/truffle/v0.4/LinkToken') 8 | const WeatherNFT = artifacts.require('WeatherNFT') 9 | const MockOracle = artifacts.require('MockOracle') 10 | 11 | 12 | const defaultAccount = accounts[0] 13 | const oracleNode = accounts[1] 14 | const stranger = accounts[2] 15 | 16 | // These parameters are used to validate the data was received 17 | // on the deployed oracle contract. The Job ID only represents 18 | // the type of data, but will not work on a public testnet. 19 | // For the latest JobIDs, visit a node listing service like: 20 | // https://market.link/ 21 | const jobId = web3.utils.toHex('4c7b7ffb66b344fbaa64995af81e355a') 22 | 23 | // Represents 1 LINK for testnet requests 24 | const payment = web3.utils.toWei('1') 25 | 26 | let linkToken, mockOracle, weatherNFT 27 | 28 | beforeEach(async () => { 29 | linkToken = await LinkToken.new({ from: defaultAccount }) 30 | mockOracle = await MockOracle.new(linkToken.address, { from: defaultAccount }) 31 | const jobId = web3.utils.toHex('4c7b7ffb66b344fbaa64995af81e355a') 32 | weatherNFT = await WeatherNFT.new(linkToken.address, linkToken.address, mockOracle.address, jobId, '1000000000000000000', { from: defaultAccount }) 33 | await weatherNFT.mintWeatherNFT({ from: defaultAccount }) 34 | }) 35 | 36 | describe('#canTransferFromOracle', () => { 37 | context('runs the full suite of sending the NFT to a new user', () => { 38 | it('triggers a log event in the new Oracle contract', async () => { 39 | owner_add = await weatherNFT.ownerOf(0) 40 | const tx1 = await weatherNFT.approve(oracleNode, 0, { from: defaultAccount }) 41 | await linkToken.transfer(weatherNFT.address, '2000000000000000000', { from: defaultAccount }) 42 | const transaction = await weatherNFT.attemptPassword("FreeBe", { from: stranger }) 43 | let requestId = await mockOracle.bigRequestId() 44 | const expected = "0" 45 | const returnData = web3.utils.padLeft(web3.utils.padLeft(web3.utils.toHex(expected)), 64) 46 | const tx = await mockOracle.fulfillOracleRequest(requestId, returnData) 47 | let ownerOfZero = await weatherNFT.ownerOf(0) 48 | assert.equal(ownerOfZero == stranger) 49 | }) 50 | }) 51 | }) 52 | }) 53 | -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | const HDWalletProvider = require('@truffle/hdwallet-provider') 2 | require('dotenv').config() 3 | 4 | // const mnemonic = process.env.MNEMONIC 5 | const private_key = process.env.PRIVATE_KEY 6 | const rinkeby_url = process.env.RINKEBY_RPC_URL 7 | const kovan_url = process.env.KOVAN_RPC_URL 8 | 9 | const matic_url = process.env.MATIC_RPC_URL 10 | 11 | 12 | module.exports = { 13 | networks: { 14 | binance_testnet: { 15 | provider: () => new HDWalletProvider(private_key, 'https://data-seed-prebsc-1-s1.binance.org:8545'), 16 | network_id: 97, 17 | confirmations: 10, 18 | timeoutBlocks: 200, 19 | skipDryRun: true 20 | }, 21 | kovan: { 22 | provider: () => { 23 | return new HDWalletProvider(private_key, kovan_url) 24 | }, 25 | network_id: '42', 26 | skipDryRun: true 27 | }, 28 | rinkeby: { 29 | provider: () => { 30 | return new HDWalletProvider(private_key, rinkeby_url) 31 | }, 32 | network_id: '4', 33 | skipDryRun: true 34 | }, 35 | matic: { 36 | provider: () => { 37 | return new HDWalletProvider(private_key, matic_url) 38 | }, 39 | network_id: '137', 40 | skipDryRun: true 41 | }, 42 | mumbai: { 43 | provider: () => { 44 | return new HDWalletProvider(private_key, 'https://matic-mumbai.chainstacklabs.com') 45 | }, 46 | network_id: '80001', 47 | skipDryRun: true 48 | }, 49 | }, 50 | compilers: { 51 | solc: { 52 | version: '0.6.6', 53 | }, 54 | }, 55 | api_keys: { 56 | etherscan: process.env.ETHERSCAN_API_KEY 57 | }, 58 | plugins: [ 59 | 'truffle-plugin-verify' 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /weather-ipfs/img/cloud-chainlink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickAlphaC/weather-nft/e014d0944e9f49653ab92372b89be075df619d60/weather-ipfs/img/cloud-chainlink.gif -------------------------------------------------------------------------------- /weather-ipfs/img/rain-chainlink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickAlphaC/weather-nft/e014d0944e9f49653ab92372b89be075df619d60/weather-ipfs/img/rain-chainlink.gif -------------------------------------------------------------------------------- /weather-ipfs/img/snow-chainlink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickAlphaC/weather-nft/e014d0944e9f49653ab92372b89be075df619d60/weather-ipfs/img/snow-chainlink.gif -------------------------------------------------------------------------------- /weather-ipfs/img/sun-chainlink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickAlphaC/weather-nft/e014d0944e9f49653ab92372b89be075df619d60/weather-ipfs/img/sun-chainlink.gif -------------------------------------------------------------------------------- /weather-ipfs/metadata/cloud-chainlink.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Cloud Chainlink", 3 | "description": "Tut tut, it looks like Rain!", 4 | "image": "https://ipfs.io/ipfs/QmUXxMue7AazMGjLKjU7SrYRU7c9va3dRq19ui39KnvwpL?filename=cloud-chainlink.gif" 5 | } 6 | -------------------------------------------------------------------------------- /weather-ipfs/metadata/rain-chainlink.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Rain Chainlink", 3 | "description": "April showers bring May flowers. ", 4 | "image": "https://ipfs.io/ipfs/QmY1J24amQ55PfVtRQZuwUCaGbWogFrPsUSteX4SLyb9LE?filename=rain-chainlink.gif" 5 | } 6 | -------------------------------------------------------------------------------- /weather-ipfs/metadata/snow-chainlink.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Snow Chainlink", 3 | "description": "It's the most wonderful time of the year. ", 4 | "image": "https://ipfs.io/ipfs/QmRsy9F5FLdAGtHo1JzfXGfSqkzT5Sh2DTY5BENYgseVZP?filename=snow-chainlink.gif" 5 | } 6 | -------------------------------------------------------------------------------- /weather-ipfs/metadata/sun-chainlink.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Sun Chainlink", 3 | "description": "I'm walking on Sunshine. ", 4 | "image": "https://ipfs.io/ipfs/QmSXAbW5kqn2Ywt5DL3hW5MsjeKJH9rLeLkQs3bRuyTxq1?filename=sun-chainlink.gif" 5 | } 6 | --------------------------------------------------------------------------------