-
Notifications
You must be signed in to change notification settings - Fork 22
feat: deposit channel based account creation #6170
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
base: main
Are you sure you want to change the base?
feat: deposit channel based account creation #6170
Conversation
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
b694786
to
3576fa6
Compare
// TODO, how to do this? | ||
// ensure!(T::SafeMode::get().deposit_enabled, Error::<T>::LiquidityDepositDisabled); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add a dedicated safe mode entry for this.
|
||
// TODO: verify the user signature | ||
let target_account_id = | ||
external_account.signer_account_id::<cf_primitives::AccountId>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should now be possible using the tools merged to main recently in #6141
The user should submit their public key and a signature over some fixed message like "Chainflip::AccountOpen". Then we verify the sig before continuing.
// TODO: This is now duplicated between pallet-cf-lp and pallet-cf-swapping | ||
LiquidityDepositAddressReady { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should name this differently (AccountCreationDepositAddressReady
or something).
}, | ||
SwapOutputAction::CreditFlipAndTransferToGateway { | ||
account_id, | ||
role_to_register, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re. the role - I hadn't thought much about this, but I think it makes sense to assume that the 'role' will always be LiquidityProvider
(ie. this is for opening LP trade/lending accounts), at least for now.
FundingSource::Swap { swap_request_id }, | ||
) | ||
|
||
// TODO: transfer funds to gateway |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if we can piggy-back on the burn_network_fee method in emissions/lib.rs, ie. we accumulate the amount that we want to send to the SC gateway, and then allow the emissions pallet to adjust the transfer amount when it does the burn. Otherwise it's likely that the transaction cost will outweigh the FLIP transferred...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the code that does the "burn and transfer" is in the on_initialize()
in the emissions lib. To make it work we'll have to keep track of the amount of FLIP to be transferred to the statechain gateway separately from the amount of FLIP to be burned.
Then in the on_initialize() we burn only the amount to be burned, but then transfer (to_be_burned + to_be_transferred
).
ChannelAction::LiquidityProvision { lp_account, additional_action, .. } => { | ||
T::Balance::credit_account(&lp_account, asset.into(), amount_after_fees.into()); | ||
|
||
// TODO execute additional_action |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we dispatch the account creation action (ie. when we receive the deposit into the channel), we want to:
- Estimate the swap input amount for 5 FLIP (or whatever our MIN_FUNDING is in the funding pallet)
- Take this off the actual deposit amount (like we do for ingress fees)
- Initiate a swap into FLIP with this much of the input
- Credit the target account with 0.01 FLIP: this should be enough to get started, pending completion of the swap.
- When the swap completes, credit the target account with the net amount (ie. swap_output_amount - 0.01 FLIP).
Ok(ScheduledEgressDetails { egress_id, egress_amount, .. }) => { | ||
T::Issuance::burn_offchain(egress_amount.into()); | ||
Self::deposit_event(Event::NetworkFeeBurned { amount: egress_amount, egress_id }); | ||
T::Issuance::burn_offchain(egress_amount.saturating_sub(flip_to_be_sent_to_gateway).into()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can deduplicate
T::Issuance::burn_offchain(egress_amount.saturating_sub(flip_to_be_sent_to_gateway).into()); | |
let flip_to_burn = egress_amount.saturating_sub(flip_to_be_sent_to_gateway); | |
T::Issuance::burn_offchain(flip_to_burn.into()); | |
Self::deposit_event(Event::NetworkFeeBurned { amount: flip_to_burn, egress_id }); |
T::FundAccount::fund_account( | ||
lp_account.clone(), | ||
None, | ||
100_000_000_000_000_000u128.into(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can use FLIPPERINOS_PER_FLIP / 10
here. Also, I see that the same value is being used below. Should this be turned into a constant?
BoundedVec::new(), | ||
None, | ||
None, | ||
origin.into(), //maybe change it to internal/OnChainAccount? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, SwapOrigin::Internal
makes more sense to me.
SwapOutputAction::CreditLendingPool { swap_type } => { | ||
log_or_panic!("Unexpected refund of a loan swap: {swap_type:?}"); | ||
}, | ||
//TODO: Not sure this is even possible we won't do a DCA swap to get the few flip necessary to fund an account |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this shouldn't be possible. However, If we want to keep this code just in case, I would deduplicate this with the code below that covers successful execution.
account_id.clone(), | ||
None, | ||
dca_state.accumulated_output_amount, | ||
dca_state.accumulated_output_amount.saturating_sub(100_000_000_000_000_000).into(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the output amount is smaller than 100_000_000_000_000_000
, won't this be an accounting problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid this scenario (and also the one where the estimation of the required_input fails), we will submit a MIN_PRICE in the extrinsic such that we can be sure to always trigger the swap and obtain as output enough FLIP to cover the initial funding.
// TODO: Use proper error -> do we want to check this? | ||
// ensure!(T::AccountRoleRegistry::is_unregistered(target_account_id), Error::<T>::); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would not enforce this. It might be useful in the future to allow for FLIP topups as part of ingressing assets.
874c0ad
to
6840d06
Compare
Pull Request
Closes: PRO-xxx
Checklist
Please conduct a thorough self-review before opening the PR.
Summary
Please include a succinct description of the purpose and content of the PR. What problem does it solve, and how? Link issues, discussions, other PRs, and anything else that will help the reviewer.