Token standards

Fungible tokens (NEP-141)

NEP-141 is the ERC-20 of NEAR — but there is no approve/allowance. ft_transfer_call does an atomic transfer-and-call instead.

NEP-141 is NEAR’s fungible-token standard — the ERC-20 equivalent. The interface looks familiar, with one big omission: there is no `approve` / `allowance` / `transferFrom`. Instead, ft_transfer_call transfers to a contract and calls it in one atomic step.

The core interface
Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);

    // the allowance dance — a spender you pre-approve
    function approve(address spender, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function transferFrom(address from, address to, uint256 amount)
        external returns (bool);
}
Rust
use near_sdk::json_types::U128;
use near_sdk::{AccountId, PromiseOrValue};

// NEP-141 core (near-contract-standards: FungibleTokenCore)
pub trait FungibleTokenCore {
    fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option<String>);

    // transfer to a CONTRACT and call its ft_on_transfer in one atomic step;
    // the receiver returns how much to refund. Replaces approve + transferFrom.
    fn ft_transfer_call(
        &mut self,
        receiver_id: AccountId,
        amount: U128,
        memo: Option<String>,
        msg: String,
    ) -> PromiseOrValue<U128>;

    fn ft_total_supply(&self) -> U128;
    fn ft_balance_of(&self, account_id: AccountId) -> U128;
}
Coming from EVM

No approve / allowance / transferFrom. ft_transfer_call atomically moves tokens to a contract and invokes its ft_on_transfer(sender, amount, msg), which returns the unused amount to refund — killing the infinite-approval footgun.

ft_transfer requires exactly 1 yoctoNEAR attached (a confirmation that the key really meant to move funds), and receivers must be registered for storage first (NEP-145) so their balance entry has a paid slot.

You rarely write this by hand: near-contract-standards provides a FungibleToken you embed, then one macro implements the whole standard — metadata is NEP-148.