Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ Please check out existing EIPs, such as [EIP-1](eip-0001.md), to understand the
| [EIP-0027](eip-0027.md) | Emission Retargeting Soft-Fork |
| [EIP-0031](eip-0031.md) | Babel Fees |
| [EIP-0034](eip-0034.md) | NFT Collection Standard |
| [EIP-0039](eip-0039.md) | Monotonic box creation height rule |
| [EIP-0039](eip-0039.md) | Monotonic box creation height rule |
| [EIP-0045](eip-0045.md) | Redistribution Smart Contract for claimed Storage Fees |
114 changes: 114 additions & 0 deletions eip-0045.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
Redistribution Smart Contract for claimed Storage Fees
======================================================

* Author: Huginn
* Status: Proposed
* Created: 06-Mar-2023
* License: CC0
* Forking: Soft-fork

Motivation
----------

The long-term security of the Ergo protocol should be prioritized and should try to avoid any potential vulnerabilities. One such can occur from claiming storage fees from boxes, that are subject to such claims. Resulting from fact if block rewards are no longer present, or negligible, compared to the claim from storage fees, mining a block claiming multiple storage fees might be subject to so called **undercutting attack** introduced in [[1]](#references). This happens when certain block has much higher reward compared to other blocks and therefore miners might be tempted to remine it to claim the reward for themselves instead of the original miner.

To circumvent such problem we introduce a Smart Contract, where the storage fees should be send and then this Smart Contract will redistribute the rewards across a span of selected blocks (for example 720 blocks, i.e. 1 day). Providing a reward from claiming storage fees to multiple blocks not only the one it was claimed in. A ratio of M to C can be used, where a miner can claim M of the storage fees and has to send C ratio to the Smart Contract. However we argue the ratio should be much smaller in favor of M as claiming storage fee is not very predictable and repeatable as claiming transaction fees, refer to [section](#previous-considerations).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To circumvent such problem we introduce a Smart Contract, where the storage fees should be send and then this Smart Contract will redistribute the rewards across a span of selected blocks (for example 720 blocks, i.e. 1 day). Providing a reward from claiming storage fees to multiple blocks not only the one it was claimed in. A ratio of M to C can be used, where a miner can claim M of the storage fees and has to send C ratio to the Smart Contract. However we argue the ratio should be much smaller in favor of M as claiming storage fee is not very predictable and repeatable as claiming transaction fees, refer to [section](#previous-considerations).
To circumvent such problem we introduce a Smart Contract, where the storage fees should be sent and then this Smart Contract will redistribute the rewards across a span of selected blocks (for example 720 blocks, i.e. 1 day). Providing a reward from claiming storage fees to multiple blocks not only the one it was claimed in. A ratio of M to C can be used, where a miner can claim M of the storage fees and has to send C ratio to the Smart Contract. However we argue the ratio should be much smaller in favor of M as claiming storage fee is not very predictable and repeatable as claiming transaction fees, refer to [section](#previous-considerations).


Redistribution Contracts
------------------------

As described with more detail in [[2]](#references) a smart contract would implement simple logic of one or more redistribution contract. Each such contract would be a tuple of (value, length, ratio), where:

* value - collected Ergs in this contract
* length - across which we target to redistribute the value
* ratio - how much of collected fees does this contract receive

and such contract would pay to the miner reward equal to (value / length). We can have multiple such contracts with different values of parameters however the total sum of all ratios must be always equal to 1 (100%). A miner, who collects the storage rent fees, sends all fees to the Smart Contract implementing this logic. This Smart Contract would then redistribute the collected storage fees.

A trait of such contract with small testing demo can be explored on the following Ergo playground [link](https://scastie.scala-lang.org/RHIwF2hwTjSJLKmRLiXKpA) but with misbehaving proper increasing blockchain height for created transaction the `heightIncreased` variable is not used in final `SigmaProp` as it evaluates always to false (height remains 0 for every created transaction and constructor for defining height of transaction is missing in Ergo playground).<br>
Please note this is just for demonstration purposes.

Code snippet of Smart Contract in ErgoScript:
```scala
val contractOut = OUTPUTS(0)

// nft identifier is preserved
val correctNftOut = contractOut.tokens(0)._1 == redistributionNft

// created for current height
val heightCorrect = contractOut.creationInfo._1 == HEIGHT

// box spendable only once per block
val heightIncreased = HEIGHT > SELF.creationInfo._1

// script is preserved
val correctProposition = contractOut.propositionBytes == SELF.propositionBytes

// we can optionally lock miner's reward

val outTxValue = OUTPUTS(1).value
val minerReward = outTxValue - contractOut.value

val values = SELF.R4[Coll[Long]].get
val indices = values.indices

val newValues = contractOut.R4[Coll[Long]].get

val claimableReward = indices.fold(0L, { (sum: Long, i: Int) => sum + values(i) / params(i)._1 })

val correctMinerClaim = minerReward <= claimableReward

// this should always be positive
val collectedFees = contractOut.value - (SELF.value - minerReward)

val correctValues = allOf(Coll({
indices.forall({ (i: Int) => ({
// optionally we can calculate from what miner actually claimed if he does not pay txFee
// (minerReward * params(i)._2) / 100
val partialClaim = (values(i) / params(i)._1)
// we calculate what will be added to contract
val addedValue = (collectedFees * params(i)._2) / 100

newValues(i) >= values(i) - partialClaim + addedValue
})
})
}))

sigmaProp(
allOf(
Coll(
correctNftOut,
heightCorrect,
heightIncreased,
correctProposition,
correctMinerClaim,
correctValues
)
)
)
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@The-Huginn, please explictily describe the box which should be protected by this contract and if it has additional registers.


Previous Considerations
-----------------------

Such idea was firstly discussed to be subject for transaction fees, which we describe into more details in [[2]](#references), where the fees would be split between miner and one or multiple Redistribution Contracts. However after a brief discussion on Bitcoin-dev mailing list we were introduced to so called "out-of-band" fees, i.e. paying fees outside the protocol. Even though this is not widely adopted, our proposed solution would lead to higher utilization of "out-of-band" fee usage and therefore to higher centralization as "out-of-band" fees are resulting in. However we argue this is not subject to storage fee claims, as the miner would not be able to benefit from notifying user of incoming storage fee claim of user's address and try utilize means outside the protocol. Nor would he be able to easily identify such user, only perhaps via a wallet provider.

Ephemeral Considerations
------------------------

Considerations accumulated for discussion. Should be removed before being merged.

The parameters of contracts could be not baked directly into the contract as parameters (values) but rather saved in registers. The contracts' script would need to be updated as well to ensure these values are not changed. However with this we would allow to change these parameters, only when voting took place, and will allow to update this contract. However not much thought was done here, whether it is possible. The header voting info could be used for this but new EIP would be needed to unify such option.

Further more not related to proposal, however miners might collectively try to ignore transaction, which spends box soon-to-be subject of storage fee claim, in order to have a change of this claim.

Kudos
-----

Thanks to kushti for initial conversation about this problem!

References
----------

1. [Carlsten, Miles, et al. **"On the instability of bitcoin without the block reward."** Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security. 2016.](https://www.cs.princeton.edu/~arvindn/publications/mining_CCS.pdf)
2. [Budinský, Rastislav, Ivan Homoliak, and Ivana Stančíková. **"Fee-Redistribution Smart Contracts for Transaction-Fee-Based Regime of Blockchains with the Longest Chain Rule"** arXiv preprint arXiv:2302.04910 (2023).](https://arxiv.org/abs/2302.04910)