Understanding Entropy after a long hack

Hello Pyth Team, it’s Krisztian from team TrustGiveAway . I was working a lot with Pyth Entropy, but unfortunately I was not able to understand it 100%. If it’s possible could you please review our entropy code? Sometimes it gave me the randomNumber as requested, but most of the time I did not receive back the callback. You can check my code here, here is the smart contract link: TrustGiveaway/contracts/contracts/Contest.sol at master · RegisGraptin/TrustGiveaway · GitHub

The two main functions which uses Pyth is EndContest and the entropyCallback.

Furthermore I have tried to make a simplified pyth contract code in Remix, attaching code here:

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

import {IEntropyConsumer} from "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol";
import {IEntropy} from "@pythnetwork/entropy-sdk-solidity/IEntropy.sol";

contract Pyth is IEntropyConsumer {
    IEntropy public entropy;
    address public entropyProvider;

    // Mapping from user address to their last random number (1-10)
    mapping(address => uint8) public lastRandomNumber;
    mapping(uint64 => address) public requesters;

    event RandomNumberGenerated(address user, uint8 number);

    constructor(address entropyAddress) {
        entropy = IEntropy(entropyAddress);
        entropyProvider = entropy.getDefaultProvider();
    }

    function generateSeed() public view returns (bytes32) {
        // For example: hash of block.timestamp + msg.sender
        return keccak256(abi.encodePacked(block.timestamp, msg.sender));
    }

    function requestRandomNumber(bytes32 userRandomNumber) external payable {
        uint256 fee = entropy.getFee(entropyProvider);
        require(msg.value >= fee, "Insufficient fee");

        uint64 requestId = entropy.requestWithCallback{value: fee}(
            entropyProvider,
            userRandomNumber
        );
        requesters[requestId] = msg.sender;
    }

    function entropyCallback(
        uint64 sequenceNumber,
        address provider,
        bytes32 randomNumber
    ) internal override {
        // Convert bytes32 randomNumber to uint256
        uint256 randNum = uint256(randomNumber);

        // Map the number to 1-10
        uint8 numberBetween1and10 = uint8((randNum % 10) + 1);

        // Store it for the caller — this example stores for the tx.origin since callback has no user param
        // WARNING: This is a simplification, in reality you need to link the callback to the original requester.
        // For demo, assume tx.origin is the user who requested.
        lastRandomNumber[tx.origin] = numberBetween1and10;
        emit RandomNumberGenerated(msg.sender, numberBetween1and10);
    }

    // Optional: get the last random number for the caller
    function getMyLastRandomNumber() external view returns (uint8) {
        return lastRandomNumber[msg.sender];
    }

    // Required by IEntropyConsumer interface - returns entropy contract address
    function getEntropy() internal view override returns (address) {
        return address(entropy);
    }
}

I have tried this code actually in 3 chains (AbstractSepolia, OptimismSepolia and BaseSepolia) but unfortunately when I called getMyLastRandomNumber I always got back 0. I am generating a bytes32 seed for random Number generation, then I am saving it in the lastRandomNumber value. I was thinking your site wDoes the tx.origin also incorrect in this case? Can you please help out?

Gm sir, it sounds like there’s no issue in requesting the callback, but the callback often doesn’t appear to get called. Usually this happens due to the callback function reverting due to exceeding gas limits or some other reason. Have you tried revealing the random number and executing the callback yourself using our debugger tool? Please send a callback request and put the tx hash in the tool. It will give you a command to execute the callback so you can see what error is occurring. Thanks!