Skip to content

Latest commit

History

History
258 lines (181 loc) 路 8.68 KB

register-feeshare.mdx

File metadata and controls

258 lines (181 loc) 路 8.68 KB

FeeShare registration

The x/FeeShare module 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.

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.

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.

    {
    "@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, set up the accounts, and prepare the environment by initializing Terra's Light Client Daemon and setting up the wallets and accounts.
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)
    }
})()

  1. 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.

</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.
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"))
})()

  1. The next few lines prepare the environment by initializing Terra's Light Client Daemon and setting up the wallets and accounts.

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.

  1. 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.

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. 

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.

  1. 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.

</CH.Scrollycoding>