Skip to content

Commit

Permalink
docs: cw-hooks & staking integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Reecepbcups committed Oct 3, 2023
1 parent 3d998da commit 2cdbb2a
Show file tree
Hide file tree
Showing 11 changed files with 326 additions and 43 deletions.
9 changes: 1 addition & 8 deletions x/cw-hooks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,4 @@

This module allows smart contracts to execute logic when staking / validator events occur without any custom bindings.

[Juno Staking Hooks Spec](./spec/README.md)

---

junod tx cw-hooks register-staking juno1qsrercqegvs4ye0yqg93knv73ye5dc3prqwd6jcdcuj8ggp6w0us66deup --from juno1 --keyring-backend=test --home $HOME/.juno1/ --chain-id local-1 --fees 500ujuno --yes
junod tx cw-hooks register-staking juno15u3dt79t6sxxa3x3kpkhzsy56edaa5a66wvt3kxmukqjz2sx0hes5sn38g --from juno1 --keyring-backend=test --home $HOME/.juno1/ --chain-id local-1 --fees 500ujuno --yes

junod q cw-hooks staking-contracts
[Juno CW Hooks Spec](./spec/README.md)
26 changes: 26 additions & 0 deletions x/cw-hooks/spec/00_concepts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Concepts

## CW-Hooks

The CW-Hooks module (CosmWasm Hooks) is an event based module which allowed developers to subscribe to wallet specific actions on Juno. This allows developers to write applications which need to following staking or governance actions for any account who performs them.

Some Examples could include:

Gov:

- When an account votes, send them 1 of your token-factory token.
- When a new proposal on the main chain is created, update your contract to allow for secondary voting through a contract or DAO.

Staking:

- When a user delegates tokens to a validator, update their new balance in the contract. This allows for synthetic DAO voting power relative to their chain stake
- Before and After a validator is slashed, auto update a vesting contract to slash the receiver of funds.
- When a validator gets into the active set, update your contract to remove the old validator.

## Registration

Developers register their contract(s) to receive fire-and-forget messages from the CW-Hooks module. This allows developers to write applications which need to following staking or governance actions for any account who performs them. Including standard wallets, DAOs, and other contracts.

### Limitations

By default, your contract can only perform 250,000 Gas execution per event. This is to prevent malicious contracts from spamming the network since all executes are feeless. If you need to perform more than 250,000 Gas execution, you can submit a proposal to increase this.
3 changes: 0 additions & 3 deletions x/cw-hooks/spec/01_authorization.md

This file was deleted.

50 changes: 50 additions & 0 deletions x/cw-hooks/spec/01_clients.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Clients

## Command Line Interface

Find below a list of `junod` commands added with the `x/cw-hooks` module. You can obtain the full list by using the `junod -h` command. A CLI command can look like this:

```bash
junod query cw-hooks params
```

### Queries

| Command | Subcommand | Description |
| :----------------- | :--------------------- | :--------------------------------------- |
| `query` `cw-hooks` | `params` | Get module params |
| `query` `cw-hooks` | `governance-contracts` | Get registered governance contracts |
| `query` `cw-hooks` | `staking-contracts` | Get registered staking contracts |

### Transactions

| Command | Subcommand | Description |
| :-------------- | :--------- | :----------------------------------------------------- |
| `tx` `cw-hooks` | `register-governance` | Register a contract for gov events |
| `tx` `cw-hooks` | `unregister-governance` | Unregister a contract from gov events |
| `tx` `cw-hooks` | `register-staking` | Register a contract for staking events |
| `tx` `cw-hooks` | `unregister-staking` | Unregister a contract from staking events |

## gRPC Queries

| Verb | Method |
| :----- | :------------------------------------------------ |
| `gRPC` | `juno.cwhooks.v1.Query/Params` |
| `gRPC` | `juno.cwhooks.v1.Query/StakingContracts` |
| `gRPC` | `juno.cwhooks.v1.Query/GovernanceContracts` |
| `GET` | `/juno/cwhooks/v1/params` |
| `GET` | `/juno/cwhooks/v1/staking_contracts` |
| `GET` | `/juno/cwhooks/v1/governance_contracts` |

