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

fast-bridge: Add fast bridge contract #361

Open
wants to merge 49 commits into
base: master
Choose a base branch
from
Open

fast-bridge: Add fast bridge contract #361

wants to merge 49 commits into from

Conversation

dhruvja
Copy link
Collaborator

@dhruvja dhruvja commented Aug 6, 2024

Has the escrow contract for fast bridge which would be used to escrow the funds of the solver and unescrow when it receives the acknowledgement through IBC.

doradelta and others added 22 commits August 8, 2024 19:32
For cross domain transfers, an acknowledgement is sent from destination
to source in form of a token transfer. The packet contains the memo that
has the information about unlocking the funds. The source would then
parse the memo and unlock the funds to the solver mentioned in the memo.
Since we only have token transfers enabled and no cross chain messages,
a token needs to be transferred. For this, we create a dummy token owned
by the program which mints a token everytime and sends a transfer. The
timeout of the transfer is set to infinite so that it always reaches the
counterparty chain.

Also the `on_receive_transfer` method accepts a memo which unlocks the
funds to the solver. Right now it is being called by the auctioneer but
once the hooks are enabled on `solana-ibc` program, this method would
then be called by the `solana-ibc` program.
Emitting events for all instructions so that they can be parsed from the
logs and be acted upon.
dhruvja and others added 19 commits August 27, 2024 18:10
If the solver is not able to solve the intent, then the escrowed funds
can be issued back to the user. In case of single domain intents, the
funds just get transferred to the user from the escrow account. But for
cross chain intents, a timeout message is sent to the other chain with a
flag of `Timeout` and the user who should receive it.

The intent should store the user on source chain so that during timeout,
we know whom to refund the funds to. For the memo, it is the same format
and only the receiver is changed to user address instead of solver.

---------

Co-authored-by: doradelta <[email protected]>
pub fn escrow_and_store_intent(
ctx: Context<EscrowAndStoreIntent>,
amount: u64,
new_intent: IntentPayload
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Remove the winner_solver and user_in from payload so that u dont need the checks below. You can just assign these value below.

);

intent.intent_id = new_intent.intent_id.clone();
intent.user_in = new_intent.user_in.clone();
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
intent.user_in = new_intent.user_in.clone();
intent.user_in = ctx.accounts.user.key();

intent.timeout_timestamp_in_sec = new_intent.timeout_timestamp_in_sec;
intent.creation_timestamp_in_sec = current_timestamp;
intent.amount_out = new_intent.amount_out.clone();
intent.winner_solver = new_intent.winner_solver;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
intent.winner_solver = new_intent.winner_solver;
intent.winner_solver = String::default();

Comment on lines +549 to +560
pub struct IntentPayload {
pub intent_id: String,
pub user_in: String,
pub user_out: Pubkey,
pub token_in: String,
pub amount_in: u64,
pub token_out: String,
pub amount_out: String,
pub winner_solver: Pubkey,
pub timeout_timestamp_in_sec: u64,
pub single_domain: bool,
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Suggested change
pub struct IntentPayload {
pub intent_id: String,
pub user_in: String,
pub user_out: Pubkey,
pub token_in: String,
pub amount_in: u64,
pub token_out: String,
pub amount_out: String,
pub winner_solver: Pubkey,
pub timeout_timestamp_in_sec: u64,
pub single_domain: bool,
}
pub struct IntentPayload {
pub intent_id: String,
pub user_out: Pubkey,
pub token_in: String,
pub amount_in: u64,
pub token_out: String,
pub amount_out: String,
pub timeout_timestamp_in_sec: u64,
pub single_domain: bool,
}

Comment on lines +150 to +153
require!(
intent.intent_id == intent_id,
ErrorCode::IntentDoesNotExist
);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You are getting the intent PDA from intent_id in the accounts below so this check might not be required.

let signer_seeds = core::slice::from_ref(&seeds);

if withdraw_user_flag {
// Case 1: User withdrawal
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

you should also check if the intent really timed out or not.

Comment on lines +375 to +381
// bool withdraw_user,
// string intentId,
// string from,
// string token,
// string to,
// string amount,
// string solver_out
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Should contain the timestamp at which the acknowledgement was sent so that if the bridge halts or smtg, it wont be considered as timeout even though the solver solved the intent.

Suggested change
// bool withdraw_user,
// string intentId,
// string from,
// string token,
// string to,
// string amount,
// string solver_out
// bool withdraw_user,
// string intentId,
// string from,
// string token,
// string to,
// string amount,
// string solver_out
// u64 current_timestamp

})?;
} else {
// Send a cross domain message to the source chain to unlock the funds
let my_custom_memo = format!(
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 memo should contain the 7 parts as above ( 8 with timestamp ), since its the same method that receives the memo.

///
/// For the cross chain intents, a message is sent to the source chain to unlock
/// the funds.
pub fn user_cancel_intent(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If the intent is stored on source chain, then the destination has no intent right? so how would this work?

Comment on lines +631 to +635
#[instruction(intent_id: String)]
pub struct SplTokenTransfer<'info> {
// Intent reading
#[account(mut, close = auctioneer, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)]
pub intent: Box<Account<'info, Intent>>,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If the intent is not stored on destination chain, we cant get the intent account.

Suggested change
#[instruction(intent_id: String)]
pub struct SplTokenTransfer<'info> {
// Intent reading
#[account(mut, close = auctioneer, seeds = [INTENT_SEED, intent_id.as_bytes()], bump)]
pub intent: Box<Account<'info, Intent>>,
pub struct SplTokenTransfer<'info> {

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