I created simple smart contract that generates game character with random attributes and pushes it to an array.

Function requestNewRandomCharacter() does three things:

  1. Changes characterNameForMinting storage variable value to: [parameter: name] + "_before";
  2. Calls Chainlink VRF requestRandomness();
  3. Changes characterNameForMinting storage variable value to: [parameter: name] + "_after";

Function fulfillRandomness() is called inside requestRandomness() function and it pushes element to an array. But element name already has "_after" suffix. Why is that? At the moment function is called characterNameForMinting storage variable value has "_before" suffix.

Full contract code:

pragma solidity ^0.8;

import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";

contract RandomNumberConsumer is VRFConsumerBase {

bytes32 internal keyHash;
uint256 internal fee;
string public characterNameForMinting;

struct Character {
    uint256 strength;
    uint256 dexterity;
    uint256 constitution;
    uint256 intelligence;
    uint256 wisdom;
    uint256 charisma;
    uint256 experience;
    string name;

Character[] public characters;

 * Constructor inherits VRFConsumerBase
 * Network: Rinkeby
 * Chainlink VRF Coordinator address: 0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B
 * LINK token address:                0x01BE23585060835E02B77ef475b0Cc51aA1e0709
 * Key Hash: 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311
        0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B, // VRF Coordinator
        0x01BE23585060835E02B77ef475b0Cc51aA1e0709  // LINK Token
    keyHash = 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311;
    fee = 0.1 * 10 ** 18; // 0.1 LINK (Varies by network)

function requestNewRandomCharacter(
    string memory name
) public returns (bytes32) {
        LINK.balanceOf(address(this)) >= fee,
        "Not enough LINK - fill contract with faucet"
    characterNameForMinting = string(abi.encodePacked(name, "_before"));
    bytes32 requestId = requestRandomness(keyHash, fee);
    characterNameForMinting = string(abi.encodePacked(name, "_after"));
    return requestId;

function fulfillRandomness(bytes32 requestId, uint256 randomNumber)
    uint256 strength = (randomNumber % 100);
    uint256 dexterity = ((randomNumber % 10000) / 100 );
    uint256 constitution = ((randomNumber % 1000000) / 10000 );
    uint256 intelligence = ((randomNumber % 100000000) / 1000000 );
    uint256 wisdom = ((randomNumber % 10000000000) / 100000000 );
    uint256 charisma = ((randomNumber % 1000000000000) / 10000000000);
    uint256 experience = 0;



1 Answer 1


this is expected behavior. Because the call to 'requestRandomness' which requests the random number is not a synchronous request. Ie it doesn't directly call the fulfillRandomness function in the same transaction. It sends the requests to the VRFCoordinator contract. Then the Oracle picks up the request, gets the random number, then posts back a response in a separate transaction, most likely in another block. This is the transaction that then calls teh 'fulfillRandomness' function. So after the requestRandomness function does that, it sets the string to have '_after' in it before the response transaction comes back in to the contract, usually 1 or 2 blocks later

  • Thank you! That makes sense now. I was wondering why there is no new element instantly in an array
    – MantasFam
    Jul 29, 2021 at 12:40
  • You're welcome. if you found the answer helpful, feel free to up-vote it, thanks! Jul 30, 2021 at 2:46
  • I would but don't have enough reputation
    – MantasFam
    Jul 30, 2021 at 2:49

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.