The Sanction Module allows management of a list of sanctioned accounts that are prevented from sending or spending any funds. It injects a restriction into the
x/bank
module to enforce these sanctions.QuickstartgRPCCLITransactionsQueriesIsSanctionedSanctionedAddressesTemporaryEntriesParamsRESTConceptsSanctioned AccountImmediate Temporary SanctionsUnsanctioningImmediate Temporary UnsanctionsUnsanctionable AddressesParamsComplex InteractionsConflicting Messages in a ProposalConflicting Governance ProposalsStateParamsSanctioned AccountsTemporary EntriesTemporary IndexMessagesMsgSanctionExpected FailuresMsgUnsanctionExpected FailuresMsgUpdateParamsExpected FailuresEventsEventAddressSanctionedEventAddressUnsanctionedEventTempAddressSanctionedEventTempAddressUnsanctionedEventParamsUpdatedQueriesIsSanctionedQueryIsSanctionedRequestQueryIsSanctionedResponseSanctionedAddressesQuerySanctionedAddressesRequestQuerySanctionedAddressesResponseTemporaryEntriesQueryTemporaryEntriesRequestQueryTemporaryEntriesResponseParamsQueryParamsRequestQueryParamsResponseParams
Quickstart
The Provenance Blockchain sanction module provides comprehensive client interfaces through gRPC, CLI, and REST endpoints for managing and querying sanction functionality. Users can interact with the module using gRPC for direct protocol communication, command-line interface tools for transaction management through governance proposals and sanction status queries with convenient aliases and pagination support, and REST endpoints for HTTP-based access to all sanction query operations including individual account sanction checks, sanctioned address listings, temporary entry queries, and parameter retrieval with standard pagination capabilities.
gRPC
A user can interact with and query the x/sanction module using gRPC.
For details see Queries.
CLI
The gRPC transaction and query endpoints are made available through CLI helpers.
Transactions
The transaction endpoints are only for use with governance proposals. As such, the CLI's
tx gov
commands can be used to interact with them.Queries
Each of these commands facilitates running a gRPC query. Standard query flags are available unless otherwise noted.
IsSanctioned
shell$ simd query sanction is-sanctioned --help Check if an address is sanctioned. Examples: $ simd query sanction is-sanctioned cosmos1v4uxzmtsd3j4zat9wfu5zerywgc47h6luruvdf $ simd query sanction is cosmos1v4uxzmtsd3j4zat9wfu5zerywgc47h6luruvdf $ simd query sanction check cosmos1v4uxzmtsd3j4zat9wfu5zerywgc47h6luruvdf Usage: simd query sanction is-sanctioned <address> [flags] Aliases: is-sanctioned, is, check, is-sanction
SanctionedAddresses
shell$ simd query sanction sanctioned-addresses --help List all the sanctioned addresses. Examples: $ simd query sanction sanctioned-addresses $ simd query sanction addresses $ simd query sanction all Usage: simd query sanction sanctioned-addresses [flags] Aliases: sanctioned-addresses, addresses, all
Standard pagination flags are also available for this command.
TemporaryEntries
shellsimd query sanction temporary-entries --help List all temporarily sanctioned/unsanctioned addresses. If an address is provided, only temporary entries for that address are returned. Otherwise, all temporary entries are returned. Examples: $ simd query sanction temporary-entries $ simd query sanction temporary-entries cosmos1v4uxzmtsd3j4zat9wfu5zerywgc47h6luruvdf $ simd query sanction temp-entries $ simd query sanction temp-entries cosmos1v4uxzmtsd3j4zat9wfu5zerywgc47h6luruvdf $ simd query sanction temp $ simd query sanction temp cosmos1v4uxzmtsd3j4zat9wfu5zerywgc47h6luruvdf Usage: simd query sanction temporary-entries [<address>] [flags] Aliases: temporary-entries, temp-entries, temp
Standard pagination flags are also available for this command.
Params
shell$ simd query sanction params --help Get the sanction module params. Example: $ simd query sanction params Usage: simd query sanction params [flags]
REST
Each of the sanction gRPC query endpoints is also available through one or more REST endpoints.
Name | URL |
IsSanctioned | /cosmos/sanction/v1beta1/check/{address} |
SanctionedAddresses | /cosmos/sanction/v1beta1/all |
TemporaryEntries - all | /cosmos/sanction/v1beta1/temp |
TemporaryEntries - specific | /cosmos/sanction/v1beta1/temp?address={address} |
Params | /cosmos/sanction/v1beta1/params |
For
SanctionedAddresses
and TemporaryEntries
, pagination parameters can be provided using the standard pagination query parameters.Concepts
The Provenance Blockchain sanction module provides governance-controlled mechanisms for freezing accounts by preventing fund removal while allowing incoming transfers, implementing both permanent sanctions through governance proposals and immediate temporary sanctions triggered by deposit thresholds that take effect before voting concludes. The system supports complex interactions between multiple proposals with different sanction and unsanction messages, includes protections for unsanctionable addresses like fee collectors, and uses configurable parameters to control immediate sanction thresholds, with temporary sanctions being resolved when governance proposals conclude and permanent sanctions remaining until explicitly removed through unsanction proposals.
Sanctioned Account
An account becomes sanctioned when a governance proposal is passed with a
MsgSanction
in it containing the account's address.When an account is sanctioned, funds cannot be removed from it. The funds cannot be sent to another account. They cannot be spent either (e.g. on Tx fees).
Funds can be sent to a sanctioned account, but would then be immediately frozen in that account.
Sanctioning is enforced as a restriction injected into the x/bank send keeper and prevents removal of funds from an account. A sanctioned account is otherwise unchanged.
When an attempt is made to remove funds from a sanctioned account, an error is returned indicating that the account is sanctioned.
Immediate Temporary Sanctions
Immediate Temporary Sanctions (sometimes called just "immediate sanctions" or "temporary sanctions") are possible. They happen when a
MsgSanction
governance proposal has a large enough deposit. They also happen if a deposit is added after proposal submittal that puts the proposal's total deposit over the threshold.This deposit threshold is managed as a module parameter:
ImmediateSanctionMinDeposit
.- If zero or empty, immediate sanctions are not possible
- If set to the governance proposal minimum deposit or less (not recommended), all
MsgSanction
governance proposals put to a vote will create immediate temporary sanctions
- If set to more than the governance proposal minimum deposit (this is recommended), it's possible to submit a
MsgSanction
proposal without the sanctions being immediate
Immediate temporary sanctions are associated with both the governance proposal and address in question. They expire once the governance proposal is resolved (e.g. the voting period ends). If the proposal passes, permanent sanctions are enacted and any temporary entries for each address are removed. If the proposal does not pass, any temporary entries associated with that proposal are removed.
Note: The phrase "permanent sanction" is used in here as a counterpart to "temporary sanction". It is "permanent" only in the sense that it isn't temporary. It is not "permanent" in the sense that it is possible to be undone (e.g. with a
MsgUnsanction
).Unsanctioning
A
MsgUnsanction
can be used in a governance proposal to unsanction accounts. Once an account is unsanctioned, it can again send or spend its funds.Immediate Temporary Unsanctions
Similar to immediate temporary sanctions, these are created when a
MsgUnsanction
proposal has a large enough deposit (either initially or later).This deposit threshold is managed as a module parameter:
ImmediateUnsanctionMinDeposit
.- If zero or empty, immediate unsanctions are not possible
- If set to the governance proposal minimum deposit or less (not recommended), all
MsgUnsanction
governance proposals put to a vote will create immediate temporary unsanctions
- If set to more than the governance proposal minimum deposit (this is recommended), it's possible to submit a
MsgUnsanction
proposal without the unsanctions being immediate
Immediate temporary unsanctions are associated with both the governance proposal and address in question. They expire once the governance proposal is resolved (e.g. the voting period ends). If the proposal passes, permanent sanctions are removed and any temporary entries for each address are removed. If the proposal does not pass, any temporary entries associated with that proposal are removed.
Unsanctionable Addresses
When creating the sanction keeper, a list of addresses of unsanctionable accounts can be provided.
An attempt to sanction or enact an immediate temporary sanction on an address in that list results in the error: "address cannot be sanctioned".
An example of an account that should not be sanctionable is the fee collector.
Params
The x/sanction module has some params that can be defined in state.
ImmediateSanctionMinDeposit
is the minimum deposit required for immediate temporary sanctions to be enacted for addresses in aMsgSanction
ImmediateUnsanctionMinDeposit
is the minimum deposit required for immediate temporary unsanctions to be enacted for addresses in aMsgUnsanction
If not defined in state, the following variables are used (defined in
x/sanction/sanction.go
):DefaultImmediateSanctionMinDeposit
DefaultImmediateUnsanctionMinDeposit
By default, those have a value of
nil
which makes it impossible to enact immediate temporary sanctions or unsanctions. They are public, though, so consuming chains can change them as desired.The default variables are only used if the state entry does not exist. If the entry exists, but is empty, that empty value is used.
It is recommended that both of these minimum deposits be significantly larger than the governance proposal minimum deposit. This is to prevent malicious use of immediate temporary sanctions or unsanctions.
Complex Interactions
It's possible to end up with some complex interactions due to multiple
MsgSanction
and MsgUnsanction
messages with large enough deposits for temporary effects. In a general sense, the last one takes precedence.Conflicting Messages in a Proposal
When a proposal has multiple messages, they are processed in the order they are listed in the proposal. So if a governance proposal contains both a
MsgSanction
and MsgUnsanction
, and one or more addresses are listed in both, then, the last message they're in takes precedence.For example, say a proposal has, a
MsgSanction
for accounts A, B, and C, then a MsgUnsanction
for accounts B, C, and D. And the proposal has enough of a deposit for both immediate sanctions and unsanctions. There will be 4 temporary entries: account A will have a temporary sanction; and B, C, and D will have temporary unsanctions. If the proposal passes, a permanent sanction will be placed on A, and accounts B, C, and D will have their sanctions removed.If a proposal contains both a
MsgSanction
and MsgUnsanction
and the total deposit is enough for immediate temporary entries of one type, but not the other, the temporary entries are enacted for the one, but not the other. If later, more deposit is added so there's enough for both, the others will then be enacted too.Conflicting Governance Proposals
If multiple governance proposals have immediate temporary effects, the effect from the proposal with the largest id takes precedence. Voting period start and end times/heights are not taken into account, only the proposal id.
For example, let's say proposal 3 has a
MsgSanction
for accounts A, B, and C; and proposal 5 has a MsgUnsanction
for accounts B, C, and D. Both have large enough deposits for immediate effects. There will be six temporary entries, A+3, B+3, C+3, B+5, C+5, and D+5. But the temporary entries for accounts B and C from prop 3 are ignored because of their prop 5 entries. In effect, account A will have a temporary sanction; and accounts, B, C, and D will have temporary unsanctions.Scenarios:
- Prop 3 passes while prop 5 is still being voted on: All temporary entries for accounts A, B, and C are removed, and those accounts are permanently sanctioned. The only temporary entry left will be an unsanction for account D.
- Prop 3 does not pass while prop 5 is still being voted on: The temporary sanction entries for accounts A, B, and C are removed leaving temporary unsanction entries for B, C, and D. No permanent sanctions are enacted.
- Prop 5 passes while prop 3 is still being voted on: All temporary entries for accounts B, C, and D are removed and permanent sanctions are also removed for those accounts. The only temporary entry left will be a sanction on account A.
- Prop 5 does not pass while prop 3 is still being voted on: The temporary unsanction entries for accounts B, C, and D are removed leaving temporary sanction entries for A, B, and C. If accounts B, C, or D were previously permanently sanctioned, those sanctions remain.
State
The Provenance Blockchain sanction module uses a structured key/value storage system to manage sanction-related data, including module parameters for controlling immediate sanction thresholds stored as SDK coins, sanctioned account records that track permanent sanctions with simple binary flags, temporary entries that associate governance proposal IDs with specific sanction or un-sanction actions on addresses, and corresponding temporary index records that enable efficient cleanup and lookup operations when proposals are resolved or accounts are permanently sanctioned or unsanctioned.
Params
Each param field is stored in its own record with this format:
plain text0x00 | []byte(<param name>) -> []byte(<param value>)
Param Field | <param name> | <param value> format |
ImmediateSanctionMinDeposit | immediate_sanction_min_deposit | sdk.Coins.String() |
ImmediateUnsanctionMinDeposit | immediate_unsanction_min_deposit | sdk.Coins.String() |
Sanctioned Accounts
When an account is sanctioned, the following record is made:
plain text0x01 | len([]byte(<account address>)) | []byte(<account address>) -> 0x01
When an account is unsanctioned, that record is deleted.
Temporary Entries
Immediate temporary sanctions and/or unsanctions are enacted by creating the following record:
plain text0x02 | len([]byte(<account address>)) | []byte(<account address>) | [8]byte(<gov prop id>) -> byte(<value>)
Entry type | <value> |
Sanction | 0x01 |
Unsanction | 0x00 |
When an account is sanctioned or unsanctioned, all temporary entry records for the address are removed. If a proposal does not pass, all temporary entry records for that proposal are removed.
Temporary Index
When a temporary entry is created, the following index record is also created:
plain text0x03 | [8]byte(<gov prop id>) | len([]byte(<account address>)) | []byte(<account address>) -> byte(<value>)
The same
<value>
is used as the correlated temporary entry.Temporary index records are removed when their correlated temporary entry record is removed.
Messages
The Provenance Blockchain sanction module provides governance-controlled message services for managing account sanctions through three primary message types: MsgSanction for requesting account sanctions with deposit-triggered immediate temporary sanctions and permanent sanctions upon proposal passage, MsgUnsanction for requesting account unsanctions with similar immediate temporary effects and permanent sanction removal, and MsgUpdateParams for updating module parameters through governance proposals. All messages require proper authority validation and include comprehensive error handling for invalid addresses, unsanctionable accounts, and parameter validation, with temporary sanctions expiring at governance proposal completion regardless of voting outcome.
MsgSanction
A user can request that accounts be sanctioned by submitting a governance proposal containing a
MsgSanction
. It contains the list of addresses
of accounts to be sanctioned and the authority
able to do it.protobuf// Source: https://github.com/provenance-io/provenance/blob/v1.19.0/proto/cosmos/sanction/v1beta1/tx.proto#L22-L32 message MsgSanction { option (cosmos.msg.v1.signer) = "authority"; // The list of addresses to sanction. repeated string addresses = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // The authority able to sanction accounts. string authority = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; }
If the proposal ever has enough total deposit (defined in params), immediate temporary sanctions are issued for each address. Temporary sanctions expire at the completion of the governance proposal regardless of outcome.
If the proposal passes, permanent sanctions are enacted for each address and temporary entries for each address are removed. Otherwise, any temporary entries associated with the governance proposal are removed.
Expected Failures
It is expected to fail if:
- The
authority
provided does not equal the authority defined for the x/sanction module's keeper. This is most often the address of the x/gov module's account
- Any
addresses
are not valid bech32 encoded address strings
- Any
addresses
are unsanctionable
MsgUnsanction
A user can request that accounts be unsanctioned by submitting a governance proposal containing a
MsgUnsanction
. It contains the list of addresses
of accounts to be unsanctioned and the authority
able to do it.protobuf// Source: https://github.com/provenance-io/provenance/blob/v1.19.0/proto/cosmos/sanction/v1beta1/tx.proto#L37-L47 message MsgUnsanction { option (cosmos.msg.v1.signer) = "authority"; // The list of addresses to unsanction. repeated string addresses = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // The authority able to unsanction accounts. string authority = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; }
If the proposal ever has enough total deposit (defined in params), immediate temporary unsanctions are issued for each address. Temporary unsanctions expire at the completion of the governance proposal regardless of outcome.
If the proposal passes, permanent sanctions are removed for each address and temporary entries for each address are also removed. Otherwise, any temporary entries associated with the governance proposal are removed.
Expected Failures
It is expected to fail if:
- The
authority
provided does not equal the authority defined for the x/sanction module's keeper. This is most often the address of the x/gov module's account
- Any
addresses
are not valid bech32 encoded address strings
MsgUpdateParams
The sanction module params can be updated by submitting a governance proposal containing a
MsgUpdateParams
. It contains the desired new params
and the authority
able to update them.protobuf// Source: https://github.com/provenance-io/provenance/blob/v1.19.0/proto/cosmos/sanction/v1beta1/tx.proto#L52-L62 message MsgUpdateParams { option (cosmos.msg.v1.signer) = "authority"; // The new parameters for the sanction module. Params params = 1; // The authority able to update params. string authority = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; }
If
params
is null
, they will be deleted from state, reverting them to their code-defined defaults.If a field in
params
is null
or empty, the record in state will reflect that.Expected Failures
It is expected to fail if:
- The
authority
provided does not equal the authority defined for the x/sanction module's keeper. This is most often the address of the x/gov module's account
- Any params are invalid
Events
The Provenance Blockchain sanction module emits five distinct events to track the complete lifecycle of sanction operations: EventAddressSanctioned and EventAddressUnsanctioned for permanent sanction and unsanction actions, EventTempAddressSanctioned and EventTempAddressUnsanctioned for immediate temporary sanction operations triggered by governance proposal deposits, and EventParamsUpdated for module parameter changes. These events provide comprehensive visibility into both permanent and temporary sanction state changes, enabling applications to track account restrictions and monitor governance-driven sanction management activities throughout the proposal and execution process.
EventAddressSanctioned
This event is emitted when an account is sanctioned.
@Type:
/cosmos.sanction.v1beta1.EventAddressSanctioned
Attribute Key | Attribute Value |
address | {bech32 string of sanctioned account} |
EventAddressUnsanctioned
This event is emitted when an account is unsanctioned.
@Type:
/cosmos.sanction.v1beta1.EventAddressUnsanctioned
Attribute Key | Attribute Value |
address | {bech32 string of unsanctioned account} |
EventTempAddressSanctioned
This event is emitted when a temporary sanction is placed on an account.
@Type:
/cosmos.sanction.v1beta1.EventTempAddressSanctioned
Attribute Key | Attribute Value |
address | {bech32 string of sanctioned account} |
EventTempAddressUnsanctioned
This event is emitted when a temporary unsanction is placed on an account.
@Type:
/cosmos.sanction.v1beta1.EventTempAddressUnsanctioned
Attribute Key | Attribute Value |
address | {bech32 string of unsanctioned account} |
EventParamsUpdated
This event is emitted when the x/sanction module's params are updated.
@Type:
/cosmos.sanction.v1beta1.EventParamsUpdated
Attribute Key | Attribute Value |
(none) |
Queries
The Provenance Blockchain sanction module provides a comprehensive query service for inspecting sanction status and managing sanction-related data across the network. The query service includes endpoints for checking individual account sanction status, retrieving lists of all sanctioned addresses with pagination support, querying temporary sanction and unsanction entries associated with governance proposals, and accessing module parameters that control immediate sanction thresholds, enabling applications to monitor and manage account restrictions throughout the governance-driven sanction lifecycle.
IsSanctioned
Checks if an account has been sanctioned.
HTTP Endpoint:
GET /cosmos/sanction/v1beta1/check/{address}
Request:
QueryIsSanctionedRequest
Response: QueryIsSanctionedResponse
QueryIsSanctionedRequest
protobuf// Source: https://github.com/provenance-io/provenance // QueryIsSanctionedRequest defines the RPC request for checking if an account is sanctioned. message QueryIsSanctionedRequest { string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; }
QueryIsSanctionedResponse
protobuf// Source: https://github.com/provenance-io/provenance // QueryIsSanctionedResponse defines the RPC response of an IsSanctioned query. message QueryIsSanctionedResponse { // is_sanctioned is true if the address is sanctioned. bool is_sanctioned = 1; }
SanctionedAddresses
Returns a list of sanctioned addresses.
HTTP Endpoint:
GET /cosmos/sanction/v1beta1/all
Request:
QuerySanctionedAddressesRequest
Response: QuerySanctionedAddressesResponse
QuerySanctionedAddressesRequest
protobuf// Source: https://github.com/provenance-io/provenance // QuerySanctionedAddressesRequest defines the RPC request for listing sanctioned accounts. message QuerySanctionedAddressesRequest { // pagination defines an optional pagination for the request. cosmos.base.query.v1beta1.PageRequest pagination = 99; }
QuerySanctionedAddressesResponse
protobuf// Source: https://github.com/provenance-io/provenance // QuerySanctionedAddressesResponse defines the RPC response of a SanctionedAddresses query. message QuerySanctionedAddressesResponse { // addresses is the list of sanctioned account addresses. repeated string addresses = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // pagination defines the pagination in the response. cosmos.base.query.v1beta1.PageResponse pagination = 99; }
TemporaryEntries
Returns temporary sanction/unsanction info.
HTTP Endpoint:
GET /cosmos/sanction/v1beta1/temp
Request:
QueryTemporaryEntriesRequest
Response: QueryTemporaryEntriesResponse
QueryTemporaryEntriesRequest
protobuf// Source: https://github.com/provenance-io/provenance // QueryTemporaryEntriesRequest defines the RPC request for listing temporary sanction/unsanction entries. message QueryTemporaryEntriesRequest { // address is an optional address to restrict results to. string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // pagination defines an optional pagination for the request. cosmos.base.query.v1beta1.PageRequest pagination = 99; }
QueryTemporaryEntriesResponse
protobuf// Source: https://github.com/provenance-io/provenance // QueryTemporaryEntriesResponse defines the RPC response of a TemporaryEntries query. message QueryTemporaryEntriesResponse { repeated TemporaryEntry entries = 1; // pagination defines the pagination in the response. cosmos.base.query.v1beta1.PageResponse pagination = 99; }
Params
Returns the sanction module's params.
HTTP Endpoint:
GET /cosmos/sanction/v1beta1/params
Request:
QueryParamsRequest
Response: QueryParamsResponse
QueryParamsRequest
protobuf// Source: https://github.com/provenance-io/provenance // QueryParamsRequest defines the RPC request for getting the sanction module params. message QueryParamsRequest {}
QueryParamsResponse
protobuf// Source: https://github.com/provenance-io/provenance // QueryParamsResponse defines the RPC response of a Params query. message QueryParamsResponse { // params are the sanction module parameters. Params params = 1; }
protobuf// Example Query Service Definition // Source: https://github.com/provenance-io/provenance service Query { // IsSanctioned checks if an account has been sanctioned. rpc IsSanctioned(QueryIsSanctionedRequest) returns (QueryIsSanctionedResponse) { option (google.api.http).get = "/cosmos/sanction/v1beta1/check/{address}"; } // SanctionedAddresses returns a list of sanctioned addresses. rpc SanctionedAddresses(QuerySanctionedAddressesRequest) returns (QuerySanctionedAddressesResponse) { option (google.api.http).get = "/cosmos/sanction/v1beta1/all"; } // TemporaryEntries returns temporary sanction/unsanction info. rpc TemporaryEntries(QueryTemporaryEntriesRequest) returns (QueryTemporaryEntriesResponse) { option (google.api.http).get = "/cosmos/sanction/v1beta1/temp"; } // Params returns the sanction module's params. rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { option (google.api.http).get = "/cosmos/sanction/v1beta1/params"; } }
Params
No param restrictions exist for the sanction module.