Location>code7788 >text

chainLink vrf experiment

Popularity:194 ℃/2024-09-19 11:39:54

goal

Write a random red packet with vrf

data structure

Red Packet:

struct Envelope {
    Type t; // type, just erc20 and eth red envelopes
    ERC20 token; // erc20 , in case of erc20 red envelopes, this is the erc2o address
    address sender; // The sender of the red packet.
    uint balance; // amount
    bool allowAll; // Allow all to receive.
    uint32 maxReceiver; // Maximum number of receivers, eg: up to 3 people can receive the red packets.
    bool avg; // egalitarian, value of each red packet is equal to balance/maxReceiver //false to use random red packets
    uint avgMonty; // average amount of red packets
    uint timeOutBlocks; // timeout can recycle red envelopes, can also open unclaimed red envelopes
    address[] received; // list of received packets.
}

Each red packet stores the information of the red packet, and you can send the red packet in the allowed process.

**Stored data: **

mapping(bytes32 => Envelope) public envelopes; // red packet hash -> red packet content, need to provide red packet hash when receiving red packet
mapping(bytes32 => mapping(address => bool)) public addressAllowList; // red packet corresponding to the allowlist this on the outside of the red packet to save because struct can not be put inside the map
mapping(bytes32 => mapping(address => bool)) addressGotList; // the list of those who have received, and received a bit of a duplicate, it is recommended that received be modified to an int, record how many people have received
mapping(uint => bytes32) openWithVRF; // the vrf of the red packet, this will be used when the red packet is a random red packet
mapping(ERC20 => uint) ERC20Balance; // the amount corresponding to each erc20, the contract itself can be judged by looking at their own eth balance, erc20 need to be recorded separately, should be able to exist at the same time for multiple contracts, if multiple contracts are the same erc20, need to determine erc20's Approve is enough
mapping(bytes32 => uint[]) VRFKey; // vrf corresponding to the list of random numbers

// VRFV2PlusClient public COORDINATOR.
bytes32 keyHash = 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae; // VRF key, you can go to the official documentation to check the

uint256 s_subscriptionId; // Another key used by VRF.

uint32 immutable callbackGasLimit = 100000; // official recommended configuration

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

The mapping above is mainly the configuration of the red packet contract
The following data is the chainlink vrf configuration, these keys can go to the official website to see the meaning of the specific

Contract initialization

    constructor(
        uint256 _subscriptionId,
        address _coordinator
    ) VRFConsumerBaseV2Plus(_coordinator){
        s_subscriptionId = _subscriptionId;
    }

Initialization is mainly about assigning the subscription id of the vrf (a detailed process follows for specific operations)

Constructing a Red Packet

    function createETHredEnvelope(
        bool allowAll,
        address[] memory allowList,
        uint32 maxReceiver,
        bool avg,
        uint timeOutBlocks
    ) public payable returns (bytes32) {}
  • allowAll: run everyone to collect, if true then anyone can call the get method to collect the red packet according to the red packet hash
  • allowList: if allowAll, then allowList is useless.
  • maxReceiver: the maximum number of receivers, the maximum number of receivers can be smaller than allowList, this means that some people can not receive the red envelope
  • avg: whether average, if average then the amount each person receives = /maxReceiver
  • timeOutBlocks: after how many blocks, the initiator of the red packet can recover the balance of the red packet or open the red packet.
    function createERC20redEnvelope(
        address token,
        uint size, // erc20numbers of
        bool allowAll,
        address[] memory allowList,
        uint32 maxReceiver,
        bool avg,
        uint timeOutBlocks
    ) public returns (bytes32) {}

createERC20redEnvelope together withcreateETHredEnvelope Just using erc20

The difference within the function is in with erc20 to check if there is enough apporve

        uint approved = ERC20(token).allowance(,address(this));
        require(approved>=ERC20Balance[ERC20(token)]+size);
        ERC20Balance[ERC20(token)] += size;

