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

Astroport DCA Module Part 2 Submission #2

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
1,428 changes: 305 additions & 1,123 deletions Cargo.lock

Large diffs are not rendered by default.

31 changes: 20 additions & 11 deletions contracts/dca/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "astroport-dca-module"
version = "1.0.0"
authors = ["Astroport", "Kaimen Sano"]
version = "2.0.0"
authors = ["Astroport", "Kaimen Sano", "yoisha <[email protected]>"]
edition = "2021"
description = "The Astroport DCA module contract implementation"
license = "MIT"
Expand All @@ -20,19 +20,28 @@ crate-type = ["cdylib", "rlib"]
[features]
# for quicker tests, cargo test --lib
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces", "cosmwasm-vm/backtraces"]
backtraces = ["cosmwasm-std/backtraces"]

[dependencies]
astroport = { git = "https://github.com/astroport-fi/astroport-core.git", branch = "main" }
astroport-dca = { path = "../../packages/astroport-dca", version = "1.0.0" }
cw2 = { version = "0.8" }
cw20 = { version = "0.8" }
cosmwasm-std = { version = "0.16.2" }
cw-storage-plus = {version = "0.8.0"}
astroport = { version = "2.0.0", git = "https://github.com/astroport-fi/astroport-core.git" }
astroport-dca = { version = "2.0.0", path = "../../packages/astroport-dca" }

cw-storage-plus = "0.14.0"
cw2 = "0.14.0"
cw20 = "0.14.0"
cosmwasm-std = "1.0.0"

schemars = "0.8.1"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.20" }

[dev-dependencies]
cosmwasm-vm = { version = "0.16.2", default-features = false, features = ["iterator"] }
cosmwasm-schema = "0.16.2"
cosmwasm-schema = "1.0.0"
cw-multi-test = "0.14.0"
cw20-base = "0.14.0"
cw1-whitelist = "0.14.0"

astroport-router = { version = "1.0.0", git = "https://github.com/astroport-fi/astroport-core.git" }
astroport-factory = { version = "1.2.0", git = "https://github.com/astroport-fi/astroport-core.git" }
astroport-pair = { version = "1.0.0", git = "https://github.com/astroport-fi/astroport-core.git" }
astroport-pair-stable = { version = "1.0.0", git = "https://github.com/astroport-fi/astroport-core.git" }
2 changes: 1 addition & 1 deletion contracts/dca/examples/dca_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::fs::create_dir_all;

use cosmwasm_schema::{export_schema_with_title, remove_schemas, schema_for};

use astroport_dca::dca::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
use astroport_dca::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};

