Distribution

Withdraw staking rewards and interact with the community pool

Overview

The Distribution precompile provides access to the Ontomir SDK x/distribution module, enabling smart contracts to manage staking rewards, interact with the community pool, and handle validator commission operations.

Precompile Address: 0x0000000000000000000000000000000000000801

Gas Costs

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

Method
Gas Cost

Transactions

2000 + (30 × bytes of input)

Queries

1000 + (3 × bytes of input)

Message Type Constants

The precompile defines the following constants for the various Ontomir SDK message types:

// Transaction message type URLs
string constant MSG_SET_WITHDRAWER_ADDRESS = "/Ontomir.distribution.v1beta1.MsgSetWithdrawAddress";
string constant MSG_WITHDRAW_DELEGATOR_REWARD = "/Ontomir.distribution.v1beta1.MsgWithdrawDelegatorReward";
string constant MSG_WITHDRAW_VALIDATOR_COMMISSION = "/Ontomir.distribution.v1beta1.MsgWithdrawValidatorCommission";

Transaction Methods

claimRewards

Claims staking rewards from multiple validators.

The `maxRetrieve` parameter limits the number of validators from which to claim rewards in a single transaction. This prevents excessive gas consumption when a delegator has rewards from many validators. ```solidity Solidity expandable lines // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;

contract DistributionClaimRewards { address constant DISTRIBUTION_PRECOMPILE = 0x0000000000000000000000000000000000000801; event RewardsClaimed(address indexed delegator, uint256 maxRetrieve, bool success); function claimRewards(uint32 maxRetrieve) external returns (bool success) { (bool callSuccess, bytes memory result) = DISTRIBUTION_PRECOMPILE.call( abi.encodeWithSignature("claimRewards(address,uint32)", msg.sender, maxRetrieve) ); require(callSuccess, "Claim rewards call failed"); success = abi.decode(result, (bool)); emit RewardsClaimed(msg.sender, maxRetrieve, success); return success; } function claimAllRewards() external returns (bool success) { // Use a high maxRetrieve value to claim from all validators return claimRewards(100); }

}

withdrawDelegatorRewards

Withdraws staking rewards from a single, specific validator.

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

contract DistributionExample { address constant DISTRIBUTION_PRECOMPILE = 0x0000000000000000000000000000000000000801; struct Coin { string denom; uint256 amount; } event RewardsWithdrawn(address indexed delegator, string indexed validator, uint256 amount); function withdrawRewards(string calldata validatorAddress) external returns (Coin[] memory amount) { (bool success, bytes memory result) = DISTRIBUTION_PRECOMPILE.call( abi.encodeWithSignature("withdrawDelegatorRewards(address,string)", msg.sender, validatorAddress) ); require(success, "Withdraw rewards failed"); amount = abi.decode(result, (Coin[])); uint256 totalAmount = 0; for (uint i = 0; i < amount.length; i++) { totalAmount += amount[i].amount; } emit RewardsWithdrawn(msg.sender, validatorAddress, totalAmount); return amount; }

}

setWithdrawAddress

Sets or changes the withdrawal address for receiving staking rewards.

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

contract DistributionSetWithdrawAddress { address constant DISTRIBUTION_PRECOMPILE = 0x0000000000000000000000000000000000000801; event WithdrawAddressSet(address indexed delegator, string withdrawerAddress, bool success); function setWithdrawAddress(string calldata withdrawerAddress) external returns (bool success) { (bool callSuccess, bytes memory result) = DISTRIBUTION_PRECOMPILE.call( abi.encodeWithSignature("setWithdrawAddress(address,string)", msg.sender, withdrawerAddress) ); require(callSuccess, "Set withdraw address call failed"); success = abi.decode(result, (bool)); emit WithdrawAddressSet(msg.sender, withdrawerAddress, success); return success; } function resetWithdrawAddress() external returns (bool success) { // Reset to delegator's own address by converting msg.sender to bech32 // Note: In practice, you'd need to convert the EVM address to bech32 format string memory selfAddress = "art1..."; // This would be the bech32 equivalent return setWithdrawAddress(selfAddress); }

}

withdrawValidatorCommission

Withdraws a validator's accumulated commission rewards.

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

contract DistributionWithdrawCommission { address constant DISTRIBUTION_PRECOMPILE = 0x0000000000000000000000000000000000000801; struct Coin { string denom; uint256 amount; } event ValidatorCommissionWithdrawn(string indexed validatorAddress, uint256 totalAmount); function withdrawValidatorCommission(string calldata validatorAddress) external returns (Coin[] memory amount) { (bool success, bytes memory result) = DISTRIBUTION_PRECOMPILE.call( abi.encodeWithSignature("withdrawValidatorCommission(string)", validatorAddress) ); require(success, "Withdraw validator commission failed"); amount = abi.decode(result, (Coin[])); uint256 totalAmount = 0; for (uint i = 0; i < amount.length; i++) { totalAmount += amount[i].amount; } emit ValidatorCommissionWithdrawn(validatorAddress, totalAmount); return amount; } // Helper function for validator operators to withdraw their own commission function withdrawMyCommission(string calldata myValidatorAddress) external returns (Coin[] memory) { return withdrawValidatorCommission(myValidatorAddress); }

}

Sends tokens directly to the community pool.

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

contract DistributionFundCommunityPool { address constant DISTRIBUTION_PRECOMPILE = 0x0000000000000000000000000000000000000801; struct Coin { string denom; uint256 amount; } event CommunityPoolFunded(address indexed depositor, string denom, uint256 amount, bool success); function fundCommunityPool(Coin[] calldata amount) external returns (bool success) { (bool callSuccess, bytes memory result) = DISTRIBUTION_PRECOMPILE.call( abi.encodeWithSignature("fundCommunityPool(address,(string,uint256)[])", msg.sender, amount) ); require(callSuccess, "Fund community pool call failed"); success = abi.decode(result, (bool)); // Emit events for each coin funded for (uint i = 0; i < amount.length; i++) { emit CommunityPoolFunded(msg.sender, amount[i].denom, amount[i].amount, success); } return success; } function fundCommunityPoolSingleCoin(string calldata denom, uint256 amount) external returns (bool success) { Coin[] memory coins = new Coin; coins[0] = Coin(denom, amount); return fundCommunityPool(coins); }

}

depositValidatorRewardsPool

Deposits tokens into a specific validator's rewards pool.

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

contract DistributionDepositValidatorRewards { address constant DISTRIBUTION_PRECOMPILE = 0x0000000000000000000000000000000000000801; struct Coin { string denom; uint256 amount; } event ValidatorRewardsPoolDeposited( address indexed depositor, string indexed validatorAddress, string denom, uint256 amount, bool success ); function depositValidatorRewardsPool( string calldata validatorAddress, Coin[] calldata amount ) external returns (bool success) { (bool callSuccess, bytes memory result) = DISTRIBUTION_PRECOMPILE.call( abi.encodeWithSignature( "depositValidatorRewardsPool(address,string,(string,uint256)[])", msg.sender, validatorAddress, amount ) ); require(callSuccess, "Deposit validator rewards pool call failed"); success = abi.decode(result, (bool)); // Emit events for each coin deposited for (uint i = 0; i < amount.length; i++) { emit ValidatorRewardsPoolDeposited( msg.sender, validatorAddress, amount[i].denom, amount[i].amount, success ); } return success; } function depositSingleCoinToValidator( string calldata validatorAddress, string calldata denom, uint256 amount ) external returns (bool success) { Coin[] memory coins = new Coin; coins[0] = Coin(denom, amount); return depositValidatorRewardsPool(validatorAddress, coins); }

}

Query Methods

delegationTotalRewards

Retrieves comprehensive reward information for all of a delegator's positions.

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

// ABI definition for the relevant parts of the precompile const precompileAbi = [ "function delegationTotalRewards(address delegatorAddress) view returns (tuple(string validatorAddress, tuple(string denom, uint256 amount, uint8 precision)[] reward)[] rewards, tuple(string denom, uint256 amount, uint8 precision)[] total)" ];

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

// Input: The address of the delegator to query const delegatorAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; // Placeholder

async function getTotalRewards() { try { const result = await contract.delegationTotalRewards(delegatorAddress); console.log("Total Rewards:", JSON.stringify({ rewards: result.rewards, total: result.total }, null, 2)); } catch (error) { console.error("Error fetching total rewards:", error); } }

getTotalRewards();

delegationRewards

Queries pending rewards for a specific delegation.

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

// ABI definition for the function const precompileAbi = [ "function delegationRewards(address delegatorAddress, string memory validatorAddress) view returns (tuple(string denom, uint256 amount, uint8 precision)[] rewards)" ];

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

// Inputs const delegatorAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; // Placeholder const validatorAddress = "artvaloper1..."; // Placeholder

async function getDelegationRewards() { try { const rewards = await contract.delegationRewards(delegatorAddress, validatorAddress); console.log("Delegation Rewards:", JSON.stringify(rewards, null, 2)); } catch (error) { console.error("Error fetching delegation rewards:", error); } }

getDelegationRewards();

delegatorValidators

Retrieves a list of all validators from which a delegator has rewards.

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

// ABI definition for the function const precompileAbi = [ "function delegatorValidators(address delegatorAddress) view returns (string[] validators)" ];

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

// Input const delegatorAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; // Placeholder

async function getDelegatorValidators() { try { const validators = await contract.delegatorValidators(delegatorAddress); console.log("Validators:", validators); } catch (error) { console.error("Error fetching delegator validators:", error); } }

getDelegatorValidators();

delegatorWithdrawAddress

Queries the address that can withdraw rewards for a given delegator.

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

// ABI definition for the function const precompileAbi = [ "function delegatorWithdrawAddress(address delegatorAddress) view returns (string withdrawAddress)" ];

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

// Input const delegatorAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; // Placeholder

async function getWithdrawAddress() { try { const withdrawAddress = await contract.delegatorWithdrawAddress(delegatorAddress); console.log("Withdraw Address:", withdrawAddress); } catch (error) { console.error("Error fetching withdraw address:", error); } }

getWithdrawAddress();

Queries the current balance of the community pool.

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

// ABI definition for the function const precompileAbi = [ "function communityPool() view returns (tuple(string denom, uint256 amount, uint8 precision)[] coins)" ];

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

async function getCommunityPoolBalance() { try { const balance = await contract.communityPool(); console.log("Community Pool Balance:", JSON.stringify(balance, null, 2)); } catch (error) { console.error("Error fetching community pool balance:", error); } }

getCommunityPoolBalance();

validatorCommission

Queries the accumulated commission for a specific validator.

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

// ABI definition for the function const precompileAbi = [ "function validatorCommission(string memory validatorAddress) view returns (tuple(string denom, uint256 amount, uint8 precision)[] commission)" ];

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

// Input const validatorAddress = "artvaloper1..."; // Placeholder

async function getValidatorCommission() { try { const commission = await contract.validatorCommission(validatorAddress); console.log("Validator Commission:", JSON.stringify(commission, null, 2)); } catch (error) { console.error("Error fetching validator commission:", error); } }

getValidatorCommission();

validatorDistributionInfo

Queries a validator's commission and self-delegation rewards.

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

// ABI definition for the function const precompileAbi = [ "function validatorDistributionInfo(string memory validatorAddress) view returns (tuple(string operatorAddress, tuple(string denom, uint256 amount, uint8 precision)[] selfBondRewards, tuple(string denom, uint256 amount, uint8 precision)[] commission) distributionInfo)" ];

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

// Input const validatorAddress = "artvaloper1..."; // Placeholder

async function getValidatorDistInfo() { try { const info = await contract.validatorDistributionInfo(validatorAddress); console.log("Validator Distribution Info:", JSON.stringify(info, null, 2)); } catch (error) { console.error("Error fetching validator distribution info:", error); } }

getValidatorDistInfo();

validatorOutstandingRewards

Queries the outstanding rewards of a validator.

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

// ABI definition for the function const precompileAbi = [ "function validatorOutstandingRewards(string memory validatorAddress) view returns (tuple(string denom, uint256 amount, uint8 precision)[] rewards)" ];

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

// Input const validatorAddress = "artvaloper1..."; // Placeholder

async function getOutstandingRewards() { try { const rewards = await contract.validatorOutstandingRewards(validatorAddress); console.log("Validator Outstanding Rewards:", JSON.stringify(rewards, null, 2)); } catch (error) { console.error("Error fetching outstanding rewards:", error); } }

getOutstandingRewards();

validatorSlashes

Queries slashing events for a validator within a specific height range.

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

// ABI definition for the function const precompileAbi = [ "function validatorSlashes(string validatorAddress, uint64 startingHeight, uint64 endingHeight, tuple(bytes key, uint64 offset, uint64 limit, bool countTotal, bool reverse) pageRequest) view returns (tuple(uint64 validatorPeriod, tuple(uint256 value, uint8 precision) fraction, int64 height)[] slashes, tuple(bytes nextKey, uint64 total) pageResponse)" ];

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

// Inputs const validatorAddress = "artvaloper1..."; // Placeholder const startingHeight = 1000; // Starting block height const endingHeight = 2000; // Ending block height const pageRequest = { key: "0x", offset: 0, limit: 10, countTotal: true, reverse: false };

async function getValidatorSlashes() { try { const [slashes, pageResponse] = await contract.validatorSlashes( validatorAddress, startingHeight, endingHeight, pageRequest ); console.log("Validator Slashes:", JSON.stringify(slashes, null, 2)); console.log("Page Response:", JSON.stringify(pageResponse, null, 2)); } catch (error) { console.error("Error fetching validator slashes:", error); } }

getValidatorSlashes();

Full Solidity Interface & ABI