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

feat(interchain-token-service): add flow limit #130

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

AttissNgo
Copy link
Contributor

@AttissNgo AttissNgo commented Jan 9, 2025

- implement flow limit for interchain transfers
- add Operatable trait and change constructor
- update golden files (tests generate different contract addresses due to updated constructor)
- minor changes to test helper functions
@AttissNgo AttissNgo requested a review from a team as a code owner January 9, 2025 02:29
@codecov-commenter
Copy link

codecov-commenter commented Jan 9, 2025

Codecov Report

Attention: Patch coverage is 99.27536% with 1 line in your changes missing coverage. Please review.

Project coverage is 94.84%. Comparing base (7adc13d) to head (f4a549a).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ntracts/interchain-token-service/src/flow_limit.rs 99.04% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #130      +/-   ##
==========================================
+ Coverage   94.63%   94.84%   +0.20%     
==========================================
  Files          52       53       +1     
  Lines        3130     3276     +146     
==========================================
+ Hits         2962     3107     +145     
- Misses        168      169       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

contracts/interchain-token-service/src/flow_limit.rs Outdated Show resolved Hide resolved
contracts/interchain-token-service/src/storage_types.rs Outdated Show resolved Hide resolved
contracts/interchain-token-service/src/interface.rs Outdated Show resolved Hide resolved
contracts/interchain-token-service/src/event.rs Outdated Show resolved Hide resolved
contracts/interchain-token-service/src/flow_limit.rs Outdated Show resolved Hide resolved
contracts/interchain-token-service/src/flow_limit.rs Outdated Show resolved Hide resolved
contracts/interchain-token-service/tests/flow_limit.rs Outdated Show resolved Hide resolved
- Add docstrings to entrypoints
- Create FlowKey struct for better organization of storage keys
- Move flow logic into FlowDirection impl
- Organize imports and group public functions
- Allow zero flow limit to 'freeze' token
pub fn set_flow_limit(
env: &Env,
token_id: BytesN<32>,
flow_limit: Option<i128>,
Copy link

Choose a reason for hiding this comment

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

why not make this u128 to avoid the ensure below?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's convention on Stellar to use i128 for token amounts. It's because of unrelated operations (clawbacks, etc), but we leave it as i128 for consistency


direction.update_flow(env, token_id.clone(), new_flow);

extend_persistent_ttl(env, &DataKey::FlowLimit(token_id));
Copy link

Choose a reason for hiding this comment

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

update_flow uses the DataKey::FlowIn(FlowKey) key yet you extend the ttl (which I'm assuming is the lifetime) of the DataKey::FlowLimit(BytesN<32>) key. Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To me it seems to be the best place to extend the ttl as it's the only write operation that regularly touches the flow limit. Do you see a better place for it?

.ok_or(ContractError::FlowLimitExceeded)?;
let max_allowed = flow_to_compare
.checked_add(flow_limit)
.ok_or(ContractError::FlowLimitExceeded)?;
Copy link

Choose a reason for hiding this comment

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

If you decide to keep i128 instead of u128 then you can subtract flow_limit (which is guaranteed to be positive but less than i128::MAX) from new_flow so that you can never overflow here.

Copy link
Member

Choose a reason for hiding this comment

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

I was thinking about this but we are already planning to introduce a custom Uint127 type which I think will be easier to reason about

flow_limit::flow_out_amount(env, token_id)
}

/// Retrieves the flow out amount for the current epoch for the token
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Retrieves the flow out amount for the current epoch for the token
/// Retrieves the flow in amount for the current epoch for the token

fn flow_limit(env: &Env, token_id: BytesN<32>) -> Option<i128> {
flow_limit::flow_limit(env, token_id)
}

/// Retrieves the flow out amount for the current epoch for the token
/// associated with the specified token ID.
Copy link
Member

Choose a reason for hiding this comment

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

explain what flow out means (might be interpreted as either of the directions)

@@ -162,10 +162,42 @@ impl InterchainTokenServiceInterface for InterchainTokenService {
.into()
}

/// Retrieves the flow limit for the token associated with the specified token ID.
Copy link
Member

Choose a reason for hiding this comment

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

Add the doc in the interface.rs instead. The contract.rs could have a note like to link it

/// See [`InterchainTokenServiceInterface::xyz`]

/// # Errors
/// - `ContractError::InvalidFlowLimit`: If the provided flow limit is not positive.
///
/// Authorization: Only the operator can call this function. Unauthorized calls will panic.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Authorization: Only the operator can call this function. Unauthorized calls will panic.
/// # Authorization
/// - Must be called by the [`Self::operator`].

perhaps?

@@ -16,6 +16,7 @@ pub struct TrustedChainRemovedEvent {
#[derive(Debug, PartialEq, Eq)]
pub struct FlowLimitSetEvent {
pub token_id: BytesN<32>,
/// Setting to None bypasses flow limit checks
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Setting to None bypasses flow limit checks
/// A `None` value implies that flow limit checks have been disabled for this `token_id`

/// Sets or updates the flow limit for a token.
///
/// Flow limit controls how many tokens can flow in/out during a single epoch.
/// Setting the limit to None disables flow limit checks for the token.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Setting the limit to None disables flow limit checks for the token.
/// Setting the limit to `None` disables flow limit checks for the token.


#[cfg(any(test, feature = "testutils"))]
pub use testutils::*;

pub trait Event: Debug + PartialEq {
fn topics(&self, env: &Env) -> impl Topics + Debug;

fn data(&self, env: &Env) -> impl IntoVal<Env, Val> + Debug;
fn data(&self, env: &Env) -> impl IntoVal<Env, Val> + Debug {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
fn data(&self, env: &Env) -> impl IntoVal<Env, Val> + Debug {
/// A default empty tuple/vector is used for event data, since majority of events only use topics.
fn data(&self, env: &Env) -> impl IntoVal<Env, Val> + Debug {

explain the reasoning

Comment on lines +12 to +15
enum FlowDirection {
In,
Out,
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
enum FlowDirection {
In,
Out,
}
enum FlowDirection {
/// An interchain transfer coming in to this chain from another chain
In,
/// An interchain transfer going out from this chain to another chain
Out,
}

enum FlowDirection {
In,
Out,
pub fn add_flow_in(
Copy link
Member

@milapsheth milapsheth Jan 10, 2025

Choose a reason for hiding this comment

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

How about moving pub fn add_flow within FlowDirection, and then you can call FlowDirection::In.add_flow(...) from ITS contract?

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.

4 participants