Skip to content

Commit 1c8fafd

Browse files
authored
feat: upgrade chainlink v2.5 for basic/15-nft-blindbox-chainlink-vr (#1171)
* upgrade ethers.js v6 12-token-crowdfund * update: upgrade chainlink v2.5 * feat: Added contract call for transferring token only by 80-chainlink-ccip * fix: update readme * Add contracts and scripts that generate NFT
1 parent 4801a4d commit 1c8fafd

File tree

8 files changed

+286
-199
lines changed

8 files changed

+286
-199
lines changed

basic/15-nft-blindbox-chainlink-vrf/README-CN.md

+14
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ npm install
1919
Node版本:v20.11.0
2020
```
2121

22+
### 生成随机数
23+
2224
- 创建 ChainLink SubscriptionID
2325
登陆 [ChainLink VRF 测试网](https://vrf.chain.link/?_ga=2.225785050.1950508783.1645630272-1230768383.1643005305) , 点击 "Create Subscription" 创建 SubscriptionID , 之后可以在 "My Subscriptions" 中看到创建的 SubscriptionID
2426
<center><img src="./imgs/CreateSubscription.png?raw=true" /></center>
@@ -81,6 +83,18 @@ RandomWords 随机数生成之后,通过合约传入。./scripts/deployment.js
8183
<center><img src="./imgs/Events.png?raw=true" /></center>
8284
<center><img src="./imgs/RequestAndResult.png?raw=true" /></center>
8385

86+
### 生成nft
87+
88+
- 部署nft721 合约
89+
```sh
90+
npx hardhat run scripts/deployDungeonsAndDragonsCharacter.js --netwrok sepolia
91+
```
92+
93+
- mint nft
94+
```sh
95+
npx hardhat run scripts/blindCharacter.js --netwrok sepolia
96+
```
97+
8498

8599
## 参考链接
86100
github 样例代码: https://github.com/PatrickAlphaC/dungeons-and-dragons-nft

basic/15-nft-blindbox-chainlink-vrf/README.md

+14
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ npm install
1919
Node Version:v20.11.0
2020
```
2121

22+
### Generate random number
23+
2224
- Create ChainLink SubscriptionID
2325
Login [ChainLink VRF Test network](https://vrf.chain.link/?_ga=2.225785050.1950508783.1645630272-1230768383.1643005305) , Click on "Create Subscription" to Create a SubscriptionID and you can see the created SubscriptionID under "My Subscriptions"
2426
<center><img src="./imgs/CreateSubscription.png?raw=true" /></center>
@@ -79,6 +81,18 @@ After the random number is generated, it can be viewed in Ehterscan
7981
<center><img src="./imgs/Events.png?raw=true" /></center>
8082
<center><img src="./imgs/RequestAndResult.png?raw=true" /></center>
8183

84+
### generate NFT
85+
86+
- Sacking the NFT721 contract
87+
```sh
88+
npx hardhat run scripts/deployDungeonsAndDragonsCharacter.js --netwrok sepolia
89+
```
90+
91+
- Mint NFT
92+
```sh
93+
npx hardhat run scripts/blindCharacter.js --netwrok sepolia
94+
```
95+
8296

8397
## Refer to the link
8498
Github sample code: https://github.com/PatrickAlphaC/dungeons-and-dragons-nft

basic/15-nft-blindbox-chainlink-vrf/contracts/DungeonsAndDragonsCharacter.sol

+84-96
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,46 @@
22
// SPDX-License-Identifier: MIT
33
pragma solidity >=0.8.0;
44

5-
import "./ERC721PresetMinterPauserAutoId.sol";
6-
import "./extensions/Strings.sol";
7-
import '@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol';
8-
import '@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol';
9-
import '@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol';
10-
11-
contract DungeonsAndDragonsCharacter is ERC721PresetMinterPauserAutoId, VRFConsumerBaseV2 {
5+
import './ERC721PresetMinterPauserAutoId.sol';
6+
import './extensions/Strings.sol';
7+
// import '@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol';
8+
// import '@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol';
9+
// import '@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol';
10+
// import {VRFConsumerBaseV2Plus} from '@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol';
11+
// import {VRFV2PlusClient} from '@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol';
12+
13+
contract DungeonsAndDragonsCharacter is ERC721PresetMinterPauserAutoId {
1214
using Strings for string;
1315

14-
event FulfillRandomness(uint256,uint256[]);
15-
event RequestId(address,uint256);
16+
// event FulfillRandomness(uint256, uint256[]);
17+
// event RequestId(address, uint256);
18+
19+
// struct RequestStatus {
20+
// bool fulfilled; // whether the request has been successfully fulfilled
21+
// bool exists; // whether a requestId exists
22+
// uint256[] randomWords;
23+
// }
24+
25+
// mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */
1626

17-
VRFCoordinatorV2Interface COORDINATOR;
18-
LinkTokenInterface LINKTOKEN;
27+
// VRFCoordinatorV2Interface COORDINATOR;
28+
// LinkTokenInterface LINKTOKEN;
1929

2030
// Your subscription ID.
21-
uint64 s_subscriptionId;
31+
// uint256 s_subscriptionId;
2232

23-
// Goerli coordinator. For other networks,
33+
// sepolia coordinator. For other networks,
2434
// see https://docs.chain.link/docs/vrf-contracts/#configurations
25-
address vrfCoordinator = 0x2Ca8E0C643bDe4C2E08ab1fA0da3401AdAD7734D;
35+
// address vrfCoordinator = 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B;
2636

27-
// Goerli LINK token contract. For other networks,
37+
// sepolia LINK token contract. For other networks,
2838
// see https://docs.chain.link/docs/vrf-contracts/#configurations
29-
address link = 0x326C977E6efc84E512bB9C30f76E30c160eD06FB;
39+
// address link = 0x779877A7B0D9E8603169DdbD7836e478b4624789;
3040

3141
// The gas lane to use, which specifies the maximum gas price to bump to.
3242
// For a list of available gas lanes on each network,
3343
// see https://docs.chain.link/docs/vrf-contracts/#configurations
34-
bytes32 keyHash = 0x79d3d8832d904592c0bf9818b621522c988bb8b0c05cdc3b15aea1b6e8db0c15;
44+
// bytes32 keyHash = 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae;
3545

3646
// Depends on the number of requested values that you want sent to the
3747
// fulfillRandomWords() function. Storing each word costs about 20,000 gas,
@@ -64,74 +74,56 @@ contract DungeonsAndDragonsCharacter is ERC721PresetMinterPauserAutoId, VRFConsu
6474

6575
Character[] public characters;
6676

67-
mapping(uint256 => string) requestToCharacterName;
68-
mapping(uint256 => address) requestToSender;
69-
mapping(uint256 => uint256) requestToRandnum;
70-
71-
constructor(uint64 subscriptionId,string memory tokenURI)
72-
public
73-
VRFConsumerBaseV2(vrfCoordinator)
74-
ERC721PresetMinterPauserAutoId("DungeonsAndDragonsCharacter", "D&D",tokenURI)
75-
{
76-
COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
77-
LINKTOKEN = LinkTokenInterface(link);
78-
s_subscriptionId = subscriptionId;
79-
}
80-
81-
function requestNewRandomCharacter(
82-
string memory name
83-
) public returns (uint256) {
84-
// Will revert if subscription is not set and funded.
85-
uint256 requestId = COORDINATOR.requestRandomWords(keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords);
86-
emit RequestId(msg.sender,requestId);
87-
88-
requestToCharacterName[requestId] = name;
89-
requestToSender[requestId] = msg.sender;
90-
return requestId;
91-
}
77+
// mapping(uint256 => string) requestToCharacterName;
78+
// mapping(uint256 => address) requestToSender;
79+
// mapping(uint256 => uint256) requestToRandnum;
80+
81+
constructor(string memory tokenURI, string memory _name) public ERC721PresetMinterPauserAutoId(_name, 'D&D', tokenURI) {}
82+
83+
// @param enableNativePayment: Set to `true` to enable payment in native tokens, or
84+
// `false` to pay in LINK
85+
// function requestNewRandomCharacter(string memory name, bool enableNativePayment) public returns (uint256) {
86+
// // Will revert if subscription is not set and funded.
87+
// // uint256 requestId = s_vrfCoordinator.requestRandomWords(keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords);
88+
// uint256 requestId = s_vrfCoordinator.requestRandomWords(
89+
// VRFV2PlusClient.RandomWordsRequest({
90+
// keyHash: keyHash,
91+
// subId: s_subscriptionId,
92+
// requestConfirmations: requestConfirmations,
93+
// callbackGasLimit: callbackGasLimit,
94+
// numWords: numWords,
95+
// extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: enableNativePayment}))
96+
// })
97+
// );
98+
// requestToCharacterName[requestId] = name;
99+
// requestToSender[requestId] = msg.sender;
100+
// emit RequestId(msg.sender, requestId);
101+
// return requestId;
102+
// }
92103

93104
function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
94-
require(
95-
_isApprovedOrOwner(_msgSender(), tokenId),
96-
"ERC721: transfer caller is not owner nor approved"
97-
);
105+
require(_isApprovedOrOwner(_msgSender(), tokenId), 'ERC721: transfer caller is not owner nor approved');
98106
_setTokenURI(tokenId, _tokenURI);
99107
}
100108

101-
function fulfillRandomWords(
102-
uint256 requestId, /* requestId */
103-
uint256[] memory randomWords)
104-
internal override
105-
{
106-
requestToRandnum[requestId] = randomWords[0];
109+
// function fulfillRandomWords(uint256 _requestId /* requestId */, uint256[] calldata _randomWords) internal override {
110+
// requestToRandnum[_requestId] = _randomWords[0];
111+
// emit FulfillRandomness(_requestId, _randomWords);
112+
// }
107113

108-
emit FulfillRandomness(requestId,randomWords);
109-
}
110-
111-
function blindCharacter(uint256 requestId) public {
112-
uint256 randomNum = requestToRandnum[requestId];
114+
function blindCharacter(uint256 _randomNum, address _requestToSender, string memory _name) public {
113115
uint256 newId = characters.length;
116+
uint256 randomNum = _randomNum;
114117
uint256 strength = (randomNum % 100);
115-
uint256 dexterity = ((randomNum % 10000) / 100 );
116-
uint256 constitution = ((randomNum % 1000000) / 10000 );
117-
uint256 intelligence = ((randomNum % 100000000) / 1000000 );
118-
uint256 wisdom = ((randomNum % 10000000000) / 100000000 );
118+
uint256 dexterity = ((randomNum % 10000) / 100);
119+
uint256 constitution = ((randomNum % 1000000) / 10000);
120+
uint256 intelligence = ((randomNum % 100000000) / 1000000);
121+
uint256 wisdom = ((randomNum % 10000000000) / 100000000);
119122
uint256 charisma = ((randomNum % 1000000000000) / 10000000000);
120123
uint256 experience = 0;
121124

122-
characters.push(
123-
Character(
124-
strength,
125-
dexterity,
126-
constitution,
127-
intelligence,
128-
wisdom,
129-
charisma,
130-
experience,
131-
requestToCharacterName[requestId]
132-
)
133-
);
134-
_safeMint(requestToSender[requestId], newId);
125+
characters.push(Character(strength, dexterity, constitution, intelligence, wisdom, charisma, experience, _name));
126+
_safeMint(_requestToSender, newId);
135127
}
136128

137129
function getLevel(uint256 tokenId) public view returns (uint256) {
@@ -142,21 +134,17 @@ contract DungeonsAndDragonsCharacter is ERC721PresetMinterPauserAutoId, VRFConsu
142134
return characters.length;
143135
}
144136

145-
function getCharacterOverView(uint256 tokenId)
146-
public
147-
view
148-
returns (
149-
string memory,
150-
uint256,
151-
uint256,
152-
uint256
153-
)
154-
{
137+
function getCharacterOverView(uint256 tokenId) public view returns (string memory, uint256, uint256, uint256) {
155138
return (
156-
characters[tokenId].name,
157-
characters[tokenId].strength + characters[tokenId].dexterity + characters[tokenId].constitution + characters[tokenId].intelligence + characters[tokenId].wisdom + characters[tokenId].charisma,
158-
getLevel(tokenId),
159-
characters[tokenId].experience
139+
characters[tokenId].name,
140+
characters[tokenId].strength +
141+
characters[tokenId].dexterity +
142+
characters[tokenId].constitution +
143+
characters[tokenId].intelligence +
144+
characters[tokenId].wisdom +
145+
characters[tokenId].charisma,
146+
getLevel(tokenId),
147+
characters[tokenId].experience
160148
);
161149
}
162150

@@ -169,12 +157,12 @@ contract DungeonsAndDragonsCharacter is ERC721PresetMinterPauserAutoId, VRFConsu
169157
}
170158
}
171159

172-
// expand to more random
173-
// function expand(uint256 randomValue, uint256 n) public pure returns (uint256[] memory expandedValues) {
174-
// expandedValues = new uint256[](n);
175-
// for (uint256 i = 0; i < n; i++) {
176-
// expandedValues[i] = uint256(keccak256(abi.encode(randomValue, i)));
177-
// }
178-
// return expandedValues;
179-
// }
160+
// expand to more random
161+
// function expand(uint256 randomValue, uint256 n) public pure returns (uint256[] memory expandedValues) {
162+
// expandedValues = new uint256[](n);
163+
// for (uint256 i = 0; i < n; i++) {
164+
// expandedValues[i] = uint256(keccak256(abi.encode(randomValue, i)));
165+
// }
166+
// return expandedValues;
167+
// }
180168
}

0 commit comments

Comments
 (0)