상세 컨텐츠

본문 제목

Random Numbers: Using Chainlink VRF

Blockchain

by Yongari 2023. 4. 4. 17:17

본문

이 가이드에서는 블록체인에서 무작위성을 생성하는 방법에 대해 알아볼 것입니다. 여기에는 체인링크 오라클로 요청과 수신 주기를 구현하는 방법과 스마트 콘트랙트에서 체인링크 VRF로 난수를 소비하는 방법을 배우게 됩니다.

 

블록체인에서 무작위성은 발생하기 매우 어렵습니다. 블록체인의 모든 노드가 동일한 결론에 도달하고 합의를 형성해야 하기 때문입니다. 난수는 다양한 블록체인 애플리케이션에서 다재다능하고 유용하지만, 스마트 콘트랙트에서는 기본적으로 생성할 수 없습니다. 이 문제에 대한 해결책은 체인링크 검증 가능한 난수 함수라고도 알려진 체인링크 VRF입니다.

What is the Request and Receive cycle?

이전 가이드에서는 오라클이 온체인에 게시하는 참조 데이터로 구성된 체인링크 데이터 피드를 사용하는 방법을 설명했습니다. 이 데이터는 콘트랙트에 저장되며, 오라클이 데이터를 다시 업데이트할 때까지 소비자가 참조할 수 있습니다.

반면 무작위성은 참조 데이터가 될 수 없습니다. 무작위성의 결과가 온체인에 저장되면 모든 행위자가 해당 값을 검색하고 결과를 예측할 수 있습니다. 대신 오라클에 무작위성을 요청해야 하며, 오라클은 숫자와 암호학적 증명을 생성합니다. 그런 다음 오라클은 해당 결과를 요청한 콘트랙트에 반환합니다. 이 순서를 요청 및 수신 주기라고 합니다.

 

 

 

What is the payment process for generating a random number?

VRF 요청은 구독 계정에서 자금을 받습니다. 구독 관리자를 사용하면 계정을 만들고 VRF 요청에 대한 자금을 선결제할 수 있으므로 모든 애플리케이션 요청의 자금이 한 곳에서 관리됩니다. VRF 요청 자금 지원에 대해 자세히 알아보려면 구독 한도를 참조하세요.

 

 

 

 

o 체인링크 VRF의 기본 구현을 보려면 난수 구하기를 참조하세요. 이 섹션에서는 체인링크 VRF를 사용해 무작위성을 생성하는 애플리케이션을 만들 것입니다. 이 애플리케이션에 사용되는 컨트랙트에는 왕좌의 게임 테마가 사용됩니다.

컨트랙트는 체인링크 VRF에 무작위성을 요청할 것입니다. 무작위성의 결과는 1에서 20 사이의 숫자로 변환되며, 20면 주사위를 굴리는 것과 유사합니다. 각 숫자는 왕좌의 게임 하우스를 나타냅니다. 주사위가 1에 나오면 사용자는 타르가르옌 가문, 2에 나오면 라니스터 가문을 배정받게 됩니다. 전체 가문 목록은 여기에서 확인할 수 있습니다.

주사위를 굴릴 때 각 가문에 할당된 주소를 추적하기 위해 주소 변수를 받습니다.

계약에는 다음과 같은 기능이 있습니다:

- rollDice: 체인링크 VRF에 무작위성 요청을 제출합니다.
- 이행랜덤워드: 오라클이 결과를 다시 전송하는 데 사용하는 함수입니다.
- 집: 주소의 할당된 집을 확인합니다.

참고: 전체 구현으로 바로 이동하려면 리믹스에서 VRFD20.sol 컨트랙트를 열면 됩니다.

 

VRFv2Consumer.sol

// SPDX-License-Identifier: MIT
// An example of a consumer contract that relies on a subscription for funding.
pragma solidity ^0.8.7;

import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/ConfirmedOwner.sol";

/**
 * Request testnet LINK and ETH here: https://faucets.chain.link/
 * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: https://docs.chain.link/docs/link-token-contracts/
 */

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */

contract VRFv2Consumer is VRFConsumerBaseV2, ConfirmedOwner {
    event RequestSent(uint256 requestId, uint32 numWords);
    event RequestFulfilled(uint256 requestId, uint256[] randomWords);

    struct RequestStatus {
        bool fulfilled; // whether the request has been successfully fulfilled
        bool exists; // whether a requestId exists
        uint256[] randomWords;
    }
    mapping(uint256 => RequestStatus)
        public s_requests; /* requestId --> requestStatus */
    VRFCoordinatorV2Interface COORDINATOR;

    // Your subscription ID.
    uint64 s_subscriptionId;

    // past requests Id.
    uint256[] public requestIds;
    uint256 public lastRequestId;

    // The gas lane to use, which specifies the maximum gas price to bump to.
    // For a list of available gas lanes on each network,
    // see https://docs.chain.link/docs/vrf/v2/subscription/supported-networks/#configurations
    bytes32 keyHash =
        0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c;

    // Depends on the number of requested values that you want sent to the
    // fulfillRandomWords() function. Storing each word costs about 20,000 gas,
    // so 100,000 is a safe default for this example contract. Test and adjust
    // this limit based on the network that you select, the size of the request,
    // and the processing of the callback request in the fulfillRandomWords()
    // function.
    uint32 callbackGasLimit = 100000;

    // The default is 3, but you can set this higher.
    uint16 requestConfirmations = 3;

    // For this example, retrieve 2 random values in one request.
    // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS.
    uint32 numWords = 2;

    /**
     * HARDCODED FOR SEPOLIA
     * COORDINATOR: 0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625
     */
    constructor(
        uint64 subscriptionId
    )
        VRFConsumerBaseV2(0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625)
        ConfirmedOwner(msg.sender)
    {
        COORDINATOR = VRFCoordinatorV2Interface(
            0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625
        );
        s_subscriptionId = subscriptionId;
    }

    // Assumes the subscription is funded sufficiently.
    function requestRandomWords()
        external
        onlyOwner
        returns (uint256 requestId)
    {
        // Will revert if subscription is not set and funded.
        requestId = COORDINATOR.requestRandomWords(
            keyHash,
            s_subscriptionId,
            requestConfirmations,
            callbackGasLimit,
            numWords
        );
        s_requests[requestId] = RequestStatus({
            randomWords: new uint256[](0),
            exists: true,
            fulfilled: false
        });
        requestIds.push(requestId);
        lastRequestId = requestId;
        emit RequestSent(requestId, numWords);
        return requestId;
    }

    function fulfillRandomWords(
        uint256 _requestId,
        uint256[] memory _randomWords
    ) internal override {
        require(s_requests[_requestId].exists, "request not found");
        s_requests[_requestId].fulfilled = true;
        s_requests[_requestId].randomWords = _randomWords;
        emit RequestFulfilled(_requestId, _randomWords);
    }

    function getRequestStatus(
        uint256 _requestId
    ) external view returns (bool fulfilled, uint256[] memory randomWords) {
        require(s_requests[_requestId].exists, "request not found");
        RequestStatus memory request = s_requests[_requestId];
        return (request.fulfilled, request.randomWords);
    }
}

 

VRFD20.sol

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

import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";

/**
 * @notice A Chainlink VRF consumer which uses randomness to mimic the rolling
 * of a 20 sided dice
 */

/**
 * Request testnet LINK and ETH here: https://faucets.chain.link/
 * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: https://docs.chain.link/docs/link-token-contracts/
 */

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */

contract VRFD20 is VRFConsumerBaseV2 {
    uint256 private constant ROLL_IN_PROGRESS = 42;

    VRFCoordinatorV2Interface COORDINATOR;

    // Your subscription ID.
    uint64 s_subscriptionId;

    // Sepolia coordinator. For other networks,
    // see https://docs.chain.link/docs/vrf-contracts/#configurations
    address vrfCoordinator = 0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625;

    // The gas lane to use, which specifies the maximum gas price to bump to.
    // For a list of available gas lanes on each network,
    // see https://docs.chain.link/docs/vrf-contracts/#configurations
    bytes32 s_keyHash =
        0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c;

    // Depends on the number of requested values that you want sent to the
    // fulfillRandomWords() function. Storing each word costs about 20,000 gas,
    // so 40,000 is a safe default for this example contract. Test and adjust
    // this limit based on the network that you select, the size of the request,
    // and the processing of the callback request in the fulfillRandomWords()
    // function.
    uint32 callbackGasLimit = 40000;

    // The default is 3, but you can set this higher.
    uint16 requestConfirmations = 3;

    // For this example, retrieve 1 random value in one request.
    // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS.
    uint32 numWords = 1;
    address s_owner;

    // map rollers to requestIds
    mapping(uint256 => address) private s_rollers;
    // map vrf results to rollers
    mapping(address => uint256) private s_results;

    event DiceRolled(uint256 indexed requestId, address indexed roller);
    event DiceLanded(uint256 indexed requestId, uint256 indexed result);

    /**
     * @notice Constructor inherits VRFConsumerBaseV2
     *
     * @dev NETWORK: Sepolia
     *
     * @param subscriptionId subscription id that this consumer contract can use
     */
    constructor(uint64 subscriptionId) VRFConsumerBaseV2(vrfCoordinator) {
        COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
        s_owner = msg.sender;
        s_subscriptionId = subscriptionId;
    }

    /**
     * @notice Requests randomness
     * @dev Warning: if the VRF response is delayed, avoid calling requestRandomness repeatedly
     * as that would give miners/VRF operators latitude about which VRF response arrives first.
     * @dev You must review your implementation details with extreme care.
     *
     * @param roller address of the roller
     */
    function rollDice(
        address roller
    ) public onlyOwner returns (uint256 requestId) {
        require(s_results[roller] == 0, "Already rolled");
        // Will revert if subscription is not set and funded.
        requestId = COORDINATOR.requestRandomWords(
            s_keyHash,
            s_subscriptionId,
            requestConfirmations,
            callbackGasLimit,
            numWords
        );

        s_rollers[requestId] = roller;
        s_results[roller] = ROLL_IN_PROGRESS;
        emit DiceRolled(requestId, roller);
    }

    /**
     * @notice Callback function used by VRF Coordinator to return the random number to this contract.
     *
     * @dev Some action on the contract state should be taken here, like storing the result.
     * @dev WARNING: take care to avoid having multiple VRF requests in flight if their order of arrival would result
     * in contract states with different outcomes. Otherwise miners or the VRF operator would could take advantage
     * by controlling the order.
     * @dev The VRF Coordinator will only send this function verified responses, and the parent VRFConsumerBaseV2
     * contract ensures that this method only receives randomness from the designated VRFCoordinator.
     *
     * @param requestId uint256
     * @param randomWords  uint256[] The random result returned by the oracle.
     */
    function fulfillRandomWords(
        uint256 requestId,
        uint256[] memory randomWords
    ) internal override {
        uint256 d20Value = (randomWords[0] % 20) + 1;
        s_results[s_rollers[requestId]] = d20Value;
        emit DiceLanded(requestId, d20Value);
    }

    /**
     * @notice Get the house assigned to the player once the address has rolled
     * @param player address
     * @return house as a string
     */
    function house(address player) public view returns (string memory) {
        require(s_results[player] != 0, "Dice not rolled");
        require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress");
        return getHouseName(s_results[player]);
    }

    /**
     * @notice Get the house name from the id
     * @param id uint256
     * @return house name string
     */
    function getHouseName(uint256 id) private pure returns (string memory) {
        string[20] memory houseNames = [
            "Targaryen",
            "Lannister",
            "Stark",
            "Tyrell",
            "Baratheon",
            "Martell",
            "Tully",
            "Bolton",
            "Greyjoy",
            "Arryn",
            "Frey",
            "Mormont",
            "Tarley",
            "Dayne",
            "Umber",
            "Valeryon",
            "Manderly",
            "Clegane",
            "Glover",
            "Karstark"
        ];
        return houseNames[id - 1];
    }

    modifier onlyOwner() {
        require(msg.sender == s_owner);
        _;
    }
}

 

 

 

Create and fund a subscription

체인링크 VRF 요청은 구독 계정에서 자금을 지원받습니다. 구독 관리자를 사용하면 계정을 생성하고 체인링크 VRF 요청에 대한 사용료를 선결제할 수 있습니다. 이 예시에서는 여기에 설명된 대로 세폴리아 테스트넷에서 새 구독을 생성합니다.

 

 

Importing VRFConsumerBaseV2 and VRFCoordinatorV2Interface

체인링크는 오라클에서 데이터를 더 쉽게 사용할 수 있도록 컨트랙트 라이브러리를 관리합니다. 체인링크 VRF의 경우, 이를 사용하게 됩니다:

생성한 컨트랙트에서 가져와서 확장해야 하는 VRFConsumerBaseV2.
VRF 코디네이터와 통신하기 위해 가져와야 하는 VRFCoordinatorV2인터페이스.

 

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

import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";

contract VRFD20 is VRFConsumerBaseV2 {

}

Contract variables

이 예제는 Sepolia 테스트넷에 맞게 조정되었지만 구성을 변경하여 지원되는 모든 네트워크에서 실행할 수 있습니다.

 

uint64 s_subscriptionId;
address vrfCoordinator = 0x2Ca8E0C643bDe4C2E08ab1fA0da3401AdAD7734D;
bytes32 s_keyHash = 0x79d3d8832d904592c0bf9818b621522c988bb8b0c05cdc3b15aea1b6e8db0c15;
uint32 callbackGasLimit = 40000;
uint16 requestConfirmations = 3;
uint32 numWords =  1;

1. uint64 s_subscriptionId: 이 컨트랙트가 펀딩 요청에 사용하는 구독 ID입니다. 생성자에서 초기화됩니다.

2. 주소 vrf코디네이터: 체인링크 VRF 코디네이터 컨트랙트의 주소입니다.

3. 바이트32 s_keyHash: 가스 레인 키 해시 값으로, 요청에 대해 지불할 수 있는 최대 가스 가격입니다. 요청에 대한 응답으로 실행되는 오프체인 VRF 작업의 ID 역할을 합니다.

4. uint32 callbackGasLimit: 컨트랙트의 이행 랜덤워드 함수에 대한 콜백 요청에 사용할 가스의 양에 대한 제한입니다. 이 값은 코디네이터 컨트랙트의 최대 가스 제한 값보다 작아야 합니다. 더 큰 요청의 경우 이 값을 조정하여 이행 랜덤워드 함수가 수신된 랜덤 값을 처리하고 저장하는 방식에 따라 조정하세요. 콜백 가스 한도가 충분하지 않으면 콜백이 실패하고 요청된 무작위 값을 생성하기 위해 수행한 작업에 대한 비용이 구독에 청구됩니다.

5. uint16 requestConfirmations: 체인링크 노드가 응답하기 전에 대기해야 하는 확인 횟수입니다. 노드가 더 오래 기다릴수록 무작위 값의 보안이 강화됩니다. 코디네이터 컨트랙트의 최소 요청 블록 컨펌 수 제한보다 커야 합니다.

6. uint32 numWords: 요청할 무작위 값의 개수입니다. 단일 콜백에서 여러 개의 무작위 값을 사용할 수 있다면 무작위 값당 소비하는 가스의 양을 줄일 수 있습니다. 이 예시에서는 각 트랜잭션이 하나의 무작위 값을 요청합니다.
주사위를 굴리는 주소를 추적하기 위해 컨트랙트는 매핑을 사용합니다. 매핑은 Java의 해시 테이블과 유사한 고유한 키-값 쌍 데이터 구조입니다.

 

주사위를 굴리는 주소를 추적하기 위해 컨트랙트는 매핑을 사용합니다. 매핑은 Java의 해시 테이블과 유사한 고유한 키-값 쌍 데이터 구조입니다.

 

 

mapping(uint256 => address) private s_rollers;
mapping(address => uint256) private s_results;

 -  s_rollers는 요청이 이루어질 때 반환되는 요청ID와 롤러의 주소 사이의 매핑을 저장합니다. 이는 컨트랙트가 결과가 돌아왔을 때 누구에게 결과를 할당할지 추적할 수 있도록 하기 위함입니다.
 -  s_results는 롤러와 주사위 굴림 결과를 저장합니다.

Initializing the contract

