Solidity: Vote on a Query

Stake collateral on a unique set of option indices. The oracle aggregates weight by identical answer-hash (keccak256 of the encoded uint8[]). This page focuses on on-chain integration (no deployment, governance, or meta info).

Requirements:

  • Your contract holds governance tokens and has approved the oracle to pull collateral via transferFrom (see ./approvals).
  • Voting window is open: block.number in [startBlock, currentEndBlock].
  • One vote per address per query.
  • selectedOptions must be non-empty, contain unique indices, and each index < totalOptions.
  • collateral > 0.

Minimal interface

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

interface IOracleVote {
    function voteOnQuery(
        uint256 queryId,
        uint8[] calldata selectedOptions,
        uint256 collateral
    ) external;
}

Vote single option

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

interface IOracleVote {
    function voteOnQuery(uint256, uint8[] calldata, uint256) external;
}

contract OracleVoteSingle {
    IOracleVote public immutable oracle;

    constructor(address oracle_) {
        oracle = IOracleVote(oracle_);
    }

    /// @notice Vote for a single option with collateral.
    /// @dev Assumes allowance to the oracle covers `collateral` and voting window is open.
    function voteSingle(uint256 queryId, uint8 option, uint256 collateral) external {
        uint8[] memory opts = new uint8[](1);
        opts[0] = option;
        oracle.voteOnQuery(queryId, opts, collateral);
    }
}

Vote multiple options

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

interface IOracleVote {
    function voteOnQuery(uint256, uint8[] calldata, uint256) external;
}

contract OracleVoteMulti {
    IOracleVote public immutable oracle;

    constructor(address oracle_) {
        oracle = IOracleVote(oracle_);
    }

    /// @notice Vote for multiple unique options.
    /// @dev Reverts if options are duplicated or out of bounds; ensure `collateral > 0`.
    function voteMulti(uint256 queryId, uint8[] calldata options, uint256 collateral) external {
        oracle.voteOnQuery(queryId, options, collateral);
    }
}

Rules recap:

  • Unique options only; duplicates revert.
  • Each option must be < totalOptions.
  • One vote per address per query (re-voting reverts).
  • Collateral must be positive and allowance must be sufficient.

Reading user vote and distribution (view)

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

interface IOracleRead {
    function getUserVote(uint256, address) external view returns (uint8[] memory, uint256, bool);
    function getQueryAnswers(uint256, uint256, uint256) external view returns (
        bytes32[] memory answerHashes,
        uint8[][] memory decodedAnswers,
        uint256[] memory weights
    );
}

contract OracleVoteViews {
    IOracleRead public immutable oracle;

    constructor(address oracle_) {
        oracle = IOracleRead(oracle_);
    }

    function myVote(uint256 queryId) external view returns (uint8[] memory options, uint256 collateral, bool claimed) {
        return oracle.getUserVote(queryId, msg.sender);
    }

    function pageAnswers(uint256 queryId, uint256 offset, uint256 limit)
        external
        view
        returns (bytes32[] memory hashes, uint8[][] memory decoded, uint256[] memory weights)
    {
        return oracle.getQueryAnswers(queryId, offset, limit);
    }
}

Common pitfalls

  • Missing allowance: approve the oracle for at least collateral before calling.
  • Voting too early/late: must be within the active window [startBlock, currentEndBlock].
  • Duplicate options: ensure each index appears only once.
  • Out-of-range option: each index must be < totalOptions.

Back to: