Skip to content

STKD-SHD is a contract to provide derivative tokens based out of SHD.

License

Notifications You must be signed in to change notification settings

stakeordie/stkd-shd-contract

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

43 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Derivative minter contract

This contract enables users to send SHD (or any SNIP-20) and receive a staking derivative token that can later be sent to the contract to unbond the sent amount's value in SHD (SNIP-20).

Index

Messages

Queries

Engineering Design Diagram

Engineering Design Diagram

How to deploy

Requirements

Steps

  1. Make sure you have the docker demon turned on.
  2. Open project in a terminal.
  3. Compile and optimized contract. In the root folder run this command:
make compile-optimized-reproducible
  1. Store contract on chain.
secretcli tx compute store contract.wasm.gz --from <ACCOUNT_NAME> -y --gas 3000000 | jq
  1. Query contract code id
CODE_ID=$(secretcli q compute list-code | jq '.[-1].code_id')
  1. Instantiate a new contract
TX_HASH=$(secretcli tx compute instantiate ${CODE_ID} '<INIT_MSG>' --from <ACCOUNT_NAME> -y --gas 3000000 --label $(openssl rand -base64 12 | tr -d /=+ | cut -c -16) | jq '.txhash' | tr -d '"') && echo ${TX_HASH}
  1. Query contract's address
ADDRESS=$(secretcli q compute tx ${TX_HASH} | jq '.output_logs[0].attributes[0].value' | tr -d '"') && echo ${ADDRESS}
  1. Set staking derivative as minter of derivative
secretcli tx compute execute <DERIVATIVE_ADDR> '{"set_minters":{"minters":["'${ADDRESS}'"]}}' --from <ACCOUNT_NAME> -y | jq
  1. Whitelist staking derivative in staking contract
secretcli tx compute execute <STAKING_ADDR> '{"add_transfer_whitelist":{"user":"'${ADDRESS}'"}}'

Troubleshooting

  • Query transaction's status
secretcli q compute tx ${TX_HASH} | jq

Init Message

import { Binary } from "cosmwasm-stargate";

interface ContractInfo {
  address: string;
  code_hash: string;
  entropy?: string | null;
}

interface Fee {
  collector: string;
  rate: number;
  decimal_places: number;
}

interface FeeInfo {
  staking: Fee;
  unbonding: Fee;
}

interface InstantiateMsg {
  prng_seed: Binary;
  staking: ContractInfo;
  query_auth: ContractInfo;
  derivative: ContractInfo;
  token: ContractInfo;
  admin: ContractInfo;
  fees: FeeInfo;
}
{
  "prng_seed": "base64-encoded binary",
  "staking": {
    "address": "secret1abcdefghjklmnopqrstuvwxyz",
    "code_hash": "string",
    "entropy": "string or null"
  },
  "query_auth": {
    "address": "secret1abcdefghjklmnopqrstuvwxyz",
    "code_hash": "string",
    "entropy": "string or null"
  },
  "derivative": {
    "address": "secret1abcdefghjklmnopqrstuvwxyz",
    "code_hash": "string",
    "entropy": "string or null"
  },
  "token": {
    "address": "secret1abcdefghjklmnopqrstuvwxyz",
    "code_hash": "string",
    "entropy": "string or null"
  },
  "admin": {
    "address": "secret1abcdefghjklmnopqrstuvwxyz",
    "code_hash": "string",
    "entropy": "string or null"
  },
  "fees": {
    "staking": {
      "collector": "secret1abcdefghjklmnopqrstuvwxyz",
      "rate": 0,
      "decimal_places": 0
    },
    "unbonding": {
      "collector": "secret1abcdefghjklmnopqrstuvwxyz",
      "rate": 0,
      "decimal_places": 0
    }
  }
}

Messages

Stake

Calculates the equivalent amount of derivative per token sent. Triggered by the receiver interface when sending SHD tokens.

🌐 Anyone can use this feature.

Request

interface ExecuteSendMsg {
  recipient: string;
  amount: string;
  msg: string; // '{"stake":{}}' Base64 encoded
  padding?: string;
}

interface ExecuteStakeMsg {
  send: ExecuteSendMsg;
}
{
  "send": {
    "recipient": "secret1b1b1b1bb1b1b1b1b1b1",
    "amount": "100000000",
    "msg": "eyJzdGFrZSI6e319",
    "padding": "random string"
  }
}

Response

interface StakeResponse {
  shd_staked: string;
  tokens_returned: string;
}
interface StakeMsgResponse {
  stake: StakeResponse;
}
{
  "stake": {
    "shd_staked": "50000000",
    "tokens_returned": "50000000"
  }
}

Errors

