-
Notifications
You must be signed in to change notification settings - Fork 828
Add ERC: Fractional Reserve Token #644
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
Merged
Merged
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
e8d8bce
Fractional Reserve Token Standard
yaronvel bc5fa6f
change file name
yaronvel ddce8c8
change file name to erc-7761
yaronvel 5afc4b2
ERC20 as required
yaronvel 5c6ab9d
CI Fixes
yaronvel e504229
fix more CI comments
yaronvel e139c0b
change eip number to 7770
yaronvel 2efe3ab
update link to ethereum magicians
yaronvel 52c4cf5
change file name to erc-7770.md
yaronvel ece4dd3
Update ERCS/erc-7770.md
yaronvel 43fd958
Update ERCS/erc-7770.md
yaronvel 78ec688
Update erc-7770.md description
yaronvel 626d263
economical => economic
yaronvel a226c2f
remove proposed
yaronvel 8a1d46b
more reserve ratio explenation from spec to rationale
yaronvel 1b3b81b
Update erc-7770.md
yaronvel aa540de
Merge branch 'master' into master
yaronvel ce1f95b
Update erc-7770.md
SamWilsn 3720207
Update erc-7770.md
yaronvel cec3965
Update erc-7770.md
SamWilsn cc25be2
Update erc-7770.md
SamWilsn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| --- | ||
| eip: 7761 | ||
| title: Fractional Reserve Token | ||
| description: An interface for fractional reserve tokens. | ||
| author: Yaron Velner (@yaronvel) | ||
| discussions-to: https://ethereum-magicians.org/t/fractional-reserve-token-standard/21103 | ||
yaronvel marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| status: Draft | ||
| type: Standards Track | ||
| category: ERC | ||
| created: 2024-09-17 | ||
| requires: 20 | ||
| --- | ||
|
|
||
|
|
||
| ## Abstract | ||
| We propose a new token standard for synthetic assets that are only partially redeemable to their underlying asset, but fully backed by other collateral assets. | ||
|
|
||
| The standard defines an interface to mint fractional reserve assets, and a standard to reflect economical risk related data to the token holders and lenders. | ||
|
|
||
| ## Motivation | ||
| The Cambrian explosion of new L1s and L2s gave rise to bridged assets which are synthetic by nature. Indeed, ETH on Arbitrum L2, or WETH on Binance Smart Chain are not fully fungible with their mainnet counterpart. However, these assets are fully backed by their mainnet counterpart and guaranteed to be redeemable to their mainnet underlying asset, albeit with certain time delay. | ||
|
|
||
| Fractional reserve tokens can allow an ecosystem (chains, L2s, and other networks of economic activity) to increase its supply by allowing users to mint the asset not only by bridging it to the ecosystem, but also by borrowing it (typically against a collateral). | ||
|
|
||
| As an example, consider a fractional reserve token, namely, frDAI, that represents a synthetic DAI. | ||
| Such token will allow users to mint 1 frDAI upon deposit of 1 DAI, or by providing a collateral that worth more than 1 DAI. | ||
| Quick redemption of frDAI to DAI is available as long as there is still some DAI balance in the frDAI token, and otherwise, the price of frDAI may temporarily fluctuate until borrowers repay their debt. | ||
|
|
||
| Fractional reserve tokens may delegate minting capabilities for multiple risk curators and lending markets. Hence, a uniform standard for fractional reserve minting is needed. | ||
| Fractional reserve banking does not come without risks, such as insolvency or a bank run. | ||
| This standard does not aim to dictate economic risk management practices, but rather to have a standard on how to reflect the risk to token holders. | ||
|
|
||
| ## Specification | ||
| The proposed standard has the following requirements: | ||
| * **MUST** be [ERC-20](../erc-20.md) compatible. | ||
| ### Interface | ||
| ``` | ||
| interface IERCXXX is IERC20 { | ||
| // events | ||
| event MintFractionalReserve(address indexed minter, address to, uint256 amount); | ||
| event BurnFractionalReserve(address indexed burner, address from, uint256 amount); | ||
| event SetSegregatedAccount(address account, bool segregated); | ||
|
|
||
| // functions | ||
| // setters | ||
| function fractionalReserveMint(address _to, uint256 _amount) external; | ||
| function fractionalReserveBurn(address _from, uint256 _amount) external; | ||
|
|
||
| // getters | ||
| function totalBorrowedSupply() external view returns (uint256); | ||
| function requiredReserveRatio() external view returns (uint256); | ||
| function segregatedAccount(address _account) external view returns (bool); | ||
| function totalSegregatedSupply() external view returns (uint256); | ||
| } | ||
| ``` | ||
| ### Reserve ratio | ||
| The reserve ratio reflects the ratio between the token that is available as cash, i.e., available for an immediate redemption (or alternatively, a token that was not minted via a fractional reserve minting), and the total supply of the token. Segregated accounts **MUST** be subtracted from the cash balance. | ||
| Lower reserve ratio gives rise to higher capital efficiency, however it increases the **likelihood** of depeg or a run on the bank, where token holders cannot immediately redeem their synthetic token. | ||
|
|
||
| Formally, the reserve ratio is denoted by $$\frac{totalSupply() - totalBorrowedSupply() - \sum_{a \in \text{Segregated Accounts}} \text{balanceOf}(a)}{totalSupply()}$$. | ||
| Additional fractional reserve minting **MUST NOT** occur when the reserve ratio, multiplied by `1e18` is lower than `requiredReserveRatio()`. | ||
|
|
||
| ### Mint and burn functionality | ||
| The `fractionalReserveMint` and `fractionalReserveBurn` functions **SHOULD** be called by permissioned addresses, e.g., risk curators or lending markets. These entities **SHOULD** mint new tokens only to addresses that already locked collateral in a dedicated contract. | ||
|
|
||
| The reserve ratio is denoted by $$\frac{totalSupply() - \sum_{a \in \text{Segregated Accounts}} \text{balanceOf}(a)}{totalSupply() + totalBorrowedSupply()}$$. | ||
| `fractionalReserveMint` **MUST** revert if the reserve ratio, multiplied by `e18` exceeds `requiredReserveRatio()`. | ||
|
|
||
| A successful call to `fractionalReserveMint(_to, _amount)` **MUST** increase the value of `totalSupply()`, `totalBorrowedSupply()`, and the token balance of address `_to`, by `_amount` units. | ||
| A call to `fractionalReserveMint` **MUST** emit a `MintFractionalReserve` event. | ||
| A call to `fractionalReserveMint` **MUST** revert if after the mint the reserve ratio, multiplied by `1e18` exceeds the value of `requiredReserveRatio()`. | ||
|
|
||
| Similarly, a successful call to `fractionalReserveBurn(_from, _amount)` **MUST** decrease the value of `totalSupply()`,`totalBorrowedSupply()`, and the token balance of address `_from` by `_amount` units. | ||
| A call to `fractionalReserveBurn` **MUST** emit a `BurnFractionalReserve` event. | ||
| ### Segregated accounts | ||
| Increasing the total supply could be a concern if a token is used for DAO votes and/or if dividends are distributed to token holders. | ||
| In order to mitigate such concerns, segregated accounts are introduced, with the premise that money in these accounts is not counted towards the reserve, and therefore, additional token supply cannot be minted against them. | ||
|
|
||
| At every point in time, it **MUST** hold that the sum of token balances for segregated addresses equals to `totalSegregatedSupply()`. | ||
|
|
||
| ### Account balance | ||
| The `fractionalReserveMint` **SHOULD** be used in conjunction with a lending operation, where the minted token is borrowed. The lending operation **SHOULD** come with an interest rate, and some of the interest rate proceedings **SHOULD** be distributed to token holders that are not in segregated accounts. | ||
| This standard does not dictate how distribution should occur. | ||
|
|
||
| ## Rationale | ||
| The proposed standard aims to standardise how multiple lending markets and risk providers can interact with a fractional reserve token. The actual lending operation should be done carefully by trusted entities, and it is the token owner's responsibility to make sure the parties who have fractional reserve minting credentials are reliable. | ||
|
|
||
| At the core of the coordination relies the need to understand how much additional supply is available for borrow, and at what interest rate. The additional borrowable supply is deduced from the required reserve ratio, and the total, borrowable and segregated supply. | ||
| The interest rate **SHOULD** be monotonically increasing with the current reserve ratio. | ||
|
|
||
| The standard does not dictate how the accrued interest rate is distributed. One possible distribution is by making the token a rebased token. An alternative way is to introduce staking, or just airdropping of proceeds. | ||
|
|
||
| While a fractional reserve is most useful when it is backed by a known asset, e.g., frDAI and DAI, it can also be used in isolation. In such a case, a token will have a fixed initial supply, however additional supply can be borrowed. In such cases the supply temporarily increases, but the net holdings (`totalSupply() - totalBorrowedSupply()`) remains unchanged. | ||
|
|
||
| ## Backwards Compatibility | ||
| Fractional reserve tokens should be backwards compatible with [ERC-20](../erc-20.md). | ||
|
|
||
| ## Reference Implementation | ||
| ``` | ||
| // The code below is provided only for illustration, DO NOT use it in production | ||
| contract FractionalReserveToken is ERC20, Ownable { | ||
|
|
||
| event MintFractionalReserve(address indexed minter, address to, uint256 amount); | ||
| event BurnFractionalReserve(address indexed burner, address from, uint256 amount); | ||
| event SetSegregatedAccount(address account, bool segregated); | ||
|
|
||
| /// @notice token supply in these accounts is not counted towards the reserve, and | ||
| /// therefore, additional token supply cannot be minted against them. | ||
| mapping(address => bool) public segregatedAccount; | ||
|
|
||
| /// @notice ratio between the token that is available as cash (immediate redemption) | ||
| /// and the total supply of the token. | ||
| uint256 public requiredReserveRatio; | ||
|
|
||
| uint256 public totalBorrowedSupply; | ||
|
|
||
| constructor( | ||
| string memory _name, | ||
| string memory _symbol | ||
| ) ERC20(_name, _symbol) Ownable(msg.sender) {} | ||
|
|
||
| function fractionalReserveMint(address to, uint256 amount) external onlyOwner { | ||
| _mint(to, amount); | ||
| totalBorrowedSupply += amount; | ||
| emit MintFractionalReserve(msg.sender, to, amount); | ||
|
|
||
| uint256 reserveRatio = (totalSupply() - totalBorrowedSupply - segregatedSupply) * 1e18 / totalSupply(); | ||
| require(reserveRatio >= requiredReserveRatio, "reserveRatio"); | ||
| } | ||
| function fractionalReserveBurn(address from, uint256 amount) external onlyOwner { | ||
| _burn(from, amount); | ||
| totalBorrowedSupply -= amount; | ||
| emit BurnFractionalReserve(msg.sender, from, amount); | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------------------ | ||
| // Code below is not part of the proposed standard | ||
| // ------------------------------------------------------------------------------ | ||
| uint256 internal segregatedSupply; // supply of segregated tokens | ||
|
|
||
| function _update(address from, address to, uint256 value) internal override { | ||
| // keep the reserve up to date on transfers | ||
| if (!segregatedAccount[from] && segregatedAccount[to]) { | ||
| segregatedSupply += value; | ||
| } | ||
| if (segregatedAccount[from] && !segregatedAccount[to]) { | ||
| segregatedSupply -= value; | ||
| } | ||
| ERC20._update(from, to, value); | ||
| } | ||
|
|
||
| function mint(address account, uint256 value) external onlyOwner { | ||
| _mint(account, value); | ||
| } | ||
|
|
||
| function burn(address account, uint256 value) external onlyOwner { | ||
| _burn(account, value); | ||
| } | ||
|
|
||
| function setSegregatedAccount(address account, bool segregated) external onlyOwner { | ||
| if (segregated) { | ||
| require(!segregatedAccount[account], "segregated"); | ||
| segregatedSupply += balanceOf(account); | ||
| } else { | ||
| require(segregatedAccount[account], "!segregated"); | ||
| segregatedSupply -= balanceOf(account); | ||
| } | ||
| segregatedAccount[account] = segregated; | ||
| emit SetSegregatedAccount(account, segregated); | ||
| } | ||
|
|
||
| function setRequiredReserveRatio(uint256 value) external onlyOwner { | ||
| requiredReserveRatio = value; | ||
| } | ||
| } | ||
| ``` | ||
| ## Security Considerations | ||
| Fractional reserve banking comes with many economic risks. This standard does not aim to provide guidelines on how to properly mitigate them. | ||
| ## Copyright | ||
| Copyright and related rights waived via [CC0](../LICENSE.md). | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.