Skip to content

Latest commit

 

History

History
1619 lines (1167 loc) · 39.3 KB

README.md

File metadata and controls

1619 lines (1167 loc) · 39.3 KB

x/foundation

Abstract

This module provides the functionalities related to the foundation. The foundation can turn off these functionalities irreversibly, through the corresponding proposal. Therefore, the users can ensure that no one can bring back these foundation-specific functionalities.

Contents

Concepts

Authority

x/foundation's authority is a module account associated with the foundation and a decision policy. It is an "administrator" which has the ability to add, remove and update members in the foundation. x/foundation has several messages which cannot be triggered but by the authority. It includes membership management messages, and other messages which controls the assets of the foundation.

Note: The authority is a module account, which means no one has the private key of the authority. Hence, foundation members MUST propose, vote and execute the corresponding proposal.

Decision Policy

A decision policy is the rules that dictate whether a proposal should pass or not based on its tally outcome.

All decision policies generally would have a mininum execution period and a maximum voting window. The minimum execution period is the minimum amount of time that must pass after submission in order for a proposal to potentially be executed, and it may be set to 0. The maximum voting window is the maximum time after submission that a proposal may be voted on before it is tallied.

The chain developer also defines an app-wide maximum execution period, which is the maximum amount of time after a proposal's voting period end where the members are allowed to execute a proposal.

The current foundation module comes shipped with two decision policies: threshold and percentage. Any chain developer can extend upon these two, by creating custom decision policies, as long as they adhere to the DecisionPolicy interface:

+++

type DecisionPolicy interface {
codec.ProtoMarshaler
// GetVotingPeriod returns the duration after proposal submission where
// votes are accepted.
GetVotingPeriod() time.Duration
// Allow defines policy-specific logic to allow a proposal to pass or not,
// based on its tally result, the foundation's total power and the time since
// the proposal was submitted.
Allow(tallyResult TallyResult, totalPower sdk.Dec, sinceSubmission time.Duration) (*DecisionPolicyResult, error)
ValidateBasic() error
Validate(info FoundationInfo, config Config) error
}

Threshold decision policy

A threshold decision policy defines a threshold of yes votes (based on a tally of voter weights) that must be achieved in order for a proposal to pass. For this decision policy, abstain and veto are simply treated as no's.

+++

// ThresholdDecisionPolicy is a decision policy where a proposal passes when it
// satisfies the two following conditions:
// 1. The sum of all `YES` voters' weights is greater or equal than the defined
// `threshold`.
// 2. The voting and execution periods of the proposal respect the parameters
// given by `windows`.
message ThresholdDecisionPolicy {
option (cosmos_proto.implements_interface) = "DecisionPolicy";
// threshold is the minimum sum of yes votes that must be met or exceeded for a proposal to succeed.
string threshold = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/Finschia/finschia-sdk/types.Dec"];
// windows defines the different windows for voting and execution.
DecisionPolicyWindows windows = 2;
}

Percentage decision policy

A percentage decision policy is similar to a threshold decision policy, except that the threshold is not defined as a constant weight, but as a percentage. It's more suited for a foundation where the membership can be updated, as the percentage threshold stays the same, and doesn't depend on how the number of members get updated.

+++

// PercentageDecisionPolicy is a decision policy where a proposal passes when
// it satisfies the two following conditions:
// 1. The percentage of all `YES` voters' weights out of the total group weight
// is greater or equal than the given `percentage`.
// 2. The voting and execution periods of the proposal respect the parameters
// given by `windows`.
message PercentageDecisionPolicy {
option (cosmos_proto.implements_interface) = "DecisionPolicy";
// percentage is the minimum percentage the sum of yes votes must meet for a proposal to succeed.
string percentage = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/Finschia/finschia-sdk/types.Dec"];
// windows defines the different windows for voting and execution.
DecisionPolicyWindows windows = 2;
}

Outsourcing decision policy

A outsourcing decision policy is a policy set after x/foundation decides to outsource its proposal relevant features to other modules (e.g. x/group). It means one can expect that any states relevant to the feature must be removed in the update to this policy.

+++

// OutsourcingDecisionPolicy is a dummy decision policy which is set after
// the proposal feature has been outsourced to x/group.
message OutsourcingDecisionPolicy {
option (cosmos_proto.implements_interface) = "DecisionPolicy";
string description = 1;
}

Proposal

Any foundation member(s) can submit a proposal for the foundation policy account to decide upon. A proposal consists of a set of messages that will be executed if the proposal passes as well as any metadata associated with the proposal.

Voting

There are four choices to choose while voting - yes, no, abstain and veto. Not all decision policies will take the four choices into account. Votes can contain some optional metadata.

In the current implementation, the voting window begins as soon as a proposal is submitted, and the end is defined by the decision policy.

Withdrawing Proposals

Proposals can be withdrawn any time before the voting period end, either by the module's authority or by one of the proposers. Once withdrawn, it is marked as PROPOSAL_STATUS_WITHDRAWN, and no more voting or execution is allowed on it.

Aborted Proposals

