Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create route to withdraw rewards #146

Merged
merged 3 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified artifacts/broker_bank.wasm
Binary file not shown.
Binary file modified artifacts/broker_staking.wasm
Binary file not shown.
5 changes: 2 additions & 3 deletions artifacts/checksums.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
3878c8fec84001d1260da6d8b7ea91af5bc3d3433d8cab293ae24de94a9fdda0 broker_bank.wasm
dfd48116b2181f477d42b7d0d697057e16814c0b703ef592a8757ca681c6e5ad broker_staking.wasm
e3d3422db32e4e6ebe0247a22f6be733ccf6b637bfeb4ff8ffcd8122a68d7853 broker_bank.wasm
40288f4cda1e48740269ab6425ca234b9b99419c165aaf1d410fa37c40843e49 broker_staking.wasm
382c05baf544f2886de849933ecf59e8bc3bcdcdd552d5a63537bd6d63f2ecf1 controller.wasm
05948cad982935aa30a9c2011649ab40a38172ab50df5781a3e24f72b76dcc56 core_compounder.wasm
ed4a89ae4669b22863fcabd18e3bd7e40d039899f863a07eb0449eed059a898e core_token_vesting_v2.wasm
b56a880d4c67d9f353f549b502256f73159f89b50aa6dae683948e117efa4792 cw3_flex_multisig.wasm
1ecff403bbf3b5fcedccb5de76a0ef5f1fdbcc5f60890e3388f5425584899f0b incentives.wasm
Expand Down
33 changes: 31 additions & 2 deletions contracts/broker-staking/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use broker_bank::state::{IS_HALTED, OPERATORS, TO_ADDRS};
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
to_json_binary, Binary, Coin, CosmosMsg, Deps, DepsMut, Env, MessageInfo,
Response, StakingMsg, StdResult, Uint128,
to_json_binary, Binary, Coin, CosmosMsg, Deps, DepsMut, DistributionMsg,
Env, MessageInfo, Response, StakingMsg, StdResult, Uint128,
};

use crate::msg::{ExecuteMsg, StakeMsg, UnstakeMsg};
Expand Down Expand Up @@ -59,9 +59,38 @@ pub fn execute(
ExecuteMsg::WithdrawAll { to } => {
withdraw_all(deps, env, info, to, contract_addr)
}
ExecuteMsg::ClaimRewards {} => claim_rewards(deps, env, info),
}
}

pub fn claim_rewards(
deps: DepsMut,
env: Env,
info: MessageInfo,
) -> Result<Response, ContractError> {
let is_halted = IS_HALTED.load(deps.storage)?;
assert_not_halted(is_halted)?;

Permissions::assert_operator(deps.storage, info.sender.to_string())?;

// query current delegations
let delegations =
deps.querier.query_all_delegations(&env.contract.address)?;

let mut messages: Vec<CosmosMsg> = vec![];
for delegation in delegations.iter() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a CLI command to do withdraw all but it's internally just doing this logic. There's no actual message to withdraw from all delegations in the comsos sdk

messages.push(CosmosMsg::Distribution(
DistributionMsg::WithdrawDelegatorReward {
validator: delegation.validator.clone(),
},
));
}

Ok(Response::new()
.add_messages(messages)
.add_attribute("action", "claim_rewards"))
}

pub fn unstake(
deps: DepsMut,
_env: Env,
Expand Down
2 changes: 2 additions & 0 deletions contracts/broker-staking/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub enum ExecuteMsg {
to: Option<String>,
},

ClaimRewards {},

/// Unstake allows to unstake a given amount of tokens from a set of
/// validators. The UnstakeMsgs defines the tokens amount and address
/// of the validator.
Expand Down
81 changes: 79 additions & 2 deletions contracts/broker-staking/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::contract::{execute, query};
use crate::msg::{ExecuteMsg, StakeMsg, UnstakeMsg};
use cosmwasm_std::{self as cw_std};
use cw_std::{
coin, from_json, testing, BankMsg, Coin, CosmosMsg, Response, StakingMsg,
Uint128,
coin, from_json, testing, BankMsg, Coin, CosmosMsg, DistributionMsg,
Response, StakingMsg, Uint128,
};
use nibiru_std::errors::TestResult;
use serde::Serialize;
Expand Down Expand Up @@ -752,3 +752,80 @@ fn exec_unstake() -> TestResult {
}
Ok(())
}

#[test]
fn test_withdraw_rewards() -> TestResult {
let to_addrs: [String; 2] = ["mm_kucoin", "mm_bybit"].map(|s| s.to_string());
let opers: [String; 1] = ["valid_oper"].map(|s| s.to_string());
let test_cases: Vec<TestCaseExec> = vec![
// Success
TestCaseExec {
to_addrs: to_addrs.to_vec(),
opers: opers.to_vec(),
sender: "owner",
exec_msg: ExecuteMsg::ClaimRewards {},
err: None,
contract_funds_start: None,
resp_msgs: vec![],
},
// Success - oper can do that
TestCaseExec {
to_addrs: to_addrs.to_vec(),
opers: opers.to_vec(),
sender: "valid_oper",
exec_msg: ExecuteMsg::ClaimRewards {},
err: None,
contract_funds_start: None,
resp_msgs: vec![],
},
// Fail - non oper can't
TestCaseExec {
to_addrs: to_addrs.to_vec(),
opers: opers.to_vec(),
sender: "invalid_oper",
exec_msg: ExecuteMsg::ClaimRewards {},
err: Some("insufficient permissions"),
contract_funds_start: None,
resp_msgs: vec![],
},
];
for tc in &test_cases {
let to_addrs = &tc.to_addrs;
let opers = &tc.opers;
// instantiate smart contract from the owner
let (mut deps, env, _info) =
setup_contract(to_addrs.clone(), opers.clone())?;

if let Some(funds_start) = &tc.contract_funds_start {
// Set up a mock querier with contract balance
let contract_addr = env.contract.address.to_string();
let balances: &[(&str, &[Coin])] =
&[(contract_addr.as_str(), funds_start.as_slice())];
let querier = testing::MockQuerier::new(balances);
deps.querier = querier;
}

// send the exec msg
let info = mock_info_for_sender(tc.sender);
let res = execute(deps.as_mut(), env, info, tc.exec_msg.clone());

if let Some(want_err) = tc.err {
let got_err = res.expect_err("errors should occur in this test");
let is_contained = got_err.to_string().contains(want_err);
assert!(is_contained, "got error {}", got_err);
return Ok(());
}
assert!(res.is_ok(), "got {res:?}");

let resp = res?;
let got_resp_msgs: Vec<CosmosMsgExt> = resp
.messages
.iter()
.map(|sub_msg| CosmosMsgExt(&sub_msg.msg))
.collect();
let want_resp_msgs: Vec<CosmosMsgExt> =
tc.resp_msgs.iter().map(CosmosMsgExt).collect();
assert_eq!(want_resp_msgs, got_resp_msgs);
}
Ok(())
}
Loading