### gRPC Transactions

| Verb | Method |
| :----- | :------------------------------------------ |
| `gRPC` | `juno.cwhooks.v1.Msg/RegisterStaking` |
| `gRPC` | `juno.cwhooks.v1.Msg/UnregisterStaking` |
| `gRPC` | `juno.cwhooks.v1.Msg/RegisterGovernance` |
| `gRPC` | `juno.cwhooks.v1.Msg/UnregisterGovernance` |
| `POST` | `/juno/cwhooks/v1/tx/register_staking` |
| `POST` | `/juno/cwhooks/v1/tx/unregister_staking` |
| `POST` | `/juno/cwhooks/v1/tx/register_governance` |
| `POST` | `/juno/cwhooks/v1/tx/unregister_governance` |
29 changes: 0 additions & 29 deletions x/cw-hooks/spec/02_integration.md

This file was deleted.

34 changes: 34 additions & 0 deletions x/cw-hooks/spec/02_state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# State

## State Objects

The `x/cw-hooks` module keeps the following objects in the state:

| State Object | Description | Key | Value | Store |
| :-------------------- | :------------------------------------ | :---------------------------------------------------------------- | :----------------- | :---- |
| `Staking Contract` | contract registered for staking events| `[]byte{"staking"} + []byte(contract_address)` | `[]byte{}` | KV |
| `Governance Contract` | contract registered for gov events | `[]byte{"gov"} + []byte(contract_address)` | `[]byte{}` | KV |

### ContractAddress

`ContractAddress` defines the contract address that has been registered for fee distribution.

## Genesis State

The `x/cw-hooks` module's `GenesisState` defines the state necessary for initializing the chain from a previously exported height. It contains the module parameters and all registered contracts:

```go
type Params struct {
// contract_gas_limit is the contract call gas limit
ContractGasLimit uint64 `protobuf:"varint,1,opt,name=contract_gas_limit,json=contractGasLimit,proto3" json:"contract_gas_limit,omitempty" yaml:"contract_gas_limit"`
}

// GenesisState defines the module's genesis state.
type GenesisState struct {
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"`

StakingContractAddresses []string `protobuf:"bytes,2,rep,name=staking_contract_addresses,json=stakingContractAddresses,proto3" json:"staking_contract_addresses,omitempty" yaml:"staking_contract_addresses"`

GovContractAddresses []string `protobuf:"bytes,3,rep,name=gov_contract_addresses,json=govContractAddresses,proto3" json:"gov_contract_addresses,omitempty" yaml:"gov_contract_addresses"`
}
```
11 changes: 11 additions & 0 deletions x/cw-hooks/spec/03_params.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Parameters

The cw-hooks module contains the following parameters:

| Key | Type | Default Value |
| :------------------------- | :---------- | :--------------- |
| `ContractGasLimit` | uint64 | `250_000` |

## Contract Gas Limit

The `ContractGasLimit` parameter is the maximum amount of gas that can be used by a contract in a single event. This is to prevent malicious contracts from spamming the network since all executes are feeless. If you need to perform more than 250,000 Gas execution, you can submit a proposal to increase this for the chain.
25 changes: 25 additions & 0 deletions x/cw-hooks/spec/04_register.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Register a contract

See [Integration](./06_integration.md)) for all events emitted by the chain.

## Staking Events

> `junod tx cw-hooks register-staking [contract_bech32] --from [admin|creator]`
*Registers the contract to receive staking events (fire and forget)*

## Governance Events

> `junod tx cw-hooks register-governance [contract_bech32] --from [admin|creator]`
*Registers the contract to receive governance events (fire and forget)*

---

### Parameters

`contract_bech32 (string, required)`: The bech32 address of the contract who will receive the updates.

### Permissions

This command can only be run by the admin of the contract. If there is no admin, then it can only be run by the contract creator.
11 changes: 11 additions & 0 deletions x/cw-hooks/spec/05_stop_events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Remove your contract from receiving events

Contracts can be removed from events at any time with the following commands:

## Staking

> `junod tx cw-hooks unregister-staking [contract_bech32] --from [admin|creator]`
## Governance

> `junod tx cw-hooks unregister-governance [contract_bech32] --from [admin|creator]`
160 changes: 160 additions & 0 deletions x/cw-hooks/spec/06_integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# CosmWasm Integration

This module does __not__ require any custom bindings. Rather, you must just add the following Sudo messages to your contract.

If you have not permissionlessly registered your contract, you can do so [here](./04_register.md)

You can find a basic [cw-hooks contract here](https://github.com/Reecepbcups/cw-juno-staking-hooks-example)

## Implementation

## Staking

Add the following to your Rust Contract:

```rust
// msg.rs
use cosmwasm_schema::cw_serde;