If the decision policy is updated during the voting period of the proposal, then the proposal is marked as PROPOSAL_STATUS_ABORTED, and no more voting or execution is allowed on it. This is because the decision policy defines the rules of proposal voting and execution, so if those rules change during the lifecycle of a proposal, then the proposal should be marked as stale.

Tallying

Tallying is the counting of all votes on a proposal. It can be triggered by the following two factors:

  • either someone tries to execute the proposal (see next section), which can happen on a Msg/Exec transaction, or a Msg/{SubmitProposal,Vote} transaction with the Exec field set. When a proposal execution is attempted, a tally is done first to make sure the proposal passes.
  • or on EndBlock when the proposal's voting period end just passed.

If the tally result passes the decision policy's rules, then the proposal is marked as PROPOSAL_STATUS_ACCEPTED, or else it is marked as PROPOSAL_STATUS_REJECTED. In any case, no more voting is allowed anymore, and the tally result is persisted to state in the proposal's FinalTallyResult.

Executing Proposals

Proposals are executed only when the tallying is done, and the decision policy allows the proposal to pass based on the tally outcome. They are marked by the status PROPOSAL_STATUS_ACCEPTED. Execution must happen before a duration of MaxExecutionPeriod (set by the chain developer) after each proposal's voting period end.

Proposals will not be automatically executed by the chain in this current design, but rather a member must submit a Msg/Exec transaction to attempt to execute the proposal based on the current votes and decision policy. Any member can execute proposals that have been accepted, and execution fees are paid by the proposal executor.

It's also possible to try to execute a proposal immediately on creation or on new votes using the Exec field of Msg/SubmitProposal and Msg/Vote requests. In the former case, proposers signatures are considered as yes votes. In these cases, if the proposal can't be executed (i.e. it didn't pass the decision policy's rules), it will still be opened for new votes and could be tallied and executed later on.

A successful proposal execution will have its ExecutorResult marked as PROPOSAL_EXECUTOR_RESULT_SUCCESS. The proposal will be automatically pruned after execution. On the other hand, a failed proposal execution will be marked as PROPOSAL_EXECUTOR_RESULT_FAILURE. Such a proposal can be re-executed multiple times, until it expires after MaxExecutionPeriod after voting period end.

Pruning

Proposals and votes are automatically pruned to avoid state bloat.

Votes are pruned:

  • either after a successful tally, i.e. a tally whose result passes the decision policy's rules, which can be trigged by a Msg/Exec or a Msg/{SubmitProposal,Vote} with the Exec field set,
  • or on EndBlock right after the proposal's voting period end. This applies to proposals with status aborted or withdrawn too.
  • or after updating the membership or decision policy.

whichever happens first.

Proposals are pruned:

  • on EndBlock whose proposal status is withdrawn or aborted on proposal's voting period end before tallying,
  • and either after a successful proposal execution,
  • or on EndBlock right after the proposal's voting_period_end + max_execution_period (defined as an app-wide configuration) is passed,

whichever happens first.

Censorship

The foundation module defines interfaces of authorizations on messages to enforce censorship on its execution. The other modules may deny the execution of the message based on the information in the foundation.

A censorship has its target message type URL and authority which can trigger the messages which manipulate the relevant censorship information:

Authorization is an interface that must be implemented by a concrete authorization logic to validate and execute grants. Authorizations are extensible and can be defined for any Msg service method even outside of the module where the Msg method is defined.

Note: The foundation module's Authorization is different from that of x/authz, while the latter allows an account to perform actions on behalf of another account.

+++

// Authorization represents the interface of various Authorization types implemented
// by other modules.
// Caution: It's not for x/authz exec.
type Authorization interface {
proto.Message
// MsgTypeURL returns the fully-qualified Msg service method URL (as described in ADR 031),
// which will process and accept or reject a request.
MsgTypeURL() string
// Accept determines whether this grant permits the provided sdk.Msg to be performed,
// and if so provides an updated authorization instance.
Accept(ctx sdk.Context, msg sdk.Msg) (AcceptResponse, error)
// ValidateBasic does a simple validation check that
// doesn't require access to any other information.
ValidateBasic() error
}

Built-in Authorizations

ReceiveFromTreasuryAuthorization

ReceiveFromTreasuryAuthorization implements the Authorization interface for the Msg/WithdrawFromTreasury.

Note: The subject which executes lbm.foundation.v1.MsgWithdrawFromTreasury is the foundation.

+++

// ReceiveFromTreasuryAuthorization allows the grantee to receive coins
// up to receive_limit from the treasury.
message ReceiveFromTreasuryAuthorization {
option (cosmos_proto.implements_interface) = "github.com/line/lbm-sdk/x/foundation.Authorization";
}

CreateValidatorAuthorization

CreateValidatorAuthorization implements the Authorization interface for the Msg/CreateValidator. An account must have this authorization prior to sending the message.

Note: You MUST provide the CreateValidatorAuthorizations into the genesis if Msg/CreateValidator is being censored (CensoredMsgTypeUrls contains the url of Msg/CreateValidator), or the chain cannot be started.

+++

