fn after_withdraw(deps: DepsMut, env: Env, triggered_by_addr: String) -> UnbondHandlerResult {
    let state = STATE.load(deps.storage)?;
    let triggered_by = deps.api.addr_validate(&triggered_by_addr)?;
    let owner = state
        .owner
        .clone()
        .ok_or(UnbondHandlerError::UnownedHandler {})?;

    let mut response = Response::new().add_attribute("action", "after_withdraw");

    // get amount of luna obtained from Anchor
    let refund_amount = query_balance(
        &deps.querier,
        env.contract.address.clone(),
        LUNA_DENOM.to_string(),
    )?;

    // if the withdrawal is done by someone other than the owner of the unbond handler AND past the expiration time, we charge a fee
    let expiration_time = state
        .expiration_time
        .ok_or(UnbondHandlerError::UnownedHandler {})?;

    // get treasury fee from luna vault, which is the admin of the unbond handler
    let luna_vault_addr = ADMIN
        .get(deps.as_ref())?
        .ok_or(UnbondHandlerError::NotAdminSet {})?;
    let vault_fees = query_luna_vault_fees(deps.as_ref(), &luna_vault_addr)?;
    let liquidation_fee_amount =
        match triggered_by != owner && env.block.time.seconds() > expiration_time {
            true => refund_amount * vault_fees.treasury_fee.share,
            false => Uint128::zero(),
        };

    // Construct refund message
    let refund_msg = Asset {
        info: AssetInfo::NativeToken {
            denom: LUNA_DENOM.to_string(),
        },
        amount: refund_amount.checked_sub(liquidation_fee_amount)?,
    }
    .into_msg(&deps.querier, owner.clone())?;
    response = response.add_attribute(
        "refund_amount",
        refund_amount.checked_sub(liquidation_fee_amount)?,
    );
    response = response.add_attribute("liquidation_fee", liquidation_fee_amount);
    response = response.add_message(refund_msg);

    // Construct liquidation reward message if withdrawal wasn't triggered by the owner
    if !liquidation_fee_amount.is_zero() {
        // Send the liquidation_fee_amount * (1 - commission_fee) to whoever triggered the liquidation as a reward
        let reward_amount =
            liquidation_fee_amount * (Decimal::one() - vault_fees.commission_fee.share);
        let reward_msg = CosmosMsg::Bank(BankMsg::Send {
            to_address: triggered_by.to_string(),
            amount: coins(reward_amount.u128(), &*LUNA_DENOM.to_string()),
        });

        // Send the remaining chunk of the liquidation_fee_amount to the treasury
        let treasury_addr =
            query_contract_from_mem(deps.as_ref(), &state.memory_contract, TREASURY_ADDRESS_ID)?;
        let treasury_fee_amount = liquidation_fee_amount.checked_sub(reward_amount)?;
        let treasury_fee_msg = CosmosMsg::Bank(BankMsg::Send {
            to_address: treasury_addr.to_string(),
            amount: coins(treasury_fee_amount.u128(), &*LUNA_DENOM.to_string()),
        });

        response = response.add_attribute("reward_amount", reward_amount);
        response = response.add_attribute("treasury_fee_amount", treasury_fee_amount);

        response = response.add_messages(vec![reward_msg, treasury_fee_msg]);
    }

    // check if there are no more pending unbonds on Anchor for this handler, so that it can be reused
    let bluna_hub_address =
        query_contract_from_mem(deps.as_ref(), &state.memory_contract, ANCHOR_BLUNA_HUB_ID)?;

    // check if there are pending unbond requests for this handler. If not, clear the unbond handler to make it reusable
    if query_unbond_requests(
        deps.as_ref(),
        bluna_hub_address,
        env.contract.address.clone(),
    )?
    .requests
    .is_empty()
    {
        // clean state so that the handler can be reused
        let mut state = state;
        state.owner = None;
        state.expiration_time = None;

        STATE.save(deps.storage, &state)?;

        // construct message for the vault to release the unbond handler
        let release_unbond_handler_msg = CosmosMsg::Wasm(WasmMsg::Execute {
            contract_addr: luna_vault_addr.to_string(),
            msg: to_binary(&UnbondHandlerMsg::AfterUnbondHandlerReleased {
                unbond_handler_addr: env.contract.address.to_string(),
                previous_owner: owner.to_string(),
            })?,
            funds: vec![],
        });

        response = response.add_message(release_unbond_handler_msg);
        response = response.add_attribute("unbond_handler_released", true.to_string());
    }

    Ok(response)
}
/// Sends luna to its owner after it is withdrawn from Anchor, along with any liquidation fee
Sends luna to its owner after it is withdrawn from Anchor, along with any liquidation fee
Sends luna to its owner after it is withdrawn from Anchor along with any liquidation fee
fn after_withdraw(deps: DepsMut, env: Env, triggered_by_addr: String) -> UnbondHandlerResult {
    let state = STATE.load(deps.storage)?;
    let triggered_by = deps.api.addr_validate(&triggered_by_addr)?;
    let owner = state
        .owner
        .clone()
        .ok_or(UnbondHandlerError::UnownedHandler {})?;
    let mut response = Response::new().add_attribute("action", "after_withdraw");
    // get amount of luna obtained from Anchor
    let refund_amount = query_balance(
        &deps.querier,
        env.contract.address.clone(),
        LUNA_DENOM.to_string(),
    )?;
    // if the withdrawal is done by someone other than the owner of the unbond handler AND past the expiration time, we charge a fee
    let expiration_time = state
        .expiration_time
        .ok_or(UnbondHandlerError::UnownedHandler {})?;
    // get treasury fee from luna vault, which is the admin of the unbond handler
    let luna_vault_addr = ADMIN
        .get(deps.as_ref())?
        .ok_or(UnbondHandlerError::NotAdminSet {})?;
    let vault_fees = query_luna_vault_fees(deps.as_ref(), &luna_vault_addr)?;
    let liquidation_fee_amount =
        match triggered_by != owner && env.block.time.seconds() > expiration_time {
            true => refund_amount * vault_fees.treasury_fee.share,
            false => Uint128::zero(),
        };
    // Construct refund message
    let refund_msg = Asset {
        info: AssetInfo::NativeToken {
            denom: LUNA_DENOM.to_string(),
        },
        amount: refund_amount.checked_sub(liquidation_fee_amount)?,
    }
    .into_msg(&deps.querier, owner.clone())?;
    response = response.add_attribute(
        "refund_amount",
        refund_amount.checked_sub(liquidation_fee_amount)?,
    );
    response = response.add_attribute("liquidation_fee", liquidation_fee_amount);
    response = response.add_message(refund_msg);
    // Construct liquidation reward message if withdrawal wasn't triggered by the owner
    if !liquidation_fee_amount.is_zero() {
        // Send the liquidation_fee_amount * (1 - commission_fee) to whoever triggered the liquidation as a reward
        let reward_amount =
            liquidation_fee_amount * (Decimal::one() - vault_fees.commission_fee.share);
        let reward_msg = CosmosMsg::Bank(BankMsg::Send {
            to_address: triggered_by.to_string(),
            amount: coins(reward_amount.u128(), &*LUNA_DENOM.to_string()),
        });
        // Send the remaining chunk of the liquidation_fee_amount to the treasury
        let treasury_addr =
            query_contract_from_mem(deps.as_ref(), &state.memory_contract, TREASURY_ADDRESS_ID)?;
        let treasury_fee_amount = liquidation_fee_amount.checked_sub(reward_amount)?;
        let treasury_fee_msg = CosmosMsg::Bank(BankMsg::Send {
            to_address: treasury_addr.to_string(),
            amount: coins(treasury_fee_amount.u128(), &*LUNA_DENOM.to_string()),
        });
        response = response.add_attribute("reward_amount", reward_amount);
        response = response.add_attribute("treasury_fee_amount", treasury_fee_amount);
        response = response.add_messages(vec![reward_msg, treasury_fee_msg]);
    }
    // check if there are no more pending unbonds on Anchor for this handler, so that it can be reused
    let bluna_hub_address =
        query_contract_from_mem(deps.as_ref(), &state.memory_contract, ANCHOR_BLUNA_HUB_ID)?;
    // check if there are pending unbond requests for this handler. If not, clear the unbond handler to make it reusable
    if query_unbond_requests(
        deps.as_ref(),
        bluna_hub_address,
        env.contract.address.clone(),
    )?
    .requests
    .is_empty()
    {
        // clean state so that the handler can be reused
        let mut state = state;
        state.owner = None;
        state.expiration_time = None;
        STATE.save(deps.storage, &state)?;
        // construct message for the vault to release the unbond handler
        let release_unbond_handler_msg = CosmosMsg::Wasm(WasmMsg::Execute {
            contract_addr: luna_vault_addr.to_string(),
            msg: to_binary(&UnbondHandlerMsg::AfterUnbondHandlerReleased {
                unbond_handler_addr: env.contract.address.to_string(),
                previous_owner: owner.to_string(),
            })?,
            funds: vec![],
        });
        response = response.add_message(release_unbond_handler_msg);
        response = response.add_attribute("unbond_handler_released", true.to_string());
    }
    Ok(response)
}
fn after_withdraw ( deps : DepsMut , env : Env , triggered_by_addr : String ) -> UnbondHandlerResult { let state = STATE . load ( deps . storage ) ? ; let triggered_by = deps . api . addr_validate ( & triggered_by_addr ) ? ; let owner = state . owner . clone ( ) . ok_or ( UnbondHandlerError :: UnownedHandler { } ) ? ; let mut response = Response :: new ( ) . add_attribute ( " " , " " ) ; // get amount of luna obtained from Anchor let refund_amount = query_balance ( & deps . querier , env . contract . address . clone ( ) , LUNA_DENOM . to_string ( ) , ) ? ; // if the withdrawal is done by someone other than the owner of the unbond handler AND past the expiration time, we charge a fee let expiration_time = state . expiration_time . ok_or ( UnbondHandlerError :: UnownedHandler { } ) ? ; // get treasury fee from luna vault, which is the admin of the unbond handler let luna_vault_addr = ADMIN . get ( deps . as_ref ( ) ) ? . ok_or ( UnbondHandlerError :: NotAdminSet { } ) ? ; let vault_fees = query_luna_vault_fees ( deps . as_ref ( ) , & luna_vault_addr ) ? ; let liquidation_fee_amount = match triggered_by != owner && env . block . time . seconds ( ) > expiration_time { true => refund_amount * vault_fees . treasury_fee . share , false => Uint128 :: zero ( ) , } ; // Construct refund message let refund_msg = Asset { info : AssetInfo :: NativeToken { denom : LUNA_DENOM . to_string ( ) , } , amount : refund_amount . checked_sub ( liquidation_fee_amount ) ? , } . into_msg ( & deps . querier , owner . clone ( ) ) ? ; response = response . add_attribute ( " " , refund_amount . checked_sub ( liquidation_fee_amount ) ? , ) ; response = response . add_attribute ( " " , liquidation_fee_amount ) ; response = response . add_message ( refund_msg ) ; // Construct liquidation reward message if withdrawal wasn't triggered by the owner if ! liquidation_fee_amount . is_zero ( ) { // Send the liquidation_fee_amount * (1 - commission_fee) to whoever triggered the liquidation as a reward let reward_amount = liquidation_fee_amount * ( Decimal :: one ( ) - vault_fees . commission_fee . share ) ; let reward_msg = CosmosMsg :: Bank ( BankMsg :: Send { to_address : triggered_by . to_string ( ) , amount : coins ( reward_amount . u128 ( ) , & * LUNA_DENOM . to_string ( ) ) , } ) ; // Send the remaining chunk of the liquidation_fee_amount to the treasury let treasury_addr = query_contract_from_mem ( deps . as_ref ( ) , & state . memory_contract , TREASURY_ADDRESS_ID ) ? ; let treasury_fee_amount = liquidation_fee_amount . checked_sub ( reward_amount ) ? ; let treasury_fee_msg = CosmosMsg :: Bank ( BankMsg :: Send { to_address : treasury_addr . to_string ( ) , amount : coins ( treasury_fee_amount . u128 ( ) , & * LUNA_DENOM . to_string ( ) ) , } ) ; response = response . add_attribute ( " " , reward_amount ) ; response = response . add_attribute ( " " , treasury_fee_amount ) ; response = response . add_messages ( vec ! [ reward_msg treasury_fee_msg ] ) ; } // check if there are no more pending unbonds on Anchor for this handler, so that it can be reused let bluna_hub_address = query_contract_from_mem ( deps . as_ref ( ) , & state . memory_contract , ANCHOR_BLUNA_HUB_ID ) ? ; // check if there are pending unbond requests for this handler. If not, clear the unbond handler to make it reusable if query_unbond_requests ( deps . as_ref ( ) , bluna_hub_address , env . contract . address . clone ( ) , ) ? . requests . is_empty ( ) { // clean state so that the handler can be reused let mut state = state ; state . owner = None ; state . expiration_time = None ; STATE . save ( deps . storage , & state ) ? ; // construct message for the vault to release the unbond handler let release_unbond_handler_msg = CosmosMsg :: Wasm ( WasmMsg :: Execute { contract_addr : luna_vault_addr . to_string ( ) , msg : to_binary ( & UnbondHandlerMsg :: AfterUnbondHandlerReleased { unbond_handler_addr : env . contract . address . to_string ( ) , previous_owner : owner . to_string ( ) , } ) ? , funds : vec ! [ ] , } ) ; response = response . add_message ( release_unbond_handler_msg ) ; response = response . add_attribute ( " " , true . to_string ( ) ) ; } Ok ( response ) }
Sends luna to its owner after it is withdrawn from Anchor, along with any liquidation fee
Sends luna to its owner after it is withdrawn from Anchor along with any liquidation fee
deps
DepsMut
env
Env
triggered_by_addr
String
deps
DepsMut
env
Env
triggered_by_addr
String