mirror of
git://holbrook.no/erc20-demurrage-token
synced 2024-11-21 15:56:46 +01:00
Update readme for calculations and inputs
This commit is contained in:
parent
65a91cc44d
commit
f75472fcf5
94
README.md
94
README.md
@ -32,63 +32,75 @@
|
||||
|
||||
## Mint
|
||||
|
||||
* Owner can add minters and remove
|
||||
- A faucet contract would be a minter and choose the amount of tokens to mint and distribute to new _validated_ users.
|
||||
- The interface says the amount and is at the caller's discretion per contract call. _validation_ is outside of this contract.
|
||||
* A minter can remove itself
|
||||
* Minters can mint any amount
|
||||
* Minters are called writers. Contract owner can add and remove writers.
|
||||
* A writer can remove itself
|
||||
* The interface says the amount and is at the caller's discretion per contract call. _validation_ is outside of this contract.
|
||||
* Writers can mint any amount. If supply cap is set, minting will be limited to this cap.
|
||||
|
||||
|
||||
## Demurrage
|
||||
* Holding Tax (`demurrage`) is applied when a **mint** or **transfer**; (it can also be triggered explicitly)
|
||||
- Note that the token supply _stays the same_ but a virtual _balance output_ is created.
|
||||
- Updates `demurrageModifier` which represents the accumulated tax value and is an exponential decay step (of size `demurrage`) for each minute that has passed.
|
||||
- `demurrageModifier = (1-demurrage)^(minute_passed)`
|
||||
- e.g. a `demurrage` of 2% after the 1st minute would be give a `demurrageModifier = (1-0.02)^1 = 0.98`.
|
||||
- e.g. a `demurrage` after the 2nd minute would be give a `demurrageModifier = (1-0.02)^2 = 0.9604`.
|
||||
* All client-facing values (_balance output_ , _transfer inputs_) are adjusted with `demurrageModifier`.
|
||||
- e.g. `_balance output_ = user_balance - user_balance * demurrageModifier`
|
||||
## Input parameters
|
||||
|
||||
The redistrbution period is passed to the contract in minutes. E.g. a redistribution period of one month would be approximately 43200 minutes.
|
||||
|
||||
The demurrage level specified as the percentage of continuous growth per minute:
|
||||
|
||||
`(1 - percentage) ^ (1 / period)`
|
||||
|
||||
E.g. A demurrage of 2% monthly would be defined as:
|
||||
|
||||
`(1 - 0.02) ^ (1 / 43200) ~ 0.99999953234484737109`
|
||||
|
||||
The number must be provided to the contract as a 64x64 bit fixed-point number (where the integer part is 0).
|
||||
|
||||
A script is included in the python package to publish the contract which takes the input as a percentage as parts-per-million and converts the correct input argument for the contract. The calculation can be found in the function `process_config_local` in `python/erc20_demurrage_token/runnable/publish.py`. It uses the python module [dexif](https://pypi.org/project/dexif/) to perform the fixed-point conversion.
|
||||
|
||||
|
||||
## Demurrage calculation
|
||||
|
||||
The demurrage calculation inside the contract is done by the following formula, where `demurrageLevel` is the demurrage level input parameter of the contract:
|
||||
|
||||
`newDemurrageModifier = currentDemurrageModifier * (e ^ (ln(demurrageLevel) * minutes))`
|
||||
|
||||
Holding Tax (`demurrage`) is applied when a **mint** or **transfer**; (it can also be triggered explicitly)
|
||||
- Note that the token supply _stays the same_ but a virtual _balance output_ is created.
|
||||
- Updates `demurrageModifier` which represents the accumulated tax value and is an exponential decay step (of size `demurrage`) for each minute that has passed.
|
||||
|
||||
|
||||
All client-facing values (_balance output_ , _transfer inputs_) are adjusted with `demurrageModifier`.
|
||||
|
||||
e.g. `_balance output_ = user_balance - user_balance * demurrageModifier`
|
||||
|
||||
|
||||
## Redistribution
|
||||
|
||||
* One redistribution entry is added to storage for each `period`;
|
||||
- When `mint` is triggered, the new totalsupply is stored to the entry
|
||||
- When `transfer` is triggered, and the account did not yet participate in the `period`, the entry's participant count is incremented.
|
||||
* Account must have "participated" in a period to be redistribution beneficiary.
|
||||
* Redistribution is applied when an account triggers a **transfer** for the first time in a new `period`;
|
||||
- Check if user has participated in `period`. (_active_ user heartbeat)
|
||||
- Each _active_ user balance in the `period` is increased by `(total supply at end of period * demurrageModifier ) / number_of_active_participants` via minting
|
||||
- Participation field is zeroed out for that user.
|
||||
* Fractions must be rounded down
|
||||
- Remainder is "dust" and should be sent to a dedicated Sink Token Address.
|
||||
- If no one is _active_ all taxes go to the Sink Token Address.
|
||||
* When `mint` is triggered, the new totalsupply is stored to the entry
|
||||
* When `transfer` is triggered, and the account did not yet participate in the `period`, the entry's participant count is incremented.
|
||||
* Redistributed tokens are added to the balance of the _sink address_ given when the contract is published.
|
||||
* _sink address_ may be changed.
|
||||
|
||||
|
||||
## Data structures
|
||||
## Data representation
|
||||
|
||||
* One word per `account`:
|
||||
- bits 000-071: value
|
||||
- bits 072-103: period
|
||||
- bits 104-255: (Unused)
|
||||
* One word per `redistributions` period:
|
||||
- bits 000-031: period
|
||||
- bits 032-103: supply
|
||||
- bits 104-139: participant count
|
||||
- bits 140-159: demurrage modifier
|
||||
- bits 160-254: (Unused)
|
||||
- bits 255: Set if individual redistribution amounts are fractions
|
||||
Token parameters are truncated when calculating demurrage and redistribution:
|
||||
|
||||
### Notes
|
||||
* Redistribution period: 32 bits
|
||||
* Token supply: 72 bits
|
||||
* Demurrage modifier: 64 bits
|
||||
|
||||
Accumulated demurrage modifier in `demurrageModifier` is 128 bit, but will be _truncated_ do 20 bits in `redistributions`. The 128 bit resolution is to used to reduce the impact of fractional drift of the long-term accumulation of the demurrage modifier. However, the demurrage snapshot values used in `redistributions` are parts-per-million and can be fully contained within a 20-bit value.
|
||||
|
||||
|
||||
## Gas usage
|
||||
|
||||
The token contract uses the [ADBKMath](https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMath64x64.sol) library to calculate exponentials.
|
||||
|
||||
Gas usage is constant regardless of the amount of time passed between each execution of demurrage and redistribution period calculations.
|
||||
|
||||
|
||||
## QA
|
||||
|
||||
* Basic python tests in place
|
||||
* How to determine and generate sufficient test vectors, and how to adapt them to scripts.
|
||||
* Audit sources?
|
||||
* Tests are implemented using the `chaintool` python package suite.
|
||||
|
||||
|
||||
## Known issues
|
||||
|
||||
|
@ -706,9 +706,6 @@ contract DemurrageTokenSingleNocap {
|
||||
if (_sum == 0x9493f8b2) { // EIP173
|
||||
return true;
|
||||
}
|
||||
if (_sum == 0x37a47be4) { // OwnedAccepter
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user