Skip to content

Commit

Permalink
Merge pull request #14 from hadronlabs-org/feat/bond
Browse files Browse the repository at this point in the history
feat: bond #LIDO-82
  • Loading branch information
ratik authored Dec 15, 2023
2 parents 89ce726 + 971ad97 commit 27c96bb
Show file tree
Hide file tree
Showing 44 changed files with 1,502 additions and 301 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,7 @@ jobs:
yarn build-images
- run: make compile
- name: Run tests
run: cd integration_tests && yarn test
run: |
cd integration_tests
yarn vitest ./src --run --shard 1/2 --bail 1
yarn vitest ./src --run --shard 2/2 --bail 1
65 changes: 64 additions & 1 deletion Cargo.lock

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

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ members = [

"contracts/stargate-poc",
"contracts/distribution",
"contracts/factory",
"contracts/interchain-interceptor",
"contracts/interchain-interceptor-authz",
"contracts/validators-stats",
"contracts/token",
"contracts/validators-set",
"contracts/strategy",
"contracts/core",
"packages/interchain-interceptor-base",
"packages/base",
]

resolver = "2"
Expand All @@ -25,6 +28,7 @@ protobuf = "3.2.0"
tendermint-proto = "0.34.0"
cosmwasm-std = { version = "1.5.0", default-features = false, features = [
"stargate",
"cosmwasm_1_2",
] }
cosmwasm-schema = { version = "1.5.0", default-features = false }
cw-storage-plus = { version = "1.2.0", default-features = false }
Expand All @@ -40,6 +44,7 @@ sha2 = { version = "0.10.8" }
bech32 = { version = "0.9.1" }

lido-interchain-interceptor-base = { path = "./packages/interchain-interceptor-base", default-features = false }
lido-staking-base = { path = "./packages/base", default-features = false }
thiserror = "1.0.50"

[profile.release]
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ compile:

check_contracts:
@cargo install cosmwasm-check
@cosmwasm-check --available-capabilities iterator,staking,stargate,neutron,cosmwasm_1_1 artifacts/*.wasm
@cosmwasm-check --available-capabilities iterator,staking,stargate,neutron,cosmwasm_1_1,cosmwasm_1_2 artifacts/*.wasm

build: schema clippy test fmt doc compile check_contracts
2 changes: 2 additions & 0 deletions contracts/core/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[alias]
schema = "run --bin lido-core-schema"
47 changes: 47 additions & 0 deletions contracts/core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[package]
authors = ["Sergey Ratiashvili <[email protected]>"]
description = "Contract to support staking core"
edition = "2021"
name = "lido-core"
version = "1.0.0"

exclude = [
# Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication.
"contract.wasm",
"hash.txt",
]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib", "rlib"]

[features]
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []

[dependencies]
cosmos-sdk-proto = { workspace = true }
prost = { workspace = true }
prost-types = { workspace = true }
protobuf = { workspace = true }
tendermint-proto = { workspace = true }

cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
cw-storage-plus = { workspace = true }
cw-ownable = { workspace = true }
cw2 = { workspace = true }
cw20 = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true }
serde-json-wasm = { workspace = true }
thiserror = { workspace = true }
lido-staking-base = { workspace = true }
neutron-sdk = { workspace = true }

[dev-dependencies]
cosmwasm-storage = { workspace = true }
cw-multi-test = { workspace = true }
1 change: 1 addition & 0 deletions contracts/core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# LIDO Staking Core
11 changes: 11 additions & 0 deletions contracts/core/src/bin/lido-core-schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use cosmwasm_schema::write_api;
use lido_staking_base::msg::core::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};

fn main() {
write_api! {
instantiate: InstantiateMsg,
query: QueryMsg,
execute: ExecuteMsg,
migrate: MigrateMsg
}
}
172 changes: 172 additions & 0 deletions contracts/core/src/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
use crate::error::{ContractError, ContractResult};
use cosmwasm_std::{
attr, ensure_eq, ensure_ne, entry_point, to_json_binary, Attribute, Binary, CosmosMsg, Decimal,
Deps, DepsMut, Env, MessageInfo, Response, StdResult, Uint128, WasmMsg,
};
use cw2::set_contract_version;
use lido_staking_base::helpers::answer::response;
use lido_staking_base::msg::core::{ExecuteMsg, InstantiateMsg, QueryMsg};
use lido_staking_base::msg::token::ExecuteMsg as TokenExecuteMsg;
use lido_staking_base::state::core::CONFIG;
use neutron_sdk::bindings::{msg::NeutronMsg, query::NeutronQuery};
use std::str::FromStr;
use std::vec;
const CONTRACT_NAME: &str = concat!("crates.io:lido-neutron-contracts__", env!("CARGO_PKG_NAME"));
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
_env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> ContractResult<Response<NeutronMsg>> {
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

CONFIG.save(deps.storage, &msg.clone().into())?;
let attrs: Vec<Attribute> = vec![
attr("token_contract", msg.token_contract),
attr("puppeteer_contract", msg.puppeteer_contract),
attr("strategy_contract", msg.strategy_contract),
attr("owner", msg.owner),
];
Ok(response("instantiate", CONTRACT_NAME, attrs))
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps<NeutronQuery>, env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::Config {} => to_json_binary(&CONFIG.load(deps.storage)?),
QueryMsg::ExchangeRate {} => to_json_binary(&query_exchange_rate(deps, env)?),
}
}

fn query_exchange_rate(_deps: Deps<NeutronQuery>, _env: Env) -> StdResult<Decimal> {
Decimal::from_str("1.01")
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut<NeutronQuery>,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> ContractResult<Response<NeutronMsg>> {
match msg {
ExecuteMsg::Bond { receiver } => execute_bond(deps, env, info, receiver),
ExecuteMsg::Unbond { amount } => execute_unbond(deps, env, info, amount),
ExecuteMsg::UpdateConfig {
token_contract,
puppeteer_contract,
strategy_contract,
owner,
} => execute_update_config(
deps,
env,
info,
token_contract,
puppeteer_contract,
strategy_contract,
owner,
),
}
}

fn execute_bond(
deps: DepsMut<NeutronQuery>,
env: Env,
info: MessageInfo,
receiver: Option<String>,
) -> ContractResult<Response<NeutronMsg>> {
let config = CONFIG.load(deps.storage)?;

let funds = info.funds;
ensure_ne!(
funds.len(),
0,
ContractError::InvalidFunds {
reason: "no funds".to_string()
}
);
ensure_eq!(
funds.len(),
1,
ContractError::InvalidFunds {
reason: "expected 1 denom".to_string()
}
);
let mut attrs = vec![attr("action", "bond")];

let amount = funds[0].amount;
let denom = funds[0].denom.to_string();
check_denom(denom)?;

let exchange_rate = query_exchange_rate(deps.as_ref(), env)?;
attrs.push(attr("exchange_rate", exchange_rate.to_string()));

let issue_amount = amount * exchange_rate;
attrs.push(attr("issue_amount", issue_amount.to_string()));

let receiver = receiver.map_or(Ok::<String, ContractError>(info.sender.to_string()), |a| {
deps.api.addr_validate(&a)?;
Ok(a)
})?;
attrs.push(attr("receiver", receiver.clone()));

let msgs = vec![CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: config.token_contract,
msg: to_json_binary(&TokenExecuteMsg::Mint {
amount: issue_amount,
receiver,
})?,
funds: vec![],
})];
Ok(response("execute-bond", CONTRACT_NAME, attrs).add_messages(msgs))
}

fn check_denom(_denom: String) -> ContractResult<()> {
//todo: check denom
Ok(())
}

fn execute_update_config(
deps: DepsMut<NeutronQuery>,
_env: Env,
info: MessageInfo,
token_contract: Option<String>,
puppeteer_contract: Option<String>,
strategy_contract: Option<String>,
owner: Option<String>,
) -> ContractResult<Response<NeutronMsg>> {
let mut config = CONFIG.load(deps.storage)?;
ensure_eq!(config.owner, info.sender, ContractError::Unauthorized {});

let mut attrs = vec![attr("action", "update_config")];
if let Some(token_contract) = token_contract {
config.token_contract = token_contract.clone();
attrs.push(attr("token_contract", token_contract));
}
if let Some(puppeteer_contract) = puppeteer_contract {
config.puppeteer_contract = puppeteer_contract.clone();
attrs.push(attr("puppeteer_contract", puppeteer_contract));
}
if let Some(strategy_contract) = strategy_contract {
config.strategy_contract = strategy_contract.clone();
attrs.push(attr("strategy_contract", strategy_contract));
}
if let Some(owner) = owner {
config.owner = owner.clone();
attrs.push(attr("owner", owner));
}
CONFIG.save(deps.storage, &config)?;
Ok(response("execute-update_config", CONTRACT_NAME, attrs))
}

fn execute_unbond(
_deps: DepsMut<NeutronQuery>,
_env: Env,
_info: MessageInfo,
_amount: Uint128,
) -> ContractResult<Response<NeutronMsg>> {
unimplemented!("todo");
}
Loading

0 comments on commit 27c96bb

Please sign in to comment.