코디네이터와 구독 ID는 컨트랙트의 생성자에서 초기화해야 합니다. VRFConsumerBaseV2를 올바르게 사용하려면 생성자에 VRF 코디네이터 주소도 전달해야 합니다. 스마트 컨트랙트를 생성하는 주소는 컨트랙트의 소유자이며, 수정자 onlyOwner()는 소유자만 일부 작업을 수행할 수 있는지 확인합니다.

 

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

import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";

contract VRFD20 is VRFConsumerBaseV2 {
    // variables
    // ...

    // constructor
    constructor(uint64 subscriptionId) VRFConsumerBaseV2(vrfCoordinator) {
        COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
        s_owner = msg.sender;
        s_subscriptionId = subscriptionId;
    }

    //...
    modifier onlyOwner() {
        require(msg.sender == s_owner);
        _;
    }
}

 

rollDice function

롤다이스 함수는 다음 작업을 완료합니다:

1. 각 롤러는 하나의 하우스에만 할당할 수 있으므로 롤러가 이미 굴러갔는지 확인합니다.
2. VRF 코디네이터를 호출하여 무작위성을 요청합니다.

3. requestId와 롤러 주소를 저장합니다.
4. 주사위가 굴리고 있음을 알리는 이벤트를 발생시킵니다.
 

주사위가 굴려졌지만 결과가 아직 반환되지 않았음을 알리기 위해 ROLL_IN_PROGRESS 상수를 추가해야 합니다. 또한 컨트랙트에 DiceRolled 이벤트를 추가합니다.

컨트랙트의 소유자만 롤다이스 함수를 실행할 수 있습니다.

 

 

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

import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";

contract VRFD20 is VRFConsumerBaseV2 {
    // variables
    uint256 private constant ROLL_IN_PROGRESS = 42;
    // ...

    // events
    event DiceRolled(uint256 indexed requestId, address indexed roller);
    // ...

    // ...
    // { constructor }
    // ...

    // rollDice function
    function rollDice(address roller) public onlyOwner returns (uint256 requestId) {
        require(s_results[roller] == 0, "Already rolled");
        // Will revert if subscription is not set and funded.
        requestId = COORDINATOR.requestRandomWords(
        s_keyHash,
        s_subscriptionId,
        requestConfirmations,
        callbackGasLimit,
        numWords
       );

        s_rollers[requestId] = roller;
        s_results[roller] = ROLL_IN_PROGRESS;
        emit DiceRolled(requestId, roller);
    }
}

 

 

fulfillRandomWords function

fulfillRandomWords는 컨트랙트가 확장된 VRFConsumerBaseV2 컨트랙트 내에 정의된 특수 함수입니다. 코디네이터는 생성된 랜덤워즈의 결과를 다시 fulfillRandomWords로 보냅니다. 여기서 결과를 처리하기 위해 몇 가지 기능을 구현합니다:

1. 결과를 1에서 20 사이의 숫자로 변경합니다. randomWords는 여러 임의의 값을 포함할 수 있는 배열이라는 점에 유의하세요. 이 예에서는 임의의 값 1개를 요청합니다.
2. 변환된 값을 s_results 매핑 변수의 주소에 할당합니다.
3. DiceLanded 이벤트를 발생시킵니다.

 

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

import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";

contract VRFD20 is VRFConsumerBaseV2 {
    // ...
    // { variables }
    // ...

    // events
    // ...
    event DiceLanded(uint256 indexed requestId, uint256 indexed result);

    // ...
    // { constructor }
    // ...

    // ...
    // { rollDice function }
    // ...

    // fulfillRandomWords function
    function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {

        // transform the result to a number between 1 and 20 inclusively
        uint256 d20Value = (randomWords[0] % 20) + 1;

        // assign the transformed value to the address in the s_results mapping variable
        s_results[s_rollers[requestId]] = d20Value;

        // emitting event to signal that dice landed
        emit DiceLanded(requestId, d20Value);
    }
}

house function

마지막으로 집 함수는 주소의 집을 반환합니다.

집의 이름 목록을 가지려면 집 함수에서 호출되는 getHouseName 함수를 만듭니다.

 

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

import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";

