On-chain governance participation through proposal submission, voting, and governance query operations
x/gov
module, enabling smart contracts to participate in on-chain governance. It allows for submitting and canceling proposals, depositing funds, and casting votes. Additionally, it offers extensive query capabilities to retrieve information about proposals, votes, deposits, and overall governance parameters.
Precompile Address: 0x0000000000000000000000000000000000000805
Related Module: x/gov
Method | Gas Cost |
---|---|
Transactions | 2000 + (30 × bytes of input) |
Queries | 1000 + (3 × bytes of input) |
submitProposal
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceExample {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
struct Coin {
string denom;
uint256 amount;
}
event ProposalSubmitted(address indexed proposer, uint64 indexed proposalId);
function submitProposal(bytes calldata jsonProposal, Coin[] calldata initialDeposit)
external
payable
returns (uint64 proposalId)
{
require(jsonProposal.length > 0, "Proposal cannot be empty");
require(initialDeposit.length > 0, "Initial deposit required");
// Call the governance precompile
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.call(
abi.encodeWithSignature(
"submitProposal(address,bytes,tuple(string,uint256)[])",
msg.sender,
jsonProposal,
initialDeposit
)
);
require(success, "Proposal submission failed");
proposalId = abi.decode(result, (uint64));
emit ProposalSubmitted(msg.sender, proposalId);
return proposalId;
}
// Helper function to create a coin struct
function createCoin(string memory denom, uint256 amount) external pure returns (Coin memory) {
return Coin({denom: denom, amount: amount});
}
}
vote
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceExample {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
enum VoteOption {
Unspecified,
Yes,
Abstain,
No,
NoWithVeto
}
event VoteCast(address indexed voter, uint64 indexed proposalId, VoteOption option);
function vote(uint64 proposalId, VoteOption option, string calldata metadata) external {
require(proposalId > 0, "Invalid proposal ID");
require(option != VoteOption.Unspecified, "Must specify a vote option");
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.call(
abi.encodeWithSignature(
"vote(address,uint64,uint8,string)",
msg.sender,
proposalId,
uint8(option),
metadata
)
);
require(success, "Vote failed");
bool voteSuccess = abi.decode(result, (bool));
require(voteSuccess, "Vote was rejected");
emit VoteCast(msg.sender, proposalId, option);
}
// Convenience function to vote yes
function voteYes(uint64 proposalId) external {
this.vote(proposalId, VoteOption.Yes, "");
}
// Convenience function to vote no
function voteNo(uint64 proposalId) external {
this.vote(proposalId, VoteOption.No, "");
}
}
voteWeighted
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceWeightedVote {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
enum VoteOption {
Unspecified,
Yes,
Abstain,
No,
NoWithVeto
}
struct WeightedVoteOption {
VoteOption option;
string weight;
}
event WeightedVoteCast(
address indexed voter,
uint64 indexed proposalId,
WeightedVoteOption[] options
);
function voteWeighted(
uint64 proposalId,
WeightedVoteOption[] calldata options,
string calldata metadata
) external returns (bool success) {
require(proposalId > 0, "Invalid proposal ID");
require(options.length > 0, "Must provide vote options");
// Validate that weights sum to 1.0 (represented as "1.000000000000000000")
// This is just a basic check - in practice you'd want more robust validation
(bool callSuccess, bytes memory result) = GOVERNANCE_PRECOMPILE.call(
abi.encodeWithSignature(
"voteWeighted(address,uint64,tuple(uint8,string)[],string)",
msg.sender,
proposalId,
options,
metadata
)
);
require(callSuccess, "Weighted vote failed");
success = abi.decode(result, (bool));
require(success, "Weighted vote was rejected");
emit WeightedVoteCast(msg.sender, proposalId, options);
return success;
}
// Helper function to create a split vote (e.g., 70% Yes, 30% Abstain)
function voteSplit(
uint64 proposalId,
uint256 yesPercent,
uint256 abstainPercent
) external returns (bool) {
require(yesPercent + abstainPercent == 100, "Percentages must sum to 100");
WeightedVoteOption[] memory options = new WeightedVoteOption[](2);
// Convert percentages to decimal weights (e.g., 70% = "0.700000000000000000")
options[0] = WeightedVoteOption({
option: VoteOption.Yes,
weight: string(abi.encodePacked("0.", _padPercentage(yesPercent)))
});
options[1] = WeightedVoteOption({
option: VoteOption.Abstain,
weight: string(abi.encodePacked("0.", _padPercentage(abstainPercent)))
});
return voteWeighted(proposalId, options, "Split vote");
}
// Helper function to pad percentage to 18 decimal places
function _padPercentage(uint256 percent) internal pure returns (string memory) {
require(percent <= 100, "Percent cannot exceed 100");
if (percent == 100) return "000000000000000000"; // Special case for 100%
// This is a simplified version - in practice you'd want more robust decimal handling
string memory percentStr = _toString(percent);
if (percent < 10) {
return string(abi.encodePacked("0", percentStr, "0000000000000000"));
} else {
return string(abi.encodePacked(percentStr, "0000000000000000"));
}
}
function _toString(uint256 value) internal pure returns (string memory) {
if (value == 0) return "0";
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
}
deposit
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceExample {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
struct Coin {
string denom;
uint256 amount;
}
event DepositMade(address indexed depositor, uint64 indexed proposalId, uint256 amount);
function deposit(uint64 proposalId, Coin[] calldata amount) external payable {
require(proposalId > 0, "Invalid proposal ID");
require(amount.length > 0, "Deposit amount required");
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.call{value: msg.value}(
abi.encodeWithSignature(
"deposit(address,uint64,tuple(string,uint256)[])",
msg.sender,
proposalId,
amount
)
);
require(success, "Deposit failed");
bool depositSuccess = abi.decode(result, (bool));
require(depositSuccess, "Deposit was rejected");
// Calculate total deposited amount for event
uint256 totalAmount = 0;
for (uint i = 0; i < amount.length; i++) {
totalAmount += amount[i].amount;
}
emit DepositMade(msg.sender, proposalId, totalAmount);
}
// Convenience function to deposit native tokens
function depositNative(uint64 proposalId, uint256 amount, string memory denom) external payable {
require(msg.value >= amount, "Insufficient value sent");
Coin[] memory coins = new Coin[](1);
coins[0] = Coin({denom: denom, amount: amount});
this.deposit{value: amount}(proposalId, coins);
}
}
cancelProposal
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceCancelProposal {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
event ProposalCanceled(address indexed proposer, uint64 indexed proposalId, bool success);
function cancelProposal(uint64 proposalId) external returns (bool success) {
require(proposalId > 0, "Invalid proposal ID");
(bool callSuccess, bytes memory result) = GOVERNANCE_PRECOMPILE.call(
abi.encodeWithSignature("cancelProposal(address,uint64)", msg.sender, proposalId)
);
require(callSuccess, "Cancel proposal call failed");
success = abi.decode(result, (bool));
emit ProposalCanceled(msg.sender, proposalId, success);
return success;
}
// Function to safely cancel a proposal with additional checks
function safeCancelProposal(uint64 proposalId) external returns (bool success) {
// First, check if the proposal exists and can be canceled
// Note: In practice, you'd want to call getProposal first to verify status
success = cancelProposal(proposalId);
require(success, "Proposal cancellation failed - check if you're the proposer and proposal is in deposit period");
return success;
}
}
getProposal
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceQueries {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
struct ProposalData {
uint64 id;
string[] messages;
uint32 status;
TallyResultData finalTallyResult;
uint64 submitTime;
uint64 depositEndTime;
Coin[] totalDeposit;
uint64 votingStartTime;
uint64 votingEndTime;
string metadata;
string title;
string summary;
address proposer;
}
struct TallyResultData {
string yes;
string abstain;
string no;
string noWithVeto;
}
struct Coin {
string denom;
uint256 amount;
}
function getProposal(uint64 proposalId) external view returns (ProposalData memory proposal) {
require(proposalId > 0, "Invalid proposal ID");
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.staticcall(
abi.encodeWithSignature("getProposal(uint64)", proposalId)
);
require(success, "Failed to get proposal");
proposal = abi.decode(result, (ProposalData));
return proposal;
}
// Helper function to check if proposal is in voting period
function isProposalInVotingPeriod(uint64 proposalId) external view returns (bool) {
ProposalData memory proposal = this.getProposal(proposalId);
return proposal.status == 2; // PROPOSAL_STATUS_VOTING_PERIOD
}
}
getProposals
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceProposalsList {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
struct PageRequest {
bytes key;
uint64 offset;
uint64 limit;
bool countTotal;
bool reverse;
}
struct PageResponse {
bytes nextKey;
uint64 total;
}
struct ProposalData {
uint64 id;
string[] messages;
uint32 status;
TallyResultData finalTallyResult;
uint64 submitTime;
uint64 depositEndTime;
Coin[] totalDeposit;
uint64 votingStartTime;
uint64 votingEndTime;
string metadata;
string title;
string summary;
address proposer;
}
struct TallyResultData {
string yes;
string abstain;
string no;
string noWithVeto;
}
struct Coin {
string denom;
uint256 amount;
}
function getProposals(
uint32 proposalStatus,
address voter,
address depositor,
PageRequest memory pagination
) external view returns (ProposalData[] memory proposals, PageResponse memory pageResponse) {
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.staticcall(
abi.encodeWithSignature(
"getProposals(uint32,address,address,(bytes,uint64,uint64,bool,bool))",
proposalStatus,
voter,
depositor,
pagination
)
);
require(success, "Failed to get proposals");
(proposals, pageResponse) = abi.decode(result, (ProposalData[], PageResponse));
return (proposals, pageResponse);
}
// Helper function to get all active proposals (in voting period)
function getActiveProposals(uint64 limit) external view returns (ProposalData[] memory) {
PageRequest memory pagination = PageRequest({
key: "",
offset: 0,
limit: limit,
countTotal: true,
reverse: false
});
uint32 votingStatus = 2; // PROPOSAL_STATUS_VOTING_PERIOD
(ProposalData[] memory proposals,) = this.getProposals(
votingStatus,
address(0),
address(0),
pagination
);
return proposals;
}
}
getTallyResult
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceTally {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
struct TallyResultData {
string yes;
string abstain;
string no;
string noWithVeto;
}
function getTallyResult(uint64 proposalId) external view returns (TallyResultData memory tallyResult) {
require(proposalId > 0, "Invalid proposal ID");
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.staticcall(
abi.encodeWithSignature("getTallyResult(uint64)", proposalId)
);
require(success, "Failed to get tally result");
tallyResult = abi.decode(result, (TallyResultData));
return tallyResult;
}
// Helper function to check if proposal is passing
function isProposalPassing(uint64 proposalId) external view returns (bool) {
TallyResultData memory tally = this.getTallyResult(proposalId);
// Convert string votes to numbers for comparison (simplified)
// In production, use proper decimal math libraries
return keccak256(bytes(tally.yes)) > keccak256(bytes(tally.no));
}
}
getVote
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceVoteQuery {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
enum VoteOption {
Unspecified,
Yes,
Abstain,
No,
NoWithVeto
}
struct WeightedVoteOption {
VoteOption option;
string weight;
}
struct WeightedVote {
uint64 proposalId;
address voter;
WeightedVoteOption[] options;
string metadata;
}
function getVote(uint64 proposalId, address voter) external view returns (WeightedVote memory vote) {
require(proposalId > 0, "Invalid proposal ID");
require(voter != address(0), "Invalid voter address");
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.staticcall(
abi.encodeWithSignature("getVote(uint64,address)", proposalId, voter)
);
require(success, "Failed to get vote");
vote = abi.decode(result, (WeightedVote));
return vote;
}
// Helper function to check if an address has voted
function hasVoted(uint64 proposalId, address voter) external view returns (bool) {
try this.getVote(proposalId, voter) returns (WeightedVote memory vote) {
return vote.options.length > 0;
} catch {
return false;
}
}
}
getVotes
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceVotesList {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
struct PageRequest {
bytes key;
uint64 offset;
uint64 limit;
bool countTotal;
bool reverse;
}
struct PageResponse {
bytes nextKey;
uint64 total;
}
enum VoteOption {
Unspecified,
Yes,
Abstain,
No,
NoWithVeto
}
struct WeightedVoteOption {
VoteOption option;
string weight;
}
struct WeightedVote {
uint64 proposalId;
address voter;
WeightedVoteOption[] options;
string metadata;
}
function getVotes(
uint64 proposalId,
PageRequest memory pagination
) external view returns (WeightedVote[] memory votes, PageResponse memory pageResponse) {
require(proposalId > 0, "Invalid proposal ID");
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.staticcall(
abi.encodeWithSignature(
"getVotes(uint64,(bytes,uint64,uint64,bool,bool))",
proposalId,
pagination
)
);
require(success, "Failed to get votes");
(votes, pageResponse) = abi.decode(result, (WeightedVote[], PageResponse));
return (votes, pageResponse);
}
// Helper function to get all Yes votes
function getYesVoters(uint64 proposalId, uint64 limit) external view returns (address[] memory) {
PageRequest memory pagination = PageRequest({
key: "",
offset: 0,
limit: limit,
countTotal: false,
reverse: false
});
(WeightedVote[] memory votes,) = this.getVotes(proposalId, pagination);
uint256 yesCount = 0;
for (uint i = 0; i < votes.length; i++) {
if (votes[i].options.length > 0 && votes[i].options[0].option == VoteOption.Yes) {
yesCount++;
}
}
address[] memory yesVoters = new address[](yesCount);
uint256 index = 0;
for (uint i = 0; i < votes.length; i++) {
if (votes[i].options.length > 0 && votes[i].options[0].option == VoteOption.Yes) {
yesVoters[index++] = votes[i].voter;
}
}
return yesVoters;
}
}
getDeposit
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceDepositQuery {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
struct Coin {
string denom;
uint256 amount;
}
struct DepositData {
uint64 proposalId;
address depositor;
Coin[] amount;
}
function getDeposit(uint64 proposalId, address depositor) external view returns (DepositData memory deposit) {
require(proposalId > 0, "Invalid proposal ID");
require(depositor != address(0), "Invalid depositor address");
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.staticcall(
abi.encodeWithSignature("getDeposit(uint64,address)", proposalId, depositor)
);
require(success, "Failed to get deposit");
deposit = abi.decode(result, (DepositData));
return deposit;
}
// Helper function to get total deposit amount for a specific denom
function getDepositAmount(uint64 proposalId, address depositor, string memory denom) external view returns (uint256) {
DepositData memory deposit = this.getDeposit(proposalId, depositor);
for (uint i = 0; i < deposit.amount.length; i++) {
if (keccak256(bytes(deposit.amount[i].denom)) == keccak256(bytes(denom))) {
return deposit.amount[i].amount;
}
}
return 0;
}
}
getDeposits
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceDepositsList {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
struct PageRequest {
bytes key;
uint64 offset;
uint64 limit;
bool countTotal;
bool reverse;
}
struct PageResponse {
bytes nextKey;
uint64 total;
}
struct Coin {
string denom;
uint256 amount;
}
struct DepositData {
uint64 proposalId;
address depositor;
Coin[] amount;
}
function getDeposits(
uint64 proposalId,
PageRequest memory pagination
) external view returns (DepositData[] memory deposits, PageResponse memory pageResponse) {
require(proposalId > 0, "Invalid proposal ID");
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.staticcall(
abi.encodeWithSignature(
"getDeposits(uint64,(bytes,uint64,uint64,bool,bool))",
proposalId,
pagination
)
);
require(success, "Failed to get deposits");
(deposits, pageResponse) = abi.decode(result, (DepositData[], PageResponse));
return (deposits, pageResponse);
}
// Helper function to get all depositors
function getDepositors(uint64 proposalId, uint64 limit) external view returns (address[] memory) {
PageRequest memory pagination = PageRequest({
key: "",
offset: 0,
limit: limit,
countTotal: false,
reverse: false
});
(DepositData[] memory deposits,) = this.getDeposits(proposalId, pagination);
address[] memory depositors = new address[](deposits.length);
for (uint i = 0; i < deposits.length; i++) {
depositors[i] = deposits[i].depositor;
}
return depositors;
}
}
getParams
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceParams {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
struct Coin {
string denom;
uint256 amount;
}
struct Params {
int64 votingPeriod;
Coin[] minDeposit;
int64 maxDepositPeriod;
string quorum;
string threshold;
string vetoThreshold;
string minInitialDepositRatio;
string proposalCancelRatio;
string proposalCancelDest;
int64 expeditedVotingPeriod;
string expeditedThreshold;
Coin[] expeditedMinDeposit;
bool burnVoteQuorum;
bool burnProposalDepositPrevote;
bool burnVoteVeto;
string minDepositRatio;
}
function getParams() external view returns (Params memory params) {
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.staticcall(
abi.encodeWithSignature("getParams()")
);
require(success, "Failed to get params");
params = abi.decode(result, (Params));
return params;
}
// Helper function to get minimum deposit amount for a specific denom
function getMinDepositForDenom(string memory denom) external view returns (uint256) {
Params memory params = this.getParams();
for (uint i = 0; i < params.minDeposit.length; i++) {
if (keccak256(bytes(params.minDeposit[i].denom)) == keccak256(bytes(denom))) {
return params.minDeposit[i].amount;
}
}
return 0;
}
// Helper function to get voting period in seconds
function getVotingPeriodSeconds() external view returns (int64) {
Params memory params = this.getParams();
return params.votingPeriod;
}
}
getConstitution
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract GovernanceConstitution {
address constant GOVERNANCE_PRECOMPILE = 0x0000000000000000000000000000000000000805;
function getConstitution() external view returns (string memory constitution) {
(bool success, bytes memory result) = GOVERNANCE_PRECOMPILE.staticcall(
abi.encodeWithSignature("getConstitution()")
);
require(success, "Failed to get constitution");
constitution = abi.decode(result, (string));
return constitution;
}
// Helper function to check if constitution is set
function hasConstitution() external view returns (bool) {
string memory constitution = this.getConstitution();
return bytes(constitution).length > 0;
}
// Helper function to get constitution length
function getConstitutionLength() external view returns (uint256) {
string memory constitution = this.getConstitution();
return bytes(constitution).length;
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.17;
import "../common/Types.sol";
/// @dev The IGov contract's address.
address constant GOV_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000805;
/// @dev The IGov contract's instance.
IGov constant GOV_CONTRACT = IGov(GOV_PRECOMPILE_ADDRESS);
/**
* @dev VoteOption enumerates the valid vote options for a given governance proposal.
*/
enum VoteOption {
// Unspecified defines a no-op vote option.
Unspecified,
// Yes defines a yes vote option.
Yes,
// Abstain defines an abstain vote option.
Abstain,
// No defines a no vote option.
No,
// NoWithVeto defines a no with veto vote option.
NoWithVeto
}
/// @dev WeightedVote represents a vote on a governance proposal
struct WeightedVote {
uint64 proposalId;
address voter;
WeightedVoteOption[] options;
string metadata;
}
/// @dev WeightedVoteOption represents a weighted vote option
struct WeightedVoteOption {
VoteOption option;
string weight;
}
/// @dev DepositData represents information about a deposit on a proposal
struct DepositData {
uint64 proposalId;
address depositor;
Coin[] amount;
}
/// @dev TallyResultData represents the tally result of a proposal
struct TallyResultData {
string yes;
string abstain;
string no;
string noWithVeto;
}
/// @dev ProposalData represents a governance proposal
struct ProposalData {
uint64 id;
string[] messages;
uint32 status;
TallyResultData finalTallyResult;
uint64 submitTime;
uint64 depositEndTime;
Coin[] totalDeposit;
uint64 votingStartTime;
uint64 votingEndTime;
string metadata;
string title;
string summary;
address proposer;
}
/// @dev Params defines the governance parameters
struct Params {
int64 votingPeriod;
Coin[] minDeposit;
int64 maxDepositPeriod;
string quorum;
string threshold;
string vetoThreshold;
string minInitialDepositRatio;
string proposalCancelRatio;
string proposalCancelDest;
int64 expeditedVotingPeriod;
string expeditedThreshold;
Coin[] expeditedMinDeposit;
bool burnVoteQuorum;
bool burnProposalDepositPrevote;
bool burnVoteVeto;
string minDepositRatio;
}
/// @author The Evmos Core Team
/// @title Gov Precompile Contract
/// @dev The interface through which solidity contracts will interact with Gov
interface IGov {
/// @dev SubmitProposal defines an Event emitted when a proposal is submitted.
/// @param proposer the address of the proposer
/// @param proposalId the proposal of id
event SubmitProposal(address indexed proposer, uint64 proposalId);
/// @dev CancelProposal defines an Event emitted when a proposal is canceled.
/// @param proposer the address of the proposer
/// @param proposalId the proposal of id
event CancelProposal(address indexed proposer, uint64 proposalId);
/// @dev Deposit defines an Event emitted when a deposit is made.
/// @param depositor the address of the depositor
/// @param proposalId the proposal of id
/// @param amount the amount of the deposit
event Deposit(address indexed depositor, uint64 proposalId, Coin[] amount);
/// @dev Vote defines an Event emitted when a proposal voted.
/// @param voter the address of the voter
/// @param proposalId the proposal of id
/// @param option the option for voter
event Vote(address indexed voter, uint64 proposalId, uint8 option);
/// @dev VoteWeighted defines an Event emitted when a proposal voted.
/// @param voter the address of the voter
/// @param proposalId the proposal of id
/// @param options the options for voter
event VoteWeighted(
address indexed voter,
uint64 proposalId,
WeightedVoteOption[] options
);
/// TRANSACTIONS
/// @notice submitProposal creates a new proposal from a protoJSON document.
/// @dev submitProposal defines a method to submit a proposal.
/// @param jsonProposal The JSON proposal
/// @param deposit The deposit for the proposal
/// @return proposalId The proposal id
function submitProposal(
address proposer,
bytes calldata jsonProposal,
Coin[] calldata deposit
) external returns (uint64 proposalId);
/// @dev cancelProposal defines a method to cancel a proposal.
/// @param proposalId The proposal id
/// @return success Whether the transaction was successful or not
function cancelProposal(
address proposer,
uint64 proposalId
) external returns (bool success);
/// @dev deposit defines a method to add a deposit to a proposal.
/// @param proposalId The proposal id
/// @param amount The amount to deposit
function deposit(
address depositor,
uint64 proposalId,
Coin[] calldata amount
) external returns (bool success);
/// @dev vote defines a method to add a vote on a specific proposal.
/// @param voter The address of the voter
/// @param proposalId the proposal of id
/// @param option the option for voter
/// @param metadata the metadata for voter send
/// @return success Whether the transaction was successful or not
function vote(
address voter,
uint64 proposalId,
VoteOption option,
string memory metadata
) external returns (bool success);
/// @dev voteWeighted defines a method to add a vote on a specific proposal.
/// @param voter The address of the voter
/// @param proposalId The proposal id
/// @param options The options for voter
/// @param metadata The metadata for voter send
/// @return success Whether the transaction was successful or not
function voteWeighted(
address voter,
uint64 proposalId,
WeightedVoteOption[] calldata options,
string memory metadata
) external returns (bool success);
/// QUERIES
/// @dev getVote returns the vote of a single voter for a
/// given proposalId.
/// @param proposalId The proposal id
/// @param voter The voter on the proposal
/// @return vote Voter's vote for the proposal
function getVote(
uint64 proposalId,
address voter
) external view returns (WeightedVote memory vote);
/// @dev getVotes Returns the votes for a specific proposal.
/// @param proposalId The proposal id
/// @param pagination The pagination options
/// @return votes The votes for the proposal
/// @return pageResponse The pagination information
function getVotes(
uint64 proposalId,
PageRequest calldata pagination
)
external
view
returns (WeightedVote[] memory votes, PageResponse memory pageResponse);
/// @dev getDeposit returns the deposit of a single depositor for a given proposalId.
/// @param proposalId The proposal id
/// @param depositor The address of the depositor
/// @return deposit The deposit information
function getDeposit(
uint64 proposalId,
address depositor
) external view returns (DepositData memory deposit);
/// @dev getDeposits returns all deposits for a specific proposal.
/// @param proposalId The proposal id
/// @param pagination The pagination options
/// @return deposits The deposits for the proposal
/// @return pageResponse The pagination information
function getDeposits(
uint64 proposalId,
PageRequest calldata pagination
)
external
view
returns (
DepositData[] memory deposits,
PageResponse memory pageResponse
);
/// @dev getTallyResult returns the tally result of a proposal.
/// @param proposalId The proposal id
/// @return tallyResult The tally result of the proposal
function getTallyResult(
uint64 proposalId
) external view returns (TallyResultData memory tallyResult);
/// @dev getProposal returns the proposal details based on proposal id.
/// @param proposalId The proposal id
/// @return proposal The proposal data
function getProposal(
uint64 proposalId
) external view returns (ProposalData memory proposal);
/// @dev getProposals returns proposals with matching status.
/// @param proposalStatus The proposal status to filter by
/// @param voter The voter address to filter by, if any
/// @param depositor The depositor address to filter by, if any
/// @param pagination The pagination config
/// @return proposals The proposals matching the filter criteria
/// @return pageResponse The pagination information
function getProposals(
uint32 proposalStatus,
address voter,
address depositor,
PageRequest calldata pagination
)
external
view
returns (
ProposalData[] memory proposals,
PageResponse memory pageResponse
);
/// @dev getParams returns the current governance parameters.
/// @return params The governance parameters
function getParams() external view returns (Params memory params);
/// @dev getConstitution returns the current constitution.
/// @return constitution The current constitution
function getConstitution() external view returns (string memory constitution);
}
{
"_format": "hh-sol-artifact-1",
"contractName": "IGov",
"sourceName": "solidity/precompiles/gov/IGov.sol",
"abi": [
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "proposer",
"type": "address"
},
{
"indexed": true,
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
}
],
"name": "CancelProposal",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "depositor",
"type": "address"
},
{
"indexed": true,
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"indexed": false,
"internalType": "struct Coin[]",
"name": "amount",
"type": "tuple[]"
}
],
"name": "Deposit",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "proposer",
"type": "address"
},
{
"indexed": true,
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
}
],
"name": "SubmitProposal",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "voter",
"type": "address"
},
{
"indexed": true,
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"indexed": false,
"internalType": "uint8",
"name": "option",
"type": "uint8"
}
],
"name": "Vote",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "voter",
"type": "address"
},
{
"indexed": true,
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"components": [
{
"internalType": "enum VoteOption",
"name": "option",
"type": "uint8"
},
{
"internalType": "string",
"name": "weight",
"type": "string"
}
],
"indexed": false,
"internalType": "struct WeightedVoteOption[]",
"name": "options",
"type": "tuple[]"
}
],
"name": "VoteWeighted",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "proposer",
"type": "address"
},
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
}
],
"name": "cancelProposal",
"outputs": [
{
"internalType": "bool",
"name": "success",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "depositor",
"type": "address"
},
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct Coin[]",
"name": "amount",
"type": "tuple[]"
}
],
"name": "deposit",
"outputs": [
{
"internalType": "bool",
"name": "success",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getConstitution",
"outputs": [
{
"internalType": "string",
"name": "constitution",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"internalType": "address",
"name": "depositor",
"type": "address"
}
],
"name": "getDeposit",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "depositor",
"type": "address"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct Coin[]",
"name": "amount",
"type": "tuple[]"
}
],
"internalType": "struct DepositData",
"name": "deposit",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"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": "pagination",
"type": "tuple"
}
],
"name": "getDeposits",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "depositor",
"type": "address"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct Coin[]",
"name": "amount",
"type": "tuple[]"
}
],
"internalType": "struct DepositData[]",
"name": "deposits",
"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": [],
"name": "getParams",
"outputs": [
{
"components": [
{
"internalType": "string",
"name": "minDeposit",
"type": "string"
},
{
"internalType": "string",
"name": "maxDepositPeriod",
"type": "string"
},
{
"internalType": "string",
"name": "votingPeriod",
"type": "string"
},
{
"internalType": "string",
"name": "quorum",
"type": "string"
},
{
"internalType": "string",
"name": "threshold",
"type": "string"
},
{
"internalType": "string",
"name": "vetoThreshold",
"type": "string"
},
{
"internalType": "string",
"name": "minInitialDepositRatio",
"type": "string"
},
{
"internalType": "string",
"name": "proposalCancelRatio",
"type": "string"
},
{
"internalType": "string",
"name": "proposalCancelDest",
"type": "string"
},
{
"internalType": "string",
"name": "minDepositRatio",
"type": "string"
}
],
"internalType": "struct Params",
"name": "params",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
}
],
"name": "getProposal",
"outputs": [
{
"components": [
{
"internalType": "uint64",
"name": "id",
"type": "uint64"
},
{
"internalType": "address",
"name": "proposer",
"type": "address"
},
{
"internalType": "string",
"name": "metadata",
"type": "string"
},
{
"internalType": "uint64",
"name": "submitTime",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "votingStartTime",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "votingEndTime",
"type": "uint64"
},
{
"internalType": "uint8",
"name": "status",
"type": "uint8"
},
{
"components": [
{
"internalType": "string",
"name": "yesCount",
"type": "string"
},
{
"internalType": "string",
"name": "abstainCount",
"type": "string"
},
{
"internalType": "string",
"name": "noCount",
"type": "string"
},
{
"internalType": "string",
"name": "noWithVetoCount",
"type": "string"
}
],
"internalType": "struct TallyResultData",
"name": "finalTallyResult",
"type": "tuple"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct Coin[]",
"name": "totalDeposit",
"type": "tuple[]"
},
{
"internalType": "string[]",
"name": "messages",
"type": "string[]"
}
],
"internalType": "struct ProposalData",
"name": "proposal",
"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": "pagination",
"type": "tuple"
},
{
"internalType": "uint8",
"name": "proposalStatus",
"type": "uint8"
},
{
"internalType": "address",
"name": "voter",
"type": "address"
},
{
"internalType": "address",
"name": "depositor",
"type": "address"
}
],
"name": "getProposals",
"outputs": [
{
"components": [
{
"internalType": "uint64",
"name": "id",
"type": "uint64"
},
{
"internalType": "address",
"name": "proposer",
"type": "address"
},
{
"internalType": "string",
"name": "metadata",
"type": "string"
},
{
"internalType": "uint64",
"name": "submitTime",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "votingStartTime",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "votingEndTime",
"type": "uint64"
},
{
"internalType": "uint8",
"name": "status",
"type": "uint8"
},
{
"components": [
{
"internalType": "string",
"name": "yesCount",
"type": "string"
},
{
"internalType": "string",
"name": "abstainCount",
"type": "string"
},
{
"internalType": "string",
"name": "noCount",
"type": "string"
},
{
"internalType": "string",
"name": "noWithVetoCount",
"type": "string"
}
],
"internalType": "struct TallyResultData",
"name": "finalTallyResult",
"type": "tuple"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct Coin[]",
"name": "totalDeposit",
"type": "tuple[]"
},
{
"internalType": "string[]",
"name": "messages",
"type": "string[]"
}
],
"internalType": "struct ProposalData[]",
"name": "proposals",
"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": [
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
}
],
"name": "getTallyResult",
"outputs": [
{
"components": [
{
"internalType": "string",
"name": "yesCount",
"type": "string"
},
{
"internalType": "string",
"name": "abstainCount",
"type": "string"
},
{
"internalType": "string",
"name": "noCount",
"type": "string"
},
{
"internalType": "string",
"name": "noWithVetoCount",
"type": "string"
}
],
"internalType": "struct TallyResultData",
"name": "tally",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"internalType": "address",
"name": "voter",
"type": "address"
}
],
"name": "getVote",
"outputs": [
{
"components": [
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"internalType": "address",
"name": "voter",
"type": "address"
},
{
"components": [
{
"internalType": "uint8",
"name": "option",
"type": "uint8"
},
{
"internalType": "string",
"name": "weight",
"type": "string"
}
],
"internalType": "struct WeightedVoteOption[]",
"name": "options",
"type": "tuple[]"
},
{
"internalType": "string",
"name": "metadata",
"type": "string"
}
],
"internalType": "struct WeightedVote",
"name": "vote",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"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": "pagination",
"type": "tuple"
}
],
"name": "getVotes",
"outputs": [
{
"components": [
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"internalType": "address",
"name": "voter",
"type": "address"
},
{
"components": [
{
"internalType": "uint8",
"name": "option",
"type": "uint8"
},
{
"internalType": "string",
"name": "weight",
"type": "string"
}
],
"internalType": "struct WeightedVoteOption[]",
"name": "options",
"type": "tuple[]"
},
{
"internalType": "string",
"name": "metadata",
"type": "string"
}
],
"internalType": "struct WeightedVote[]",
"name": "votes",
"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": [
{
"internalType": "address",
"name": "proposer",
"type": "address"
},
{
"internalType": "bytes",
"name": "jsonProposal",
"type": "bytes"
},
{
"components": [
{
"internalType": "string",
"name": "denom",
"type": "string"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"internalType": "struct Coin[]",
"name": "deposit",
"type": "tuple[]"
}
],
"name": "submitProposal",
"outputs": [
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "voter",
"type": "address"
},
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"internalType": "enum VoteOption",
"name": "option",
"type": "uint8"
},
{
"internalType": "string",
"name": "metadata",
"type": "string"
}
],
"name": "vote",
"outputs": [
{
"internalType": "bool",
"name": "success",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "voter",
"type": "address"
},
{
"internalType": "uint64",
"name": "proposalId",
"type": "uint64"
},
{
"components": [
{
"internalType": "enum VoteOption",
"name": "option",
"type": "uint8"
},
{
"internalType": "string",
"name": "weight",
"type": "string"
}
],
"internalType": "struct WeightedVoteOption[]",
"name": "options",
"type": "tuple[]"
},
{
"internalType": "string",
"name": "metadata",
"type": "string"
}
],
"name": "voteWeighted",
"outputs": [
{
"internalType": "bool",
"name": "success",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]
}