duly / mock-usdc/src/lib.rs · raw
//! Test-only NEP-141 token used by Duly test mode on NEAR testnet.//! Anyone can mint: it has no value and is never deployed to mainnet.use near_contract_standards::fungible_token::metadata::{    FungibleTokenMetadata, FungibleTokenMetadataProvider, FT_METADATA_SPEC,};use near_contract_standards::fungible_token::{    FungibleToken, FungibleTokenCore, FungibleTokenResolver, Balance,};use near_contract_standards::storage_management::{    StorageBalance, StorageBalanceBounds, StorageManagement,};use near_sdk::json_types::U128;use near_sdk::{env, near, AccountId, BorshStorageKey, NearToken, PanicOnDefault, PromiseOrValue};#[derive(BorshStorageKey)]#[near]enum Key {    Ft,}#[near(contract_state)]#[derive(PanicOnDefault)]pub struct MockUsdc {    token: FungibleToken,}#[near]impl MockUsdc {    #[init]    pub fn new() -> Self {        Self { token: FungibleToken::new(Key::Ft) }    }    /// Mint test tokens. Registers the account if needed. Capped per call.    pub fn mint(&mut self, account_id: AccountId, amount: U128) {        assert!(amount.0 <= 1_000_000_000, "mint at most 1000 per call");        if self.token.accounts.get(&account_id).is_none() {            self.token.internal_register_account(&account_id);        }        self.token.internal_deposit(&account_id, amount.0);    }    /// Register an account for free so test flows need no storage deposit.    pub fn register(&mut self, account_id: AccountId) {        if self.token.accounts.get(&account_id).is_none() {            self.token.internal_register_account(&account_id);        }    }}#[near]impl FungibleTokenCore for MockUsdc {    #[payable]    fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option<String>) {        self.token.ft_transfer(receiver_id, amount, memo)    }    #[payable]    fn ft_transfer_call(        &mut self,        receiver_id: AccountId,        amount: U128,        memo: Option<String>,        msg: String,    ) -> PromiseOrValue<U128> {        self.token.ft_transfer_call(receiver_id, amount, memo, msg)    }    fn ft_total_supply(&self) -> U128 {        self.token.ft_total_supply()    }    fn ft_balance_of(&self, account_id: AccountId) -> U128 {        self.token.ft_balance_of(account_id)    }}#[near]impl FungibleTokenResolver for MockUsdc {    #[private]    fn ft_resolve_transfer(        &mut self,        sender_id: AccountId,        receiver_id: AccountId,        amount: U128,    ) -> U128 {        let (used, _burned): (Balance, Balance) =            self.token.internal_ft_resolve_transfer(&sender_id, receiver_id, amount);        used.into()    }}#[near]impl StorageManagement for MockUsdc {    #[payable]    fn storage_deposit(        &mut self,        account_id: Option<AccountId>,        registration_only: Option<bool>,    ) -> StorageBalance {        self.token.storage_deposit(account_id, registration_only)    }    #[payable]    fn storage_withdraw(&mut self, amount: Option<NearToken>) -> StorageBalance {        self.token.storage_withdraw(amount)    }    #[payable]    fn storage_unregister(&mut self, force: Option<bool>) -> bool {        self.token.storage_unregister(force)    }    fn storage_balance_bounds(&self) -> StorageBalanceBounds {        self.token.storage_balance_bounds()    }    fn storage_balance_of(&self, account_id: AccountId) -> Option<StorageBalance> {        self.token.storage_balance_of(account_id)    }}#[near]impl FungibleTokenMetadataProvider for MockUsdc {    fn ft_metadata(&self) -> FungibleTokenMetadata {        let _ = env::current_account_id();        FungibleTokenMetadata {            spec: FT_METADATA_SPEC.to_string(),            name: "Test USDC (no value)".to_string(),            symbol: "tUSDC".to_string(),            icon: None,            reference: None,            reference_hash: None,            decimals: 6,        }    }}