Message Cause How to solve it
Sender is not SHD contract The token sent is not the same as indicated at contract's instantiation Send the appropriate token
No SHD was sent for staking You send 0 tokens to the contract (if that's possible) Send more than 0
The amount of SHD deposited is not enough to receive any of the derivative token at the current price The price is high causing that the amount sent is not enough to buy 1 derivative. Send more SHD to the contract than before

Unbond

Calculates the equivalent amount of SHD per derivative sent. Triggered by Receiver interface when sending derivative tokens.

🌐 Anyone can use this feature.

Request

interface ExecuteSendMsg {
  recipient: string;
  amount: string;
  msg: string; // '{"unbond":{}}' Base64 encoded
  padding?: string;
}

interface ExecuteUnbondMsg {
  send: ExecuteSendMsg;
}
{
  "send": {
    "recipient": "secret1b1b1b1bb1b1b1b1b1b1",
    "amount": "100000000",
    "msg": "eyJ1bmJvbmQiOnt9fQ==",
    "padding": "random string"
  }
}

Response

interface UnbondResponse {
  tokens_redeemed: string;
  shd_to_be_received: string;
  estimated_time_of_maturity: string;
}
interface UnbondMsgResponse {
  unbond: UnbondResponse;
}
{
  "unbond": {
    "tokens_redeemed": "50000000",
    "shd_to_be_received": "50000000",
    "estimated_time_of_maturity": "50000000"
  }
}

Errors

Message Cause How to solve it
Sender is not derivative (SNIP20) contract The token sent is not the same as indicated at contract's instantiation Send the appropriate tokens
0 amount sent to unbond You send 0 tokens to the contract (if that's possible) Send more than 0
Redeeming derivative tokens would be worth less than 1 SHD The price is high causing that the amount sent is not enough to buy 1 SHD. Send more derivatives to the contract than before

TransferStaked

Calculates the equivalent amount of SHD per derivative sent. Then sends this SHD as staked position to the sender. Triggered by Receiver interface when sending derivative tokens.

🌐 Anyone can use this feature.

Request

interface ExecuteSendMsg {
  recipient: string;
  amount: string;
  msg: string; // '{"transfer_staked":{"receiver":"opt_receiver_address"}}' Base64 encoded
  padding?: string;
}

interface ExecuteUnbondMsg {
  send: ExecuteSendMsg;
}
{
  "send": {
    "recipient": "secret1b1b1b1bb1b1b1b1b1b1",
    "amount": "100000000",
    "msg": "eyJ0cmFuc2Zlcl9zdGFrZWQiOnsicmVjZWl2ZXIiOiJzZWNyZXQxcjZ5OXBxdXkwc3l4a2tndXJodXBnN2tzY3NuMDd6Mmo3ZGo3NyJ9fQ==",
    "padding": "random string"
  }
}

Response

interface TransferStakedResponse {
  tokens_returned: string;
  amount_sent: string;
}
interface TransferStakedMsgResponse {
  transfer_staked: TransferStakedResponse;
}
{
  "transfer_staked": {
    "amount_sent": "50000000",
    "tokens_returned": "50000000"
  }
}

Errors

Message Cause How to solve it
Sender is not derivative (SNIP20) contract The token sent is not the same as indicated at contract's instantiation Send the appropriate tokens
0 amount sent to unbond You send 0 tokens to the contract (if that's possible) Send more than 0
Redeeming derivative tokens would be worth less than 1 SHD The price is high causing that the amount sent is not enough to buy 1 SHD. Send more derivatives to the contract than before

Claim

This message claims user's mature unbondings in case there is any.

🌐 Anyone can use this feature.

Request

interface ExecuteClaimMsg {
  claim: {};
}
{
  "claim": {}
}

Response

interface ClaimMsgResponse {
  claim: {
    amount_claimed: string;
  };
}
{
  "claim": {
    "amount_claimed": "200000000"
  }
}

Errors

Message Cause How to solve it
No mature unbondings to claim None of your unbondings in progress are matured or you haven't unbonded any SHD Query your unbondings to see when they will matured or unbond some SHD

CompoundRewards

Claims SHD rewards generated and re-stake them. Claims non-SHD rewards and sends them to fee's collector.

🌐 Anyone can use this feature.

Request

interface ExecuteCompoundRewardsMsg {
  compound_rewards: {};
}
{
  "compound_rewards": {}
}

Response

import ResponseStatus from "shade-protocol";

interface CompoundRewardsMsgResponse {
  compound_rewards: {
    status: ResponseStatus;
  };
}
{
  "compound_rewards": {
    "status": "success"
  }
}

Errors

There are no errors triggered by this contract but the staking contract.

UpdateFees

Updates fee's collector, percentage or decimal places.

πŸ‘₯ Only admin(s) can use this feature.

Request

interface Fee {
  rate: number;
  decimal_places: number;
}

interface UpdateFeesMsg {
  staking?: Fee;
  unbonding?: Fee;
  collector?: string;
}

interface ExecuteUpdateFeesMsg {
  update_fees: UpdateFeesMsg;
}
{
  "update_fees": {
    "collector": "secretb1b1b1b1b1b1b1b1b1b1b1b1",
    "staking": {
      "rate": 50000,
      "decimal_places": 5
    },
    "unbonding": {
      "rate": 50000,
      "decimal_places": 5
    }
  }
}

Response

import ResponseStatus from "shade-protocol";

interface Fee {
  rate: number;
  decimal_places: number;
}

interface FeeInfo {
  staking: Fee;
  unbonding: Fee;
  collector: string;
}

interface UpdateFeesMsgResponse {
  update_fees: {
    status: ResponseStatus;
    fee: FeeInfo;
  };
}
{
  "update_fees": {
    "status": "success",
    "fee": {
      "collector": "secretb1b1b1b1b1b1b1b1b1b1b1b1",
      "staking": {
        "rate": 50000,
        "decimal_places": 5
      },
      "unbonding": {
        "rate": 50000,
        "decimal_places": 5
      }
    }
  }
}

Errors

Message Cause How to solve it
Unauthorize admin Sender is not part of the admins list Use an admin account to perform this action.

PanicUnbond

Unbonds X amount staked from staking contract.

πŸ‘₯ Only admin(s) can use this feature.

Request

interface ExecutePanicUnbondMsg {
  panic_unbond: {
    amount: string;
  };
}
{
  "panic_unbond": {
    "amount": "100000000"
  }
}

Response

Default response

Errors

Message Cause How to solve it
Unauthorize admin Sender is not part of the admins list Use an admin account to perform this action.

PanicWithdraw

Withdraws all rewards, matured unbondings and SHD balance. This funds will be sent to super admin.

πŸ‘₯ Only admin(s) can use this feature.

Request

interface ExecutePanicWithdrawMsg {
  panic_withdraw: {};
}
{
  "panic_withdraw": {}
}

Response

Default response

Errors

Message Cause How to solve it
Unauthorize admin Sender is not part of the admins list Use an admin account to perform this action.

SetContractStatus

Sets contract status.

πŸ‘₯ Only admin(s) can use this feature.

Request

enum ContractStatusLevel {
  NormalRun,
  Panicked
  StopAll,
}

interface ExecuteSetContractStatusMsg {
  set_contract_status: {
    level: ContractStatusLevel;
    padding?: string;
  };
}
{
  "set_contract_status": {
    "level": "stop_all",
    "padding": "random string"
  }
}

Response

import ResponseStatus from "shade-protocol";

interface ContractStatusMsgResponse {
  set_contract_status: {
    status: ResponseStatus;
  };
}
{
  "set_contract_status": {
    "status": "success"
  }
}

Errors

Message Cause How to solve it
Unauthorize admin Sender is not part of the admins list Use an admin account to perform this action.

Queries

Holdings

Queries user's claimable total amount and unbonding total amount.

Request

interface HoldingsQuery {
  holdings: {
    address: string;
    viewing_key: string;
  };
}
{
  "holdings": {
    "address": "secret1b1b1b1b1b1b1b1b1",
    "viewing_key": "password"
  }
}

Response

interface HoldingsQueryResponse {
  holdings: {
    derivative_claimable: string;
    derivative_unbonding: string;
  };
}
{
  "holdings": {
    "derivative_claimable": "100000000",
    "derivative_unbonding": "200000000"
  }
}

StakingInfo

Queries contract's balances and price information.

Request

interface StakingInfoQuery {
  staking_info: {};
}
{
  "staking_info": {}
}

Response

interface StakingInfoQueryResponse {
  staking_info: {
    unbonding_time: string;
    bonded_shd: string;
    available_shd: string;
    rewards: string;
    total_derivative_token_supply: string;
    price: string;
  };
}
{
  "staking_info": {
    "unbonding_time": "36000",
    "bonded_shd": "100000000",
    "available_shd": "0",
    "rewards": "320400",
    "total_derivative_token_supply": "100000000",
    "price": "102000000"
  }
}

Unbondings

Queries user's unbondings in progress.

Request

interface UnbondingsQuery {
  unbondings: {
    address: string;
    viewing_key: string;
  };
}
{
  "unbondings": {
    "address": "secret1b1b1b1b1b1b1b1b1",
    "viewing_key": "password"
  }
}

Response

import Unbonding from "shade-protocol";
interface UnbondingsQueryResponse {
  unbondings: {
    unbonds: Unbonding[];
  };
}
{
  "unbondings": {
    "unbonds": [
      {
        "id": "1",
        "amount": "400000000",
        "complete": "39478094578404"
      }
    ]
  }
}

FeeInfo

Queries staking and unbonding fees configuration.

Request

interface FeeInfoQuery {
  fee_info: {};
}
{
  "fee_info": {}
}

Response

interface Fee {
  rate: number;
  decimal_places: number;
}

interface FeeInfoQueryResponse {
  fee_info: {
    collector: string;
    staking: Fee;
    unbonding: Fee;
  };
}
{
  "fee_info": {
    "collector": "secret1b1b1b1b1b1b1b1b1",
    "staking": {
      "rate": 100,
      "decimal_places": 3
    },
    "unbonding": {
      "rate": 100,
      "decimal_places": 3
    }
  }
}

ContractStatus

Queries contracts status.

Request

interface ContractStatusQuery {
  contract_status: {};
}
{
  "contract_status": {}
}

Response

interface ContractStatusLevel {
  NormalRun;
  StopAll;
}

interface ContractStatusQueryResponse {
  contract_status: {
    status: ContractStatusLevel;
  };
}
{
  "contract_status": {
    "status": "stop_all"
  }
}