Account Storage Standard (formerly Account Registration) #145
Replies: 17 comments 84 replies
-
Proposal: Account Registration InterfaceDEPRECATED. New design is presented in a discussion below: #145 (comment) pub trait AccountRegistrar {
/// Registers an account for using smart-contract. Enough NEAR must be attach
/// to cover storage cost.
/// Parameters:
/// * `account_id` - an account to register. Anyone can register any other account.
/// * `msg` - a transaction reference note for accounting.
/// If the account is already registered then the function early returns and refunds the attached NEAR.
/// MUST not panic if caller is already registered.
/// Returns `false` iff account was already registered.
/// Panics:
/// * If not enough deposit was attached to pay for account storage
#[payable]
fn ar_register(&mut self, account_id: string, msg: string|null, msg: string|null) -> bool;
/// Checks if the `account_id` is registered.
fn ar_is_registered(&mut self, account_id: string) -> bool;
/// Unregisters the caller for accepting token transfers and return the storage NEAR deposit back.
/// If the caller is not registered, the function should early return without throwing exception.
/// If `force=true` the function SHOULD ignore account balances (burn them) and close the account.
/// Otherwise, MUST panic if caller has a positive registered balance (eg token holdings)
/// MUST require exactly 1 yoctoNEAR attached balance to prevent restricted function-call access-key call
/// (UX wallet security)
/// Returns `false` iff account was not registered.
#[payable]
fn ar_unregister(&mut self, force: bool|null) -> bool;
/// Returns a minimum amount of NEAR which must be attached for `ar_register`
fn ar_registration_fee(&self) -> U128;
} RationaleAccount registration To simplify the interface we and make sure we send funds only to accounts which agree to receive token of a given type we introduce account registration concept. NEP-21 transfer (and approval) functions require payment to cover the potential storage fees.
NOTE: Each method which calls a #payment method must be marked with #payment. This complicates the tools design - they will need to ask user to attach payment for every such transaction. However we decided to keep the payment requirement for security reasons related to wallet and transaction signing. Please look at NEP-141 (Fungible Token Core Standard) for details. An account, once registered, can opt-out - with that, a storage deposit will be returned, and the account will stop accepting token transfers. |
Beta Was this translation helpful? Give feedback.
-
There also needs be a way to have "accept all" scenario where e.g. a smart contract receiving token does not need to register for receiving it beforehand. |
Beta Was this translation helpful? Give feedback.
-
Change proposal: Allow to burn existing token balances (e.g. for spam tokens), but you can still keep the registration fee. Unregisters the caller for accepting token transfers and return the storage NEAR deposit back. If the caller is not registered, the Arguments:
function unregister_account(force: bool); |
Beta Was this translation helpful? Give feedback.
-
Change proposal: Require 1 yoctoNEAR for
|
Beta Was this translation helpful? Give feedback.
-
Change proposal: Introduce view method Returns the amount of tokens in yoctoNEAR required to register an account (e.g. to pay for storage). The value is in decimal string representation. function acct_registration_fee(): string; |
Beta Was this translation helpful? Give feedback.
-
If we want to use prefix, can we use something else than
|
Beta Was this translation helpful? Give feedback.
-
Are we sure we don't want to pass an I really dislike the idea of adding restrictive measures like these to token standards. It is really against the open-web ethos. With regards to spamming: let spammers pay the storage cost for registration. |
Beta Was this translation helpful? Give feedback.
-
LAST CALL 2021-02-01We are planning to finalize this standard on Monday, 2021-02-01 if we won't get other critical comment by that time. |
Beta Was this translation helpful? Give feedback.
-
ReimbursingAccount can be updated, or a fees can change on a protocol level. In that case it's recommended that the service provider will reimburse users by sending back NEAR for them (minus tx cost). We don't need to have a standard method for that, because it's only in an interest of the service provider, not a general inter-smart contract communication. Instead we recommend few methods how to do that:
Note: a fully decentralized smart contract can just ignore that -- if a user will will like to get back his allowance, he will unregister and register himself back. |
Beta Was this translation helpful? Give feedback.
-
Account Registration APIThe primary use case for account registration is to address storage staking costs. This is an issue that needs On NEAR, the contract is responsible to pay for its long term persistent storage. Thus, multi-user contracts should be Additional benefits provided by account registration are:
The API specifies 4 functions: #[payable]
function ar_register(account_id: string|null): bool;
#[payable]
function ar_unregister(force: bool|null): bool;
function ar_is_registered(account_id: string): bool;
function ar_registration_fee(): string;
Function#[payable]
function ar_register(account_id: string|null): bool; change method Used for accounts to register with a contract. This function supports 2 modes of account registration:
Account registration fee is required and must be attached to the function all.
Arguments
Returns
Panics
Function#[payable]
function ar_unregister(force: bool|null): bool; Used to unregister the predecessor account that invoked the the function. Unregistration supports 2 modes:
If the account is not registered, then the function is a no-op, i.e., simply returns false. Sender account is required to attach exactly 1 yoctoNEAR to the function call to prevent restricted function-call access-key call. Arguments
Returns
Panics
NotesHow refunds are handled is out of scope for account registration standard. Refund business logic is contract specific. Functionfunction ar_is_registered(account_id: string): bool; view method Used to check if the account is registered with the contract. Arguments
Returns
Panics
Functionfunction ar_registration_fee(): string; view method Used to lookup the account registration fee that is required for registering an account with the contract. Returnsthe account registration fee amount in yoctoNEAR as an unsigned integer in string representation. |
Beta Was this translation helpful? Give feedback.
-
[OPTIONAL] Change proposal: Generic storage accountingI've reviewed Flux AMM contract and spotted a problem where they need to increase/refund storage in the It made me think that we potentially should generalize this standard to support variable storage amounts. I know I made the argument against this to simplify fungible token standard, but let's still consider it. APIs
Notes:
Fixed size account storage contractsE.g. current proposal can be migrated using the following:
|
Beta Was this translation helpful? Give feedback.
-
2021-02-05 Standards Meeting AgendaMeeting Time: 11 AM - 12 PM ET NOTE: Please reply to this post to submit questions and discussion items prior to the meeting
/// may be used to deposit funds for caller (predecessor account) or for specified account
///
/// Returns updated balance
///
/// PANICS
/// - if deposit is less than minimum balance
#[payable]
function storage_deposit(account_id: string|null): string;
/// requires 1 yoctoNEAR attached, which is refunded along with withdrawal
///
/// Returns updated balance
///
/// PANICS
/// - if withdrawal results in account balance below minimum balanace
#[payable]
function storage_withdraw(amount: string): string
/// minimum balance that is required in order for the account to use the contract
function storage_minimum_balance(): string;
function storage_balance(account_id: string): AccountStorageBalance|null;
class AccountStorageBalance {
total: string;
available: string;
} Replaces the need for account registration API because the main problem that account registration was trying to solve was account storage staking cost management. Storage staking costs is a problem for any multi-user contract and is not specific for token contracts. Questions and Discussion Items
|
Beta Was this translation helpful? Give feedback.
-
2021-02-05 Standards Review Meeting Meeting Minutes:
Account Storage APIStorage staking is an issue that needs to be addressed by any multi-user contract that allocates storage for the On NEAR, the contract is responsible to pay for its long term persistent storage. Thus, multi-user contracts should be
Out of Scope
Quick API Overview// Deposit funds to pay for account storage for the specified `account_id`.
// If the `account_id` is not specified, then it defaults to the `predecessor_id`.
//
// Returns the account's updated balance
#[payable]
function storage_deposit(account_id: string|null): AccountStorageBalance;
// Withdraw the specified amount from the `predecessor_id` available storage balance.
// If no `amount` is specified, then all of the account's available storage balance is withdrawn.
//
// Returns the account's updated balance
#[payable]
function storage_withdraw(amount: string|null): AccountStorageBalance;
function storage_minimum_balance(): string;
function storage_balance_of(account_id: string): AccountStorageBalance;
class AccountStorageBalance {
total: string;
available: string;
} See below for details. Domain Modelclass AccountStorageBalance {
total: string;
available: string;
}
Function#[payable]
function storage_deposit(account_id: string|null): AccountStorageBalance; change method Used by accounts to deposit funds to pay for account storage staking fees. This function supports 2 deposit modes:
If this is the initial deposit for the account, then the deposit must be enough to cover the minimum required balance. Example Use Cases
Arguments
ReturnsThe account's updated storage balance. Panics
Function#[payable]
function storage_withdraw(amount: string|null): AccountStorageBalance; change method Used to withdraw NEAR from the predecessor account's storage available balance. If amount is not specified, then all of the account's storage available balance will be withdrawn. The attached yoctoNEAR will be refunded with the withdrawal transfer. The account is required to attach exactly 1 yoctoNEAR to the function call to prevent restricted function-call access-key call. Arguments
ReturnsThe account's updated storage balance. Panics
Functionfunction storage_minimum_balance(): string; view method Used to look up the minimum balance required for the initial deposit. ReturnsAmount in yoctoNEAR (in string representation) Functionfunction storage_balance_of(account_id: string): AccountStorageBalance; view method Used to lookup the account storage balance for the specified account. If the account is unknown to the contract then the total Panics
|
Beta Was this translation helpful? Give feedback.
-
Change proposalRename |
Beta Was this translation helpful? Give feedback.
-
I've attempted to use this standard for fixed-size fungible token storage. It somewhat works with limitations. E.g. I require that you deposit only the exact minimum balance and you can withdraw only the exact minimum balance. See https://github.com/near/core-contracts/pull/128/files#diff-1f33dbff2263c13dc7cea606765b6a2326c6c355a6b659f7f22be1262cd3ea70 |
Beta Was this translation helpful? Give feedback.
-
2021-02-12 Standards Review Meeting AgendaNOTE: Meeting is shortened to 30 minutes for tomorrow due to ETHDenver constraints
Please vote on the 2 above APIs with a thumbs up to approve or thumbs down to reject. Account Storage APIStorage staking is an issue that needs to be addressed by any multi-user contract that allocates storage for the On NEAR, the contract is responsible to pay for its long term persistent storage. Thus, multi-user contracts should be
Out of Scope
Quick API Overview// Deposit funds to pay for account storage for the specified `account_id`.
// If the `account_id` is not specified, then it defaults to the `predecessor_id`.
//
// Returns the account's updated balance
#[payable]
function storage_deposit(account_id: string|null): AccountStorageBalance;
// Withdraw the specified amount from the `predecessor_id` available storage balance.
// If no `amount` is specified, then all of the account's available storage balance is withdrawn.
//
// Returns the account's updated balance
#[payable]
function storage_withdraw(amount: string|null): AccountStorageBalance;
function storage_minimum_balance(): string;
function storage_balance_of(account_id: string): AccountStorageBalance;
class AccountStorageBalance {
total: string;
available: string;
} See below for details. Domain Modelclass AccountStorageBalance {
total: string;
available: string;
}
Function#[payable]
function storage_deposit(account_id: string|null): AccountStorageBalance; change method Used by accounts to deposit funds to pay for account storage staking fees. This function supports 2 deposit modes:
If this is the initial deposit for the account, then the deposit must be enough to cover the minimum required balance. Example Use Cases
Arguments
ReturnsThe account's updated storage balance. Panics
Function#[payable]
function storage_withdraw(amount: string|null): AccountStorageBalance; change method Used to withdraw NEAR from the predecessor account's storage available balance. If amount is not specified, then all of the account's storage available balance will be withdrawn. The attached yoctoNEAR will be refunded with the withdrawal transfer. The account is required to attach exactly 1 yoctoNEAR to the function call to prevent restricted function-call access-key call. Arguments
ReturnsThe account's updated storage balance. Panics
Functionfunction storage_minimum_balance(): string; view method Used to look up the minimum balance required for the initial deposit. ReturnsAmount in yoctoNEAR (in string representation) Functionfunction storage_balance_of(account_id: string): AccountStorageBalance; view method Used to lookup the account storage balance for the specified account. If the account is unknown to the contract then the total Panics
|
Beta Was this translation helpful? Give feedback.
-
2021-02-12 Meeting Minutes
Action Items
Fungible Token Metadata APIclass FungibleTokenMetadata {
name: string,
decimals: number,
reference: string,
reference_hash: string, // base64 encoded hash bytes
} Functionfunction ft_metadata(): FungibleTokenMetadata; view method |
Beta Was this translation helpful? Give feedback.
-
Introduction
While designing the Fungible Token core standard, it became apparent for a need
to standardize account registration. This discussion is focused specifically on account registration, but that is a subset of the bigger problem domain of account management, which includes access control - we can save that for a separate discussion.
Account registration is a common use case for any multi-user contract. There are several benefits to require accounts to pre-register with the contract:
Lessons Learned from NEP-141 Discussion
acct_
, unless someone has a better one. We can sleep on it, and finalize the prefix at the end. Feel free to choose alternative names when proposing functions for the contract interface.Beta Was this translation helpful? Give feedback.
All reactions