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

ibc forwarder #95

Merged
merged 19 commits into from
Aug 10, 2023
Merged

ibc forwarder #95

merged 19 commits into from
Aug 10, 2023

Conversation

bekauz
Copy link
Collaborator

@bekauz bekauz commented Aug 9, 2023

Base implementation for #86 .
Does not cover completion yet.

Introduces covenant-utils and depositor query macro.

@bekauz bekauz added this to the v2 milestone Aug 9, 2023
@bekauz bekauz requested a review from Art3miX August 9, 2023 16:02
Copy link
Collaborator

@Art3miX Art3miX left a comment

Choose a reason for hiding this comment

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

Nothing major, just some code suggestions, 3 questions tho:

  1. You never change the state to completed, on purpose?
  2. forwarder will never send a bank message on other chain? it will always be a ibc call?
  3. Seems like this only meant for a single message, so the forwarder will never be used twice?
  • Only reviewed forwarder and packages, nothing else.

Comment on lines 111 to 117
let deposit_address = if let Some(addr) = deposit_address_query {
addr
} else {
return Err(NeutronError::Std(
StdError::not_found("Next contract is not ready for receiving the funds yet")
))
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

You can do:

Suggested change
let deposit_address = if let Some(addr) = deposit_address_query {
addr
} else {
return Err(NeutronError::Std(
StdError::not_found("Next contract is not ready for receiving the funds yet")
))
};
let Some(deposit_address) = deposit_address_query else {
return Err(NeutronError::Std(
StdError::not_found("Next contract is not ready for receiving the funds yet")
))
};

Something nice I learned today, much cleaner and clearer.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is great

Comment on lines 170 to 173
None => Ok(Response::default()
.add_attribute("method", "try_forward_funds")
.add_attribute("error", "no_ica_found")
),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't we error here? or revert state back to instantiated?
if we reached this state, and still don't have ICA, it means something went wrong, reverting to instantiate state, can fix this issue without admin intervention.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good point. In theory this should never happen as we only end up in ICACreated state in case sudo_open_ack callback executes this:

INTERCHAIN_ACCOUNTS.save(
            deps.storage,
            port_id,
            &Some((
                parsed_version.clone().address,
                parsed_version.clone().controller_connection_id,
            )),
        )?;
CONTRACT_STATE.save(deps.storage, &ContractState::ICACreated)?;

However looking at it again, it probably makes sense to revert state to Instantiated to force recreation of the ICA. Will add this.

Comment on lines 210 to 214
let ica = if let Some((addr, _)) = INTERCHAIN_ACCOUNTS.load(deps.storage, key)? {
Some(addr)
} else {
None
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you can use map here:

Suggested change
let ica = if let Some((addr, _)) = INTERCHAIN_ACCOUNTS.load(deps.storage, key)? {
Some(addr)
} else {
None
};
let ica = INTERCHAIN_ACCOUNTS.load(deps.storage, key)?.map(|(addr, _)| addr);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Actually realized we should probably use may_load here to not error in case ICA creation hadn't been triggered yet, will update to that

Comment on lines +270 to +282
if let Ok(parsed_version) = parsed_version {
INTERCHAIN_ACCOUNTS.save(
deps.storage,
port_id,
&Some((
parsed_version.clone().address,
parsed_version.clone().controller_connection_id,
)),
)?;
CONTRACT_STATE.save(deps.storage, &ContractState::ICACreated)?;
return Ok(Response::default().add_attribute("method", "sudo_open_ack"));
}
Err(StdError::generic_err("Can't parse counterparty_version"))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above, just a bit more cleaner.

Suggested change
if let Ok(parsed_version) = parsed_version {
INTERCHAIN_ACCOUNTS.save(
deps.storage,
port_id,
&Some((
parsed_version.clone().address,
parsed_version.clone().controller_connection_id,
)),
)?;
CONTRACT_STATE.save(deps.storage, &ContractState::ICACreated)?;
return Ok(Response::default().add_attribute("method", "sudo_open_ack"));
}
Err(StdError::generic_err("Can't parse counterparty_version"))
let Ok(parsed_version) = parsed_version else {
return Err(StdError::generic_err("Can't parse counterparty_version"))
}
INTERCHAIN_ACCOUNTS.save(
deps.storage,
port_id,
&Some((
parsed_version.clone().address,
parsed_version.clone().controller_connection_id,
)),
)?;
CONTRACT_STATE.save(deps.storage, &ContractState::ICACreated)?;
Ok(Response::default().add_attribute("method", "sudo_open_ack"))

Comment on lines +43 to +55
impl InstantiateMsg {
pub fn get_response_attributes(&self) -> Vec<Attribute> {
vec![
Attribute::new("clock_address", &self.clock_address),
Attribute::new("remote_chain_connection_id", &self.remote_chain_connection_id),
Attribute::new("remote_chain_channel_id", &self.remote_chain_channel_id),
Attribute::new("remote_chain_denom", &self.denom),
Attribute::new("remote_chain_amount", &self.amount),
Attribute::new("ibc_transfer_timeout", self.ibc_transfer_timeout.to_string()),
Attribute::new("ica_timeout", self.ica_timeout.to_string()),
]
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

NICE

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I feel like it should be possible to write a macro that would extract struct field names and generate an array of attributes 🤔

}

#[proc_macro_attribute]
pub fn covenant_deposit_address(metadata: TokenStream, input: TokenStream) -> TokenStream {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why new package? why not just use the clock one and rename that one, there should be just 1 macro package.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fair, merged all macros into one package in incoming pr.

@bekauz
Copy link
Collaborator Author

bekauz commented Aug 9, 2023

Art3miX

Indeed it doesn't reach completion yet. I think we can discuss on whether we will want to use ICQs or alternative methods for that.

In terms of bank msg / ibc calls, I was thinking of having a separate contract for non-ibc forwarding. Native forwarder?

Overall I imagine forwarders to be disposable. Only responsible for facilitating a single transfer and reaching completion after that is done.

@bekauz bekauz merged commit d2a53d2 into v2 Aug 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants