Skip to content

Commit

Permalink
feat(vft-gateway): Add function to mint tokens (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
LouiseMedova authored Sep 10, 2024
1 parent 4d63233 commit 1ac623d
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 97 deletions.
2 changes: 2 additions & 0 deletions gear-programs/bridging-payment/src/wasm/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,13 @@ impl VftGateway for Program<'_> {
let init_config = vft_gateway_app::services::InitConfig::new(
[1; 20].into(),
BRIDGE_BUILTIN_ID.into(),
1010.into(),
vft_gateway_app::services::Config::new(
15_000_000_000,
15_000_000_000,
15_000_000_000,
15_000_000_000,
15_000_000_000,
1000,
20_000_000_000,
),
Expand Down
2 changes: 2 additions & 0 deletions gear-programs/vft-gateway/src/services/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ pub enum Error {
BurnTokensFailed,
BridgeBuiltinMessageFailed,
TokensRefunded,
NotEthClient,
NotEnoughGas,
}
89 changes: 54 additions & 35 deletions gear-programs/vft-gateway/src/services/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub mod msg_tracker;
mod utils;
mod vft;
use error::Error;
use msg_tracker::{MessageInfo, MessageStatus, MessageTracker};
use msg_tracker::{MessageInfo, MessageStatus, MessageTracker, TxDetails};
mod token_operations;

pub struct VftGateway<ExecContext> {
Expand All @@ -31,24 +31,28 @@ pub struct VftGatewayData {
admin: ActorId,
receiver_contract_address: H160,
vara_to_eth_token_id: HashMap<ActorId, H160>,
eth_client: ActorId,
}

#[derive(Debug, Decode, Encode, TypeInfo)]
pub struct InitConfig {
pub receiver_contract_address: H160,
pub gear_bridge_builtin: ActorId,
pub eth_client: ActorId,
pub config: Config,
}

impl InitConfig {
pub fn new(
receiver_contract_address: H160,
gear_bridge_builtin: ActorId,
eth_client: ActorId,
config: Config,
) -> Self {
Self {
receiver_contract_address,
gear_bridge_builtin,
eth_client,
config,
}
}
Expand All @@ -59,6 +63,7 @@ pub struct Config {
gas_to_burn_tokens: u64,
gas_for_reply_deposit: u64,
gas_to_mint_tokens: u64,
gas_to_process_mint_request: u64,
gas_to_send_request_to_builtin: u64,
reply_timeout: u32,
gas_for_transfer_to_eth_msg: u64,
Expand All @@ -69,6 +74,7 @@ impl Config {
gas_to_burn_tokens: u64,
gas_for_reply_deposit: u64,
gas_to_mint_tokens: u64,
gas_to_process_mint_request: u64,
gas_to_send_request_to_builtin: u64,
reply_timeout: u32,
gas_for_transfer_to_eth_msg: u64,
Expand All @@ -77,6 +83,7 @@ impl Config {
gas_to_burn_tokens,
gas_for_reply_deposit,
gas_to_mint_tokens,
gas_to_process_mint_request,
gas_to_send_request_to_builtin,
reply_timeout,
gas_for_transfer_to_eth_msg,
Expand Down Expand Up @@ -112,41 +119,51 @@ where
self.data_mut().vara_to_eth_token_id.remove(&vara_token_id);
}

pub fn update_config(
&mut self,
gas_to_burn_tokens: Option<u64>,
gas_to_mint_tokens: Option<u64>,
gas_for_reply_deposit: Option<u64>,
gas_to_send_request_to_builtin: Option<u64>,
reply_timeout: Option<u32>,
gas_for_transfer_to_eth_msg: Option<u64>,
) {
pub fn update_config(&mut self, config: Config) {
if self.data().admin != self.exec_context.actor_id() {
panic!("Not admin")
}
if let Some(gas_to_burn_tokens) = gas_to_burn_tokens {
self.config_mut().gas_to_burn_tokens = gas_to_burn_tokens;
}

if let Some(gas_to_mint_tokens) = gas_to_mint_tokens {
self.config_mut().gas_to_mint_tokens = gas_to_mint_tokens;
unsafe {
CONFIG = Some(config);
}
}

if let Some(gas_to_send_request_to_builtin) = gas_to_send_request_to_builtin {
self.config_mut().gas_to_send_request_to_builtin = gas_to_send_request_to_builtin;
}
pub async fn mint_tokens(
&mut self,
vara_token_id: ActorId,
receiver: ActorId,
amount: U256,
) -> Result<(), Error> {
let data = self.data();
let sender = self.exec_context.actor_id();

if let Some(reply_timeout) = reply_timeout {
self.config_mut().reply_timeout = reply_timeout;
if sender != data.eth_client {
return Err(Error::NotEthClient);
}

if let Some(gas_for_reply_deposit) = gas_for_reply_deposit {
self.config_mut().gas_for_reply_deposit = gas_for_reply_deposit;
let config = self.config();
if gstd::exec::gas_available()
< config.gas_to_mint_tokens
+ config.gas_to_process_mint_request
+ config.gas_for_reply_deposit
{
return Err(Error::NotEnoughGas);
}

if let Some(gas_for_transfer_to_eth_msg) = gas_for_transfer_to_eth_msg {
self.config_mut().gas_for_transfer_to_eth_msg = gas_for_transfer_to_eth_msg;
}
let msg_id = gstd::msg::id();
let transaction_details = TxDetails::MintTokens {
vara_token_id,
receiver,
amount,
};
msg_tracker_mut().insert_message_info(
msg_id,
MessageStatus::SendingMessageToMintTokens,
transaction_details,
);
utils::set_critical_hook(msg_id);
token_operations::mint_tokens(vara_token_id, receiver, amount, config, msg_id).await
}

pub async fn transfer_vara_to_eth(
Expand All @@ -158,7 +175,6 @@ where
let data = self.data();
let sender = self.exec_context.actor_id();
let msg_id = gstd::msg::id();

let eth_token_id = self.get_eth_token_id(&vara_token_id)?;
let config = self.config();

Expand All @@ -170,6 +186,7 @@ where
{
panic!("Please attach more gas");
}

token_operations::burn_tokens(vara_token_id, sender, receiver, amount, config, msg_id)
.await?;
let nonce = match bridge_builtin_operations::send_message_to_bridge_builtin(
Expand Down Expand Up @@ -207,7 +224,16 @@ where
.get_message_info(&msg_id)
.expect("Unexpected: msg status does not exist");

let (sender, amount, receiver, vara_token_id) = msg_info.details.data();
let TxDetails::TransferVaraToEth {
vara_token_id,
sender,
amount,
receiver,
} = msg_info.details
else {
panic!("Wrong message type")
};

let eth_token_id = data
.vara_to_eth_token_id
.get(&vara_token_id)
Expand Down Expand Up @@ -295,6 +321,7 @@ where
gear_bridge_builtin: config.gear_bridge_builtin,
receiver_contract_address: config.receiver_contract_address,
admin: exec_context.actor_id(),
eth_client: config.eth_client,
..Default::default()
});
CONFIG = Some(config.config);
Expand All @@ -321,14 +348,6 @@ where
}
}

fn config_mut(&mut self) -> &mut Config {
unsafe {
CONFIG
.as_mut()
.expect("VftGateway::seed() should be called")
}
}

fn get_eth_token_id(&self, vara_token_id: &ActorId) -> Result<H160, Error> {
self.data()
.vara_to_eth_token_id
Expand Down
36 changes: 14 additions & 22 deletions gear-programs/vft-gateway/src/services/msg_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,30 @@ pub struct MessageTracker {
#[derive(Debug, Clone, Encode, Decode, TypeInfo)]
pub struct MessageInfo {
pub status: MessageStatus,
pub details: TransactionDetails,
pub details: TxDetails,
}

#[derive(Debug, Clone, Encode, Decode, TypeInfo)]
pub struct TransactionDetails {
vara_token_id: ActorId,
sender: ActorId,
amount: U256,
receiver: H160,
pub enum TxDetails {
TransferVaraToEth {
vara_token_id: ActorId,
sender: ActorId,
amount: U256,
receiver: H160,
},
MintTokens {
vara_token_id: ActorId,
receiver: ActorId,
amount: U256,
},
}

impl MessageTracker {
pub fn insert_message_info(
&mut self,
msg_id: MessageId,
status: MessageStatus,
details: TransactionDetails,
details: TxDetails,
) {
self.message_info
.insert(msg_id, MessageInfo { status, details });
Expand Down Expand Up @@ -111,18 +118,3 @@ pub enum MessageStatus {

MessageProcessedWithSuccess(U256),
}

impl TransactionDetails {
pub fn new(sender: ActorId, amount: U256, receiver: H160, vara_token_id: ActorId) -> Self {
Self {
vara_token_id,
sender,
amount,
receiver,
}
}

pub fn data(&self) -> (ActorId, U256, H160, ActorId) {
(self.sender, self.amount, self.receiver, self.vara_token_id)
}
}
18 changes: 11 additions & 7 deletions gear-programs/vft-gateway/src/services/token_operations.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::msg_tracker::TransactionDetails;
use super::msg_tracker::TxDetails;
use super::{msg_tracker_mut, utils, vft::vft::io as vft_io, Config, Error, MessageStatus};

use sails_rs::prelude::*;

pub async fn burn_tokens(
token_id: ActorId,
vara_token_id: ActorId,
sender: ActorId,
receiver: H160,
amount: U256,
Expand All @@ -13,7 +13,12 @@ pub async fn burn_tokens(
) -> Result<(), Error> {
let bytes: Vec<u8> = vft_io::Burn::encode_call(sender, amount);

let transaction_details = TransactionDetails::new(sender, amount, receiver, token_id);
let transaction_details = TxDetails::TransferVaraToEth {
vara_token_id,
sender,
amount,
receiver,
};

msg_tracker_mut().insert_message_info(
msg_id,
Expand All @@ -23,7 +28,7 @@ pub async fn burn_tokens(

utils::set_critical_hook(msg_id);
utils::send_message_with_gas_for_reply(
token_id,
vara_token_id,
bytes,
config.gas_to_burn_tokens,
config.gas_for_reply_deposit,
Expand All @@ -36,15 +41,14 @@ pub async fn burn_tokens(

pub async fn mint_tokens(
token_id: ActorId,
sender: ActorId,
receiver: ActorId,
amount: U256,
config: &Config,
msg_id: MessageId,
) -> Result<(), Error> {
msg_tracker_mut().update_message_status(msg_id, MessageStatus::SendingMessageToMintTokens);

let bytes: Vec<u8> = vft_io::Mint::encode_call(sender, amount);

let bytes: Vec<u8> = vft_io::Mint::encode_call(receiver, amount);
utils::send_message_with_gas_for_reply(
token_id,
bytes,
Expand Down
43 changes: 42 additions & 1 deletion gear-programs/vft-gateway/src/wasm/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use vft_gateway_app::services::{error::Error, msg_tracker::MessageInfo, Config,
pub const ADMIN_ID: u64 = 1000;
pub const TOKEN_ID: u64 = 200;
pub const BRIDGE_BUILTIN_ID: u64 = 300;
pub const ETH_CLIENT_ID: u64 = 500;

// Mocks for programs
macro_rules! create_mock {
Expand Down Expand Up @@ -134,6 +135,14 @@ pub trait VftGateway {
from: u64,
msg_id: MessageId,
) -> Result<(U256, H160), Error>;
fn mint_tokens(
&self,
from: u64,
vara_token_id: ActorId,
amount: U256,
receiver: ActorId,
error: bool,
);
fn get_msg_tracker_state(&self) -> Vec<(MessageId, MessageInfo)>;
}

Expand All @@ -143,8 +152,10 @@ impl VftGateway for Program<'_> {
let init_config = InitConfig::new(
[1; 20].into(),
BRIDGE_BUILTIN_ID.into(),
ETH_CLIENT_ID.into(),
Config::new(
2_000_000_000,
15_000_000_000,
15_000_000_000,
15_000_000_000,
15_000_000_000,
15_000_000_000,
Expand Down Expand Up @@ -231,6 +242,36 @@ impl VftGateway for Program<'_> {
reply.2
}

fn mint_tokens(
&self,
from: u64,
vara_token_id: ActorId,
amount: U256,
receiver: ActorId,
error: bool,
) {
let payload = [
"VftGateway".encode(),
"MintTokens".encode(),
(vara_token_id, receiver, amount).encode(),
]
.concat();
let result = self.send_bytes(from, payload);
let log_entry = result
.log()
.iter()
.find(|log_entry| log_entry.destination() == from.into())
.expect("Unable to get reply");

let reply = <(String, String, Result<(), Error>)>::decode(&mut log_entry.payload())
.expect("Unable to decode reply");
if error {
assert!(reply.2.is_err());
} else {
assert!(reply.2.is_ok());
}
}

fn get_msg_tracker_state(&self) -> Vec<(MessageId, MessageInfo)> {
let payload = ["VftGateway".encode(), "MsgTrackerState".encode()].concat();

Expand Down
Loading

0 comments on commit 1ac623d

Please sign in to comment.