Add AllowList

    function allowSome(bytes32 hash, address[] memory allowList) public {
        require(envelopes[hash].balance != 0, "envelop balance is 0");
        require(envelopes[hash].sender == ,"only envelops sender can do this");
        for (uint i = 0; i < ; i++) {
            addressAllowList[hash][allowList[i]] = true;
        }
    }

That's not much of an explanation.

Receive a red packet

    function get(bytes32 hash) public {}

The signature of the method to receive the red envelope is very simple, only need to pass a red envelope hash can be, but the internal logic is very complex, focus on it inside the judgment

        require(envelopes[hash].balance != 0, "envelop balance is 0"); // Judging the balance of the red packet is not0
        require(!addressGotList[hash][], "has got"); // Determine if the sponsor has already received
        require( // Determine if the red packet has timed out
            envelopes[hash].timeOutBlocks > ,
            "envelop timeOutBlocks is not enough"
        );
        require(
            addressAllowList[hash][] || envelopes[hash].allowAll,// Determining whether the initiator is permitted
            "not allow"
        );
        require(envelopes[hash]. < envelopes[hash].maxReceiver, "no more"); // Or to determine if it's been picked up

There are two kinds of logic in receiving, one is the average red packet, the average red packet get will be immediately after the account. One is a random number of red packets, random number of red packets will not immediately to the account need to wait for the number of red packets to reach the maxReceiver or red packets timeout, later on will talk about how to lead the random number of red packets in detail.

Open Random Number Red Packet

    function openEnvelopes(bytes32 hash)public{
        require(
            envelopes[hash].timeOutBlocks <  || envelopes[hash]. == envelopes[hash].maxReceiver,
            "envelop timeOutBlocks is not enough"
        );
        require(envelopes[hash].maxReceiver > 0,"max receriver max more than 0");

Open random number red packet is usually called automatically when receiving, if the recipient does not reach maxReciver, can be called manually after the red packet timeout.

A random number is requested from the vrf in this method, and normally chainlink will call the fullfillRandomWords method to return the random number.

    function fulfillRandomWords(
        uint256 requestId,
        uint256[] calldata randomWords
    ) internal override {
        require( == envelopes[openWithVRF[requestId]].);
        VRFKey[openWithVRF[requestId]] = randomWords;
    }

In fact, you can write the content of the red packet distribution in this method, but since this step is triggered by chainlink to execute the handling fee, the logic here can't be too complex (in fact, the limiting parameter is the keyHash variable)

Open the red packet manually

Since chainlink returns cannot have complex logic, the random number bonus can only be triggered manually by the

    function openVRFEnvelop(bytes32 hash)public {
        uint[] memory randomWords = VRFKey[hash];
        require(envelopes[hash].maxReceiver > 0,"max receriver max more than 0");
        require(!=0,"can not get vrf words");
        uint16[] memory words = new uint16[]();
        // Calculate the weight of each sub-segment
     }

vrf subscription id fetch

First we need to go to chainlink and get a little bit of test coins (link coins and eth coins, both, if you already have them you can skip them)

Web site:/

image-20240913182431182

Then you need to go to the crf admin page to build a wallet contract that will deduct Link coins when requesting vrf random numbers later on

Web site:/

image-20240913182732964

After filling out the information, or so the URL, below will appear your sub

image-20240913182948316

Click on your sub, there is a sub id, this id is the contract to be used when deploying the id, you can use this id first to deploy the contract, the back to the contract address

image-20240913183148412

In the bottom right corner of this page, find the fund and give this sub some link coins.

image-20240913183021680

When you're done, click on "add cousumer" on the left and fill in your contract address.

At this point, this bonus contract is ready to use

beta (software)

I've deployed this bonus on a test network, so you can try it directly on there!

/address/0xc81c0913e6365eb31e761d1062b41dd5a96d2e90#code

The contract source code will be posted here later (internet is so bad today that my environment has been unable to download it)

Source code address: (the environment in the next two days to get good I will put the code up, is still an empty project)

/bighu630/redEnvelop