ERC-6808 Key-Bound Fungible Token (Fungible Key Bound Token)

Final · Tokens · created 2023-03-31

An optional security standard that binds two key wallets to an ERC-20 token so that transfers and approvals happen only under conditions the key wallets have allowed in advance. Even if a wallet is compromised, you can move the assets to safety or reset the settings.

Why it is needed

A self-custody wallet puts all authority on a single private key. Once a seed phrase or private key leaks, an attacker can move the tokens immediately, and there is no way to reverse it. According to the original document, from January 2021 to March 2022 the US Federal Trade Commission received more than 46,000 crypto fraud reports, and consumer losses exceeded 1 billion dollars. Decentralized alternatives such as hardware wallets require purchase and shipping, which limits adoption, and centralized services require creating an account and providing personal information. With an existing ERC-20 token, there is no means at all to protect the assets the moment the wallet is compromised. This standard tries to build an optional security feature into the asset itself rather than the wallet, giving a second chance to protect the tokens even if one of the three wallets is compromised.

What to implement

In depth

The 3-wallet structure and addBindings

When the holding wallet (Holding Wallet) that holds the tokens calls addBindings(_keyWallet1, _keyWallet2), the account becomes secured and the AccountSecured event is emitted. After that, the assets stay in the holding wallet but the authority to spend them is held by the key wallets, so responsibility is divided. It SHOULD revert if the caller is not a holder, the account is already secured, the two key wallets are the same, a key wallet is the same as the caller, a key wallet is the zero address, or a key wallet is already in use as a key wallet of another holding account. If addBindings is never used, it behaves as a regular ERC-20 by default.

Specifying conditions in allowTransfer

A key wallet calls allowTransfer(_amount, _time, _to, _allFunds) before transfer to allow a transfer. If _amount is 0 there is no amount limit, if _time is 0 there is no time limit, and if _to is the zero address there is no destination limit. If _allFunds is true, it allows the full balance to be sent to anyone at any time, regardless of the other parameters. It must revert if the caller is not a key wallet or _amount is greater than the holding account's balance, and on success it MUST emit the AccountEnabledTransfer event. If a secured account calls transfer without this allowance, the transfer must be reverted.

allowApproval and approval control

When a key wallet calls allowApproval(_time, _numberOfTransfers), the holding wallet can use approve, increaseAllowance and decreaseAllowance for _time, and the number of transfers the spender can make is limited to _numberOfTransfers (0 means unlimited within the allowance limit). Calling approve again overwrites both the allowance and the permitted number of transfers. Each time transferFrom is called, it decrements the remaining count and checks whether it has reached 0. When it reaches 0, it revokes the approval with an approve of amount 0. If a secure account calls an approve-type function without allowApproval, or after the configured time has passed, the call must revert.

Two recovery mechanisms: safeFallback and resetBindings

safeFallback is called from a key wallet when the holding wallet has been compromised or access to it has been lost. All tokens in the holding account move to a key wallet other than the one that made the call, and a SafeFallbackActivated event is emitted. resetBindings is called from a key wallet when a key wallet has been compromised. It removes the bound key wallets and emits an AccountResetBinding event. After the reset, the token behaves like a regular ERC-20, and the holding wallet can bind new key wallets by calling addBindings again. Both functions must revert if the caller is not a key wallet.

ERC-20 compatibility and optional security

FKBT is designed to inherit all the characteristics of ERC-20 (requires: 20). The aim is to let it work out of the box in existing dApps that use fungible tokens, and existing tokens and wallets continue to work unchanged, unaffected by the introduction of FKBT. Having allowTransfer and allowApproval return a bool on success and revert on failure is also a decision made for consistency with ERC-20. In addition, callers must handle a false value of returns (bool success) and must not assume that false is never returned.

Query functions and holder-tracking events

getBindings returns the two key wallets of an account, getTransferableFunds returns the transfer permission conditions (amount, time, to, allFunds), and getApprovalConditions returns the approval permission conditions (time, numberOfTransfers), each as a struct. The time in getApprovalConditions is the deadline, expressed as a block.timestamp value, until which approve-type functions can be called. getNumberOfTransfersAllowed reports the number of transfers remaining for the spender, and isSecureWallet reports whether an account is a secure account. When an account newly becomes a holder, an Ingress event is emitted, and when it sends its entire balance and stops being a holder, an Egress event is emitted. For reference, the original Test Cases record the average gas usage per function (addBindings 154,991, among others).

Things to watch out for

Original ERC · ← ERCs