Overview

The Evidence precompile allows for the submission and querying of evidence related to validator misbehavior, such as equivocation (double-signing blocks). It serves as the Solidity interface for the Cosmos SDK’s x/evidence module.

Precompile Address: 0x0000000000000000000000000000000000000807 Related Module: x/evidence

Methods

submitEvidence

Submits evidence of validator misbehavior (equivocation).

evidence

Queries a specific piece of evidence by its hash.

import { ethers } from "ethers";

// ABI for the precompile
const precompileAbi = [
  "function evidence(bytes32 evidenceHash) view returns (tuple(int64 height, int64 time, int64 power, string consensusAddress) evidence)"
];

// Provider and contract setup
const provider = new ethers.JsonRpcProvider("<RPC_URL>");
const precompileAddress = "0x0000000000000000000000000000000000000807";
const contract = new ethers.Contract(precompileAddress, precompileAbi, provider);

// Input: The hash of the evidence to query
const evidenceHash = "0x..."; // Placeholder for a 32-byte hash

async function getEvidence() {
  try {
    const ev = await contract.evidence(evidenceHash);
    console.log("Evidence:", JSON.stringify(ev, null, 2));
  } catch (error) {
    console.error("Error fetching evidence:", error);
  }
}

getEvidence();

getAllEvidence

Queries all evidence with pagination support.

import { ethers } from "ethers";

// ABI for the precompile
const precompileAbi = [
  "function getAllEvidence(tuple(bytes key, uint64 offset, uint64 limit, bool count_total, bool reverse) pageRequest) view returns (tuple(int64 height, int64 time, int64 power, string consensusAddress)[] evidence, tuple(bytes next_key, uint64 total) page_response)"
];

// Provider and contract setup
const provider = new ethers.JsonRpcProvider("<RPC_URL>");
const precompileAddress = "0x0000000000000000000000000000000000000807";
const contract = new ethers.Contract(precompileAddress, precompileAbi, provider);

// Input for pagination
const pagination = {
  key: "0x",
  offset: 0,
  limit: 10,
  count_total: true,
  reverse: false,
};

async function getAllEvidences() {
  try {
    const result = await contract.getAllEvidence(pagination);
    console.log("All Evidence:", JSON.stringify(result.evidence, null, 2));
    console.log("Pagination Response:", result.page_response);
  } catch (error) {
    console.error("Error fetching all evidence:", error);
  }
}

getAllEvidences();

Full Solidity Interface & ABI

Evidence Solidity Interface
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.18;

import "../common/Types.sol";

/// @dev The IEvidence contract's address.
address constant EVIDENCE_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000807;

/// @dev The IEvidence contract's instance.
IEvidence constant EVIDENCE_CONTRACT = IEvidence(EVIDENCE_PRECOMPILE_ADDRESS);

/// @dev The Equivocation struct contains information about a validator's equivocation
struct Equivocation {
    // height is the equivocation height
    int64 height;
    // time is the equivocation time
    int64 time;
    // power is the validator's power at the time of the equivocation
    int64 power;
    // consensusAddress is the validator's consensus address
    string consensusAddress;
}

/// @author The Evmos Core Team
/// @title Evidence Precompile Contract
/// @dev The interface through which solidity contracts will interact with the x/evidence module
interface IEvidence {
    /// @dev Event emitted when evidence is submitted
    /// @param submitter The address of the submitter
    /// @param hash The hash of the submitted evidence
    event SubmitEvidence(address indexed submitter, bytes hash);

    /// @dev Submit evidence of misbehavior (equivocation)
    /// @param evidence The evidence of misbehavior
    /// @return success True if the evidence was submitted successfully
    function submitEvidence(Equivocation calldata evidence) external returns (bool success);

    /// @dev Query evidence by hash
    /// @param evidenceHash The hash of the evidence to query
    /// @return evidence The equivocation evidence data
    function evidence(bytes memory evidenceHash) external view returns (Equivocation memory evidence);

    /// @dev Query all evidence with pagination
    /// @param pageRequest Pagination request
    /// @return evidence List of equivocation evidence
    /// @return pageResponse Pagination response
    function getAllEvidence(PageRequest calldata pageRequest)
        external
        view
        returns (Equivocation[] memory evidence, PageResponse memory pageResponse);
}
Evidence ABI
{
  "_format": "hh-sol-artifact-1",
  "contractName": "IEvidence",
  "sourceName": "solidity/precompiles/evidence/IEvidence.sol",
  "abi": [
    { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "submitter", "type": "address" }, { "indexed": false, "internalType": "bytes", "name": "hash", "type": "bytes" } ], "name": "SubmitEvidence", "type": "event" },
    { "inputs": [ { "internalType": "bytes", "name": "evidenceHash", "type": "bytes" } ], "name": "evidence", "outputs": [ { "components": [ { "internalType": "int64", "name": "height", "type": "int64" }, { "internalType": "int64", "name": "time", "type": "int64" }, { "internalType": "int64", "name": "power", "type": "int64" }, { "internalType": "string", "name": "consensusAddress", "type": "string" } ], "internalType": "struct Equivocation", "name": "evidence", "type": "tuple" } ], "stateMutability": "view", "type": "function" },
    { "inputs": [ { "components": [ { "internalType": "bytes", "name": "key", "type": "bytes" }, { "internalType": "uint64", "name": "offset", "type": "uint64" }, { "internalType": "uint64", "name": "limit", "type": "uint64" }, { "internalType": "bool", "name": "countTotal", "type": "bool" }, { "internalType": "bool", "name": "reverse", "type": "bool" } ], "internalType": "struct PageRequest", "name": "pageRequest", "type": "tuple" } ], "name": "getAllEvidence", "outputs": [ { "components": [ { "internalType": "int64", "name": "height", "type": "int64" }, { "internalType": "int64", "name": "time", "type": "int64" }, { "internalType": "int64", "name": "power", "type": "int64" }, { "internalType": "string", "name": "consensusAddress", "type": "string" } ], "internalType": "struct Equivocation[]", "name": "evidence", "type": "tuple[]" }, { "components": [ { "internalType": "bytes", "name": "nextKey", "type": "bytes" }, { "internalType": "uint64", "name": "total", "type": "uint64" } ], "internalType": "struct PageResponse", "name": "pageResponse", "type": "tuple" } ], "stateMutability": "view", "type": "function" },
    { "inputs": [ { "components": [ { "internalType": "int64", "name": "height", "type": "int64" }, { "internalType": "int64", "name": "time", "type": "int64" }, { "internalType": "int64", "name": "power", "type": "int64" }, { "internalType": "string", "name": "consensusAddress", "type": "string" } ], "internalType": "struct Equivocation", "name": "evidence", "type": "tuple" } ], "name": "submitEvidence", "outputs": [ { "internalType": "bool", "name": "success", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }
  ]
}