fn main() {
let mut out_dir = current_dir().unwrap();
Expand Down
136 changes: 92 additions & 44 deletions contracts/dca/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
use std::str::FromStr;

use crate::error::ContractError;
use crate::handlers::{
add_bot_tip, cancel_dca_order, create_dca_order, modify_dca_order, perform_dca_purchase,
update_config, update_user_config, withdraw, ModifyDcaOrderParameters,
};
use crate::queries::{get_config, get_user_config, get_user_dca_orders};
use crate::state::{Config, CONFIG};

use astroport::asset::addr_validate_to_lower;
use astroport::asset::{Asset, AssetInfo};
use astroport_dca::{Cw20HookMsg, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
use cosmwasm_std::{
entry_point, to_binary, Binary, Decimal, Deps, DepsMut, Env, MessageInfo, Response, StdResult,
entry_point, from_binary, to_binary, Binary, Decimal, Deps, DepsMut, Env, MessageInfo,
Response, StdResult, Uint128,
};

use astroport_dca::dca::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg};
use cw2::set_contract_version;

use crate::{
error::ContractError,
handlers::{
add_bot_tip, cancel_dca_order, create_dca_order, modify_dca_order, perform_dca_purchase,
update_config, update_user_config, withdraw,
},
queries::{get_all_dca_orders, get_config, get_tips, get_user_config, get_user_dca_orders},
state::{Config, CONFIG, DCA_ID, TIPS},
};

/// Contract name that is used for migration.
const CONTRACT_NAME: &str = "astroport-dca";
/// Contract version that is used for migration.
Expand Down Expand Up @@ -46,21 +48,38 @@ pub fn instantiate(
let max_spread = Decimal::from_str(&msg.max_spread)?;

// validate that factory_addr and router_addr is an address
let factory_addr = addr_validate_to_lower(deps.api, &msg.factory_addr)?;
let router_addr = addr_validate_to_lower(deps.api, &msg.router_addr)?;
let factory_addr = deps.api.addr_validate(&msg.factory_addr)?;
let router_addr = deps.api.addr_validate(&msg.router_addr)?;

set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

msg.whitelisted_tokens
.iter()
.try_for_each(|e| e.check(deps.api))?;

msg.tips
.iter()
.try_for_each(|tip| -> Result<_, ContractError> {
(tip.amount > Uint128::zero())
.then(|| ())
.ok_or(ContractError::InvalidTipAmount {})?;

tip.info.check(deps.api)?;

Ok(())
})?;

let config = Config {
max_hops: msg.max_hops,
per_hop_fee: msg.per_hop_fee,
whitelisted_tokens: msg.whitelisted_tokens,
max_spread,
factory_addr,
router_addr,
};

CONFIG.save(deps.storage, &config)?;
DCA_ID.save(deps.storage, &0)?;
TIPS.save(deps.storage, &msg.tips)?;

Ok(Response::new())
}
Expand All @@ -74,7 +93,9 @@ pub fn instantiate(
///
/// * `_msg` - The [`MigrateMsg`] to migrate the contract.
#[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) -> StdResult<Response> {
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

Ok(Response::default())
}

Expand Down Expand Up @@ -134,19 +155,30 @@ pub fn execute(
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::Receive(receive_msg) => {
let sender = deps.api.addr_validate(&receive_msg.sender)?;
match from_binary(&receive_msg.msg)? {
Cw20HookMsg::AddBotTips {} => add_bot_tip(
deps,
MessageInfo {
sender,
funds: vec![],
},
vec![Asset {
info: AssetInfo::Token {
contract_addr: info.sender,
},
amount: receive_msg.amount,
}],
),
}
}
ExecuteMsg::UpdateConfig {
max_hops,
per_hop_fee,
whitelisted_tokens,
max_spread,
} => update_config(
deps,
info,
max_hops,
per_hop_fee,
whitelisted_tokens,
max_spread,
),
tips,
} => update_config(deps, info, max_hops, whitelisted_tokens, max_spread, tips),
ExecuteMsg::UpdateUserConfig {
max_hops,
max_spread,
Expand All @@ -156,6 +188,8 @@ pub fn execute(
target_asset,
interval,
dca_amount,
start_at,
config_override,
} => create_dca_order(
deps,
env,
Expand All @@ -164,32 +198,40 @@ pub fn execute(
target_asset,
interval,
dca_amount,
start_at,
config_override,
),
ExecuteMsg::AddBotTip {} => add_bot_tip(deps, info),
ExecuteMsg::Withdraw { tip: amount } => withdraw(deps, info, amount),
ExecuteMsg::PerformDcaPurchase { user, hops } => {
perform_dca_purchase(deps, env, info, user, hops)
ExecuteMsg::AddTips {} => add_bot_tip(
deps,
info.clone(),
info.funds
.into_iter()
.map(|e| Asset {
info: AssetInfo::NativeToken { denom: e.denom },
amount: e.amount,
})
.collect::<Vec<_>>(),
),
ExecuteMsg::WithdrawTips { tips } => withdraw(deps, info, tips),
ExecuteMsg::PerformDcaPurchase { id, hops } => {
perform_dca_purchase(deps, env, info, id, hops)
}
ExecuteMsg::CancelDcaOrder { initial_asset } => cancel_dca_order(deps, info, initial_asset),
ExecuteMsg::CancelDcaOrder { id } => cancel_dca_order(deps, info, id),
ExecuteMsg::ModifyDcaOrder {
old_initial_asset,
new_initial_asset,
new_target_asset,
new_interval,
new_dca_amount,
should_reset_purchase_time,
id,
interval,
dca_amount,
initial_amount,
config_override,
} => modify_dca_order(
deps,
env,
info,
ModifyDcaOrderParameters {
old_initial_asset,
new_initial_asset,
new_target_asset,
new_interval,
new_dca_amount,
should_reset_purchase_time,
},
id,
initial_amount,
interval,
dca_amount,
config_override,
),
}
}
Expand All @@ -216,7 +258,13 @@ pub fn execute(
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::Config {} => to_binary(&get_config(deps)?),
QueryMsg::Tips {} => to_binary(&get_tips(deps)?),
QueryMsg::UserConfig { user } => to_binary(&get_user_config(deps, user)?),
QueryMsg::UserDcaOrders { user } => to_binary(&get_user_dca_orders(deps, env, user)?),
QueryMsg::AllDcaOrders {
start_after,
limit,
is_ascending,
} => to_binary(&get_all_dca_orders(deps, start_after, limit, is_ascending)?),
}
}
21 changes: 21 additions & 0 deletions contracts/dca/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ pub enum ContractError {
#[error("Token has already been used to DCA")]
AlreadyDeposited {},

#[error("DCA amount is not equal to fund sent")]
InvalidNativeTokenDeposit {},

#[error("DCA amount is not equal to allowance set by token")]
InvalidTokenDeposit {},

Expand All @@ -50,6 +53,9 @@ pub enum ContractError {
#[error("Hop route does not end up at target_asset")]
TargetAssetAssertion {},

#[error("Hop route does not start at initial_asset")]
InitialAssetAssertion {},

#[error("Asset balance is less than DCA purchase amount")]
InsufficientBalance {},

Expand All @@ -61,4 +67,19 @@ pub enum ContractError {

#[error("Initial asset deposited is not divisible by the DCA amount")]
IndivisibleDeposit {},

#[error("Native swap is not allowed")]
InvalidNativeSwap {},

#[error("New initial amount must be greater than old initial amount")]
InvalidNewInitialAmount {},

#[error("Tip amount must be greater than zero")]
InvalidTipAmount {},

#[error("Tip asset info must be whitelisted")]
InvalidTipAssetInfo {},

#[error("Tip balance is insufficient to withdraw")]
InsufficientTipWithdrawBalance {},
}
Loading