contract VRFD20 is VRFConsumerBaseV2 {
    // ...
    // { variables }
    // ...

    // ...
    // { events }
    // ...

    // ...
    // { constructor }
    // ...

    // ...
    // { rollDice function }
    // ...

    // ...
    // { fulfillRandomWords function }
    // ...

    // house function
    function house(address player) public view returns (string memory) {
        // dice has not yet been rolled to this address
        require(s_results[player] != 0, "Dice not rolled");

        // not waiting for the result of a thrown dice
        require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress");

        // returns the house name from the name list function
        return getHouseName(s_results[player]);
    }

    // getHouseName function
    function getHouseName(uint256 id) private pure returns (string memory) {
        // array storing the list of house's names
        string[20] memory houseNames = [
            "Targaryen",
            "Lannister",
            "Stark",
            "Tyrell",
            "Baratheon",
            "Martell",
            "Tully",
            "Bolton",
            "Greyjoy",
            "Arryn",
            "Frey",
            "Mormont",
            "Tarley",
            "Dayne",
            "Umber",
            "Valeryon",
            "Manderly",
            "Clegane",
            "Glover",
            "Karstark"
        ];

        // returns the house name given an index
        return houseNames[id - 1];
    }
}

How do I deploy to testnet?

이제 완료된 컨트랙트를 배포합니다. 이 배포는 첫 번째 컨트랙트 배포 가이드의 예시와 약간 다릅니다. 이 경우에는 배포 시 생성자에 매개변수를 전달해야 합니다.

컴파일이 완료되면 배포 창에 다음과 같은 드롭다운 메뉴가 표시됩니다:

 

 

 

VRFD20 컨트랙트 또는 컨트랙트에 지정한 이름을 선택합니다. 이 컨트랙트를 Sepolia 테스트 네트워크에 배포합니다.

배포 오른쪽에 있는 캐럿 화살표를 클릭하여 파라미터 필드를 확장하고 구독 ID를 붙여넣습니다.

 

 

그런 다음 배포 버튼을 클릭하고 메타마스크 계정을 사용하여 트랜잭션을 확인합니다.

참고: 가스 비용을 지불하려면 메타마스크 계정에 세폴리아 이더리움이 있어야 합니다.

 

주소, 키 해시 등

각 네트워크의 주소, 키 해시 및 수수료에 대한 전체 참조는 VRF 지원 네트워크를 참조하세요.

 

이 시점에서 계약이 성공적으로 배포되었을 것입니다. 그러나 아직 구독에서 LINK 잔액을 사용하도록 승인되지 않았기 때문에 아무것도 요청할 수 없습니다. 롤다이스를 클릭하면 트랜잭션이 되돌릴 것입니다.

 

How do I add my contract to my subscription account?

컨트랙트를 배포한 후에는 승인된 소비자 컨트랙트로 추가해야 무작위 추출을 요청할 때 구독 잔액을 사용할 수 있습니다. 구독 관리자로 이동하여 배포한 컨트랙트 주소를 소비자 목록에 추가합니다. 왼쪽 하단의 배포된 컨트랙트에서 리믹스의 컨트랙트 주소를 찾습니다.

 

How do I test rollDice?

왼쪽 하단에서 배포된 컨트랙트 탭을 열면 기능 버튼을 사용할 수 있습니다. 롤다이스를 찾아 캐럿을 클릭하여 매개변수 필드를 확장합니다. 이더리움 주소를 입력하여 "주사위 롤러"를 지정하고 '롤다이스'를 클릭합니다.

거래가 확인되고 응답이 전송될 때까지 몇 분 정도 기다려야 합니다. 롤다이스에 전달된 주소로 하우스 기능 버튼을 클릭하면 하우스를 받을 수 있습니다. 응답이 전송되면 왕좌의 게임 하우스를 배정받게 됩니다!

 

출처 : https://docs.chain.link/getting-started/intermediates-tutorial

 

Random Numbers: Using Chainlink VRF | Chainlink Documentation

Chainlink is the most widely used oracle network for powering universally connected smart contracts, enabling any blockchain to access real-world data & APIs.

docs.chain.link

 

 

'Blockchain' 카테고리의 다른 글

Chainlink Node Fulfilling Requests  (0) 2023.04.06
Running a Chainlink Node  (0) 2023.04.05
Chainlink Single Word Response  (0) 2023.04.04
Obol Key concepts  (0) 2023.03.30
Obol Network  (0) 2023.03.30

관련글 더보기