Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,12 @@ impl EthConnectorContract {
sdk::return_output(0.to_string().as_bytes());
}

/// Get accounts counter for statistics.
/// It represents total unique accounts (all-time, including accounts which now have zero balance).
pub fn get_accounts_counter(&self) {
sdk::return_output(self.ft.get_accounts_counter().to_string().as_bytes());
Comment thread
mrLSD marked this conversation as resolved.
Outdated
}

/// Save eth-connector contract data
fn save_ft_contract(&mut self) {
sdk::save_contract(
Expand Down
26 changes: 25 additions & 1 deletion src/fungible_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,24 @@ impl FungibleToken {
}
}

/// Insert account.
/// Calculate total unique accounts
pub fn accounts_insert(&self, account_id: &str, amount: Balance) {
sdk::save_contract(&Self::account_to_key(account_id), &amount)
if !self.accounts_contains_key(account_id) {
let key = Self::get_statistic_key();
Comment thread
mrLSD marked this conversation as resolved.
let accounts_counter = sdk::read_u64(&key)
.unwrap_or(0)
.checked_add(1)
.expect("ERR_ACCOUNTS_COUNTER_OVERFLOW");
sdk::write_storage(&key, &accounts_counter.to_le_bytes());
}
sdk::save_contract(&Self::account_to_key(account_id), &amount);
}

/// Get accounts counter for statistics
Comment thread
mrLSD marked this conversation as resolved.
/// It represents total unique accounts.
pub fn get_accounts_counter(&self) -> u64 {
sdk::read_u64(&Self::get_statistic_key()).unwrap_or(0)
}

fn accounts_contains_key(&self, account_id: &str) -> bool {
Expand All @@ -446,4 +462,12 @@ impl FungibleToken {
key.extend_from_slice(account_id.as_bytes());
key
}

/// Key for store contract statistics data
fn get_statistic_key() -> Vec<u8> {
storage::bytes_to_key(
storage::KeyPrefix::EthConnector,
&[storage::EthConnectorStorageId::StatisticsAuroraAccountsCounter as u8],
)
}
}
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,11 @@ mod contract {
EthConnectorContract::get_instance().ft_on_transfer(&engine)
}

#[no_mangle]
pub extern "C" fn get_accounts_counter() {
EthConnectorContract::get_instance().get_accounts_counter()
}

#[cfg(feature = "integration-test")]
#[no_mangle]
pub extern "C" fn verify_log_entry() {
Expand Down
1 change: 1 addition & 0 deletions src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub enum EthConnectorStorageId {
Contract = 0x0,
FungibleToken = 0x1,
UsedEvent = 0x2,
StatisticsAuroraAccountsCounter = 0x3,
}

/// We can't use const generic over Enum, but we can do it over integral type
Expand Down
13 changes: 13 additions & 0 deletions tests/test_connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,3 +585,16 @@ fn test_ft_transfer_call_fee_greater_than_amount() {
let balance = total_supply_eth(&master_account, CONTRACT_ACC);
assert_eq!(balance, 0);
}

#[test]
fn test_get_accounts_counter() {
let (master_account, contract) = init(CUSTODIAN_ADDRESS);
call_deposit_near(&contract, CONTRACT_ACC);

let counter = master_account.view(CONTRACT_ACC.into(), "get_accounts_counter", &[]);
let counter: u128 = String::from_utf8(counter.unwrap())
.unwrap()
.parse()
.unwrap();
assert_eq!(counter, 2);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is the value 2? I only see one call to deposit so I would only expect there to be one account.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Please look to that test:

#[test]
fn test_near_deposit_balance_total_supply() {
    let (master_account, contract) = init(CUSTODIAN_ADDRESS);
    call_deposit_near(&contract, CONTRACT_ACC);

    let balance = get_near_balance(&master_account, DEPOSITED_RECIPIENT, CONTRACT_ACC);
    assert_eq!(balance, DEPOSITED_AMOUNT - DEPOSITED_FEE);

    let balance = get_near_balance(&master_account, CONTRACT_ACC, CONTRACT_ACC);
    assert_eq!(balance, DEPOSITED_FEE);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Right, there is a fee as well, so one deposit creates two accounts. Thanks for clarifying; it might be worth saying this in a comment as well.

Also, I recommend extending the test to have a transfer between those two accounts after the deposit, and confirm that the count does not change (because the number of unique accounts is the same).

}