Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
28 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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@
# program outputs
# Remove if you want to save them to your github
programs/**/output/*
!programs/**/output/README.md
!programs/**/output/README.md

*scratch*
111 changes: 75 additions & 36 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 0 additions & 12 deletions manager_configs/mainnet/bridges/neutron_gaia.toml

This file was deleted.

12 changes: 12 additions & 0 deletions manager_configs/mainnet/bridges/neutron_juno.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[bridges.neutron.juno.polytone.neutron]
voice_addr = "neutron15c0d3k8nf5t82zzkl8l7he3smx033hsr9dvzjeeuj7e8n46rqy5se0pn3e"
note_addr = "neutron174ne8p7zh539sht8sfjsa9r6uwe3pzlvqedr0yquml9crfzsfnlshvlse8"
other_note_port = "wasm.juno1yt5kcplze0sark8f55fklk70uay3863t5q3j3a8kgvs3rlmjya9qys0d2y"
connection_id = "connection-95"
channel_id = "channel-4721"
[bridges.neutron.juno.polytone.juno]
voice_addr = "juno1c9hx3q7sd2d0xgknc52ft6qsqxemkuxh3nt8d4rmdtdua25x5h0sdd2zm5"
note_addr = "juno1yt5kcplze0sark8f55fklk70uay3863t5q3j3a8kgvs3rlmjya9qys0d2y"
other_note_port = "wasm.neutron174ne8p7zh539sht8sfjsa9r6uwe3pzlvqedr0yquml9crfzsfnlshvlse8"
connection_id = "connection-530"
channel_id = "channel-620"
9 changes: 9 additions & 0 deletions manager_configs/mainnet/chains.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,12 @@ prefix = "neutron"
gas_price = "0.0053"
gas_denom = "untrn"
coin_type = "118"

[chains.juno]
name = "juno"
rpc = "https://juno-rpc.polkachu.com"
grpc = "https://juno-grpc.polkachu.com:12690"
prefix = "juno"
gas_price = "0.075"
gas_denom = "ujuno"
coin_type = "118"
12 changes: 11 additions & 1 deletion manager_configs/mainnet/contracts.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@
[contracts.code_ids.neutron]
# Registry is not used and only needed on neutron
valence_program_registry = 3234
polytone_proxy = 231
valence_authorization = 3225
valence_processor = 3226
valence_base_account = 3227
valence_forwarder_library = 3228
valence_splitter_library = 3229
valence_reverse_splitter_library = 3230
valence_drop_liquid_staker = 3231
valence_drop_liquid_unstaker = 3255
valence_astroport_lper = 3232
valence_astroport_withdrawer = 3233
valence_drop_liquid_unstaker = 3255

[contracts.code_ids.juno]
polytone_proxy = 3321
valence_processor = 4780
valence_base_account = 4781
valence_forwarder_library = 4782
valence_splitter_library = 4783
valence_reverse_splitter_library = 4784
valence_generic_ibc_transfer_library = 4785
46 changes: 46 additions & 0 deletions programs/crosschain_astroport_lper/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[package]
name = "crosschain_astroport_lper"
authors = ["Timewave Labs"]
edition = "2021"
license = "Apache-2.0"
version = "0.1.0"
repository = "https://github.com/timewave-computer/program_deployer"

[dependencies]
deployer-lib = { workspace = true }
valence-program-manager = { workspace = true }
serde_json = { workspace = true }
clap = { workspace = true }
tokio = { workspace = true }

# Libraries
valence-authorization = { workspace = true }
valence-base-account = { workspace = true }
valence-storage-account = { workspace = true }
valence-processor = { workspace = true }
valence-splitter-library = { workspace = true }
valence-astroport-lper = { workspace = true }
valence-forwarder-library = { workspace = true }
valence-astroport-withdrawer = { workspace = true }
valence-generic-ibc-transfer-library = { workspace = true }
valence-neutron-ibc-transfer-library = { workspace = true }
valence-reverse-splitter-library = { workspace = true }
valence-osmosis-gamm-lper = { workspace = true }
valence-osmosis-gamm-withdrawer = { workspace = true }
valence-osmosis-cl-lper = { workspace = true }
valence-osmosis-cl-withdrawer = { workspace = true }
valence-encoder-broker = { workspace = true }
valence-neutron-ic-querier = { workspace = true }
valence-drop-liquid-staker = { workspace = true }
valence-program-registry = { workspace = true }

