Slashing

Validator slashing and jail management for network security

Overview

The Slashing precompile provides an interface to the Ontomir SDK's x/slashing module, which is responsible for penalizing validators for misbehavior, such as downtime or double-signing. This precompile allows smart contracts to unjail validators and query slashing-related information, including validator signing info and module parameters.

Precompile Address: 0x0000000000000000000000000000000000000806

Gas Costs

Gas costs are approximated and may vary based on chain settings.

Method
Gas Cost

Transactions

2000 + (30 × bytes of input)

Queries

1000 + (3 × bytes of input)

Transaction Methods

unjail

Allows a validator to unjail themselves after being jailed for downtime.

```solidity Solidity expandable lines // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;

contract SlashingExample { address constant SLASHING_PRECOMPILE = 0x0000000000000000000000000000000000000806; struct SigningInfo { address validatorAddress; int64 startHeight; int64 indexOffset; int64 jailedUntil; bool tombstoned; int64 missedBlocksCounter; } event ValidatorUnjailed(address indexed validator); event ValidatorSlashingInfoQueried(address indexed validator, bool isJailed, bool isTombstoned); function unjailValidator(address validatorAddress) external returns (bool success) { require(validatorAddress != address(0), "Invalid validator address"); // Check signing info to prevent unjailing tombstoned validators SigningInfo memory info = this.getValidatorSigningInfo(validatorAddress); require(!info.tombstoned, "Tombstoned validators cannot be unjailed"); require(info.jailedUntil > int64(int256(block.timestamp)), "Validator is not jailed"); (bool callSuccess, bytes memory result) = SLASHING_PRECOMPILE.call( abi.encodeWithSignature("unjail(address)", validatorAddress) ); require(callSuccess, "Unjail call failed"); success = abi.decode(result, (bool)); require(success, "Unjail operation failed"); emit ValidatorUnjailed(validatorAddress); return success; } function getValidatorSigningInfo(address consAddress) external view returns (SigningInfo memory signingInfo) { (bool success, bytes memory result) = SLASHING_PRECOMPILE.staticcall( abi.encodeWithSignature("getSigningInfo(address)", consAddress) ); require(success, "Signing info query failed"); signingInfo = abi.decode(result, (SigningInfo)); return signingInfo; } function canValidatorBeUnjailed(address consAddress) external view returns (bool canUnjail, string memory reason) { SigningInfo memory info = this.getValidatorSigningInfo(consAddress); // CRITICAL: Tombstoned validators can NEVER be unjailed if (info.tombstoned) { return (false, "PERMANENT_TOMBSTONE: Validator can never be unjailed due to severe infractions (e.g., double-signing)"); } if (info.jailedUntil <= int64(int256(block.timestamp))) { return (false, "Validator is not currently jailed"); } return (true, "Validator can be unjailed"); } function getValidatorStatus(address consAddress) external view returns (bool isJailed, bool isTombstoned, int64 missedBlocks) { SigningInfo memory info = this.getValidatorSigningInfo(consAddress); isJailed = info.jailedUntil > int64(int256(block.timestamp)); isTombstoned = info.tombstoned; missedBlocks = info.missedBlocksCounter; emit ValidatorSlashingInfoQueried(consAddress, isJailed, isTombstoned); return (isJailed, isTombstoned, missedBlocks); }

}

</CodeGroup>

## Query Methods

### `getSigningInfo`

Returns the signing information for a specific validator.

<CodeGroup>
```javascript Ethers.js expandable lines
import { ethers } from "ethers";

// ABI definition for the function
const precompileAbi = [
  "function getSigningInfo(address consAddress) view returns (tuple(address validatorAddress, int64 startHeight, int64 indexOffset, int64 jailedUntil, bool tombstoned, int64 missedBlocksCounter) signingInfo)"
];

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

// Input: The consensus address of the validator
const consAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; // Placeholder

async function getSigningInfo() {
  try {
    const signingInfo = await contract.getSigningInfo(consAddress);
    console.log("Signing Info:", JSON.stringify(signingInfo, null, 2));
  } catch (error) {
    console.error("Error fetching signing info:", error);
  }
}

getSigningInfo();

getSigningInfos

Returns the signing information for all validators, with pagination support.

```javascript Ethers.js expandable lines import { ethers } from "ethers";

// ABI definition for the function const precompileAbi = [ "function getSigningInfos(tuple(bytes key, uint64 offset, uint64 limit, bool countTotal, bool reverse) pagination) view returns (tuple(address validatorAddress, int64 startHeight, int64 indexOffset, int64 jailedUntil, bool tombstoned, int64 missedBlocksCounter)[] signingInfos, tuple(bytes nextKey, uint64 total) pageResponse)" ];

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

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

async function getSigningInfos() { try { const result = await contract.getSigningInfos(pagination); console.log("Signing Infos:", JSON.stringify(result.signingInfos, null, 2)); console.log("Pagination Response:", result.pageResponse); } catch (error) { console.error("Error fetching signing infos:", error); } }

getSigningInfos();

getParams

Returns the current parameters for the slashing module.

```javascript Ethers.js expandable lines import { ethers } from "ethers";

// ABI definition for the function const precompileAbi = [ "function getParams() view returns (tuple(int64 signedBlocksWindow, tuple(uint256 value, uint8 precision) minSignedPerWindow, int64 downtimeJailDuration, tuple(uint256 value, uint8 precision) slashFractionDoubleSign, tuple(uint256 value, uint8 precision) slashFractionDowntime) params)" ];

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

async function getParams() { try { const params = await contract.getParams(); console.log("Slashing Parameters:", JSON.stringify(params, null, 2)); } catch (error) { console.error("Error fetching slashing parameters:", error); } }

getParams();

Full Solidity Interface & ABI