0

I am beginning my journey in web3 so please be understanding 🙂

I am struggling to find an issue in my contract that uses VRF. It is a simple coinflip written in Vyper. I have deployed a consumer and checked it separately. I am able to receive random number.

I have the same calls in my contract that I have used for the test. I use ape and I receive ContractLogicError. Metamask cannot estimate gas and also suggests that there is an error in the contract. I have deployed it on sepolia.

The contract works correctly with simple mock for the random part so that must be some problem with how I call or use the VRF. I have no idea why though.

Here is the contract:
https://github.com/mcpiatkowski/vyper-coinflip/blob/main/contracts/Coinflip.vy

Contract address on sepolia:
0x63cBA955ADA0504e87fB6E8f3141c58E1d5f307f

To verify if the consumer works you can call it directly. There is a script in the repo with consumer address:
test_vrf_sepolia.py

Local contract execution with mocked random functionality:
flip_local.py

The error happens when calling resolve function. To be able to resolve the game you need to be either the owner of the contract or you need to be in the game. The easiest way to reproduce the error is to join the game and then call resolve.

# HEADS=2; TAILS=4;
join_txn = coinflip.join(HEADS, sender=your_account, value="0.01 ether")
resolve_txn = coinflip.resolve(sender=your_account)

Appreciate all the help I can get. Thanks!

1
  • could you share more details (including the error) and a step by step instruction set on how the error can be reproduced? That will reduce the effort required for people to figure out what exactly is happening and increase the value of responses for you
    – ZeusLawyer
    Nov 24, 2023 at 0:42

3 Answers 3

0

Your problem seems related to your attempts to send the request and read the response in a single tx, here:

@internal
def _get_random_number() -> uint256:
    """
    @dev This functionality is mocked for development purpose.
    @return Random number from Chainlink VRF.
    """
    self.vrf_consumer.request_random_words()
    return self.vrf_consumer.random_words(0)

You cannot request a random value to the VRF Coordinator and read the result in the same tx.

You need to wait for Chainlink to get your request from the Coordinator contract, compute the randomness and the proof, and send back that info to the blockchain.

At that point, the Coordinator will call back the rawFulfillRandomWords function of the VRF Consumer, and you can decide what to do with that value, for example:

  1. You can call back the original VRF Consumer's caller to do something like resolve the game or
  2. You store the value for the original contract to read it later with another TX.

The process above is typical for many Oracle services, and you can read more about the specific Chainlink's Request and Receive cycle in the official doc.

Remember, your subscription account covers costs spent by Chainlink when they answer your request, so if you want to delegate part of the cost to others (i.e., the winning player), it's better to opt for the second option that stores a value and let the winner resolve the game to get paid. But you need to be careful if you use two different contracts, like in your case, separating the game and the VRF consumer contracts, because you need to link results correctly.

Everything works in your mock environment and local tests because your mocked service answers the caller in the same TX.

2
  • Great answer! I will code it up and confirm the solution. Thank you.
    – szaleju
    Nov 25, 2023 at 5:55
  • Making calls to the consumer as a separate transactions worked perfectly. Getting the random word from the consumer also needed to be in separate transaction. I will be rewriting the contract in solidity. Thank you for the time taken to help me.
    – szaleju
    Nov 25, 2023 at 10:58
0

The error could be related to how you're calling the VRFConsumer's functions.

Ensure that the VRFConsumer contract is correctly deployed and that the address you're passing to your Coinflip contract is correct.

Also, remember that the VRFConsumer's request_random_words() function will consume LINK tokens as a fee, so you should have enough LINK tokens in the contract.

Make sure that the Chainlink node you're using has enough ETH to fulfill the request.

1
  • Thanks for quick answer! As I mentioned I have tested deployed consumer separately. The test script is in the repo: vrf-test. I have double checked the consumer address. It looks correct. In the subscription there is almost twelve LINK. Last test consumed around three LINK. I have also wondered whether I have the right interface for the consumer in the Coinflip contract. Don't know how it could be different though.
    – szaleju
    Nov 22, 2023 at 16:29
-2

You can't call chainlink VRF functions in Vyper

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.