Skip to content

Commit

Permalink
feat: operator
Browse files Browse the repository at this point in the history
  • Loading branch information
kerber0x authored Mar 28, 2024
2 parents b78a6c4 + 180846f commit dcde68a
Show file tree
Hide file tree
Showing 9 changed files with 269 additions and 49 deletions.
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ terra-proto-rs = { version = "3.0.1", default-features = false}
thiserror = { version = "1.0.38" }
cw2 = "1.0.1"
cw20 ="1.0.1"
semver = "1.0.22"

alliance-protocol = { path = "./packages/alliance-protocol" }
3 changes: 2 additions & 1 deletion contracts/alliance-hub/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "alliance-hub"
version = "0.1.0"
version = "0.1.1"
authors = ["Terra Money <[email protected]>"]
edition = "2018"

Expand All @@ -26,6 +26,7 @@ schemars = { workspace = true }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
alliance-protocol = { workspace = true }
semver = { workspace = true }

cw2 = "1.0.1"
cw20 = "1.0.1"
Expand Down
89 changes: 72 additions & 17 deletions contracts/alliance-hub/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
use std::collections::{HashMap, HashSet};

use cosmwasm_schema::cw_serde;
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
ensure, from_binary, to_binary, Addr, Binary, Coin as CwCoin, CosmosMsg, Decimal, DepsMut,
Empty, Env, MessageInfo, Reply, Response, StdError, StdResult, Storage, SubMsg, Timestamp,
Uint128, WasmMsg,
};
use cw2::{get_contract_version, set_contract_version};
use cw20::Cw20ReceiveMsg;
use cw_asset::{Asset, AssetInfo, AssetInfoBase, AssetInfoKey};
use cw_storage_plus::Item;
use cw_utils::parse_instantiate_response_data;
use semver::Version;
use terra_proto_rs::alliance::alliance::{
MsgClaimDelegationRewards, MsgDelegate, MsgRedelegate, MsgUndelegate,
};
use terra_proto_rs::cosmos::base::v1beta1::Coin;
use terra_proto_rs::traits::Message;

// use alliance_protocol::alliance_oracle_types::QueryMsg as OracleQueryMsg;
use alliance_protocol::alliance_oracle_types::ChainId;
use alliance_protocol::alliance_protocol::{
AllianceDelegateMsg, AllianceRedelegateMsg, AllianceUndelegateMsg, AssetDistribution, Config,
Cw20HookMsg, ExecuteMsg, InstantiateMsg, MigrateMsg,
};
use cosmwasm_std::{
from_binary, to_binary, Addr, Binary, Coin as CwCoin, CosmosMsg, Decimal, DepsMut, Empty, Env,
MessageInfo, Reply, Response, StdError, StdResult, Storage, SubMsg, Timestamp, Uint128,
WasmMsg,
};
use cw2::set_contract_version;
use cw_asset::{Asset, AssetInfo, AssetInfoBase, AssetInfoKey};
use cw_utils::parse_instantiate_response_data;
use std::collections::{HashMap, HashSet};

// use alliance_protocol::alliance_oracle_types::{AssetStaked, ChainId, EmissionsDistribution};
use crate::error::ContractError;
use crate::state::{
ASSET_REWARD_DISTRIBUTION, ASSET_REWARD_RATE, BALANCES, CONFIG, TEMP_BALANCE, TOTAL_BALANCES,
UNCLAIMED_REWARDS, USER_ASSET_REWARD_RATE, VALIDATORS, WHITELIST,
};
use crate::token_factory::{CustomExecuteMsg, DenomUnit, Metadata, TokenExecuteMsg};
use cw20::Cw20ReceiveMsg;
use terra_proto_rs::alliance::alliance::{
MsgClaimDelegationRewards, MsgDelegate, MsgRedelegate, MsgUndelegate,
};
use terra_proto_rs::cosmos::base::v1beta1::Coin;
use terra_proto_rs::traits::Message;

// version info for migration info
const CONTRACT_NAME: &str = "crates.io:terra-alliance-protocol";
Expand All @@ -37,7 +42,46 @@ const CREATE_REPLY_ID: u64 = 1;
const CLAIM_REWARD_ERROR_REPLY_ID: u64 = 2;

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> StdResult<Response> {
pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result<Response, ContractError> {
let version: Version = CONTRACT_VERSION.parse()?;
let storage_version: Version = get_contract_version(deps.storage)?.version.parse()?;

ensure!(
storage_version < version,
StdError::generic_err("Invalid contract version")
);

if storage_version <= Version::parse("0.1.1")? {
// parse operator address
let operator = deps.api.addr_validate(msg.operator.as_str())?;

#[cw_serde]
pub struct ConfigV010 {
pub governance: Addr,
pub controller: Addr,
pub oracle: Addr,
pub last_reward_update_timestamp: Timestamp,
pub alliance_token_denom: String,
pub alliance_token_supply: Uint128,
pub reward_denom: String,
}
const CONFIG_V010: Item<ConfigV010> = Item::new("config");
let config_v010 = CONFIG_V010.load(deps.storage)?;

let config = Config {
governance: config_v010.governance,
controller: config_v010.controller,
oracle: config_v010.oracle,
operator,
last_reward_update_timestamp: config_v010.last_reward_update_timestamp,
alliance_token_denom: config_v010.alliance_token_denom,
alliance_token_supply: config_v010.alliance_token_supply,
reward_denom: config_v010.reward_denom,
};
CONFIG.save(deps.storage, &config)?;
}

set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
Ok(Response::default())
}

Expand All @@ -52,6 +96,7 @@ pub fn instantiate(
let governance_address = deps.api.addr_validate(msg.governance.as_str())?;
let controller_address = deps.api.addr_validate(msg.controller.as_str())?;
let oracle_address = deps.api.addr_validate(msg.oracle.as_str())?;
let operator_address = deps.api.addr_validate(msg.operator.as_str())?;
let create_msg = TokenExecuteMsg::CreateDenom {
subdenom: msg.alliance_token_denom.to_string(),
};
Expand All @@ -77,6 +122,7 @@ pub fn instantiate(
governance: governance_address,
controller: controller_address,
oracle: oracle_address,
operator: operator_address,
alliance_token_denom: "".to_string(),
alliance_token_supply: Uint128::zero(),
last_reward_update_timestamp: Timestamp::default(),
Expand Down Expand Up @@ -168,7 +214,7 @@ fn set_asset_reward_distribution(
asset_reward_distribution: Vec<AssetDistribution>,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;
is_governance(&info, &config)?;
is_authorized(&info, &config)?;

// Ensure the dsitributions add up to 100%
let total_distribution = asset_reward_distribution
Expand Down Expand Up @@ -775,3 +821,12 @@ fn is_governance(info: &MessageInfo, config: &Config) -> Result<(), ContractErro
}
Ok(())
}

// Only governance or the operator can pass through this function
fn is_authorized(info: &MessageInfo, config: &Config) -> Result<(), ContractError> {
ensure!(
info.sender == config.governance || info.sender == config.operator,
ContractError::Unauthorized {}
);
Ok(())
}
9 changes: 9 additions & 0 deletions contracts/alliance-hub/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,13 @@ pub enum ContractError {

#[error("Invalid Distribution")]
InvalidDistribution {},

#[error("Semver parsing error: {0}")]
SemVer(String),
}

impl From<semver::Error> for ContractError {
fn from(err: semver::Error) -> Self {
Self::SemVer(err.to_string())
}
}
93 changes: 82 additions & 11 deletions contracts/alliance-hub/src/tests/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
use crate::contract::{execute, instantiate};
use crate::query::query;
use crate::state::CONFIG;
use crate::token_factory::CustomExecuteMsg;
use std::collections::HashMap;

use cosmwasm_std::testing::{mock_env, mock_info};
use cosmwasm_std::{
coin, from_binary, to_binary, Decimal, Deps, DepsMut, Response, StdResult, Uint128,
};
use cw20::Cw20ReceiveMsg;
use cw_asset::{Asset, AssetInfo};

use alliance_protocol::alliance_oracle_types::ChainId;
use alliance_protocol::alliance_protocol::{
AllPendingRewardsQuery, AllianceDelegateMsg, AllianceDelegation, AllianceRedelegateMsg,
AllianceRedelegation, AllianceUndelegateMsg, AssetQuery, Config, Cw20HookMsg, ExecuteMsg,
InstantiateMsg, PendingRewardsRes, QueryMsg, StakedBalanceRes,
AllianceRedelegation, AllianceUndelegateMsg, AssetDistribution, AssetQuery, Config,
Cw20HookMsg, ExecuteMsg, InstantiateMsg, PendingRewardsRes, QueryMsg, StakedBalanceRes,
};
use cosmwasm_std::testing::{mock_env, mock_info};
use cosmwasm_std::{coin, from_binary, to_binary, Deps, DepsMut, Response, StdResult, Uint128};
use cw20::Cw20ReceiveMsg;
use cw_asset::{Asset, AssetInfo};
use std::collections::HashMap;

use crate::contract::{execute, instantiate};
use crate::query::query;
use crate::state::CONFIG;
use crate::token_factory::CustomExecuteMsg;

pub const DENOM: &str = "token_factory/token";

Expand All @@ -24,6 +29,7 @@ pub fn setup_contract(deps: DepsMut) -> Response<CustomExecuteMsg> {
governance: "gov".to_string(),
controller: "controller".to_string(),
oracle: "oracle".to_string(),
operator: "operator".to_string(),
alliance_token_denom: "ualliance".to_string(),
reward_denom: "uluna".to_string(),
};
Expand Down Expand Up @@ -64,6 +70,7 @@ pub fn stake(deps: DepsMut, user: &str, amount: u128, denom: &str) -> Response {
let msg = ExecuteMsg::Stake {};
execute(deps, env, info, msg).unwrap()
}

pub fn stake_cw20(deps: DepsMut, user: &str, amount: u128, denom: &str) -> Response {
let info = mock_info(denom, &[]);
let env = mock_env();
Expand Down Expand Up @@ -173,3 +180,67 @@ pub fn query_all_rewards(deps: Deps, user: &str) -> Vec<PendingRewardsRes> {
pub fn query_all_staked_balances(deps: Deps) -> Vec<StakedBalanceRes> {
from_binary(&query(deps, mock_env(), QueryMsg::TotalStakedBalances {}).unwrap()).unwrap()
}

pub fn query_asset_reward_distribution(deps: Deps) -> Vec<AssetDistribution> {
from_binary(&query(deps, mock_env(), QueryMsg::RewardDistribution {}).unwrap()).unwrap()
}

#[inline]
pub fn asset_distribution_1() -> Vec<AssetDistribution> {
vec![
AssetDistribution {
asset: AssetInfo::Native("aWHALE".to_string()),
distribution: Decimal::percent(50),
},
AssetDistribution {
asset: AssetInfo::Native("bWHALE".to_string()),
distribution: Decimal::percent(50),
},
]
}

#[inline]
pub fn asset_distribution_2() -> Vec<AssetDistribution> {
vec![
AssetDistribution {
asset: AssetInfo::Native("aWHALE".to_string()),
distribution: Decimal::percent(40),
},
AssetDistribution {
asset: AssetInfo::Native("bWHALE".to_string()),
distribution: Decimal::percent(40),
},
AssetDistribution {
asset: AssetInfo::Native("willy".to_string()),
distribution: Decimal::percent(20),
},
]
}

#[inline]
pub fn asset_distribution_broken_1() -> Vec<AssetDistribution> {
vec![
AssetDistribution {
asset: AssetInfo::Native("aWHALE".to_string()),
distribution: Decimal::percent(40),
},
AssetDistribution {
asset: AssetInfo::Native("bWHALE".to_string()),
distribution: Decimal::percent(70),
},
]
}

#[inline]
pub fn asset_distribution_broken_2() -> Vec<AssetDistribution> {
vec![
AssetDistribution {
asset: AssetInfo::Native("aWHALE".to_string()),
distribution: Decimal::percent(40),
},
AssetDistribution {
asset: AssetInfo::Native("bWHALE".to_string()),
distribution: Decimal::percent(20),
},
]
}
2 changes: 2 additions & 0 deletions contracts/alliance-hub/src/tests/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ fn test_setup_contract() {
governance: Addr::unchecked("gov"),
controller: Addr::unchecked("controller"),
oracle: Addr::unchecked("oracle"),
operator: Addr::unchecked("operator"),
reward_denom: "uluna".to_string(),
alliance_token_denom: "".to_string(),
alliance_token_supply: Uint128::new(0),
Expand Down Expand Up @@ -107,6 +108,7 @@ fn test_reply_create_token() {
governance: Addr::unchecked("gov"),
controller: Addr::unchecked("controller"),
oracle: Addr::unchecked("oracle"),
operator: Addr::unchecked("operator"),
reward_denom: "uluna".to_string(),
alliance_token_denom: "factory/cosmos2contract/ualliance".to_string(),
alliance_token_supply: Uint128::new(1000000000000),
Expand Down
Loading

0 comments on commit dcde68a

Please sign in to comment.