// CreateValidatorAuthorization allows the grantee to create a new validator.
message CreateValidatorAuthorization {
option (cosmos_proto.implements_interface) = "github.com/line/lbm-sdk/x/foundation.Authorization";
// redundant, but good for the query.
string validator_address = 1;
}

Foundation Treasury

x/foundation intercepts the rewards prior to its distribution (by x/distribution). The rate would be FoundationTax.

The foundation can withdraw coins from the treasury. The recipient must have the corresponding authorization (ReceiveFromTreasuryAuthorization) prior to sending the message Msg/WithdrawFromTreasury.

Parameters

FoundationTax

The value of FoundationTax is the foundation tax rate.

  • FoundationTax: sdk.Dec

State

FoundationInfo

FoundationInfo contains the information relevant to the foundation.

  • FoundationInfo: 0x01 -> ProtocolBuffer(FoundationInfo).

Version

The Version is used to track changes to the foundation membership. Whenever the membership is changed, this value is incremented, which will cause proposals based on older versions to fail.

TotalWeight

The TotalWeight is the number of the foundation members.

DecisionPolicy

The DecisionPolicy is the decision policy of the foundation.

Member

The Member is the foundation member.

  • Member: 0x10 | []byte(member.Address) -> ProtocolBuffer(Member).

PreviousProposalID

The value of the PreviousProposalID is the last used proposal ID. The chain uses this value to issue the ID of the next new proposal.

  • PreviousProposalID: 0x11 -> BigEndian(ProposalId).

Proposal

  • Proposal: 0x12 | BigEndian(ProposalId) -> ProtocolBuffer(Proposal).

ProposalByVotingPeriodEnd

ProposalByVotingPeriodEnd allows to retrieve proposals sorted by chronological voting_period_end. This index is used when tallying the proposal votes at the end of the voting period, and for pruning proposals at VotingPeriodEnd + MaxExecutionPeriod.

  • ProposalByVotingPeriodEnd: 0x13 | sdk.FormatTimeBytes(proposal.VotingPeriodEnd) | BigEndian(ProposalId) -> []byte().

Vote

  • Vote: 0x40 | BigEndian(ProposalId) | []byte(voter.Address) -> ProtocolBuffer(Vote).

Censorship

Censorships are identified by its target message type URL.

  • Censorship: 0x20 | []byte(censorship.MsgTypeURL) -> ProtocolBuffer(Censorship)

Grant

Grants are identified by combining grantee address and Authorization type (its target message type URL). Hence we only allow one grant for the (grantee, Authorization) tuple.

  • Grant: 0x21 | len(grant.Grantee) (1 byte) | []byte(grant.Grantee) | []byte(grant.Authorization.MsgTypeURL()) -> ProtocolBuffer(Authorization)

Msg Service

Msg/UpdateDecisionPolicy

The MsgUpdateDecisionPolicy can be used to update the decision policy.

+++

// MsgUpdateDecisionPolicy is the Msg/UpdateDecisionPolicy request type.
message MsgUpdateDecisionPolicy {
// authority is the address of the privileged account.
string authority = 1;
// decision_policy is the updated decision policy.
google.protobuf.Any decision_policy = 2 [(cosmos_proto.accepts_interface) = "DecisionPolicy"];
}

It's expected to fail if:

  • the authority is not the module's authority.
  • the new decision policy's Validate() method doesn't pass.

Msg/UpdateMembers

Foundation members can be updated with the MsgUpdateMembers.

+++

// MsgUpdateMembers is the Msg/UpdateMembers request type.
message MsgUpdateMembers {
// authority is the address of the privileged account.
string authority = 1;
// member_updates is the list of members to update,
// set remove to true to remove a member.
repeated MemberRequest member_updates = 2 [(gogoproto.nullable) = false];
}

In the list of MemberUpdates, an existing member can be removed by setting its remove flag to true.

It's expected to fail if:

  • the authority is not the module's authority.
  • if the decision policy's Validate() method fails against the updated membership.

Msg/LeaveFoundation

The MsgLeaveFoundation allows a foundation member to leave the foundation.

+++

// MsgLeaveFoundation is the Msg/LeaveFoundation request type.
message MsgLeaveFoundation {
// address is the account address of the foundation member.
string address = 1;
}

It's expected to fail if:

  • the address is not of a foundation member.
  • if the decision policy's Validate() method fails against the updated membership.

Msg/SubmitProposal

A new proposal can be created with the MsgSubmitProposal, which has a list of proposers addresses, a list of messages to execute if the proposal is accepted and some optional metadata. An optional Exec value can be provided to try to execute the proposal immediately after proposal creation. Proposers signatures are considered as yes votes in this case.

+++

// MsgSubmitProposal is the Msg/SubmitProposal request type.
message MsgSubmitProposal {
// proposers are the account addresses of the proposers.
// Proposers signatures will be counted as yes votes.
repeated string proposers = 1;
// metadata is any arbitrary metadata to attached to the proposal.
string metadata = 2;
// messages is a list of `sdk.Msg`s that will be executed if the proposal passes.
repeated google.protobuf.Any messages = 3;
// exec defines the mode of execution of the proposal,
// whether it should be executed immediately on creation or not.
// If so, proposers signatures are considered as Yes votes.
Exec exec = 4;
}

