Problems debugging _entropyCallback function

Today it’s the first day an _entropyCallback hasn’t been called. So I tried this tool to execute the transaction on my own, but it returns the next error:

(code: 3, message: insufficient funds for gas + value. balance: 768620445299700, fee: 1206997865500000, value: 0, data: Some(String("0x")))

  • Chain: Abstract Mainnet
  • Timestamp: Apr-17-2025 07:37:16 AM UTC
  • Execute this: cast send 0x5a4a369F4db5df2054994AF031b7b23949b98c0e 'revealWithCallback(address, uint64, bytes32, bytes32)' 0x52DeaA1c84233F7bb8C8A45baeDE41091c616506 434048 0x013f7b7434f99454eaef6e61aae029e9810ba60c38adccae6d2539ba7edd1044 6ef1f5a2d5c92dc0963d62f13d63f8fe927f3e91b415751a5c5be406b31d61f6 -r https://api.mainnet.abs.xyz --private-key <YOUR_PRIVATE_KEY>

Code contract it’s fully verified: https://abscan.org/address/0x22213392c0541e03540e06a581d08f4e077529c0#code

Alright, so far I still don’t understand why this transaction didn’t trigger the _entropyCallback() . My implementation doesn’t exceed the gas limit, but I’m attaching it here in case you want to test it.

    /// @notice Callback function called by the entropy provider with random number
    /// @dev Processes the hit result and awards prizes if applicable
    /// @param sequenceNumber Unique identifier for this hit attempt
    /// @param provider Address of the entropy provider
    /// @param randomNumber Random number provided by the entropy service
    function entropyCallback(
        uint64 sequenceNumber,
        address provider,
        bytes32 randomNumber
    ) internal override {
        address user = numberToPlayer[sequenceNumber];
        require(user != address(0), "Invalid user address");

        hasBeenHit += 1;

        uint256[3] memory sequence = generateSequence(
            randomNumber,
            secondNumberMaxRange
        );

        uint256 prize = getPrizeForSequence(sequence);

        if (prize > 0) {
            // Calculate the amount that the owner should be able to withdraw
            uint256 ownerWithdrawable = originalPrizePool - ownerWithdrawn;

            // Calculate the actual balance after paying the prize (excluding fees)
            uint256 balanceAfterPrize = token.balanceOf(address(this)) -
                creatorBenefits -
                platformBenefits -
                prize;

            // If the balance after prize payment would be less than what the owner can withdraw,
            // adjust the originalPrizePool to reflect that the prize is coming from the owner's investment
            if (balanceAfterPrize < ownerWithdrawable) {
                // The difference is how much of the owner's investment is being used for the prize
                uint256 difference = ownerWithdrawable - balanceAfterPrize;

                // Adjust originalPrizePool to reflect this reduction
                // Just reduce originalPrizePool by the minimum of difference and originalPrizePool
                originalPrizePool = difference >= originalPrizePool
                    ? 0
                    : originalPrizePool - difference;
            }

            sendPrize(prize, user);
        }

        delete numberToPlayer[sequenceNumber];
        playerNumbers[user] = 0;

        emit HitResult(
            user,
            provider,
            sequenceNumber,
            sequence[0],
            sequence[1],
            sequence[2],
            hasBeenHit,
            hasBeenPaid,
            address(this),
            token.balanceOf(address(this)),
            prize,
            pinataIsBroken,
            address(token)
        );
    }
    /// @notice Generates a sequence of three random numbers
    /// @dev Creates three random numbers within the specified range using the provided random number
    /// @param randomNumber The source random number
    /// @param maxRange The maximum value for the generated numbers
    /// @return A fixed array of three random numbers
    function generateSequence(
        bytes32 randomNumber,
        uint256 maxRange
    ) internal pure returns (uint256[3] memory) {
        uint256 firstResult = mapRandomNumber(
            keccak256(abi.encodePacked(randomNumber, "first")),
            1,
            maxRange
        );
        uint256 secondResult = mapRandomNumber(
            keccak256(abi.encodePacked(randomNumber, "second")),
            1,
            maxRange
        );
        uint256 thirdResult = mapRandomNumber(
            keccak256(abi.encodePacked(randomNumber, "third")),
            1,
            maxRange
        );

        uint256[3] memory sequence = [firstResult, secondResult, thirdResult];

        return sequence;
    }
    /// @notice Calculates the prize amount for a given sequence of numbers
    /// @dev Determines if the sequence wins a prize and how much based on matching patterns
    /// @param _sequence Array of three numbers representing the hit result
    /// @return The prize amount (0 if no prize)
    function getPrizeForSequence(
        uint256[3] memory _sequence
    ) public view returns (uint256) {
        // Create sequence array directly without additional conversion
        uint8[] memory sequence = new uint8[](3);
        for (uint256 i = 0; i < 3; i++) {
            require(
                _sequence[i] <= type(uint8).max,
                "Sequence number too large"
            );
            sequence[i] = uint8(_sequence[i]);
        }
        // Check for jackpot (all numbers match maximum)
        if (
            sequence[0] == secondNumberMaxRange &&
            sequence[1] == secondNumberMaxRange &&
            sequence[2] == secondNumberMaxRange
        ) {
            return token.balanceOf(address(this)) - creatorBenefits - platformBenefits;
        }

        // Calculate prize based on sequence pattern
        if (sequence[0] == sequence[1] && sequence[1] == sequence[2]) {
            // All three numbers match
            return sequence[0] * hitCost;
        } else if (
            sequence[0] == sequence[1] ||
            sequence[1] == sequence[2] ||
            sequence[0] == sequence[2]
        ) {
            // Two numbers match (adjacent or first and last)
            uint8 matchingNumber;
            if (sequence[0] == sequence[1]) {
                matchingNumber = sequence[0];
            } else if (sequence[1] == sequence[2]) {
                matchingNumber = sequence[1];
            } else {
                // sequence[0] == sequence[2]
                matchingNumber = sequence[0];
            }
            return (hitCost * matchingNumber) / 2;
        }

        return 0;
    }
    /// @notice Sends a prize to the winner after deducting fees
    /// @dev Calculates fees, updates state, and transfers the prize amount
    /// @param _amount The gross prize amount before fees
    /// @param _winner The address of the prize winner
    function sendPrize(uint256 _amount, address _winner) internal {
        require(_winner != address(0), "Invalid winner address");
        require(_amount > 0, "Prize amount must be greater than 0");
        require(
            _amount <=
                token.balanceOf(address(this)) - creatorBenefits - platformBenefits,
            "Insufficient contract balance"
        );

        // Calculate fees using basis points
        uint256 creatorAmount = (_amount * creatorFee) / 10000;
        uint256 platformAmount = (_amount * platformFee) / 10000;
        uint256 finalPrizeAmount = _amount - creatorAmount - platformAmount;

        // Check if this is a jackpot win (all max numbers)
        bool isJackpot = _amount ==
            (token.balanceOf(address(this)) - creatorBenefits - platformBenefits);

        // Update state before transfer
        creatorBenefits += creatorAmount;
        platformBenefits += platformAmount;
        hasBeenPaid += finalPrizeAmount;

        if (isJackpot) {
            pinataIsBroken = true; // Set pinata as broken when jackpot is hit
            emit UserWonJackpot(
                _winner,
                finalPrizeAmount,
                address(this),
                token.balanceOf(address(this)),
                address(token)
            );
        } else {
            emit UserWonPrize(
                _winner,
                finalPrizeAmount,
                address(this),
                token.balanceOf(address(this)),
                address(token)
            );
        }

        // Send prize to user
        token.safeTransfer(_winner, finalPrizeAmount);
    }

My suspicion is this: the error likely isn’t from Pyth but from the AGW (Abstract Global Wallet). When I executed this transaction, I closed the window before receiving confirmation. This shouldn’t cause the failure, but at the same time, this is the only transaction out of hundreds that failed to call _entropyCallback() , and the only one I canceled before getting confirmation.

Thank you for the detailed questions. I believe you answered your question in the first reply. You can try again with sufficient funds. :slight_smile:
Let us know if you need more help.