-
Notifications
You must be signed in to change notification settings - Fork 203
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #589 from terra-money/fee
Fee
- Loading branch information
Showing
10 changed files
with
804 additions
and
350 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
# FeeShare registration | ||
|
||
The [x/FeeShare module](../module-specifications/spec-feeshare.mdx) allows smart contracts to receive a portion of the gas fees generated by interactions with the contract. Use this guide to learn how to register your contract and earn a portion of transaction fees. For more information on this module, visit the [FeeShare spec](../module-specifications/spec-feeshare.mdx). | ||
|
||
## Register an existing contract | ||
|
||
### Using Terrad | ||
|
||
You can use Terrad to register your contract with the following commands. Be sure to use the appropriate flags when submitting the transaction. | ||
|
||
The following command can only be used by the contract's admin. If the contract has no admin, only the creator can use it. | ||
|
||
```sh Terrad | ||
terrad tx feeshare [contract] [withdraw] --from [your_address] | ||
``` | ||
|
||
To use the command, specify the following: | ||
|
||
- _`[contract]`_: The address of the deployed contract. | ||
- _`[withdraw]`_: An address to which the portion of the fee revenue will be sent. | ||
- _`[your_address]`_: The address of the signer. | ||
|
||
### Using a JSON message | ||
|
||
The following example is a JSON message that can be sent to register a contract address in the FeeShare module. | ||
|
||
```json | ||
{ | ||
"@type": "/juno.feeshare.v1.MsgRegisterFeeShare", | ||
"contract_address": "terra1w8ta7vhpzwe0y99tvvtp7k0k8uex2jq8jts8k2hsyg009ya06qts5fwftt", | ||
"deployer_address": "terra1880xn49l4x947pjv4a9k2qe5mf423kjzkn4ceu", | ||
"withdrawer_address": "terra1zdpgj8am5nqqvht927k3etljyl6a52kwqup0je" | ||
}, | ||
``` | ||
|
||
### Using feather.js | ||
|
||
<CH.Scrollycoding> | ||
|
||
1. In this example, the first portion of the code is used to import the [feather.js SDK](https://github.com/terra-money/feather.js), set up the accounts, and prepare the environment by initializing Terra's [Light Client Daemon](../feather-js/getting-started.mdx#2-initialize-the-lcd) and setting up the wallets and accounts. | ||
|
||
```js Example.ts focus=1:9 | ||
import { LCDClient, MnemonicKey, MsgRegisterFeeShare } from "@terra-money/feather.js"; | ||
|
||
// Prepare environment clients, accounts and wallets | ||
const lcd = LCDClient.fromDefaultConfig("testnet"); | ||
const mnemonic = new MnemonicKey({ mnemonic: "..." }); | ||
const deployerAddr = mnemonic.accAddress("terra"); | ||
const withdrawerAddr = mnemonic.accAddress("terra"); | ||
const wallet = lcd.wallet(mnemonic); | ||
const contractAddr = "terra1eaxcahzxp0x8wqejqjlqaey53tp06l728qad6z395lyzgl026qkq20xj43"; | ||
|
||
|
||
(async () => { | ||
try { | ||
// Submit a transaction to register the feeshare | ||
let tx = await wallet.createAndSignTx({ | ||
msgs: [new MsgRegisterFeeShare( | ||
contractAddr, | ||
deployerAddr, | ||
withdrawerAddr, | ||
)], | ||
chainID: "pisco-1", | ||
memo: "Registering feeshare #TerraDevs", | ||
}); | ||
let result = await lcd.tx.broadcastSync(tx, "test-1"); | ||
|
||
console.log("Transaction Hash", result.txhash) | ||
} | ||
catch (e) { | ||
console.log(e) | ||
} | ||
})() | ||
``` | ||
|
||
--- | ||
|
||
2. Next, a contract is registered with the FeeShare module by executing a `MsgRegisterFeeShare` transaction. This message is created by supplying it with the following addresses: | ||
|
||
- _`contractAddress`_: The address of the deployed contract. | ||
- _`deployerAddress`_: The address of the deployer of the contract. | ||
- _`withdrawerAddress`_: An address to which the portion of the fee revenue will be sent. | ||
|
||
```js Example.ts focus=12:31 | ||
|
||
``` | ||
|
||
</CH.Scrollycoding> | ||
|
||
## Register a new contract | ||
|
||
Use the following example to instantiate your contract and register with the FeeShare module. | ||
|
||
<CH.Scrollycoding> | ||
|
||
### Setup | ||
|
||
1. The first portion of the code is used to import the necessary functions, classes, and objects from the [feather.js SDK](https://github.com/terra-money/feather.js). | ||
|
||
|
||
```js Example.ts mark=1:7 | ||
import { getMnemonics } from "../helpers/mnemonics"; | ||
import { getLCDClient } from "../helpers/lcd.connection"; | ||
import { Coins, Fee, MnemonicKey, MsgExecuteContract, MsgInstantiateContract, MsgRegisterFeeShare, MsgStoreCode } from "@terra-money/feather.js"; | ||
import { blockInclusion } from "../helpers/const"; | ||
import fs from "fs"; | ||
import path from 'path'; | ||
|
||
// Prepare environment clients, accounts and wallets | ||
const LCD = getLCDClient(); | ||
const accounts = getMnemonics(); | ||
const wallet = LCD.chain1.wallet(accounts.feeshareMnemonic); | ||
const deployerAddress = accounts.feeshareMnemonic.accAddress("terra"); | ||
const withdrawerAddress = new MnemonicKey().accAddress("terra"); | ||
let contractAddress: string; | ||
|
||
(async () => { | ||
// Read the reflect contract, store it on chain and | ||
// read the code id from the result... | ||
let tx = await wallet.createAndSignTx({ | ||
msgs: [new MsgStoreCode( | ||
deployerAddress, | ||
fs.readFileSync(path.join(__dirname, "/../contracts/reflect.wasm")).toString("base64"), | ||
)], | ||
chainID: "test-1", | ||
}); | ||
|
||
let result = await LCD.chain1.tx.broadcastSync(tx, "test-1"); | ||
await blockInclusion(); | ||
let txResult = await LCD.chain1.tx.txInfo(result.txhash, "test-1") as any; | ||
let codeId = Number(txResult.logs[0].events[1].attributes[1].value); | ||
expect(codeId).toBeDefined(); | ||
|
||
// ... then instantiate the reflect contract | ||
// wait for the block inclusion and read the | ||
// contract adddress from the result logs | ||
tx = await wallet.createAndSignTx({ | ||
msgs: [new MsgInstantiateContract( | ||
deployerAddress, | ||
deployerAddress, | ||
codeId, | ||
{}, | ||
Coins.fromString("1uluna"), | ||
"Reflect contract " + Math.random(), | ||
)], | ||
chainID: "test-1", | ||
}); | ||
result = await LCD.chain1.tx.broadcastSync(tx, "test-1"); | ||
await blockInclusion(); | ||
txResult = await LCD.chain1.tx.txInfo(result.txhash, "test-1") as any; | ||
contractAddress = txResult.logs[0].eventsByType.instantiate._contract_address[0]; | ||
|
||
// Submit a transaction to register the feeshare | ||
tx = await wallet.createAndSignTx({ | ||
msgs: [new MsgRegisterFeeShare( | ||
contractAddress, | ||
deployerAddress, | ||
withdrawerAddress, | ||
)], | ||
chainID: "test-1", | ||
}); | ||
|
||
result = await LCD.chain1.tx.broadcastSync(tx, "test-1"); | ||
await blockInclusion(); | ||
|
||
// Send an execute message to the reflect contract | ||
let msgExecute = new MsgExecuteContract( | ||
deployerAddress, | ||
contractAddress, | ||
{ | ||
change_owner: { | ||
owner: withdrawerAddress, | ||
} | ||
}, | ||
); | ||
tx = await wallet.createAndSignTx({ | ||
msgs: [msgExecute], | ||
chainID: "test-1", | ||
fee: new Fee(200_000, "400000uluna"), | ||
}); | ||
result = await LCD.chain1.tx.broadcastSync(tx, "test-1"); | ||
await blockInclusion(); | ||
|
||
|
||
// Query the withdrawer adddress (new owner of the contract) | ||
// and validate that the account has received 50% of the fees | ||
const bankAmount = await LCD.chain1.bank.balance(withdrawerAddress); | ||
expect(bankAmount[0]) | ||
.toMatchObject(Coins.fromString("200000uluna")) | ||
})() | ||
``` | ||
|
||
--- | ||
|
||
2. The next few lines prepare the environment by initializing Terra's [Light Client Daemon](../feather-js/getting-started.mdx#2-initialize-the-lcd) and setting up the wallets and accounts. | ||
```js Example.ts focus=9:14 | ||
|
||
``` | ||
|
||
--- | ||
|
||
### Deploy the contract | ||
|
||
1. This code creates and signs a transaction to store the smart contract on the blockchain. It waits for the transaction to be completed and gets the contract's code id from the result. | ||
|
||
```js Example.ts focus=16:31 | ||
|
||
``` | ||
|
||
--- | ||
|
||
2. A contract instantiation message is created and signed to deploy the contract to the blockchain. The contract has an initial balance of `1uluna`. It waits for the transaction to be completed and gets the contract address from the result. | ||
|
||
|
||
```js Example.ts focus=33:50 | ||
|
||
``` | ||
|
||
--- | ||
|
||
### Register with the FeeShare module | ||
|
||
The contract is registered with the FeeShare module by executing a `MsgRegisterFeeShare` transaction. This message is created by supplying it with the following addresses: | ||
|
||
- _`contractAddress`_: The address of the deployed contract. | ||
- _`deployerAddress`_: The address of the deployer of the contract. | ||
- _`withdrawerAddress`_: An address to which the portion of the fee revenue will be sent. | ||
|
||
|
||
```js Example.ts focus=52:63 | ||
|
||
``` | ||
|
||
|
||
--- | ||
|
||
|
||
### Check for fees | ||
|
||
1. In this example, a transaction is created by executing the sample contract's _`change_owner`_ message along with a fee of _`400000uluna`_ for the transaction. | ||
|
||
```js Example.ts focus=65:81 | ||
|
||
``` | ||
|
||
--- | ||
|
||
2. To check that the FeeShare is working properly, the _`withdrawer_address`_ is queried. In this code, the expected portion of fees sent to a contract's registered _`withdrawer_address`_ is _`0.500000000000000000`_, or half of the fees. If the module is working properly, half of the fees (_`200000uluna`_) are expected to be sent to the _`withdrawer_address`_. | ||
|
||
```js Example.ts focus=84:89 | ||
|
||
``` | ||
|
||
|
||
</CH.Scrollycoding> | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import Admonition from '@theme/Admonition'; | ||
|
||
# FeeShare | ||
|
||
<Admonition type="info" icon="ℹ️"> | ||
|
||
The FeeShare module is an open-source module created by the Juno network. This document is a stub and mainly covers Terra-specific notes on how it is used. Visit the [original documentation](https://docs.junonetwork.io/developer-guides/juno-modules/feeshare#registering-factory-contracts) for more information. | ||
|
||
</Admonition> | ||
|
||
The FeeShare module enables contracts to share in the distribution of fees generated from contract transactions. Whenever a transaction occurs, a gas fee is incurred and distributed to validators via the [Distribution module](./spec-distribution.mdx). With FeeShare, a portion of this fee can be diverted back to an address specified by the contract the transaction originated from. In order to participate in fee sharing, contracts must be [registered with the module](../guides/register-feeshare.mdx). | ||
|
||
## Governance parameters | ||
|
||
The following parameters can be adjusted by creating a [governance proposal](./spec-governance.mdx). | ||
|
||
| Key | Type | Default Value | | ||
| :------------------------- | :---------- | :--------------- | | ||
| `EnableFeeShare` | bool | `true` | | ||
| `DeveloperShares` | sdk.Dec | `50%` | | ||
| `AllowedDenoms` | []string{} | `[]string(nil)` | | ||
|
||
### `EnableFeeShare` | ||
|
||
This parameter enables the module. When set to _`false`_, it will disable all feeshare capabilities. | ||
|
||
### `DeveloperShares` | ||
|
||
This parameter denotes the percentage of fees diverted back to a registered contract. When set at 50%, half of all fees generated will be sent to the withdraw address specified by the registered contract. | ||
|
||
### `AllowedDenoms` | ||
|
||
This parameter specifies which denominations will be diverted back to a registered contract. If empty, all denominations available as fees will be diverted. | ||
|
||
## Registering a contract | ||
|
||
To register a new or existing contract, follow the [FeeShare registration guide](../guides/register-feeshare.mdx). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.