It's expected to fail if:

  • metadata length is greater than MaxMetadataLen config.
  • if any of the proposers is not a foundation member.

Msg/WithdrawProposal

A proposal can be withdrawn using MsgWithdrawProposal which has an address (can be either a proposer or the module's authority) and a proposal_id (which has to be withdrawn).

+++

// MsgWithdrawProposal is the Msg/WithdrawProposal request type.
message MsgWithdrawProposal {
// proposal is the unique ID of the proposal.
uint64 proposal_id = 1;
// address of one of the proposer of the proposal.
string address = 2;
}

It's expected to fail if:

  • the address is neither the module's authority nor a proposer of the proposal.
  • the proposal is already closed or aborted.

Msg/Vote

A new vote can be created with the MsgVote, given a proposal id, a voter address, a choice (yes, no, veto or abstain) and some optional metadata. An optional Exec value can be provided to try to execute the proposal immediately after voting.

+++

// MsgVote is the Msg/Vote request type.
message MsgVote {
// proposal is the unique ID of the proposal.
uint64 proposal_id = 1;
// voter is the voter account address.
string voter = 2;
// option is the voter's choice on the proposal.
VoteOption option = 3;
// metadata is any arbitrary metadata to attached to the vote.
string metadata = 4;
// exec defines whether the proposal should be executed
// immediately after voting or not.
Exec exec = 5;
}

It's expected to fail if:

  • metadata length is greater than MaxMetadataLen config.
  • the proposal is not in voting period anymore.

Msg/Exec

A proposal can be executed with the MsgExec.

+++

// MsgExec is the Msg/Exec request type.
message MsgExec {
// proposal is the unique ID of the proposal.
uint64 proposal_id = 1;
// signer is the account address used to execute the proposal.
string signer = 2;
}

The messages that are part of this proposal won't be executed if:

  • the proposal has not been accepted by the decision policy.
  • the proposal has already been successfully executed.

Msg/UpdateCensorship

A censorship information is updated by using the MsgUpdateCensorship message. One cannot introduce a censorship over a new message type URL by this message.

+++

// MsgUpdateCensorship is the Msg/UpdateCensorship request type.
message MsgUpdateCensorship {
// authority over the target censorship.
string authority = 1;
// new censorship information
Censorship censorship = 2 [(gogoproto.nullable) = false];
}

The authority of the following modules are candidates of censorship authority:

  • CENSORSHIP_AUTHORITY_GOVERNANCE: x/gov
  • CENSORSHIP_AUTHORITY_FOUNDATION: x/foundation

One may specify CENSORSHIP_AUTHORITY_UNSPECIFIED to remove the censorship.

+++

enum CensorshipAuthority {
option (gogoproto.goproto_enum_prefix) = false;
// CENSORSHIP_AUTHORITY_UNSPECIFIED defines an invalid authority.
CENSORSHIP_AUTHORITY_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "CensorshipAuthorityUnspecified"];
// CENSORSHIP_AUTHORITY_GOVERNANCE defines x/gov authority.
CENSORSHIP_AUTHORITY_GOVERNANCE = 1 [(gogoproto.enumvalue_customname) = "CensorshipAuthorityGovernance"];
// CENSORSHIP_AUTHORITY_FOUNDATION defines x/foundation authority.
CENSORSHIP_AUTHORITY_FOUNDATION = 2 [(gogoproto.enumvalue_customname) = "CensorshipAuthorityFoundation"];
}

The message handling should fail if:

  • the authority is not the current censorship's authority.
  • corresponding enum value of the current censorship's authority is lesser than that of the provided censorship's authority.

Note: Do NOT confuse with that of x/authz.

Msg/Grant

An authorization grant is created by using the MsgGrant message. If there is already a grant for the (grantee, Authorization) tuple, then the new grant overwrites the previous one. To update or extend an existing grant, a new grant with the same (grantee, Authorization) tuple should be created.

+++

// MsgGrant is the Msg/Grant request type.
// on behalf of the foundation.
message MsgGrant {
// authority is the address of the privileged account.
string authority = 1;
string grantee = 2;
google.protobuf.Any authorization = 3
[(cosmos_proto.accepts_interface) = "github.com/line/lbm-sdk/x/foundation.Authorization"];
}

The message handling should fail if:

  • the authority is not the current censorship's authority.
  • provided Authorization is not implemented.
  • Authorization.MsgTypeURL() is not defined in the router (there is no defined handler in the app router to handle that Msg types).

Note: Do NOT confuse with that of x/authz.

Msg/Revoke

A grant can be removed with the MsgRevoke message.

+++

// MsgRevoke is the Msg/Revoke request type.
message MsgRevoke {
// authority is the address of the privileged account.
string authority = 1;
string grantee = 2;
string msg_type_url = 3;
}

The message handling should fail if:

  • the authority is not the current censorship's authority.
  • provided MsgTypeUrl is empty.

Msg/FundTreasury