# utils
valence-account-utils = { workspace = true }
valence-astroport-utils = { workspace = true }
valence-osmosis-utils = { workspace = true }
valence-authorization-utils = { workspace = true }
valence-ibc-utils = { workspace = true }
valence-macros = { workspace = true }
valence-processor-utils = { workspace = true }
valence-library-base = { workspace = true }
valence-library-utils = { workspace = true }
9 changes: 9 additions & 0 deletions programs/crosschain_astroport_lper/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Program builder

This is a single program builder, structure:

- `output/` - Output directory for deployed program
- `src/` - Program source code
- `src/main.rs` - entry point to the script
- `src/program.rs` - Program builder code, this is rust helper that allows you to build the program config, this is the only file that should be modified to deploy a program.
- `program_params/` - Program parameters that will injected into the program builder function, each environment will have its own program parameters toml file, name with the environment name, Example: `program_params/local.toml` or `program_params/mainnet.toml`
6 changes: 6 additions & 0 deletions programs/crosschain_astroport_lper/output/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Output

This directory will hold all the output files of programs, running the script will generate a directory per run with the date and time of the run, inside each directory you will find:

- instantiated-program-config.json - The instantiated program config which includes all the addresses of the contracts
- raw-program-config.json - The generated raw program config before instantiation
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
owner="neutron14wey3cpz2cxswu9u6gaalz2xxh03xdeyqal9cf"
pool_addr="neutron145z3nj7yqft2vpugr5a5p7jsnagvms90tvtej45g4s0xkqalhy7sj20vgz"
ntrn_on_neutron="untrn"
atom_on_neutron="ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9"
atom_on_juno="ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9"
permissioned_withdrawer="neutron14wey3cpz2cxswu9u6gaalz2xxh03xdeyqal9cf"
juno_gaia_ibc_channel_id="channel-1"
gaia_neutron_ibc_channel_id="channel-569"
10 changes: 10 additions & 0 deletions programs/crosschain_astroport_lper/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
mod program_builder;

use std::error::Error;

use program_builder::program_builder;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
deployer_lib::main(file!(), program_builder).await
}
226 changes: 226 additions & 0 deletions programs/crosschain_astroport_lper/src/program_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
use std::collections::BTreeMap;

use valence_authorization_utils::{
authorization::{ AuthorizationModeInfo, PermissionTypeInfo },
authorization_message::{ Message, MessageDetails, MessageType, ParamRestriction },
builders::{ AtomicFunctionBuilder, AtomicSubroutineBuilder, AuthorizationBuilder }, domain::Domain,
};
use valence_generic_ibc_transfer_library::msg::{IbcTransferAmount, RemoteChainInfo};
use valence_ibc_utils::types::PacketForwardMiddlewareConfig;
use valence_program_manager::{
account::{ AccountInfo, AccountType },
library::{ LibraryConfig, LibraryInfo },
program_config::ProgramConfig,
program_config_builder::ProgramConfigBuilder,
};
use valence_astroport_utils::PoolType;
use valence_astroport_lper::msg::LiquidityProviderConfig;
use valence_astroport_withdrawer::msg::LiquidityWithdrawerConfig;
use valence_library_utils::liquidity_utils::AssetData;

