Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERC-1843 - Claims Token Standard #1843

Closed
jo-tud opened this issue Mar 13, 2019 · 13 comments
Closed

ERC-1843 - Claims Token Standard #1843

jo-tud opened this issue Mar 13, 2019 · 13 comments
Labels

Comments

@jo-tud
Copy link

jo-tud commented Mar 13, 2019


eip: ERC-1843
title: Claims Token Standard
author: Johannes Pfeffer (@jo-tud), Johannes Escherich (@jo-es)
discussions-to: #1843
status: Deprecated
type: Standards Track
category: ERC
created: 2019-03-13
requires: ERC-20 (#20), ERC-223 (#223)
superseded by: ERC-2222 (#2222 )


Simple Summary

A standard for a token that represents claims on future cash flow of an asset such as dividends, loan repayments, fee or revenue shares among large numbers of token holders. Anyone can deposit funds, token holders can withdraw their claims.

  • Very simple interface
  • ERC-20 backwards compatible
  • Supports funds in Ether or in ERC223 compatible tokens
  • Efficient handling of fractional ownership of cash-flow claims
  • Correctly distributes cash flow honoring all token transfers
  • Scales well to many token holders and frequent transfers

Abstract

The Claims Token

This standard proposes an efficient solution for distributing recurring payments such as dividends, loan repayments, fee or revenue shares among large numbers of token holders. The token holders are seen as fractional owners of future cash flow. The payments can be in Ether or ERC20 tokens and are stored in the token's "fund". Holders of a claims token can transfer their tokens at any time and can still be sure that their past claims to the cash flow of the token will be honored. The interface provides methods to deposit funds to be distributed, to get information about available funds and to withdraw funds a token holder is entitled to.

This standard can handle funds in Ether or in ERC223 compatible tokens.

This standard is backwards compatible with ERC20 (#20) and can easily be extended to be compatible with ERC-1400 (#1411) security token standards.

Motivation

In the DeFi and OpenFinance ecosystem assets such as debt positions, loans, derivatives and bonds are emerging. These assets incur future cash flows, e.g. repayments or dividends. Currently there is no standard for efficiently distributing claims on future cash flow of financial contracts among token holders. A clear and simple standard is needed to allow Dapps and exchanges to work with cash-flow producing tokens.

Rationale

Sending cash flow to a large group of token holders whenever it is received is limited by gas consumption. Thus, a solution must be used in which token holders actively withdraw the cumulative funds that they have a claim on. A token holder must be able to withdraw funds she has a claim on at any time. It must also be possible to transfer tokens at any time and the already accrued claims must still be honored. This requires some background accounting to be done in the transfer functions. The claims token standard solves this elegantly.

Example: A bond is represented by 100 tokens. Alice owns all 100 of these tokens and Bob own zero. The bond yields 10 Ether. Alice has a claim on 100% of that cash flow because when the 10 Ether were received she owned all the tokens. She decides to not withdraw the tokens but wait until more has accumulated.

Now Alice sends 50 tokens to Bob. Shortly after the bond yield another 10 Ether. Now Alice has is entitled to 15 Ether and Bob to 5 Ether. The ownership history is honored and Alice doesn't need to withdraw before she transfers the tokens.

Requirements

Requirements a claims token should fulfill

Executing tokenized financial contracts on a public ledger requires standards for distribution of cash flow incurred by the asset. In discussions with issuers the following requirements have been collected.

  • Token MUST be ERC-20 compatible
  • MUST be support claims in tokens or Ether
  • MUST support a large number of token holders that hold claims on an assets cash flow
  • MUST support efficient withdrawal of available funds
  • MUST support efficient addition of funds to be distributed
  • clients/token holders MUST be able to observe new deposits to the fund

Requirements to observe when using the standard

The following requirements MUST be met in order to use the claims token standard.

  • The extended token MUST be ERC-20 compatible
  • The token in which funds are deposited MUST be specified before the first deposit.
  • The extended token MUST have a fixed total supply. After the first token transfer the total supply MUST NOT be changed.
  • IF the funds are payed in ERC20 tokens (and not in Ether), this token MUST comply to ERC223

Specification

Methods

default function

Anyone can send Ether or tokens to be distributed among token holders. The default/fallback function behaves differently if Ether or tokens are sent to the contract.

In case of funds in Ether any Ether sent to the contract will be added to the fund by the default function.

In case of funds in ERC20/223 tokens the token that is registered will be added to the fund by the default function when it's sent to the contract.

totalReceivedFunds

The monotonously rising cumulative sum of funds received since the creation of the token. This number is the amount that the contract has had available for distribution so far.

totalReceivedFunds() external view returns (uint256);

availableFunds

Returns the amount of funds that can be withdrawn by a current or former token holder given as the _address parameter.

availableFunds(address _address) external view returns (uint256);

withdrawFunds

Withdraws the funds the message sender is entitled to at the time of execution of the function.

function withdrawFunds() external payable;

fundsToken

A field that stores a reference to the token used for the funds. In case of funds in Ether, the field must be set to 0x0.

Events

FundsReceived

Emits when funds (Ether or tokens) are sent to the token contract's default/fallback function.

event FundsReceived(address indexed from, uint256 fundsReceived);

FundsWithdrawn

Emits when a token holder claims funds from the token contract.

event FundsWithdrawn(address indexed by, uint256 fundsWithdrawn);

Interface

/// @title IERCxxxx Claims Token Standard
/// @dev See https://github.com/atpar/claims-token

interface IClaimsToken {
	
	/**
	 * @dev This event emits when funds to be deposited are sent to the token contract
	 * @param from contains the address of the sender of the received funds
	 * @param fundsReceived contains the amount of funds received for distribution
	 */
	event FundsReceived(address indexed from, uint256 fundsReceived);
	
	/**
	 * @dev This event emits when distributed funds are withdrawn by a token holder.
	 * @param by contains the address of the receiver of funds
	 * @param fundsWithdrawn contains the amount of funds that were withdrawn
	 */
	event FundsWithdrawn(address indexed by, uint256 fundsWithdrawn);
	
	/**
	 * @dev Withdraws available funds for user.
	 */
	function withdrawFunds() external payable;

	/**
	 * @dev Returns the amount of funds a given address is able to withdraw currently.
	 * @param _forAddress Address of ClaimsToken holder
	 * @return A uint256 representing the available funds for a given account
	 */
	function availableFunds(address _forAddress) external view returns (uint256);

	/**
	 * @dev Get cumulative funds received by ClaimsToken.
	 * @return A uint256 representing the cumulative funds received
	 */
	function totalReceivedFunds() external view returns (uint256);
}

Implementation

The reference implementation consists of the accounting contract and two specializations. The first is for funds denoted in Ether and the second is for funds denoted in ERC20/ERC223 compatible tokens.

The claims token is realized by implementing the transfer functions to do the necessary accounting on two additional mappings (processedFunds & claimedFunds). A uint256 is introduced to track the total amount of funds sent to the token contract (receivedFunds).

Calculation of the available funds

The high efficiency of the solution is achieved by tracking 2 values for each token holder: claimedFunds and processedFunds. By updating these at transfer events and postponing calculation of available funds to withdrawal time, this implementation achieves very low gas cost for both transfers and withdrawals.

Terms:
balance_A -> Balance of token owner A
claimedFunds_A -> Amount of funds owned by A that is already claimed
receivedFunds -> Total cumulative sum of funds received for distribution (monotonously rising)
processedFunds_A-> This value tracks the amount of funds for which a user has already claimed their portion of the cash flow
unprocessedFunds_A -> Represents the amount of funds for which a user holds a claim but that were not yet processed
ownershipFraction_A -> Percentage of cash-flow that can be claimed by A
totalSupply-> Total and immutable amount of minted tokens
availableFunds_A -> The amount of funds token holder A can withdraw

Calculations:
The ownership fraction is the balance relative to the total supply.
ownershipFraction_A = balance_A/totalSupply

The available funds are calculated as the sum of the unprocessed funds and the claimed funds. Unprocessed funds are calculated by multiplying the ownership fraction with the difference between the total received funds and the fund that have already been considered for a user (processedFunds)

unprocessedFunds_A = ownershipFraction_A * (receivedFunds-processedFunds_A)
availableFunds_A = unprocessedFunds_A + claimedFunds_A

Example

Total supply: 100 tokens
Initial distribution: Alice owns 100 tokens and Bob owns 0 tokens. 0 funds received.

Step balance Alice balance Bob funds available Alice funds available Bob funds received event
0 100 0 0 0 0 token creation
1 100 0 20 0 20 20 Ether sent to the contract
2   75       25        20               0               20             Alice has sent 25 tokens to Bob
3   75       25        35               5               40             20 Ether sent to the contract
4   75       25        0               5               40             Alice withdraws her funds
5   75       25        12               9               56             16 Ether sent to the contract
6   50       50        12               9               56             Alice has sent 25 tokens to Bob
7   50       50        16               13               64             8 Ether sent to the contract
8   50       0         16               13               64             Bob has sent 50 tokens to X

The Claims Token accounting system works in the background to take care of the fact that Alice's claims fraction changes and Bob sends his tokens away before withdrawing his available funds.

Backwards Compatibility

The standard is backwards compatible with ERC20 tokens.

Copyright

Public domain via CC0

Attribution

The idea for the implementation of the claims token goes back to work originally done by @Georgi87, @ethers, @miladmostavi and @popra and was used in the Tokit SingularDTVFund contracts.

@jo-tud jo-tud changed the title ERC-xxxx - Claims Token Standard ERC-1843 - Claims Token Standard Mar 13, 2019
@jo-tud
Copy link
Author

jo-tud commented Mar 13, 2019

Maybe merge #1726 and this. @Roger-Wu

@fulldecent
Copy link
Contributor

totalReceivedFunds can overflow if you deposit tokens, withdraw, and then deposit them back in

@jo-tud
Copy link
Author

jo-tud commented Mar 14, 2019

totalReceivedFunds can overflow if you deposit tokens, withdraw, and then deposit them back in

Yes, theoretically that is a potential problem. However it is limited by the economics of an attack:

costFactorPerAttackCycle >= 1-fractionOwnedByAttacker

  • In case of Ether, overflowing totalReceivedFunds is economically only possible if the attacker is the only token holder. If there are one or more independent parties holding tokens, each round incurs a cost relative to the percentage of tokens held.
  • In case of a token, generally the same applies. But the token could have a very high total supply and be available at a much lower cost - thus making the overflow more viable.

@rudolfix
Copy link

why do you add this to token itself instead of using snapshots from MiniMe token (that btw. are used extensively in AragonOs apps) and implementing separate, specialized disbursal contract? claiming token is an app on the snapshot/MiniMe token protocol and 90% of the code to implement it, would be token snapshot re-implementation.

@jo-tud
Copy link
Author

jo-tud commented Mar 20, 2019

why do you add this to token itself instead of using snapshots from MiniMe token

The MiniMe token is great, no question! It can probably be used to create an alternative implementation for the proposed interface. However, I see the snapshots as an unnecessary overhead for the core functionality of claims distribution. The elegance in our reference implementation lies in the fact that the balance history doesn't have to be recorded explicitly and it is still possible to correctly distribute payments to token holders. The consequence is that payments are free and transfers and payouts are very cheap, allowing for scaling to high frequency payments and large amounts of transfers.

The Claims Token is specifically designed to be integrated into the ERC1400 and similar modular frameworks. It adds a very well defined & limited functionality to Tokens derived from e.g. the OpenZeppelin reference implementations. Happy to discuss this further.

@Roger-Wu
Copy link

Is it possible to mint/burn tokens and keep the available funds unchanged in your implementation?

@jo-tud
Copy link
Author

jo-tud commented Mar 29, 2019

Is it possible to mint/burn tokens and keep the available funds unchanged in your implementation?

No, in the provided reference implementation this is not possible, it needs a fixed total supply (see requirements).

@nbundi
Copy link

nbundi commented Apr 26, 2019

@Roger-Wu this is a good point. in the financial context minting/burning is an interesting feature directly related to corporate actions such as stock splits for example.

@jo-tud
Copy link
Author

jo-tud commented May 2, 2019

@Roger-Wu We're currently working on a merge between our approaches. It uses the implementation of #1726 but the terminology of this EIP #1843 (avoiding the term Dividend). We also integrated our solution for claims paid in Tokens, so now ERC20 token payments can be distributed. Let's have a conversation with on the past path to converge. I'll ping you via mail.

@frozeman
Copy link
Contributor

In light of #777 you should think about how you can support that standard, as it will play a more significant role in the near future.

@jo-es
Copy link

jo-es commented May 29, 2019

We have that on our roadmap. Through the ClaimsToken extension architecture it's straightforward to support ERC777 and future token standards.

@github-actions
Copy link

There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review.

@github-actions github-actions bot added the stale label Nov 20, 2021
@github-actions
Copy link

github-actions bot commented Dec 4, 2021

This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment.

@github-actions github-actions bot closed this as completed Dec 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants