Skip to content

Commit

Permalink
Merge pull request #159 from hadronlabs-org/fix/lsm-amounts
Browse files Browse the repository at this point in the history
fix: lsm amounts
  • Loading branch information
oldremez authored Aug 20, 2024
2 parents bdbb1a7 + 5ca6914 commit 6735bb6
Show file tree
Hide file tree
Showing 7 changed files with 566 additions and 176 deletions.
143 changes: 0 additions & 143 deletions .github/workflows/build.yml

This file was deleted.

45 changes: 45 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -647,3 +647,48 @@ jobs:
docker stop -t0 $(docker ps -a -q) || true
docker container prune -f || true
docker volume rm $(docker volume ls -q) || true
test-splitter:
name: test:splitter Integration Tests
needs:
- images-prepare
- artifacts-prepare
runs-on: self-hosted
steps:
- name: Upgrade docker compose to use v2
run: sudo curl -L
"https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname
-s)-$(uname -m)" -o /usr/local/bin/docker-compose && sudo chmod +x
/usr/local/bin/docker-compose
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20.12.2
- name: Install Yarn
run: npm install -g yarn
- name: Log in to Private Registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Clean volumes
run: docker volume prune -f
- name: Download images
run: |
cd integration_tests
yarn build-images
- name: Download artifacts
uses: actions/cache@v4
with:
path: artifacts
key: ${{ runner.os }}-${{ github.sha }}
- name: Run test test:splitter
run: cd integration_tests && yarn && yarn test:splitter
- name: Cleanup resources
if: always()
run: |
docker stop -t0 $(docker ps -a -q) || true
docker container prune -f || true
docker volume rm $(docker volume ls -q) || true
59 changes: 37 additions & 22 deletions contracts/core/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub fn query(deps: Deps<NeutronQuery>, _env: Env, msg: QueryMsg) -> ContractResu
}

fn query_pending_lsm_shares(deps: Deps<NeutronQuery>) -> ContractResult<Binary> {
let shares: Vec<(String, (String, Uint128))> = PENDING_LSM_SHARES
let shares: Vec<(String, (String, Uint128, Uint128))> = PENDING_LSM_SHARES
.range(deps.storage, None, None, cosmwasm_std::Order::Ascending)
.collect::<StdResult<Vec<_>>>()?;
to_json_binary(&shares).map_err(From::from)
Expand All @@ -135,7 +135,7 @@ fn query_pause_info(deps: Deps<NeutronQuery>) -> ContractResult<Binary> {
}

fn query_lsm_shares_to_redeem(deps: Deps<NeutronQuery>) -> ContractResult<Binary> {
let shares: Vec<(String, (String, Uint128))> = LSM_SHARES_TO_REDEEM
let shares: Vec<(String, (String, Uint128, Uint128))> = LSM_SHARES_TO_REDEEM
.range(deps.storage, None, None, cosmwasm_std::Order::Ascending)
.collect::<StdResult<Vec<_>>>()?;
to_json_binary(&shares).map_err(From::from)
Expand Down Expand Up @@ -455,18 +455,23 @@ fn execute_puppeteer_hook(
if *reason == IBCTransferReason::LSMShare {
let current_pending =
PENDING_LSM_SHARES.may_load(deps.storage, denom.to_string())?;
if let Some((remote_denom, current_amount)) = current_pending {
if let Some((remote_denom, shares_amount, real_amount)) = current_pending {
let sent_amount = Uint128::from(*amount);
LSM_SHARES_TO_REDEEM.update(
deps.storage,
denom.to_string(),
|one| {
let mut new = one.unwrap_or((remote_denom, Uint128::zero()));
let mut new = one.unwrap_or((
remote_denom,
Uint128::zero(),
Uint128::zero(),
));
new.1 += sent_amount;
new.2 += real_amount;
StdResult::Ok(new)
},
)?;
if current_amount == sent_amount {
if shares_amount == sent_amount {
PENDING_LSM_SHARES.remove(deps.storage, denom.to_string());
} else {
PENDING_LSM_SHARES.update(
Expand All @@ -476,6 +481,7 @@ fn execute_puppeteer_hook(
Some(one) => {
let mut new = one;
new.1 -= Uint128::from(*amount);
new.2 -= real_amount;
StdResult::Ok(new)
}
None => unreachable!("denom should be in the map"),
Expand All @@ -488,7 +494,9 @@ fn execute_puppeteer_hook(
drop_puppeteer_base::msg::Transaction::RedeemShares { items, .. } => {
let mut sum = 0u128;
for item in items {
sum += item.amount.u128();
let (_remote_denom, _shares_amount, real_amount) = LSM_SHARES_TO_REDEEM
.load(deps.storage, item.local_denom.to_string())?;
sum += real_amount.u128();
LSM_SHARES_TO_REDEEM.remove(deps.storage, item.local_denom.to_string());
}
TOTAL_LSM_SHARES.update(deps.storage, |one| StdResult::Ok(one - sum))?;
Expand Down Expand Up @@ -1012,39 +1020,43 @@ fn execute_bond(
return Err(ContractError::BondLimitExceeded {});
}
}
BONDED_AMOUNT.update(deps.storage, |total| StdResult::Ok(total + amount))?;
let denom_type = check_denom::check_denom(&deps.as_ref(), &denom, &config)?;
let mut msgs = vec![];
let mut attrs = vec![attr("action", "bond")];
let exchange_rate = query_exchange_rate(deps.as_ref(), &config)?;
attrs.push(attr("exchange_rate", exchange_rate.to_string()));

if let check_denom::DenomType::LsmShare(remote_denom, validator) = denom_type {
amount = calc_lsm_share_underlying_amount(
let share_amount = amount;
let real_amount = calc_lsm_share_underlying_amount(
deps.as_ref(),
&config.puppeteer_contract,
&amount,
validator,
)?;
if amount < config.lsm_min_bond_amount {
if real_amount < config.lsm_min_bond_amount {
return Err(ContractError::LSMBondAmountIsBelowMinimum {
min_stake_amount: config.lsm_min_bond_amount,
bond_amount: amount,
bond_amount: real_amount,
});
}
TOTAL_LSM_SHARES.update(deps.storage, |total| StdResult::Ok(total + amount.u128()))?;
TOTAL_LSM_SHARES.update(deps.storage, |total| {
StdResult::Ok(total + real_amount.u128())
})?;
PENDING_LSM_SHARES.update(deps.storage, denom, |one| {
let mut new = one.unwrap_or((remote_denom, Uint128::zero()));
new.1 += amount;
let mut new = one.unwrap_or((remote_denom, Uint128::zero(), Uint128::zero()));
new.1 += share_amount;
new.2 += real_amount;
StdResult::Ok(new)
})?;
amount = real_amount;
} else {
// if it's not LSM share, we send this amount to the staker
msgs.push(CosmosMsg::Bank(BankMsg::Send {
to_address: config.staker_contract.to_string(),
amount: vec![Coin::new(amount.u128(), denom)],
}));
}
BONDED_AMOUNT.update(deps.storage, |total| StdResult::Ok(total + amount))?;
let issue_amount = amount * (Decimal::one() / exchange_rate);
attrs.push(attr("issue_amount", issue_amount.to_string()));

Expand Down Expand Up @@ -1518,11 +1530,13 @@ pub fn get_pending_redeem_msg<T>(

let items = shares_to_redeeem
.iter()
.map(|(local_denom, (denom, amount))| RedeemShareItem {
amount: *amount,
local_denom: local_denom.to_string(),
remote_denom: denom.to_string(),
})
.map(
|(local_denom, (denom, share_amount, _real_amount))| RedeemShareItem {
amount: *share_amount,
local_denom: local_denom.to_string(),
remote_denom: denom.to_string(),
},
)
.collect();
Ok(Some(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: config.puppeteer_contract.to_string(),
Expand All @@ -1542,9 +1556,10 @@ fn get_pending_lsm_share_msg<T, X: CustomQuery>(
env: &Env,
funds: Vec<cosmwasm_std::Coin>,
) -> ContractResult<Option<CosmosMsg<T>>> {
let lsm_share: Option<(String, (String, Uint128))> = PENDING_LSM_SHARES.first(deps.storage)?;
let lsm_share: Option<(String, (String, Uint128, Uint128))> =
PENDING_LSM_SHARES.first(deps.storage)?;
match lsm_share {
Some((local_denom, (_remote_denom, amount))) => {
Some((local_denom, (_remote_denom, share_amount, _real_amount))) => {
Ok(Some(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: config.puppeteer_contract.to_string(),
msg: to_json_binary(
Expand All @@ -1556,7 +1571,7 @@ fn get_pending_lsm_share_msg<T, X: CustomQuery>(
funds: {
let mut all_funds = vec![cosmwasm_std::Coin {
denom: local_denom,
amount,
amount: share_amount,
}];
all_funds.extend(funds);
all_funds
Expand Down
Loading

0 comments on commit 6735bb6

Please sign in to comment.