Anyone can fund treasury with MsgFundTreasury.

+++

// MsgFundTreasury is the Msg/FundTreasury request type.
message MsgFundTreasury {
string from = 1;
repeated cosmos.base.v1beta1.Coin amount = 2
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/line/lbm-sdk/types.Coins"];
}

Msg/WithdrawFromTreasury

The foundation can withdraw coins from the treasury with MsgWithdrawFromTreasury.

+++

// MsgWithdrawFromTreasury is the Msg/WithdrawFromTreasury request type.
message MsgWithdrawFromTreasury {
// authority is the address of the privileged account.
string authority = 1;
string to = 2;
repeated cosmos.base.v1beta1.Coin amount = 3
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/line/lbm-sdk/types.Coins"];
}

The message handling should fail if:

  • the authority is not the module's authority.
  • the address which receives the coins has no authorization of ReceiveFromTreasuryAuthorization.

Events

EventUpdateDecisionPolicy

EventUpdateDecisionPolicy is an event emitted when the decision policy have been updated.

Attribute Key Attribute Value
decision_policy {decisionPolicy}

EventUpdateMembers

EventUpdateMembers is an event emitted when the foundation members have been updated.

Attribute Key Attribute Value
member_updates {members}

EventLeaveFoundation

EventLeaveFoundation is an event emitted when a foundation member leaves the foundation.

Attribute Key Attribute Value
address {memberAddress}

EventSubmitProposal

EventSubmitProposal is an event emitted when a proposal is submitted.

Attribute Key Attribute Value
proposal {proposal}

EventWithdrawProposal

EventWithdrawProposal is an event emitted when a proposal is withdrawn.

Attribute Key Attribute Value
proposal_id {proposalId}

EventVote

EventVote is an event emitted when a voter votes on a proposal.

Attribute Key Attribute Value
vote {vote}

EventExec

EventExec is an event emitted when a proposal is executed.

Attribute Key Attribute Value
proposal_id {proposalId}
result {result}

EventUpdateCensorship

EventCensorship is an event emitted when a censorship is updated.

Attribute Key Attribute Value
censorship {censorship}

EventGrant

EventGrant is an event emitted when an authorization is granted to a grantee.

Attribute Key Attribute Value
grantee {granteeAddress}
authorization {authorization}

EventRevoke

EventRevoke is an event emitted when an authorization is revoked from a grantee.

Attribute Key Attribute Value
grantee {granteeAddress}
msg_type_url {msgTypeURL}

EventFundTreasury

EventFundTreasury is an event emitted when one funds the treasury.

Attribute Key Attribute Value
from {fromAddress}
amount {amount}

EventWithdrawFromTreasury

EventWithdrawFromTreasury is an event emitted when coins are withdrawn from the treasury.

Attribute Key Attribute Value
to {toAddress}
amount {amount}

Client

CLI

A user can query and interact with the foundation module using the CLI.

Query

The query commands allow users to query foundation state.

simd query foundation --help

params

The params command allows users to query for the parameters of foundation.

simd query foundation params [flags]

Example:

simd query foundation params

Example Output:

params:
  foundation_tax: "0.200000000000000000"

foundation-info

The foundation-info command allows users to query for the foundation info.

simd query foundation foundation-info [flags]

Example:

simd query foundation foundation-info

Example Output:

info:
  decision_policy:
    '@type': /lbm.foundation.v1.ThresholdDecisionPolicy
    threshold: "3.000000000000000000"
    windows:
      min_execution_period: 0s
      voting_period: 86400s
  total_weight: "3.000000000000000000"
  version: "1"

member

The member command allows users to query for a foundation member by address.

simd query foundation member [address] [flags]

Example:

simd query foundation member link1...

Example Output:

member:
  added_at: "0001-01-01T00:00:00Z"
  address: link1...
  metadata: genesis member

members

The members command allows users to query for the foundation members with pagination flags.

simd query foundation members [flags]

Example:

simd query foundation members

Example Output:

members:
- added_at: "0001-01-01T00:00:00Z"
  address: link1...
  metadata: genesis member
- added_at: "0001-01-01T00:00:00Z"
  address: link1...
  metadata: genesis member
- added_at: "0001-01-01T00:00:00Z"
  address: link1...
  metadata: genesis member
pagination:
  next_key: null
  total: "3"

proposal

The proposal command allows users to query for proposal by id.

simd query foundation proposal [id] [flags]

Example:

simd query foundation proposal 1

Example Output:

proposal:
  executor_result: PROPOSAL_EXECUTOR_RESULT_NOT_RUN
  final_tally_result:
    abstain_count: "0.000000000000000000"
    no_count: "0.000000000000000000"
    no_with_veto_count: "0.000000000000000000"
    yes_count: "0.000000000000000000"
  foundation_version: "1"
  id: "1"
  messages:
  - '@type': /lbm.foundation.v1.MsgWithdrawFromTreasury
    authority: link1...
    amount:
    - amount: "1000000000"
      denom: stake
    to: link1...
  metadata: show-me-the-money
  proposers:
  - link1...
  status: PROPOSAL_STATUS_SUBMITTED
  submit_time: "2022-09-19T01:26:38.544943184Z"
  voting_period_end: "2022-09-20T01:26:38.544943184Z"

