From 5fee9897912066eb9277390554e7f64a9d26b11b Mon Sep 17 00:00:00 2001 From: Olga Kunyavskaya Date: Mon, 29 Apr 2024 02:49:27 +0300 Subject: [PATCH] Storage deposit before account register (#79) * storage deposit before register * fmt * fix clippy --------- Co-authored-by: karim-en --- eth-connector/src/connector_impl.rs | 1 + eth-connector/src/lib.rs | 70 ++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/eth-connector/src/connector_impl.rs b/eth-connector/src/connector_impl.rs index 7919109..506eb63 100644 --- a/eth-connector/src/connector_impl.rs +++ b/eth-connector/src/connector_impl.rs @@ -140,6 +140,7 @@ impl EthConnector { .then( ext_funds_finish::ext(current_account_id) .with_static_gas(GAS_FOR_FINISH_DEPOSIT) + .with_attached_deposit(env::attached_deposit()) .finish_deposit(finish_deposit_data), ) } diff --git a/eth-connector/src/lib.rs b/eth-connector/src/lib.rs index 772b5a8..5c301b0 100644 --- a/eth-connector/src/lib.rs +++ b/eth-connector/src/lib.rs @@ -1,5 +1,6 @@ #![deny(clippy::pedantic, clippy::nursery)] #![allow(clippy::module_name_repetitions)] + use crate::connector::{ ext_engine_connector, ext_migrate, Deposit, EngineConnectorWithdraw, EngineFungibleToken, EngineStorageManagement, FundsFinish, KnownEngineAccountsManagement, Withdraw, @@ -33,6 +34,7 @@ use near_sdk::{ PromiseOrValue, }; use serde::{Deserialize, Serialize}; +use std::collections::HashSet; pub mod connector; pub mod connector_impl; @@ -92,7 +94,6 @@ impl EthConnectorContract { fn mint_eth_on_near(&mut self, owner_id: &AccountId, amount: Balance) { log!("Mint {} nETH tokens for: {}", amount, owner_id); // Create account to avoid panic with deposit - self.register_if_not_exists(owner_id); self.ft.internal_deposit(owner_id, amount); } @@ -118,6 +119,32 @@ impl EthConnectorContract { } } + fn multiple_storage_deposit(&mut self, accounts: Vec<&AccountId>) { + let amount: Balance = env::attached_deposit(); + let accounts: Vec<_> = accounts + .into_iter() + .collect::>() + .into_iter() + .collect(); + + let mut storage_amount = 0; + let min_balance = self.storage_balance_bounds().min.0; + for account_id in accounts { + if !self.ft.accounts.contains_key(account_id) { + storage_amount += min_balance; + } + } + + if amount < storage_amount { + env::panic_str("The attached deposit is less than the minimum storage balance"); + } + + let refund = amount - storage_amount; + if refund > 0 { + Promise::new(env::predecessor_account_id()).transfer(refund); + } + } + fn internal_ft_transfer_call( &mut self, sender_id: AccountId, @@ -126,8 +153,6 @@ impl EthConnectorContract { memo: Option, msg: String, ) -> PromiseOrValue { - self.register_if_not_exists(&receiver_id); - let amount: Balance = amount.into(); log!( "Transfer call from {} to {} amount {}", @@ -290,7 +315,7 @@ impl FungibleTokenCore for EthConnectorContract { #[payable] #[pause(except(roles(Role::DAO)))] fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option) { - self.register_if_not_exists(&receiver_id); + self.ft.storage_deposit(Some(receiver_id.clone()), None); self.ft.ft_transfer(receiver_id, amount, memo); } @@ -309,6 +334,7 @@ impl FungibleTokenCore for EthConnectorContract { "More gas is required" ); let sender_id = env::predecessor_account_id(); + self.ft.storage_deposit(Some(receiver_id.clone()), None); self.internal_ft_transfer_call(sender_id, receiver_id, amount, memo, msg) } @@ -338,8 +364,8 @@ impl EngineFungibleToken for EthConnectorContract { memo: Option, ) { self.assert_aurora_engine_access_right(); + self.ft.storage_deposit(Some(receiver_id.clone()), None); - self.register_if_not_exists(&receiver_id); assert_one_yocto(); let amount: Balance = amount.into(); self.ft @@ -363,6 +389,7 @@ impl EngineFungibleToken for EthConnectorContract { env::prepaid_gas() > GAS_FOR_FT_TRANSFER_CALL, "More gas is required" ); + self.ft.storage_deposit(Some(receiver_id.clone()), None); self.internal_ft_transfer_call(sender_id, receiver_id, amount, memo, msg) } } @@ -595,6 +622,7 @@ impl EngineConnectorWithdraw for EthConnectorContract { #[near_bindgen] impl Deposit for EthConnectorContract { + #[payable] #[pause(except(roles(Role::DAO)))] fn deposit(&mut self, #[serializer(borsh)] proof: Proof) -> Promise { self.connector.deposit(proof) @@ -614,21 +642,31 @@ impl FundsFinish for EthConnectorContract { if !verify_log_result { panic_err(errors::ERR_VERIFY_PROOF); } - log!("Finish deposit with the amount: {}", deposit_call.amount); - // Mint - calculate new balances - self.mint_eth_on_near(&deposit_call.new_owner_id, deposit_call.amount); - // Store proof only after `mint` calculations - self.record_proof(&deposit_call.proof_key).sdk_unwrap(); - // Mint tokens to recipient minus fee - deposit_call.msg.map_or_else( - || PromiseOrValue::Value(None), - |msg| { + match deposit_call.msg { + None => { + self.ft + .storage_deposit(Some(deposit_call.new_owner_id.clone()), None); + // Mint - calculate new balances + self.mint_eth_on_near(&deposit_call.new_owner_id, deposit_call.amount); + // Store proof only after `mint` calculations + self.record_proof(&deposit_call.proof_key).sdk_unwrap(); + PromiseOrValue::Value(None) + } + Some(msg) => { let args = TransferCallCallArgs::try_from_slice(&msg) .map_err(|_| crate::errors::ERR_BORSH_DESERIALIZE) .sdk_unwrap(); + + self.multiple_storage_deposit(vec![&deposit_call.new_owner_id, &args.receiver_id]); + + // Mint - calculate new balances + self.mint_eth_on_near(&deposit_call.new_owner_id, deposit_call.amount); + // Store proof only after `mint` calculations + self.record_proof(&deposit_call.proof_key).sdk_unwrap(); + let promise = self.internal_ft_transfer_call( env::predecessor_account_id(), args.receiver_id, @@ -640,8 +678,8 @@ impl FundsFinish for EthConnectorContract { PromiseOrValue::Promise(p) => PromiseOrValue::Promise(p), PromiseOrValue::Value(v) => PromiseOrValue::Value(Some(v)), } - }, - ) + } + } } }