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

Fix ft transfer call message check #12

Merged
merged 8 commits into from
Jan 24, 2023
193 changes: 189 additions & 4 deletions eth-connector-tests/src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ async fn test_deposit_eth_to_near_balance_total_supply() -> anyhow::Result<()> {
#[tokio::test]
async fn test_deposit_eth_to_aurora_balance_total_supply() -> anyhow::Result<()> {
let contract = TestContract::new().await?;
contract
.set_engine_account(contract.contract.id())
.await
.unwrap();

contract.call_deposit_eth_to_aurora().await?;
assert!(
contract.call_is_used_proof(PROOF_DATA_ETH).await?,
Expand Down Expand Up @@ -266,7 +271,11 @@ async fn test_ft_transfer_call_without_message() -> anyhow::Result<()> {
let transfer_amount: U128 = 50.into();
let memo: Option<String> = None;
let message = "";
// Send to Aurora contract with wrong message should failed
contract
.set_engine_account(contract.contract.id())
.await
.unwrap();
// Send to Engine contract with wrong message should failed
let res = contract
.contract
.call("ft_transfer_call")
Expand Down Expand Up @@ -311,6 +320,131 @@ async fn test_ft_transfer_call_without_message() -> anyhow::Result<()> {
Ok(())
}

#[tokio::test]
async fn test_ft_transfer_call_user_message() {
let contract = TestContract::new().await.unwrap();
contract.call_deposit_eth_to_near().await.unwrap();

let user_acc = contract.create_sub_account("eth_recipient").await.unwrap();
let receiver_id = contract.contract.id();
let balance = contract
.get_eth_on_near_balance(user_acc.id())
.await
.unwrap();
assert_eq!(balance.0, DEPOSITED_AMOUNT - DEPOSITED_FEE);

let balance = contract
.get_eth_on_near_balance(contract.contract.id())
.await
.unwrap();
assert_eq!(balance.0, DEPOSITED_FEE);

let transfer_amount: U128 = 50.into();
let memo: Option<String> = None;
let message = "";
// Send to non-engine contract with wrong message should failed
let res = user_acc
.call(contract.contract.id(), "ft_transfer_call")
.args_json((&receiver_id, transfer_amount, &memo, message))
.gas(DEFAULT_GAS)
.deposit(ONE_YOCTO)
.transact()
.await
.unwrap();
assert!(res.is_success());

let balance = contract.get_eth_on_near_balance(receiver_id).await.unwrap();
assert_eq!(balance.0, DEPOSITED_FEE + transfer_amount.0);
let balance = contract
.get_eth_on_near_balance(user_acc.id())
.await
.unwrap();
assert_eq!(
balance.0,
DEPOSITED_AMOUNT - DEPOSITED_FEE - transfer_amount.0
);

contract
.set_and_check_access_right(contract.contract.id())
.await
.unwrap();

contract.set_engine_account(receiver_id).await.unwrap();

let res = contract
.contract
.call("get_engine_accounts")
.view()
.await
.unwrap()
.json::<Vec<AccountId>>()
.unwrap();
assert!(res.contains(receiver_id));

// Send to engine contract with wrong message should failed
let res = user_acc
.call(contract.contract.id(), "ft_transfer_call")
.args_json((&receiver_id, transfer_amount, &memo, message))
.gas(DEFAULT_GAS)
.deposit(ONE_YOCTO)
.transact()
.await
.unwrap();
assert!(res.is_failure());
assert!(contract.check_error_message(res, "ERR_INVALID_ON_TRANSFER_MESSAGE_FORMAT"));
let balance = contract.get_eth_on_near_balance(receiver_id).await.unwrap();
assert_eq!(balance.0, DEPOSITED_FEE + transfer_amount.0);
let balance = contract
.get_eth_on_near_balance(user_acc.id())
.await
.unwrap();
assert_eq!(
balance.0,
DEPOSITED_AMOUNT - DEPOSITED_FEE - transfer_amount.0
);
}

#[tokio::test]
async fn test_set_and_get_engine_account() {
let contract = TestContract::new().await.unwrap();
contract.call_deposit_eth_to_near().await.unwrap();

let user_acc = contract.create_sub_account("eth_recipient").await.unwrap();
let res = user_acc
.call(contract.contract.id(), "set_engine_account")
.args_json((&contract.contract.id(),))
.gas(DEFAULT_GAS)
.transact()
.await
.unwrap();
assert!(res.is_failure());
assert!(contract.check_error_message(res, "ERR_ACCESS_RIGHT"));

contract
.set_and_check_access_right(user_acc.id())
.await
.unwrap();

let res = user_acc
.call(contract.contract.id(), "set_engine_account")
.args_json((&contract.contract.id(),))
.gas(DEFAULT_GAS)
.transact()
.await
.unwrap();
assert!(res.is_success());

let res = contract
.contract
.call("get_engine_accounts")
.view()
.await
.unwrap()
.json::<Vec<AccountId>>()
.unwrap();
assert!(res.contains(contract.contract.id()));
}

#[tokio::test]
async fn test_deposit_with_0x_prefix() -> anyhow::Result<()> {
let contract = TestContract::new().await?;
Expand Down Expand Up @@ -477,6 +611,9 @@ async fn test_ft_transfer_call_fee_greater_than_amount() -> anyhow::Result<()> {
let relayer_id = "relayer.root";
let message = [relayer_id, hex::encode(msg).as_str()].join(":");
let memo: Option<String> = None;

// For `ft_transfer_call` we don't check correcness for `fee amount`.
// So transactions should be success, and balances shouldn't changes
let res = contract
.contract
.call("ft_transfer_call")
Expand All @@ -485,13 +622,11 @@ async fn test_ft_transfer_call_fee_greater_than_amount() -> anyhow::Result<()> {
.deposit(ONE_YOCTO)
.transact()
.await?;
assert!(res.is_failure());
assert!(contract.check_error_message(res, "insufficient balance for fee"));
assert!(res.is_success());

let receiver_id = AccountId::try_from(DEPOSITED_RECIPIENT.to_string()).unwrap();
let balance = contract.get_eth_on_near_balance(&receiver_id).await?;
assert_eq!(balance.0, DEPOSITED_AMOUNT - DEPOSITED_FEE);
assert_eq!(balance.0, DEPOSITED_AMOUNT - DEPOSITED_FEE);

let balance = contract
.get_eth_on_near_balance(contract.contract.id())
Expand Down Expand Up @@ -569,6 +704,10 @@ async fn test_admin_controlled_admin_can_perform_actions_when_paused() -> anyhow
// 2nd deposit call when paused, but the admin is calling it - should succeed
// NB: We can use `PROOF_DATA_ETH` this will be just a different proof but the same deposit
// method which should be paused
contract
.set_engine_account(contract.contract.id())
.await
.unwrap();
contract.call_deposit_eth_to_aurora().await?;

// Pause withdraw
Expand Down Expand Up @@ -1541,3 +1680,49 @@ async fn test_engine_storage_unregister() {
assert!(res.is_failure());
assert!(contract.check_error_message(res, "The account eth_recipient.root is not registered"));
}

#[tokio::test]
async fn test_manage_engine_accounts() {
let contract = TestContract::new().await.unwrap();
contract
.set_and_check_access_right(contract.contract.id())
.await
.unwrap();

let acc1 = AccountId::try_from("acc1.root".to_string()).unwrap();
let acc2 = AccountId::try_from("acc2.root".to_string()).unwrap();
contract.set_engine_account(&acc1).await.unwrap();
contract.set_engine_account(&acc2).await.unwrap();
let res = contract
.contract
.call("get_engine_accounts")
.view()
.await
.unwrap()
.json::<Vec<AccountId>>()
.unwrap();
assert_eq!(res.len(), 2);
assert!(res.contains(&acc1));
assert!(res.contains(&acc2));

let res = contract
.contract
.call("remove_engine_account")
.args_json((&acc1,))
.gas(DEFAULT_GAS)
.transact()
.await
.unwrap();
assert!(res.is_success());
let res = contract
.contract
.call("get_engine_accounts")
.view()
.await
.unwrap()
.json::<Vec<AccountId>>()
.unwrap();
assert_eq!(res.len(), 1);
assert!(!res.contains(&acc1));
assert!(res.contains(&acc2));
}
13 changes: 13 additions & 0 deletions eth-connector-tests/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,19 @@ impl TestContract {
}
Ok(())
}

pub async fn set_engine_account(&self, acc: &AccountId) -> anyhow::Result<()> {
let res = self
.contract
.call("set_engine_account")
.args_json((&acc,))
.gas(DEFAULT_GAS)
.transact()
.await
.unwrap();
assert!(res.is_success());
aleksuss marked this conversation as resolved.
Show resolved Hide resolved
Ok(())
}
}

pub fn print_logs(res: ExecutionFinalResult) {
Expand Down
9 changes: 9 additions & 0 deletions eth-connector/src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,12 @@ pub trait EngineStorageManagement {

fn engine_storage_unregister(&mut self, sender_id: AccountId, force: Option<bool>) -> bool;
}

#[ext_contract(ext_known_engine_accounts)]
pub trait KnownEngineAccountsManagement {
fn set_engine_account(&mut self, engine_account: AccountId);

fn remove_engine_account(&mut self, engine_account: AccountId);

fn get_engine_accounts(&self) -> Vec<AccountId>;
}
Loading