Skip to content

Commit

Permalink
Start refactoring request_bridging
Browse files Browse the repository at this point in the history
  • Loading branch information
mertwole committed Dec 17, 2024
1 parent 1fcad31 commit 07fc9a1
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ pub async fn send_message_to_bridge_builtin(
}
.encode();

utils::set_critical_hook(msg_id);
utils::send_message_with_gas_for_reply(
gear_bridge_builtin,
bytes,
Expand Down
80 changes: 64 additions & 16 deletions gear-programs/vft-manager/app/src/services/request_bridging/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mod token_operations;
mod utils;

use bridge_builtin_operations::Payload;
use msg_tracker::{MessageStatus, TxDetails};
use msg_tracker::{msg_tracker_mut, MessageStatus, TxDetails};

pub use msg_tracker::{msg_tracker_state, MessageInfo as MsgTrackerMessageInfo};

Expand All @@ -29,21 +29,27 @@ pub async fn request_bridging<T: ExecContext>(
let supply_type = service.state().token_map.get_supply_type(&vara_token_id)?;
let config = service.config();

if gstd::exec::gas_available()
< config.gas_for_token_ops
+ config.gas_to_send_request_to_builtin
+ config.gas_for_request_bridging
+ 3 * config.gas_for_reply_deposit
{
panic!("Please attach more gas");
}
let transaction_details = TxDetails {
vara_token_id,
sender,
amount,
receiver,
token_supply: TokenSupply::Ethereum,
};

msg_tracker_mut().insert_message_info(
msg_id,
MessageStatus::SendingMessageToDepositTokens,
transaction_details,
);
set_critical_hook(msg_id);

match supply_type {
TokenSupply::Ethereum => {
token_operations::burn(vara_token_id, sender, receiver, amount, config, msg_id).await?;
token_operations::burn(vara_token_id, sender, amount, config, msg_id).await?;
}
TokenSupply::Gear => {
token_operations::lock(vara_token_id, sender, amount, receiver, config, msg_id).await?;
token_operations::lock(vara_token_id, sender, amount, config, msg_id).await?;
}
}

Expand All @@ -52,15 +58,17 @@ pub async fn request_bridging<T: ExecContext>(
token_id: eth_token_id,
amount,
};
let nonce = match bridge_builtin_operations::send_message_to_bridge_builtin(

let bridge_builtin_reply = bridge_builtin_operations::send_message_to_bridge_builtin(
state.gear_bridge_builtin,
state.erc20_manager_address,
payload,
config,
msg_id,
)
.await
{
.await;

let nonce = match bridge_builtin_reply {
Ok(nonce) => nonce,
Err(e) => {
match supply_type {
Expand Down Expand Up @@ -117,7 +125,7 @@ pub async fn handle_interrupted_transfer<T: ExecContext>(
.expect("Failed to get ethereum token id");

match msg_info.status {
MessageStatus::TokenDepositCompleted(true) | MessageStatus::BridgeBuiltinStep => {
MessageStatus::TokenDepositCompleted(true) => {
let payload = Payload {
receiver,
token_id: eth_token_id,
Expand Down Expand Up @@ -155,7 +163,8 @@ pub async fn handle_interrupted_transfer<T: ExecContext>(
msg_tracker::msg_tracker_mut().remove_message_info(&msg_id);
Ok((nonce, eth_token_id))
}
MessageStatus::WithdrawTokensStep => {
MessageStatus::SendingMessageToReturnTokens | MessageStatus::TokenReturnFailed => {
// TODO: Or unlock.
token_operations::mint(vara_token_id, sender, amount, config, msg_id).await?;
Err(Error::TokensRefunded)
}
Expand All @@ -164,3 +173,42 @@ pub async fn handle_interrupted_transfer<T: ExecContext>(
}
}
}

fn set_critical_hook(msg_id: MessageId) {
gstd::critical::set_hook(move || {
let msg_tracker = msg_tracker_mut();
let msg_info = msg_tracker
.get_message_info(&msg_id)
.expect("Unexpected: msg info does not exist");

match msg_info.status {
MessageStatus::SendingMessageToDepositTokens => {
// If still sending, transition to `WaitingReplyFromBurn`.
msg_tracker.update_message_status(
msg_id,
MessageStatus::WaitingReplyFromTokenDepositMessage,
);
}
// MessageStatus::TokenDepositCompleted(false) => {
// // If the token burn fails, cancel the transaction.
// msg_tracker.remove_message_info(&msg_id);
// }
MessageStatus::SendingMessageToBridgeBuiltin => {
// If still sending, transition to `WaitingReplyFromBuiltin`.
msg_tracker.update_message_status(msg_id, MessageStatus::WaitingReplyFromBuiltin);
}
// MessageStatus::BridgeResponseReceived(None) => {
// // If error occurs during builtin message, go to mint step
// msg_tracker.update_message_status(msg_id, MessageStatus::ReturnTokensStep)
// }
MessageStatus::SendingMessageToReturnTokens => {
msg_tracker.update_message_status(
msg_id,
MessageStatus::WaitingReplyFromTokenReturnMessage,
);
}

_ => {}
};
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ impl MessageTracker {
pub fn check_withdraw_result(&mut self, msg_id: &MessageId) -> Result<(), Error> {
if let Some(info) = self.message_info.get(msg_id) {
match info.status {
MessageStatus::TokenWithdrawCompleted => Ok(()),
MessageStatus::WithdrawTokensStep => Err(Error::MessageFailed),
MessageStatus::TokensReturned => Ok(()),
MessageStatus::TokenReturnFailed => Err(Error::MessageFailed),
_ => Err(Error::InvalidMessageStatus),
}
} else {
Expand All @@ -96,22 +96,21 @@ impl MessageTracker {

#[derive(Debug, Clone, PartialEq, Encode, Decode, TypeInfo)]
pub enum MessageStatus {
// Send message to bridge builtin
SendingMessageToBridgeBuiltin,
BridgeResponseReceived(Option<U256>),
WaitingReplyFromBuiltin,
BridgeBuiltinStep,

// Deposit tokens statuses
SendingMessageToDepositTokens,
TokenDepositCompleted(bool),
WaitingReplyFromTokenDepositMessage,
TokenDepositCompleted(bool),

// Send message to bridge builtin
SendingMessageToBridgeBuiltin,
WaitingReplyFromBuiltin,
BridgeResponseReceived(Option<U256>),

// Withdraw tokens statuses.
SendingMessageToWithdrawTokens,
TokenWithdrawCompleted,
WaitingReplyFromTokenWithdrawMessage,
WithdrawTokensStep,
// Return tokens statuses.
SendingMessageToReturnTokens,
WaitingReplyFromTokenReturnMessage,
TokensReturned,
TokenReturnFailed,

MessageProcessedWithSuccess(U256),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,19 @@ use sails_rs::prelude::*;

use extended_vft_client::vft::io as vft_io;

use super::super::{Config, Error, TokenSupply};
use super::msg_tracker::{msg_tracker_mut, MessageStatus, TxDetails};
use super::super::{Config, Error};
use super::msg_tracker::{msg_tracker_mut, MessageStatus};
use super::utils;

pub async fn burn(
vara_token_id: ActorId,
sender: ActorId,
receiver: H160,
amount: U256,
config: &Config,
msg_id: MessageId,
) -> Result<(), Error> {
let bytes: Vec<u8> = vft_io::Burn::encode_call(sender, amount);

let transaction_details = TxDetails {
vara_token_id,
sender,
amount,
receiver,
token_supply: TokenSupply::Ethereum,
};

msg_tracker_mut().insert_message_info(
msg_id,
MessageStatus::SendingMessageToDepositTokens,
transaction_details,
);

utils::set_critical_hook(msg_id);
utils::send_message_with_gas_for_reply(
vara_token_id,
bytes,
Expand All @@ -47,28 +31,12 @@ pub async fn lock(
vara_token_id: ActorId,
sender: ActorId,
amount: U256,
eth_receiver: H160,
config: &Config,
msg_id: MessageId,
) -> Result<(), Error> {
let receiver = gstd::exec::program_id();
let bytes: Vec<u8> = vft_io::TransferFrom::encode_call(sender, receiver, amount);

let transaction_details = TxDetails {
vara_token_id,
sender,
amount,
receiver: eth_receiver,
token_supply: TokenSupply::Gear,
};

msg_tracker_mut().insert_message_info(
msg_id,
MessageStatus::SendingMessageToDepositTokens,
transaction_details,
);

utils::set_critical_hook(msg_id);
utils::send_message_with_gas_for_reply(
vara_token_id,
bytes,
Expand All @@ -89,7 +57,7 @@ pub async fn mint(
config: &Config,
msg_id: MessageId,
) -> Result<(), Error> {
msg_tracker_mut().update_message_status(msg_id, MessageStatus::SendingMessageToWithdrawTokens);
msg_tracker_mut().update_message_status(msg_id, MessageStatus::SendingMessageToReturnTokens);

let bytes: Vec<u8> = vft_io::Mint::encode_call(receiver, amount);
utils::send_message_with_gas_for_reply(
Expand All @@ -112,7 +80,7 @@ pub async fn unlock(
config: &Config,
msg_id: MessageId,
) -> Result<(), Error> {
msg_tracker_mut().update_message_status(msg_id, MessageStatus::SendingMessageToWithdrawTokens);
msg_tracker_mut().update_message_status(msg_id, MessageStatus::SendingMessageToReturnTokens);

let sender = gstd::exec::program_id();
let bytes: Vec<u8> = vft_io::TransferFrom::encode_call(sender, recepient, amount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,6 @@ use gstd::{msg, MessageId};
use sails_rs::calls::ActionIo;
use sails_rs::prelude::*;

pub fn set_critical_hook(msg_id: MessageId) {
gstd::critical::set_hook(move || {
let msg_tracker = msg_tracker_mut();
let msg_info = msg_tracker
.get_message_info(&msg_id)
.expect("Unexpected: msg info does not exist");

match msg_info.status {
MessageStatus::SendingMessageToDepositTokens => {
// If still sending, transition to `WaitingReplyFromBurn`.
msg_tracker.update_message_status(
msg_id,
MessageStatus::WaitingReplyFromTokenDepositMessage,
);
}
MessageStatus::TokenDepositCompleted(true) => {
// If the token transfer is successful, continue to bridge builtin step.
msg_tracker.update_message_status(msg_id, MessageStatus::BridgeBuiltinStep);
}
MessageStatus::TokenDepositCompleted(false) => {
// If the token burn fails, cancel the transaction.
msg_tracker.remove_message_info(&msg_id);
}

MessageStatus::SendingMessageToBridgeBuiltin => {
// If still sending, transition to `WaitingReplyFromBuiltin`.
msg_tracker.update_message_status(msg_id, MessageStatus::WaitingReplyFromBuiltin);
}
MessageStatus::BridgeResponseReceived(None) => {
// If error occurs during builtin message, go to mint step
msg_tracker.update_message_status(msg_id, MessageStatus::WithdrawTokensStep)
}

MessageStatus::SendingMessageToWithdrawTokens => {
msg_tracker.update_message_status(
msg_id,
MessageStatus::WaitingReplyFromTokenWithdrawMessage,
);
}

_ => {}
};
});
}

pub async fn send_message_with_gas_for_reply(
destination: ActorId,
message: Vec<u8>,
Expand Down Expand Up @@ -81,7 +36,8 @@ fn handle_reply_hook(msg_id: MessageId) {
let reply_bytes = msg::load_bytes().expect("Unable to load bytes");

match msg_info.status {
MessageStatus::SendingMessageToDepositTokens => {
MessageStatus::SendingMessageToDepositTokens
| MessageStatus::WaitingReplyFromTokenDepositMessage => {
let reply = match msg_info.details.token_supply {
TokenSupply::Ethereum => decode_burn_reply(&reply_bytes),
TokenSupply::Gear => decode_lock_reply(&reply_bytes),
Expand All @@ -97,21 +53,7 @@ fn handle_reply_hook(msg_id: MessageId) {
}
};
}
MessageStatus::WaitingReplyFromTokenDepositMessage => {
let reply = match msg_info.details.token_supply {
TokenSupply::Ethereum => decode_burn_reply(&reply_bytes),
TokenSupply::Gear => decode_lock_reply(&reply_bytes),
}
.unwrap_or(false);

if reply {
msg_tracker.update_message_status(msg_id, MessageStatus::BridgeBuiltinStep);
} else {
msg_tracker.remove_message_info(&msg_id);
}
}

MessageStatus::SendingMessageToBridgeBuiltin => {
MessageStatus::SendingMessageToBridgeBuiltin | MessageStatus::WaitingReplyFromBuiltin => {
let reply = decode_bridge_reply(&reply_bytes);
let result = match reply {
Ok(Some(nonce)) => Some(nonce),
Expand All @@ -120,33 +62,18 @@ fn handle_reply_hook(msg_id: MessageId) {
msg_tracker
.update_message_status(msg_id, MessageStatus::BridgeResponseReceived(result));
}
MessageStatus::WaitingReplyFromBuiltin => {
let reply = decode_bridge_reply(&reply_bytes);
match reply {
Ok(Some(nonce)) => {
msg_tracker.update_message_status(
msg_id,
MessageStatus::MessageProcessedWithSuccess(nonce),
);
}
_ => {
msg_tracker.update_message_status(msg_id, MessageStatus::WithdrawTokensStep);
}
};
}

MessageStatus::WaitingReplyFromTokenWithdrawMessage
| MessageStatus::SendingMessageToWithdrawTokens => {
MessageStatus::WaitingReplyFromTokenReturnMessage
| MessageStatus::SendingMessageToReturnTokens => {
let reply = match msg_info.details.token_supply {
TokenSupply::Ethereum => decode_mint_reply(&reply_bytes),
TokenSupply::Gear => decode_unlock_reply(&reply_bytes),
}
.unwrap_or(false);

if !reply {
msg_tracker.update_message_status(msg_id, MessageStatus::WithdrawTokensStep);
msg_tracker.update_message_status(msg_id, MessageStatus::TokenReturnFailed);
} else {
msg_tracker.update_message_status(msg_id, MessageStatus::TokenWithdrawCompleted);
msg_tracker.update_message_status(msg_id, MessageStatus::TokensReturned);
}
}

Expand Down

0 comments on commit 07fc9a1

Please sign in to comment.