Skip to content

Commit f0b8c2c

Browse files
committed
fix test code
1 parent 0b37d09 commit f0b8c2c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2734
-406
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
PRIVATE_KEY=xxxxxxxxxxxxxxxx
22
INFURA_ID=yyyyyyyy
3-
RandomNumberConsumer_ADDRESS=cccccccc
43
SubscriptionId=ddddd

basic/14-chainlink-price-feed/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ node_modules
33
#Hardhat files
44
cache
55
artifacts
6+
7+
# contract address
8+
scripts/deployment.json

basic/14-chainlink-price-feed/README.md

+3-10
Original file line numberDiff line numberDiff line change
@@ -93,24 +93,17 @@ SubscriptionId=ddddd
9393
npx hardhat run scripts/02-RandomNumberConsumerDeploy.js --network rinkeby
9494
```
9595

96-
4. 将打印出来的合约部署地址,添加到 .env 文件中,运行测试脚本
97-
98-
```js
99-
// .env
100-
RandomNumberConsumer_ADDRESS=xxxx; // <--- you need fill this
101-
```
102-
103-
5. 获取 ChainLink 币
96+
4. 获取 ChainLink 币
10497
登陆 [ChainLink Faucet](https://faucets.chain.link/) , 在, 获取 ChainLink 币用于后续的 RandomNumberConsume , 其中 Network 选择 rinkeby, "Testnet account address" 输入合约 owner 的账户地址
10598
<center><img src="https://github.com/Dapp-Learning-DAO/Dapp-Learning-Arsenal/blob/main/images/basic/14-chainlink-price-feed/ChainLinkFaucet.png?raw=true" /></center>
10699

107100

108-
6. 赋权合约消费 ChainLink 币以进行随机数获取
101+
5. 赋权合约消费 ChainLink 币以进行随机数获取
109102
登陆 [ChainLink VRF 测试网](https://vrf.chain.link/?_ga=2.225785050.1950508783.1645630272-1230768383.1643005305) , 点击其中的 SubscriptionID
110103
<center><img src="https://github.com/Dapp-Learning-DAO/Dapp-Learning-Arsenal/blob/main/images/basic/14-chainlink-price-feed/ClickSubscriptionID.png?raw=true" /></center>
111104

112105

113-
之后在新出现的页面中, 进行 "Add Funds" 和 "Add consumer". 其中 "Add Funds" 为存入 ChainLink 币的数量, "Add consumer" 需要填入部署成功的 RandomNumberConsumer 合约地址, 即为 .env 文件中 RandomNumberConsumer_ADDRESS 的值
106+
之后在新出现的页面中, 进行 "Add Funds" 和 "Add consumer". 其中 "Add Funds" 为存入 ChainLink 币的数量, "Add consumer" 需要填入部署成功的 RandomNumberConsumer 合约地址, 即为步骤 3中打印出来的合约地址
114107
<center><img src="https://github.com/Dapp-Learning-DAO/Dapp-Learning-Arsenal/blob/main/images/basic/14-chainlink-price-feed/AddFundsAddCustomer.png?raw=true" /></center>
115108

116109

basic/14-chainlink-price-feed/hardhat.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ module.exports = {
6565
]
6666
},
6767
etherscan: {
68-
apiKey: "HT789QWQ9RXQQ86K3HP4EAVTEWYVKKPPJ9"
68+
apiKey: "1234"
6969
},
7070
mocha: {
7171
timeout: 6000000000000000

basic/14-chainlink-price-feed/scripts/01-PriceConsumerV3Deploy.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const hre = require("hardhat");
2-
require("@nomiclabs/hardhat-web3")
2+
require("@nomiclabs/hardhat-web3");
33

44
async function main() {
55

basic/14-chainlink-price-feed/scripts/02-RandomNumberConsumerDeploy.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
const hre = require('hardhat');
22
require('@nomiclabs/hardhat-web3');
33
require('dotenv').config();
4+
const { saveDeployment } = require('./utils');
5+
46

57
async function main() {
68
const [deployer] = await ethers.getSigners();
@@ -14,9 +16,11 @@ async function main() {
1416

1517
console.log('----------------------------------------------------');
1618
console.log('RandomNumberConsumer address:', instance.address);
17-
console.log('Now you need transfer Link token to this contract address.')
18-
console.log('Then add address to .env file, and run the test script file.')
1919

20+
// save contract address to file
21+
saveDeployment({
22+
RandomNumberConsumerAddress: instance.address,
23+
});
2024
}
2125

2226
// We recommend this pattern to be able to use async/await everywhere

basic/14-chainlink-price-feed/scripts/03-RandomNumberConsumer.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ const hre = require('hardhat');
22
require('@nomiclabs/hardhat-web3');
33
const { BigNumber } = require('ethers');
44
require('dotenv').config();
5+
const { readDeployment } = require('./utils');
56

67
async function main() {
78
const provider = new ethers.providers.WebSocketProvider(`wss://rinkeby.infura.io/ws/v3/${process.env.INFURA_ID}`);
89
const { abi: RandomNumberConsumerABI } = require('../artifacts/contracts/RandomNumberConsumer.sol/RandomNumberConsumer.json');
910

