-
Notifications
You must be signed in to change notification settings - Fork 34
EIP-0031 - Babel Fees #54
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 all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
ad20164
EIP-0028 - Babel Fees
nitram147 446955c
Fixed accidently commited old version of eip-0028.md file
nitram147 93dc555
Changed EIP name from EIP-0028 to EIP-0031
nitram147 718e4cd
add requested changes
arobsn d0c4b62
Merge branch 'master' into eip28
arobsn 7332f82
update index
arobsn ee86d5f
fix contract
arobsn 349b5d5
add contract template subsection and link ref implementations
arobsn af56cc7
Merge branch 'master' into eip28
arobsn 6fb3449
fix titles capitalization
arobsn 81edece
add description
arobsn 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
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,162 @@ | ||
| Babel Fees | ||
| ============================================ | ||
|
|
||
| * Author: nitram147, lucagdangelo, anon-br | ||
| * Status: Proposed | ||
| * Created: 25-January-2022 | ||
| * Last edited: 03-November-2022 | ||
| * License: CC0 | ||
| * Forking: not needed | ||
|
|
||
| Introduction | ||
| -------------------------------------------- | ||
|
|
||
| The term “babel fees“ refers to the concept of paying transaction fees in tokens (fe. stablecoins) instead of platform’s primary token (ERG). For more information about the origin of the term and concepts behind “babel fees“, please see the following articles: | ||
| * [Babel fees - denominating transaction costs in native tokens](https://iohk.io/en/blog/posts/2021/02/25/babel-fees/) | ||
| * [Paying fee in ErgoMix in primary tokens](https://www.ergoforum.org/t/paying-fee-in-ergomix-in-primary-tokens/73) | ||
|
|
||
| EIP-0031 aims to provide the standard for paying fees in tokens, and thus has the same goal as Cardano’s “babel fees“, however, it chooses a different approach, with the main difference being that EIP-0031 does not require any type of forking. | ||
|
|
||
| With the Cardano’s approach, user publishes “invalid"(incomplete) transaction and has to wait, hoping that somebody will take his tokens and pay the transaction fees in a primary token (ADA), therefore completing the transaction. EIP-0031, on the other hand, chooses the opposite approach. | ||
|
|
||
| Supporters who wish to make money out of EIP-0031 will publish UTXOs, containing primary tokens locked by smartcontract. These will contain price attribute (i.e. how much of the primary tokens is that one specific supporter willing to pay for one piece of user’s tokens (fe. stablecoins)). Let’s call this user’s token a “babel token”. | ||
|
|
||
| User who is willing to pay the transaction fee in babel tokens can now find whether there exist any UTXOs belonging to the P2S address specified by the corresponding smartcontract for that specific babel token. If there is any UTXO which contains enough primary tokens for required fees, the user can calculate the price of buying the required amount of primary tokens from this UTXO and then decide whether or not he wishes to use it. In case he accepts this exchange ratio (defined by the UTXO’s price attribute), he can consequently spend this UTXO in his transaction to cover the transaction fees. This spending user now has to recreate the UTXO with the same parameters and insert the required amount of babel tokens into it (primary tokens difference should be less or equal to inserted babel tokens amount times price), which is going to be ensured by the smartcontract. | ||
|
|
||
| Strong advantage of this approach (compared to Cardano’s one) is that user always knows in advance whether there is an opportunity to pay via “babel fees” or not, and if there is, what is the exchange ratio. He can therefore be (almost) certain that if he decides to use it, his transaction will be included in the blockchain ledger. Be aware, however, that there exist some exceptions to this rule, which is later discussed in the “Wallets implementation” section. | ||
|
|
||
| Motivation | ||
| -------------------------------------------- | ||
|
|
||
| Many users use blockchain solely for transferring (native)tokens, such as stablecoins, or even “meme” coins. These users, understandably, do not want to be bothered with keeping an eye on the amount of blockchain’s primary token they own, or even obtaining this primary token in the first place. | ||
|
|
||
| Once they run out of primary token, they have to difficultly (and often costly), swap their tokens of interest for the primary tokens, that they can later use to cover transaction fees. Since primary tokens are also needed for these swaps, users may be forced to introduce new capital to their portfolio solely for the purpose of purchasing primary tokens, used for fee paying. | ||
|
|
||
| Since basic transactional fees on the Ergo blockchain are generally quite low, the "babel fees" users would be probaby willing to pay a fee that could be higher than that of a primary token transaction, in exchange for being able to pay in their token of interest and not having to bother with the blockchain’s primary token purchase. | ||
|
|
||
| This brings up a financial incentive for “EIP-0031 supporters”, who could benefit out of this arbitrage by providing the liquidity for such “babel fees” users, with primary token’s selling price (expressed in tokens of interest) being higher compared to the same token pair on the exchanges. | ||
|
|
||
| Smartcontract specification | ||
| -------------------------------------------- | ||
| Here is the smartcontract's source code in ErgoScript which will be used to protect the babel fee box: | ||
| ```scala | ||
| { | ||
|
|
||
| // ===== Contract Information ===== // | ||
| // Name: EIP-0031 Babel Fees Contract | ||
| // Description: Contract guarding the babel fee box, checking if valid output babel box was recreated and the token exchange was valid. | ||
| // Version: 1.0.0 | ||
|
|
||
| // ===== Relevant Variables ===== // | ||
| val babelFeeBoxCreator: SigmaProp = SELF.R4[SigmaProp].get | ||
| val ergPricePerToken: Long = SELF.R5[Long].get | ||
| val tokenId: Coll[Byte] = _tokenId | ||
| val recreatedBabelBoxIndex: Option[Int] = getVar[Int](0) | ||
|
|
||
| // ===== Perform Babel Fee Swap ===== // | ||
| if (recreatedBabelBoxIndex.isDefined) { | ||
|
|
||
| // Check conditions for a valid babel fee swap | ||
| val validBabelFeeSwap: Boolean = { | ||
|
|
||
| // Output babel fee box | ||
| val recreatedBabelBox: Box = OUTPUTS(recreatedBabelBoxIndex.get) | ||
|
|
||
| // Check that the babel fee box is recreated correctly | ||
| val validBabelFeeBoxRecreation: Boolean = { | ||
|
|
||
| allOf(Coll( | ||
| (recreatedBabelBox.propositionBytes == SELF.propositionBytes), | ||
| (recreatedBabelBox.tokens(0)._1 == tokenId), | ||
| (recreatedBabelBox.R4[SigmaProp].get == babelFeeBoxCreator), | ||
| (recreatedBabelBox.R5[Long].get == ergPricePerToken), | ||
| (recreatedBabelBox.R6[Coll[Byte]].get == SELF.id) | ||
| )) | ||
|
|
||
| } | ||
|
|
||
| // Check that the user's token was exchanged correctly | ||
| val validBabelFeeExchange: Boolean = { | ||
|
|
||
| val nanoErgsDifference: Long = SELF.value - recreatedBabelBox.value | ||
| val babelTokensBefore: Long = if (SELF.tokens.size > 0) SELF.tokens(0)._2 else 0L | ||
| val babelTokensDifference: Long = recreatedBabelBox.tokens(0)._2 - babelTokensBefore | ||
|
|
||
| allOf(Coll( | ||
| (babelTokensDifference * ergPricePerToken >= nanoErgsDifference), | ||
| (nanoErgsDifference >= 0) | ||
| )) | ||
|
|
||
| } | ||
|
|
||
| allOf(Coll( | ||
| validBabelFeeBoxRecreation, | ||
| validBabelFeeExchange | ||
| )) | ||
|
|
||
| } | ||
|
|
||
| sigmaProp(validBabelFeeSwap) | ||
|
|
||
| } else { | ||
|
|
||
| // ===== Perform Babel Fee Box Withdrawl ===== // | ||
| babelFeeBoxCreator | ||
|
|
||
| } | ||
|
|
||
| } | ||
| ``` | ||
|
|
||
| ### Contract template | ||
| Compilation of babel fee box smartcontracts for different tokens of interest will result in different P2S addresses, leading to each token having a unique corresponding ErgoTree and consequently a unique P2S babel fee box smartcontract address. To avoid having to rebuild the contract for each token, the implementer can use the following contract template, where the `{tokenId}` fragment must be replaced by the hexadecimal identifier of the token of interest. | ||
|
|
||
| ``` | ||
| 100604000e20{tokenId}0400040005000500d803d601e30004d602e4c6a70408d603e4c6a7050595e67201d804d604b2a5e4720100d605b2db63087204730000d606db6308a7d60799c1a7c17204d1968302019683050193c27204c2a7938c720501730193e4c672040408720293e4c672040505720393e4c67204060ec5a796830201929c998c7205029591b1720673028cb272067303000273047203720792720773057202 | ||
| ``` | ||
|
|
||
| ### Output position | ||
|
|
||
| The position of the recreated Babel Box in transaction's outputs must be set as a context extension variable in the spending Babel Box. | ||
|
|
||
| 1. Context variable `0`: | ||
| * Type: `SInt` | ||
| * Value: position of the recreated Babel Box in transaction's outputs | ||
|
|
||
| ### Parameters | ||
| Parameters (creator’s public key and price) are specified via registers, meaning the resulting babel fee boxes from different creators will always belong to the same P2S address, which will improve their searchability. | ||
|
|
||
| 1. Register `R4`: | ||
| * Type: `SigmaProp` | ||
| * Value: creator's public key | ||
| 2. Register `R5`: | ||
| * Type: `SLong` | ||
| * Value: how much nanoErgs is the creator willing to pay for one babel token | ||
| 3. Register `R6`: | ||
| * Type: `SColl[Byte]` | ||
| * Value: id of the Babel Box being spent by this | ||
| * Only required for recreated boxes | ||
|
|
||
| Babel fee box creator is able to spent the babel box in any circumstances. | ||
|
|
||
| Other users on the other hand can spend this box as input to their transaction only when they also recreate it as output of their transaction with the very same `R4` and `R5` registers values together with `R6` as described above and insertion of a required amount of babel tokens (the amount of inserted babel tokens multiplied by the price specified in the R5 register has to be equal to or bigger than the amount of nanoErgs spent from the babel fee box). | ||
|
|
||
| Wallets implementation | ||
| -------------------------------------------- | ||
|
|
||
| Wallet developers will need to decide whether they want to support EIP-0031 or not. If they do decide to support this standard, they should also decide on which tokens they want to support (this could be done based on user requirements – e.g. implementing big stablecoins or “meme” coins, etc.), as this could be more convenient than supporting all tokens. | ||
|
|
||
| As P2S addresses belonging to specific token of interest stay the same, these addresses could be easily “hardcoded” when supporting only a few tokens. If the developers decide to support any token, the previously mentioned smartcontract for each token which user holds should be compiled or "mounted" as described on ["Contract template"](#contract-template) subsection and the availability of Babel Fee boxes (UTXOs) for the specific tokens of interest in the blockchain should be subsequently checked. | ||
|
|
||
| The proposed babel fee smartcontract is quite general and does not impose much restriction for the transaction. It is therefore possible to transact some tokens while paying babel fees with another tokens, etc. | ||
|
|
||
| Once the wallet finds a babel fee box which could be used to pay required transaction fees, it should calculate the required price for the transaction fee and present it to the user, so he can decide on using this particular option or not. | ||
|
|
||
| The wallet should also check current mempool and determine whether there exists someone who is currently trying to spend this specific babel fee box. In that case, the wallet should construct “chained” transaction (using the mempool’s transaction output (recreated babel fee output) as the new babel fee box input). This way, many transactions spending “the same” box could be chained and mined inside a single block. There can also occur a situation when the babel fee box owner is trying to spend his own box. In that case, the wallet should select another babel fee box, if available. | ||
|
|
||
| Once the wallet successfully crafts and relays the transaction to the mempool, it MUST keep an eye on the transaction until it is mined. This is important because the wallet cannot prevent somebody else from trying to spend the exact same babel fee box as our user’s transaction is trying to spend. When there are two transactions trying to spend the same box, only one from them can be mined and therefore included in the blockchain, while the other one has to be recrafted with the new babel fee box and relayed again to the network. Such thing should occur rarely, but when it does, the wallet has to be able to handle the situation correctly while notifying the user that the transaction did not go through. | ||
|
|
||
| Reference implementations | ||
| -------------------------------------------- | ||
| * [Nautilus Wallet implementation](https://github.com/capt-nemo429/nautilus-wallet/pull/82) | ||
| * [AppKit implementation](https://github.com/ergoplatform/ergo-appkit/pull/204) | ||
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to enforce that the erg swapped from the babel box should be sent to a miner?
I can see a scenario were the price of a certain token spikes above the rate settled on
R5, and anyone can make use of babel boxes for arbitrage. I don't know if this is something desired.PS: I'm on my first steps on ErgoScript so It's almost certain that I'm missing something. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's ok. Babel fee box is in reality just an order book order to sell ERG in exchange for specified tokens at specified price. The babel fee box creator doesn't care about how these ERGs are spent - he earned revenue by selling these ERGs for a higher price than the ordinary market price (see text about financial incentives in this EIP). It's fully up to him to monitor whether he still wants to sell ERGs for the price specified in the R5, in case he no longer wants doing so, he can withdraw all funds from his babel fee box (and recreate it with new price in R5 in case he just wanted to update the price).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There can be coded offchain bots which will monitor current market price for some token and always recreate babel fee box with price equal to market price times some constant (in case that it would be worth spending ERG to pay fees for box recreation).