Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(39. 链上随机数) 适配于Chainlink VRF v2.5的Random.sol #738

Open
REBOA opened this issue Jun 5, 2024 · 2 comments
Open

(39. 链上随机数) 适配于Chainlink VRF v2.5的Random.sol #738

REBOA opened this issue Jun 5, 2024 · 2 comments

Comments

@REBOA
Copy link

REBOA commented Jun 5, 2024

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import "https://github.com/AmazingAng/WTFSolidity/blob/main/34_ERC721/ERC721.sol";
import "https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";
import "https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";

contract Random is ERC721, VRFConsumerBaseV2Plus {
    // NFT related variables
    uint256 public totalSupply = 100; // Total supply
    uint256[100] public ids; // Array for available token IDs
    uint256 public mintCount; // Number of minted tokens

    // Chainlink VRF parameters
    address vrfCoordinator = 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B;
    bytes32 keyHash = 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae;
    uint16 requestConfirmations = 3;
    uint32 callbackGasLimit = 1_000_000;
    uint32 numWords = 1;
    uint256 public requestId;
    uint256 public subId;

    // Mapping to keep track of request IDs and mint addresses
    mapping(uint256 => address) public requestToSender;

    constructor(uint256 _subId) 
        VRFConsumerBaseV2Plus(vrfCoordinator)
        ERC721("WTF Random", "WTF")
    {
        subId = _subId;
    }

    function pickRandomUniqueId(uint256 random) private returns (uint256 tokenId) {
        uint256 len = totalSupply - mintCount++;
        require(len > 0, "All tokens have been minted");
        uint256 randomIndex = random % len;

        tokenId = ids[randomIndex] != 0 ? ids[randomIndex] : randomIndex;
        ids[randomIndex] = ids[len - 1] == 0 ? len - 1 : ids[len - 1];
        ids[len - 1] = 0;
    }

    function getRandomOnchain() public view returns (uint256) {
        bytes32 randomBytes = keccak256(abi.encodePacked(blockhash(block.number - 1), msg.sender, block.timestamp));
        return uint256(randomBytes);
    }

    function mintRandomOnchain() public {
        uint256 tokenId = pickRandomUniqueId(getRandomOnchain());
        _mint(msg.sender, tokenId);
    }

    function mintRandomVRF() public {
        requestId = s_vrfCoordinator.requestRandomWords(
            VRFV2PlusClient.RandomWordsRequest({
                keyHash: keyHash,
                subId: subId,
                requestConfirmations: requestConfirmations,
                callbackGasLimit: callbackGasLimit,
                numWords: numWords,
                extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})
                )
            })
        );
        requestToSender[requestId] = msg.sender;
    }

    function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override {
        address sender = requestToSender[requestId];
        uint256 tokenId = pickRandomUniqueId(randomWords[0]);
        _mint(sender, tokenId);
    }
}

subId 由 uint64 更改为 uint256

新合约继承 VRFConsumerBaseV2Plus,s_vrfCoordinator 在 VRFConsumerBaseV2Plus.sol 初始化为 IVRFCoordinatorV2Plus 类型的实例

s_vrfCoordinator.requestRandomWords 调用了接口 IVRFCoordinatorV2Plus.sol 的 requestRandomWords 来获取 requestId,其具体实现在合约 VRFCoordinatorV2_5.sol

Chainlink 从 VRF v2 迁移 官方文档

@XdpCs
Copy link
Contributor

XdpCs commented Jun 30, 2024

下周我有空去看一下

@XdpCs
Copy link
Contributor

XdpCs commented Jun 30, 2024

#526 这两个问题 类似可以合并处理 并关闭#526这个 @AmazingAng

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants