Skip to content

Commit

Permalink
FeePay Documentation (CosmosContracts#886)
Browse files Browse the repository at this point in the history
* Structure FeePay Docs

* Complete FeePay Docs

* fmt on 04 page

---------

Co-authored-by: Reece Williams <[email protected]>
Co-authored-by: Reece Williams <[email protected]>
  • Loading branch information
3 people authored Nov 22, 2023
1 parent c7f8966 commit d48ff12
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 0 deletions.
5 changes: 5 additions & 0 deletions x/feepay/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# FeePay

The `x/feepay` allows developers to register contracts, fund them with juno, and then cover the execution fees of wallets interacting with their contract.

[FeePay Spec](./spec/README.md)
65 changes: 65 additions & 0 deletions x/feepay/spec/01_concepts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<!--
order: 1
-->

# Concepts

## FeePay

The FeePay module provides functionality for Smart Contract developers to cover the execution fees of transactions interacting with their contract. This aims to improve the user experience and help onboard wallets with little to no available funds. Developers can setup their contract with FeePay by first registering it and then funding it with Juno. Clients can then interact with the contract by explicitly specifying 0 fees.

## Registering a Contract

Register a contract with FeePay by executing the following transaction:

```bash
junod tx feepay register [contract_address] [wallet_limit]
```

> Note: the sender of this transaction must be the contract admin, if exists, or else the contract creator.
The `contract_address` is the bech32 address of the contract whose execution fees will be covered. The `wallet_limit` is the maximum number of times a wallet can execute the contract with 0 fees. This is a safety measure to prevent draining the account. The `wallet_limit` can be set to 0 to disable all FeePay interactions with this contract. Executions can still take place if the client explicitly specifies gas or a fee.

## Updating the Wallet Limit

The `wallet_limit` can be updated by executing the following transaction:

```bash
junod tx feepay update-wallet-limit [contract_address] [wallet_limit]
```

> Note: the sender of this transaction must be the contract admin, if exists, or else the contract creator.
The `contract_address` is the bech32 address of the FeePay contract to update. The `wallet_limit` is the maximum number of times a wallet can execute the contract with 0 fees. A `wallet_limit` of 0 disables all FeePay interactions with this contract. Executions can still take place if the client explicitly specifies gas or a fee.

## Unregistering a Contract

A contract can be unregistered by executing the following transaction:

```bash
junod tx feepay unregister [contract_address]
```

> Note: the sender of this transaction must be the contract admin, if exists, or else the contract creator.
The `contract_address` is the bech32 address of the FeePay contract to unregister. Unregistering a contract will remove it from the FeePay module. This means that clients will no longer be able to interact with the contract with 0 fees. Executions can still take place if the client explicitly specifies gas or a fee. All funds in the contract will be sent to the contract creator.

## Funding a Contract

A contract can be funded by executing the following transaction:

```bash
junod tx feepay fund [contract_address] [amount]
```

The `contract_address` is the bech32 address of the FeePay contract to fund. The `amount` is the amount of Juno to send to the contract. This amount will be used to pay for the execution fees of transactions interacting with the contract. Presently the FeePay module only supports Juno. The `amount` must be specified in ujuno.

## Client Interactions

Clients can interact with a contract registered with FeePay by explicitly specifying 0 fees. This can be done by setting the `--fees=0ujuno` flag.

```bash
junod tx wasm execute [contract_address] [json] --fees=0ujuno
```

The `contract_address` is the bech32 address of the FeePay contract to interact with. The `json` is the JSON-encoded transaction message. The `--fees=0ujuno` flag explicitly sets the fees to 0. This will trigger the FeePay module to attempt to pay for the execution fees of the transaction. See the [Ante](03_ante.md) for more details on how this works.
66 changes: 66 additions & 0 deletions x/feepay/spec/02_state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!--
order: 2
-->

# State

## State Objects

The `x/feepay` module keeps the following objects in the state: FeePayContract and FeePayWalletUsage. These objects are used to store the state of a contract and the number of times a wallet has interacted with a contract.

```go
// This defines the address, balance, and wallet limit
// of a fee pay contract.
message FeePayContract {
// The address of the contract.
string contract_address = 1;
// The ledger balance of the contract.
uint64 balance = 2;
// The number of times a wallet may interact with the contract.
uint64 wallet_limit = 3;
}
```

```go
// This object is used to store the number of times a wallet has
// interacted with a contract.
message FeePayWalletUsage {
// The contract address.
string contract_address = 1;
// The wallet address.
string wallet_address = 2;
// The number of uses corresponding to a wallet.
uint64 uses = 3;
}
```

## Genesis & Params

The `x/feepay` module's `GenesisState` defines the state necessary for initializing the chain from a previously exported height. It contains the module parameters and the fee pay contracts. As of now, it does not contain the wallet usage. The params are used to enable or disable the module. This value can be modified with a governance proposal.

```go
// GenesisState defines the module's genesis state.
message GenesisState {
// params are the feepay module parameters
Params params = 1 [ (gogoproto.nullable) = false ];

// fee_pay_contracts are the feepay module contracts
repeated FeePayContract fee_pay_contracts = 2 [ (gogoproto.nullable) = false ];
}

// Params defines the feepay module params
message Params {
// enable_feepay defines a parameter to enable the feepay module
bool enable_feepay = 1;
}
```

## State Transitions

The following state transitions are possible:

- Registering a contract creates a FeePayContract object in the state.
- Unregistering a contract removes the FeePayContract object from the state.
- Funding a contract updates the balance of the FeePayContract object in the state.
- Updating the wallet limit of a contract updates the FeePayContract object in the state.
- Interacting with a contract updates the FeePayWalletUsage object in the state and deducts the balance of the FeePayContract object in the state.
39 changes: 39 additions & 0 deletions x/feepay/spec/03_ante.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!--
order: 3
-->

# Ante

The `x/feepay` module implements two handlers to perform all of the necessary logic on incoming transactions.

## FeeRouteDecorator Logic

The FeeRouteDecorator is responsible for determining if a transaction is to be processed as a FeePay transaction and correctly routes it to additional decorators for further processing. Below are the steps taken by the FeeRouteDecorator to process a transaction:

1. Flag incoming transaction as a FeePay transaction or not a FeePay transaction (Requirements: 0 provided gas, 0 provided fee, contains only 1 message, only message is a MsgExecuteContract message, & the contract is registered with FeePay)
2. If a FeePay transaction:
1. Route to FeePayDecorator (If an error occurs: Handle transaction normally with the SDK's DeductFeeDecorator logic & proceed if no additional errors occur)
2. Route to GlobalFeeDecorator
3. If not a FeePay transaction:
1. Route to GlobalFeeDecorator
2. Route to FeePayDecorator

The purpose of routing a FeePay transaction to the FeePayDecorator first is to avoid the GlobalFeeDecorator from erroring out due to no provided fees. Additionally, if the FeePayDecorator logic fails, the transaction will attempt to be processed by the SDK's DeductFeeDecorator logic and then proceed to the GlobalFeeDecorator if no errors occur.

## FeePayDecorator Logic

> Note: The FeePayDecorator is an extension of the SDK's DeductFeeDecorator.
The FeePayDecorator is responsible for handling normal fee deductions (on normal transactions) and all FeePay transaction logic (on FeePay transactions). Below are the steps taken by the FeePayDecorator to process a transaction:

1. If not a FeePay transaction:
1. Deduct fees from the transaction normally, just like the default SDK decorator
2. If a FeePay transaction:
1. Determine the required fee to cover the contract execution gas cost
2. Ensure wallet has not exceeded limit
3. Ensure contract has enough funds to cover fee
4. Transfer funds to the FeeCollector module from the contract's funds
5. Update contract funds in state
6. Increment wallet usage in state

If any of the FeePay transaction steps fail, the transaction will attempt to be processed normally by the SDK's DeductFeeDecorator logic. If the fallback attempt succeeds, the transaction will pass. If the fallback attempt fails, the transaction will fail and the client will be notified of any and all errors.
28 changes: 28 additions & 0 deletions x/feepay/spec/04_clients.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!--
order: 4
-->

# Clients

## Command Line Interface (CLI)

The CLI has been updated with new queries and transactions for the `x/feepay` module. View the entire list below.

### Queries

| Command | Subcommand | Arguments | Description |
| :------------------- | :------------ | :---------------------------------- | :-------------------------------------------------------------- |
| `junod query feepay` | `params` | | Get FeePay params |
| `junod query feepay` | `contract` | [contract_address] | Get a FeePay contract |
| `junod query feepay` | `contracts` | | Get all FeePay contracts |
| `junod query feepay` | `uses` | [contract_address] [wallet_address] | Get the number of times a wallet has interacted with a contract |
| `junod query feepay` | `is-eligible` | [contract_address] [wallet_address] | Check if a wallet has not met the wallet limit on a contract |

### Transactions

| Command | Subcommand | Arguments | Description |
| :-----------------| :-------------------- | :-------------------------------- | :--------------------------------------------- |
| `junod tx feepay` | `register` | [contract_address] [wallet_limit] | Register a FeePay contract with a wallet limit |
| `junod tx feepay` | `update-wallet-limit` | [contract_address] [wallet_limit] | Update the wallet limit of a FeePay contract |
| `junod tx feepay` | `unregister` | [contract_address] | Unregister a FeePay contract |
| `junod tx feepay` | `fund` | [contract_address] [amount] | Fund a FeePay contract |
14 changes: 14 additions & 0 deletions x/feepay/spec/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# `feepay`

## Abstract

This document specifies the internal `x/feepay` module of Juno Network.

The `x/feepay` module provides functionality for Smart Contract developers to cover the execution fees of transactions interacting with their contract. This aims to improve the user experience and help onboard wallets with little to no available funds.

## Contents

1. **[Concepts](01_concepts.md)**
2. **[State](02_state.md)**
3. **[Ante](03_ante.md)**
4. **[Clients](04_clients.md)**

0 comments on commit d48ff12

Please sign in to comment.