/// Write your program using the program builder
pub fn program_builder(params: deployer_lib::ProgramParams) -> ProgramConfig {
// program params
let owner = params.get("owner");
let pool_addr = params.get("pool_addr");
let ntrn_on_neutron = params.get("ntrn_on_neutron");
let atom_on_neutron = params.get("atom_on_neutron");
let atom_on_juno = params.get("atom_on_juno");
let permissioned_withdrawer = params.get("permissioned_withdrawer");
let juno_gaia_ibc_channel_id = params.get("juno_gaia_ibc_channel_id");
let gaia_neutron_ibc_channel_id = params.get("gaia_neutron_ibc_channel_id");

Comment thread
coderabbitai[bot] marked this conversation as resolved.
// Initialize builder
let mut builder = ProgramConfigBuilder::new(owner);

// Domains
let neutron_domain = valence_program_manager::domain::Domain::CosmosCosmwasm(
"neutron".to_string()
);
let juno_domain = valence_program_manager::domain::Domain::CosmosCosmwasm(
"juno".to_string()
);

// Accounts
let juno_input_account = builder.add_account(
AccountInfo::new("juno_input_account".to_string(), &juno_domain, AccountType::default())
);
let neutron_input_account = builder.add_account(
AccountInfo::new("neutron_input_account".to_string(), &neutron_domain, AccountType::default())
);
let liquidity_position_account = builder.add_account(
AccountInfo::new("liquidity_position_account".to_string(), &neutron_domain, AccountType::default())
);
let withdraw_output_account = builder.add_account(
AccountInfo::new("withdraw_output_account".to_string(), &neutron_domain, AccountType::default())
);

let mut juno_to_neutron_pfm_map:BTreeMap<String, PacketForwardMiddlewareConfig> = BTreeMap::new();
juno_to_neutron_pfm_map.insert(atom_on_juno.clone(),PacketForwardMiddlewareConfig {
local_to_hop_chain_channel_id: juno_gaia_ibc_channel_id.to_string(),
hop_to_destination_chain_channel_id: gaia_neutron_ibc_channel_id.to_string(),
hop_chain_receiver_address: "invalid-pfm".to_string(), // necessary so entire transaction is reverted
});

// Libraries
let juno_ibc_transfer_library = builder.add_library(
LibraryInfo::new(
"juno_ibc_transfer".to_string(),
&juno_domain,
LibraryConfig::ValenceGenericIbcTransferLibrary({
valence_generic_ibc_transfer_library::msg::LibraryConfig {
input_addr: juno_input_account.clone(),
output_addr: neutron_input_account.clone(),
denom: valence_library_utils::denoms::UncheckedDenom::Native(atom_on_juno.to_string()),
amount: IbcTransferAmount::FullAmount,
remote_chain_info: RemoteChainInfo {
channel_id: juno_gaia_ibc_channel_id.to_string(),
ibc_transfer_timeout: Some(600u64.into()), // 10 mins
},
denom_to_pfm_map: juno_to_neutron_pfm_map,
memo: "".to_owned(),
}
})
)
);

let pool_type = PoolType::NativeLpToken(
valence_astroport_utils::astroport_native_lp_token::PairType::Custom("concentrated".to_string())
);

let astroport_lper_library = builder.add_library(LibraryInfo::new(
"astroport_lper".to_string(),
&neutron_domain,
LibraryConfig::ValenceAstroportLper(
valence_astroport_lper::msg::LibraryConfig {
input_addr: neutron_input_account.clone(),
output_addr: liquidity_position_account.clone(),
pool_addr: pool_addr.to_string(),
lp_config:LiquidityProviderConfig {
pool_type: pool_type.clone(),
asset_data: AssetData {
asset1: ntrn_on_neutron.clone(),
asset2: atom_on_neutron.clone(),
},
max_spread: None,
}
}
)
));

let astroport_withdrawer_library = builder.add_library( LibraryInfo::new(
"astroport_withdrawer".to_string(),
&neutron_domain,
LibraryConfig::ValenceAstroportWithdrawer(
valence_astroport_withdrawer::msg::LibraryConfig {
input_addr: liquidity_position_account.clone(),
output_addr: withdraw_output_account.clone(),
pool_addr: pool_addr.to_string(),
withdrawer_config: LiquidityWithdrawerConfig {
pool_type: pool_type.clone(),
asset_data: AssetData {
asset1: ntrn_on_neutron.clone(),
asset2: atom_on_neutron.clone()
},
},
}
)
));

// links
builder.add_link(&juno_ibc_transfer_library, vec![&juno_input_account], vec![&neutron_input_account]);
builder.add_link(&astroport_lper_library, vec![&neutron_input_account], vec![&liquidity_position_account]);
builder.add_link(&astroport_withdrawer_library, vec![&liquidity_position_account], vec![&withdraw_output_account]);



// authorizations
let ibc_transfer_subroutine = AtomicSubroutineBuilder::new()
.with_function(AtomicFunctionBuilder::new()
// NOTE: for crosschain domains, this must be added
.with_domain(Domain::External("juno".to_string()))
.with_contract_address(juno_ibc_transfer_library.clone())
.with_message_details(MessageDetails {
message_type: MessageType::CosmwasmExecuteMsg,
message: Message {
name: "process_function".to_string(),
params_restrictions: Some(
vec![
ParamRestriction::MustBeIncluded(
vec!["process_function".to_string(), "ibc_transfer".to_string()]
)
]
)
}
}).build());
builder.add_authorization(
AuthorizationBuilder::new()
.with_label("juno_neutron_ibc_transfer")
.with_subroutine(
ibc_transfer_subroutine.build()
)
.build()
);

let provide_liquidity_subroutine= AtomicSubroutineBuilder::new().with_function(AtomicFunctionBuilder::new()
.with_contract_address(astroport_withdrawer_library.clone())
.with_message_details(MessageDetails {
message_type: MessageType::CosmwasmExecuteMsg,
message: Message {
name: "process_function".to_string(),
params_restrictions: Some(
vec![
ParamRestriction::MustBeIncluded(
vec![
"process_function".to_string(),
"provide_double_sided_liquidity".to_string()
]
)
]
),
},
})
.build());

Comment on lines +171 to +190

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Verify that the “provide_liquidity_subroutine” calls the correct contract.
The subroutine references astroport_withdrawer_library instead of astroport_lper_library. This likely prevents proper liquidity provisioning.

 let provide_liquidity_subroutine = AtomicSubroutineBuilder::new().with_function(
     AtomicFunctionBuilder::new()
-        .with_contract_address(astroport_withdrawer_library.clone())
+        .with_contract_address(astroport_lper_library.clone())
         ...
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let provide_liquidity_subroutine= AtomicSubroutineBuilder::new().with_function(AtomicFunctionBuilder::new()
.with_contract_address(astroport_withdrawer_library.clone())
.with_message_details(MessageDetails {
message_type: MessageType::CosmwasmExecuteMsg,
message: Message {
name: "process_function".to_string(),
params_restrictions: Some(
vec![
ParamRestriction::MustBeIncluded(
vec![
"process_function".to_string(),
"provide_double_sided_liquidity".to_string()
]
)
]
),
},
})
.build());
let provide_liquidity_subroutine = AtomicSubroutineBuilder::new().with_function(
AtomicFunctionBuilder::new()
.with_contract_address(astroport_lper_library.clone())
.with_message_details(MessageDetails {
message_type: MessageType::CosmwasmExecuteMsg,
message: Message {
name: "process_function".to_string(),
params_restrictions: Some(
vec![
ParamRestriction::MustBeIncluded(
vec![
"process_function".to_string(),
"provide_double_sided_liquidity".to_string()
]
)
]
),
},
})
.build()
);

builder.add_authorization(
AuthorizationBuilder::new()
.with_label("provide_liquidity")
.with_subroutine(
provide_liquidity_subroutine.build()
)
.build()
);

let withdraw_liquidity_subroutine = AtomicSubroutineBuilder::new().with_function(AtomicFunctionBuilder::new()
.with_contract_address(astroport_withdrawer_library.clone())
.with_message_details(MessageDetails {
message_type: MessageType::CosmwasmExecuteMsg,
message: Message {
name: "process_function".to_string(),
params_restrictions: Some(
vec![
ParamRestriction::MustBeIncluded(
vec!["process_function".to_string(), "withdraw_liquidity".to_string()]
)
]
),
},
})
.build());

builder.add_authorization(
AuthorizationBuilder::new()
.with_mode(
AuthorizationModeInfo::Permissioned(
PermissionTypeInfo::WithoutCallLimit(vec![permissioned_withdrawer])
)
)
.with_label("withdraw_liquidity")
.with_subroutine(
withdraw_liquidity_subroutine.build()
)
.build()
);

builder.build()
}
Comment on lines +1 to +232

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding error handling mechanisms.

The program lacks explicit error handling for scenarios like failed IBC transfers or liquidity provision operations. Consider implementing recovery mechanisms or fallback strategies.

For a cross-chain application, consider:

  1. Adding monitoring capabilities to track the state of cross-chain operations
  2. Implementing recovery mechanisms for when packets fail to arrive
  3. Adding logging for key events to aid in debugging