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).
Messages
- Stake
- Unbond
- TransferStaked
- Claim
- CompoundRewards
- UpdateFees
- PanicUnbond
- PanicWithdraw
- SetContractStatus
Queries
- SecretCLI installed and configured
- Account with funds (~6 scrt)
- Derivative (SNIP-20) deployed
- Make sure you have the docker demon turned on.
- Open project in a terminal.
- Compile and optimized contract. In the root folder run this command:
make compile-optimized-reproducible
- Store contract on chain.
secretcli tx compute store contract.wasm.gz --from <ACCOUNT_NAME> -y --gas 3000000 | jq
- Query contract code id
CODE_ID=$(secretcli q compute list-code | jq '.[-1].code_id')
- 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}
- Query contract's address
ADDRESS=$(secretcli q compute tx ${TX_HASH} | jq '.output_logs[0].attributes[0].value' | tr -d '"') && echo ${ADDRESS}
- Set staking derivative as minter of derivative
secretcli tx compute execute <DERIVATIVE_ADDR> '{"set_minters":{"minters":["'${ADDRESS}'"]}}' --from <ACCOUNT_NAME> -y | jq
- Whitelist staking derivative in staking contract
secretcli tx compute execute <STAKING_ADDR> '{"add_transfer_whitelist":{"user":"'${ADDRESS}'"}}'
- Query transaction's status
secretcli q compute tx ${TX_HASH} | jq
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
}
}
}
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 |
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 |
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 |
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 |
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
.
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. |
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. |
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. |
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 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"
}
}
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"
}
}
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"
}
]
}
}
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
}
}
}
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"
}
}