#[cw_serde]
pub enum SudoMsg {
// Validators
AfterValidatorCreated {
moniker: String,
validator_address: String,
commission: String,
validator_tokens: String,
bonded_tokens: String,
bond_status: String,
},
AfterValidatorRemoved {
moniker: String,
validator_address: String,
commission: String,
validator_tokens: String,
bonded_tokens: String,
bond_status: String,
},
BeforeValidatorModified {
moniker: String,
validator_address: String,
commission: String,
validator_tokens: String,
bonded_tokens: String,
bond_status: String,
},
AfterValidatorModified {
moniker: String,
validator_address: String,
commission: String,
validator_tokens: String,
bonded_tokens: String,
bond_status: String,
},
AfterValidatorBonded {
moniker: String,
validator_address: String,
commission: String,
validator_tokens: String,
bonded_tokens: String,
bond_status: String,
},
AfterValidatorBeginUnbonding {
moniker: String,
validator_address: String,
commission: String,
validator_tokens: String,
bonded_tokens: String,
bond_status: String,
},
BeforeValidatorSlashed {
moniker: String,
validator_address: String,
slashed_amount: String,
},

// Delegations
BeforeDelegationCreated {
validator_address: String,
delegator_address: String,
shares: String,
},
BeforeDelegationSharesModified {
validator_address: String,
delegator_address: String,
shares: String,
},
AfterDelegationModified {
validator_address: String,
delegator_address: String,
shares: String,
},
BeforeDelegationRemoved {
validator_address: String,
delegator_address: String,
shares: String,
},
}

// state.rs
#[cw_serde]
pub struct ValidatorSlashed {
pub moniker: String,
pub validator_address: String,
pub slashed_amount: String,
}
pub const VALIDATOR_SLASHED: Item<ValidatorSlashed> = Item::new("vs");

// contract.rs
use crate::state::{ValidatorSlashed, VALIDATOR_SLASHED};

pub fn instantiate(
deps: DepsMut,
_env: Env,
_info: MessageInfo,
_msg: InstantiateMsg,
) -> Result<Response, ContractError> {

...

VALIDATOR_SLASHED.save(
deps.storage,
&ValidatorSlashed {
moniker: "".to_string(),
validator_address: "".to_string(),
slashed_amount: "".to_string(),
},
)?;

Ok(Response::new().add_attribute("method", "instantiate"))
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> Result<Response, ContractError> {
match msg {

...

SudoMsg::BeforeValidatorSlashed {
moniker,
validator_address,
slashed_amount,
} => {
// perform ANY logic here when a validator is slashed on your contract.
VALIDATOR_SLASHED.save(
deps.storage,
&ValidatorSlashed {
moniker,
validator_address,
slashed_amount,
},
)?;
Ok(Response::new())
}
}
}
```

## Governance

- TODO:
11 changes: 8 additions & 3 deletions x/cw-hooks/spec/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# `clock`
# `cw-hooks`

## Abstract

Expand All @@ -10,5 +10,10 @@ By using this module, your application can remove the headache of external white

## Contents

1. **[Authorization](01_authorization.md)**
2. **[Contract Integration](02_integration.md)**
1. **[Concepts](./00_concepts.md)**
1. **[Clients](./01_clients.md)**
1. **[State](./02_state.md)**
1. **[Params](./03_params.md)**
1. **[Register Contracts](./04_register.md)**
1. **[Unregister Contracts](./05_stop_events.md)**
1. **[Rust CW Integration](./06_integration.md)**

0 comments on commit 2cdbb2a

Please sign in to comment.