10-
const addr = process.env.RandomNumberConsumer_ADDRESS; // <--- you need fill it in .env file
11+
const deployment = readDeployment();
12+
const addr = deployment.RandomNumberConsumerAddress;
13+
1114
if (!addr) {
12-
console.log('Please set the contract address in .env file.');
15+
console.log('Please deploy contract RandomNumberConsumer first');
1316
return;
1417
}
1518

@@ -66,7 +69,7 @@ async function main() {
6669
// wait for the result event
6770
for (let i = 0; i < 500; i++) {
6871
if (random0Res) break;
69-
console.log("Please be patient, it will take sometime to get the result")
72+
console.log(`${i}: Please be patient, it will take a little long time to get the result`)
7073
await new Promise((resolve) => {
7174
setTimeout(() => {
7275
resolve();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// read and save redpacket contract deployment json file
2+
const path = require('path');
3+
const fs = require('fs');
4+
5+
const DEPLOYMENGT_DIR = path.join(__dirname, '/deployment.json');
6+
7+
/*
8+
* deployment:
9+
* redPacketAddress
10+
* redPacketOwner
11+
* redPacketID
12+
* simpleTokenAddress
13+
*/
14+
function readDeployment() {
15+
if (!fs.existsSync(DEPLOYMENGT_DIR)) return null;
16+
try {
17+
return JSON.parse(fs.readFileSync(DEPLOYMENGT_DIR, { encoding: 'utf-8' }));
18+
} catch {
19+
return null;
20+
}
21+
}
22+
23+
function saveDeployment(payload) {
24+
let oldData = readDeployment();
25+
if (!oldData) oldData = {};
26+
fs.writeFileSync(
27+
DEPLOYMENGT_DIR,
28+
JSON.stringify({
29+
...oldData,
30+
...payload,
31+
}),
32+
{ flag: 'w+' }
33+
);
34+
return true;
35+
}
36+
37+
module.exports = {
38+
readDeployment,
39+
saveDeployment,
40+
};
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
PRIVATE_KEY=xxxxxxxxxxxxxxxx
2-
INFURA_ID=yyyyyyyy
2+
INFURA_ID=yyyyyyyy
3+
SubscriptionId=ddddd

basic/15-nft-blindbox-chainlink-vrf/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ node_modules
33
#Hardhat files
44
cache
55
artifacts
6+
7+
# contract address
8+
scripts/deployment.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
// contracts/DungeonsAndDragonsCharacter.sol
2+
// SPDX-License-Identifier: MIT
3+
pragma solidity >=0.8.0;
4+
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 {
12+
using Strings for string;
13+
14+
event FulfillRandomness(uint256,uint256[]);
15+
event RequestId(address,uint256);
16+
17+
VRFCoordinatorV2Interface COORDINATOR;
18+
LinkTokenInterface LINKTOKEN;
19+
20+
// Your subscription ID.
21+
uint64 s_subscriptionId;
22+
23+
// Rinkeby coordinator. For other networks,
24+
// see https://docs.chain.link/docs/vrf-contracts/#configurations
25+
address vrfCoordinator = 0x6168499c0cFfCaCD319c818142124B7A15E857ab;
26+
27+
// Rinkeby LINK token contract. For other networks,
28+
// see https://docs.chain.link/docs/vrf-contracts/#configurations
29+
address link = 0x01BE23585060835E02B77ef475b0Cc51aA1e0709;
30+
31+
// The gas lane to use, which specifies the maximum gas price to bump to.
32+
// For a list of available gas lanes on each network,
33+
// see https://docs.chain.link/docs/vrf-contracts/#configurations
34+
bytes32 keyHash = 0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc;
35+
36+
// Depends on the number of requested values that you want sent to the
37+
// fulfillRandomWords() function. Storing each word costs about 20,000 gas,
38+
// so 100,000 is a safe default for this example contract. Test and adjust
39+
// this limit based on the network that you select, the size of the request,
40+
// and the processing of the callback request in the fulfillRandomWords()
41+
// function.
42+
uint32 callbackGasLimit = 100000;
43+
44+
// The default is 3, but you can set this higher.
45+
uint16 requestConfirmations = 3;
46+
47+
// For this example, retrieve 2 random values in one request.
48+
// Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS.
49+
uint32 numWords = 2;
50+
51+
bool public flag;
52+
uint256 public tag;
53+
54+
struct Character {
55+
uint256 strength;
56+
uint256 dexterity;
57+
uint256 constitution;
58+
uint256 intelligence;
59+
uint256 wisdom;
60+
uint256 charisma;
61+
uint256 experience;
62+
string name;
63+
}
64+
65+
Character[] public characters;
66+
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+
}
92+
93+
function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
94+
require(
95+
_isApprovedOrOwner(_msgSender(), tokenId),
96+
"ERC721: transfer caller is not owner nor approved"
97+
);
98+
_setTokenURI(tokenId, _tokenURI);
99+
}
100+
101+
function fulfillRandomWords(
102+
uint256 requestId, /* requestId */
103+
uint256[] memory randomWords)
104+
internal override
105+
{
106+
requestToRandnum[requestId] = randomWords[0];
107+
108+
emit FulfillRandomness(requestId,randomWords);
109+
}
110+
111+
function blindCharacter(uint256 requestId) public {
112+
uint256 randomNum = requestToRandnum[requestId];
113+
uint256 newId = characters.length;
114+
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 );
119+
uint256 charisma = ((randomNum % 1000000000000) / 10000000000);
120+
uint256 experience = 0;
121+
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);
135+
}
136+
137+
function getLevel(uint256 tokenId) public view returns (uint256) {
138+
return sqrt(characters[tokenId].experience);
139+
}
140+
141+
function getNumberOfCharacters() public view returns (uint256) {
142+
return characters.length;
143+
}
144+
145+
function getCharacterOverView(uint256 tokenId)
146+
public
147+
view
148+
returns (
149+
string memory,
150+
uint256,
151+
uint256,
152+
uint256
153+
)
154+
{
155+
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
160+
);
161+
}
162+
163+
function sqrt(uint256 x) internal view returns (uint256 y) {
164+
uint256 z = (x + 1) / 2;
165+
y = x;
166+
while (z < y) {
167+
y = z;
168+
z = (x / z + z) / 2;
169+
}
170+
}
171+
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+
// }
180+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.0;
4+
5+
import "./IERC165.sol";
6+
7+
/**
8+
* @dev Implementation of the {IERC165} interface.
9+
*
10+
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
11+
* for the additional interface id that will be supported. For example:
12+
*
13+
* ```solidity
14+
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
15+
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
16+
* }
17+
* ```
18+
*
19+
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
20+
*/
21+
abstract contract ERC165 is IERC165 {
22+
/**
23+
* @dev See {IERC165-supportsInterface}.
24+
*/
25+
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
26+
return interfaceId == type(IERC165).interfaceId;
27+
}
28+
}

0 commit comments

Comments
 (0)