proposals

The proposals command allows users to query for proposals with pagination flags.

simd query foundation proposals [flags]

Example:

simd query foundation proposals

Example Output:

pagination:
  next_key: null
  total: "1"
proposals:
- executor_result: PROPOSAL_EXECUTOR_RESULT_NOT_RUN
  final_tally_result:
    abstain_count: "0.000000000000000000"
    no_count: "0.000000000000000000"
    no_with_veto_count: "0.000000000000000000"
    yes_count: "0.000000000000000000"
  foundation_version: "1"
  id: "1"
  messages:
  - '@type': /lbm.foundation.v1.MsgWithdrawFromTreasury
    authority: link1...
    amount:
    - amount: "1000000000"
      denom: stake
    to: link1...
  metadata: show-me-the-money
  proposers:
  - link1...
  status: PROPOSAL_STATUS_SUBMITTED
  submit_time: "2022-09-19T01:26:38.544943184Z"
  voting_period_end: "2022-09-20T01:26:38.544943184Z"

vote

The vote command allows users to query for vote by proposal id and voter account address.

simd query foundation vote [proposal-id] [voter] [flags]

Example:

simd query foundation vote 1 link1...

Example Output:

vote:
  metadata: nope
  option: VOTE_OPTION_NO
  proposal_id: "1"
  submit_time: "2022-09-19T01:35:30.920689570Z"
  voter: link1...

votes

The votes command allows users to query for votes by proposal id with pagination flags.

simd query foundation votes [proposal-id] [flags]

Example:

simd query foundation votes 1

Example Output:

pagination:
  next_key: null
  total: "1"
votes:
- metadata: nope
  option: VOTE_OPTION_NO
  proposal_id: "1"
  submit_time: "2022-09-19T01:35:30.920689570Z"
  voter: link1...

tally

The tally command allows users to query for the tally in progress by its proposal id.

simd query foundation tally [proposal-id] [flags]

Example:

simd query foundation tally 1

Example Output:

tally:
  abstain_count: "0.000000000000000000"
  no_count: "1.000000000000000000"
  no_with_veto_count: "0.000000000000000000"
  yes_count: "0.000000000000000000"

censorships

The censorships command allows users to query for all the censorships.

simd query foundation censorships [flags]

Example:

simd query foundation censorships

Example Output:

censorships:
- authority: CENSORSHIP_AUTHORITY_GOVERNANCE
  msg_type_url: /cosmos.staking.v1beta1.MsgCreateValidator
- authority: CENSORSHIP_AUTHORITY_FOUNDATION
  msg_type_url: /lbm.foundation.v1.MsgWithdrawFromTreasury
pagination:
  next_key: null
  total: "2"

grants

The grants command allows users to query grants for a grantee. If the message type URL is set, it selects grants only for that message type.

simd query foundation grants [grantee] [msg-type-url]? [flags]

Example:

simd query foundation grants link1... /lbm.foundation.v1.MsgWithdrawFromTreasury

Example Output:

authorizations:
- '@type': /lbm.foundation.v1.ReceiveFromTreasuryAuthorization
pagination: null

treasury

The treasury command allows users to query for the foundation treasury.

simd query foundation treasury [flags]

Example:

simd query foundation treasury

Example Output:

amount:
- amount: "1000000000000.000000000000000000"
  denom: stake

Transactions

The tx commands allow users to interact with the foundation module.

simd tx foundation --help

Note: Some commands must be signed by the module's authority, which means you cannot broadcast the message directly. The use of those commands is to make it easier to generate the messages by end users.

update-members

The update-members command allows users to update the foundation's members.

simd tx foundation update-members [authority] [members-json] [flags]

Example:

simd tx foundation update-members link1... \
    '[
       {
         "address": "link1...",
         "metadata": "some new metadata"
       },
       {
         "address": "link1...",
         "remove": true,
       }
     ]'

Note: The signer MUST be the module's authority.

update-decision-policy

The update-decision-policy command allows users to update the foundation's decision policy.

simd tx foundation update-decision-policy [authority] [decision-policy-json] [flags]

Example:

simd tx foundation update-decision-policy link1... \
    '{
       "@type": "/lbm.foundation.v1.ThresholdDecisionPolicy",
       "threshold": "4",
       "windows": {
         "voting_period": "1h",
         "min_execution_period": "0s"
       }
     }'

Note: The signer MUST be the module's authority.

submit-proposal

The submit-proposal command allows users to submit a new proposal.

simd tx foundation submit-proposal [metadata] [proposers-json] [messages-json] [flags]

Example:

simd tx foundation submit-proposal show-me-the-money \
    '[
       "link1...",
       "link1..."
     ]' \
    '[
       {
         "@type": "/lbm.foundation.v1.MsgWithdrawFromTreasury",
         "authority": "link1...",
         "to": "link1...",
         "amount": [
           {
             "denom": "stake",
             "amount": "10000000000"
           }
         ]
       }
     ]'

withdraw-proposal

The withdraw-proposal command allows users to withdraw a proposal.

simd tx foundation withdraw-proposal [proposal-id] [authority-or-proposer] [flags]

Example:

simd tx foundation withdraw-proposal 1 link1...

vote

The vote command allows users to vote on a proposal.

simd tx foundation vote [proposal-id] [voter] [option] [metadata] [flags]

Example:

simd tx foundation vote 1 link1... VOTE_OPTION_NO nope

exec

The exec command allows users to execute a proposal.

simd tx foundation exec [proposal-id] [flags]

Example:

simd tx foundation exec 1

leave-foundation

The leave-foundation command allows foundation member to leave the foundation.

simd tx foundation leave-foundation [address] [flags]

Example:

simd tx foundation leave-foundation link1...

update-censorship

The update-censorship command allows users to update a censorship information.

simd tx foundation update-censorship [authority] [msg-type-url] [new-authority] [flags]

Example:

simd tx foundation update-censorship link1.. /lbm.foundation.v1.MsgWithdrawFromTreasury CENSORSHIP_AUTHORITY_UNSPECIFIED

Note: The signer MUST be the current authority of the censorship.

grant

The grant command allows users to grant an authorization to a grantee.

simd tx foundation grant [authority] [grantee] [authorization-json] [flags]

Example:

simd tx foundation grant link1.. link1... \
    '{
       "@type": "/lbm.foundation.v1.ReceiveFromTreasuryAuthorization",
     }'

Note: The signer MUST be the authority of the censorship.

revoke

The revoke command allows users to revoke an authorization from a grantee.

simd tx foundation revoke [authority] [grantee] [msg-type-url] [flags]

Example:

simd tx foundation revoke link1.. link1... /lbm.foundation.v1.MsgWithdrawFromTreasury

Note: The signer MUST be the authority of the censorship.

fund-treasury

The fund-treasury command allows users to fund the foundation treasury.

simd tx foundation fund-treasury [from] [amount] [flags]

Example:

simd tx foundation fund-treasury link1.. 1000stake

withdraw-from-treasury

The withdraw-from-treasury command allows users to withdraw coins from the foundation treasury.

simd tx foundation withdraw-from-treasury [authority] [to] [amount] [flags]

Example:

simd tx foundation withdraw-from-treasury link1.. link1... 1000stake

Note: The signer MUST be the module's authority.

gRPC

A user can query the foundation module using gRPC endpoints.

grpcurl -plaintext \
    localhost:9090 list lbm.foundation.v1.Query

Params

The Params endpoint allows users to query for the parameters of foundation.

lbm.foundation.v1.Query/Params

Example:

grpcurl -plaintext \
    localhost:9090 lbm.foundation.v1.Query/Params

Example Output:

{
  "params": {
    "foundationTax": "200000000000000000"
  }
}

FoundationInfo

The FoundationInfo endpoint allows users to query for the foundation info.

lbm.foundation.v1.Query/FoundationInfo

Example:

grpcurl -plaintext \
    localhost:9090 lbm.foundation.v1.Query/FoundationInfo

Example Output:

{
  "info": {
    "version": "1",
    "totalWeight": "3000000000000000000",
    "decisionPolicy": {"@type":"/lbm.foundation.v1.ThresholdDecisionPolicy","threshold":"3000000000000000000","windows":{"votingPeriod":"86400s","minExecutionPeriod":"0s"}}
  }
}

Member

The Member endpoint allows users to query for a foundation member by address.

lbm.foundation.v1.Query/Member

Example:

grpcurl -plaintext \
    -d '{"address": "link1..."}'
    localhost:9090 lbm.foundation.v1.Query/Member

Example Output:

{
  "member": {
    "address": "link1...",
    "metadata": "genesis member",
    "addedAt": "0001-01-01T00:00:00Z"
  }
}

Members

The Members endpoint allows users to query for the foundation members with pagination flags.

lbm.foundation.v1.Query/Members

Example:

grpcurl -plaintext \
    localhost:9090 lbm.foundation.v1.Query/Members

Example Output:

{
  "members": [
    {
      "address": "link1...",
      "metadata": "genesis member",
      "addedAt": "0001-01-01T00:00:00Z"
    },
    {
      "address": "link1...",
      "metadata": "genesis member",
      "addedAt": "0001-01-01T00:00:00Z"
    },
    {
      "address": "link1...",
      "metadata": "genesis member",
      "addedAt": "0001-01-01T00:00:00Z"
    }
  ],
  "pagination": {
    "total": "3"
  }
}

Proposal

The Proposal endpoint allows users to query for proposal by id.

lbm.foundation.v1.Query/Proposal

Example:

grpcurl -plaintext \
    -d '{"proposal_id": "1"}' \
    localhost:9090 lbm.foundation.v1.Query/Proposal

Example Output:

{
  "proposal": {
    "id": "1",
    "metadata": "show-me-the-money",
    "proposers": [
      "link1..."
    ],
    "submitTime": "2022-09-19T01:26:38.544943184Z",
    "foundationVersion": "1",
    "status": "PROPOSAL_STATUS_SUBMITTED",
    "finalTallyResult": {
      "yesCount": "0",
      "abstainCount": "0",
      "noCount": "0",
      "noWithVetoCount": "0"
    },
    "votingPeriodEnd": "2022-09-20T01:26:38.544943184Z",
    "executorResult": "PROPOSAL_EXECUTOR_RESULT_NOT_RUN",
    "messages": [
      {"@type":"/lbm.foundation.v1.MsgWithdrawFromTreasury","authority":"link1...","amount":[{"denom":"stake","amount":"1000000000"}],"to":"link1..."}
    ]
  }
}

Proposals

The Proposals endpoint allows users to query for proposals with pagination flags.

lbm.foundation.v1.Query/Proposals

Example:

grpcurl -plaintext \
    localhost:9090 lbm.foundation.v1.Query/Proposals

Example Output:

{
  "proposals": [
    {
      "id": "1",
      "metadata": "show-me-the-money",
      "proposers": [
        "link1..."
      ],
      "submitTime": "2022-09-19T01:26:38.544943184Z",
      "foundationVersion": "1",
      "status": "PROPOSAL_STATUS_SUBMITTED",
      "finalTallyResult": {
        "yesCount": "0",
        "abstainCount": "0",
        "noCount": "0",
        "noWithVetoCount": "0"
      },
      "votingPeriodEnd": "2022-09-20T01:26:38.544943184Z",
      "executorResult": "PROPOSAL_EXECUTOR_RESULT_NOT_RUN",
      "messages": [
        {"@type":"/lbm.foundation.v1.MsgWithdrawFromTreasury","authority":"link1...","amount":[{"denom":"stake","amount":"1000000000"}],"to":"link1..."}
      ]
    }
  ],
  "pagination": {
    "total": "1"
  }
}

Vote

The Vote endpoint allows users to query for vote by proposal id and voter account address.

lbm.foundation.v1.Query/Vote

Example:

grpcurl -plaintext \
    -d '{"proposal_id": "1", "voter": "link1..."}' \
    localhost:9090 lbm.foundation.v1.Query/Vote

Example Output:

{
  "vote": {
    "proposalId": "1",
    "voter": "link1...",
    "option": "VOTE_OPTION_NO",
    "metadata": "nope",
    "submitTime": "2022-09-19T01:35:30.920689570Z"
  }
}

Votes

The Votes endpoint allows users to query for votes by proposal id with pagination flags.

lbm.foundation.v1.Query/Votes

Example:

grpcurl -plaintext \
    -d '{"proposal_id": "1"}' \
    localhost:9090 lbm.foundation.v1.Query/Votes

Example Output:

{
  "votes": [
    {
      "proposalId": "1",
      "voter": "link1...",
      "option": "VOTE_OPTION_NO",
      "metadata": "nope",
      "submitTime": "2022-09-19T01:35:30.920689570Z"
    }
  ],
  "pagination": {
    "total": "1"
  }
}

TallyResult

The TallyResult endpoint allows users to query for the tally in progress by its proposal id.

lbm.foundation.v1.Query/Vote

Example:

grpcurl -plaintext \
    -d '{"proposal_id": "1"}' \
    localhost:9090 lbm.foundation.v1.Query/TallyResult

Example Output:

{
  "tally": {
    "yesCount": "0",
    "abstainCount": "0",
    "noCount": "1000000000000000000",
    "noWithVetoCount": "0"
  }
}

Censorships

The Censorships endpoint allows users to query for all the censorships.

lbm.foundation.v1.Query/Censorships

Example:

grpcurl -plaintext \
    localhost:9090 lbm.foundation.v1.Query/Censorships

Example Output:

{
  "censorships": [
    {
      "msgTypeUrl": "/cosmos.staking.v1beta1.MsgCreateValidator",
      "authority": "CENSORSHIP_AUTHORITY_GOVERNANCE"
    },
    {
      "msgTypeUrl": "/lbm.foundation.v1.MsgWithdrawFromTreasury",
      "authority": "CENSORSHIP_AUTHORITY_FOUNDATION"
    }
  ],
  "pagination": {
    "total": "2"
  }
}

Grants

The Grants endpoint allows users to query grants for a grantee. If the message type URL is set, it selects grants only for that message type.

lbm.foundation.v1.Query/Grants

Example:

grpcurl -plaintext \
    -d '{"grantee": "link1...", "msg_type_url": "/lbm.foundation.v1.MsgWithdrawFromTreasury"}' \
    localhost:9090 lbm.foundation.v1.Query/Grants

Example Output:

{
  "authorizations": [
    {"@type":"/lbm.foundation.v1.ReceiveFromTreasuryAuthorization"}
  ]
}

Treasury

The Treasury endpoint allows users to query for the foundation treasury.

lbm.foundation.v1.Query/Treasury

Example:

grpcurl -plaintext \
    localhost:9090 lbm.foundation.v1.Query/Treasury

Example Output:

{
  "amount": [
    {
      "denom": "stake",
      "amount": "1000000000000000000000000000000"
    }
  ]
}