├── .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 |
7 |
8 |
9 |
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 |
--------------------------------------------------------------------------------