Update readme for calculations and inputs

This commit is contained in:
lash 2023-03-01 12:01:32 +00:00
parent 65a91cc44d
commit f75472fcf5
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
2 changed files with 53 additions and 44 deletions

View File

@ -32,63 +32,75 @@
## Mint ## Mint
* Owner can add minters and remove * Minters are called writers. Contract owner can add and remove writers.
- A faucet contract would be a minter and choose the amount of tokens to mint and distribute to new _validated_ users. * 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. * 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 * Writers can mint any amount. If supply cap is set, minting will be limited to this cap.
* Minters can mint any amount
## Demurrage ## Input parameters
* 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. The redistrbution period is passed to the contract in minutes. E.g. a redistribution period of one month would be approximately 43200 minutes.
- 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)` The demurrage level specified as the percentage of continuous growth per minute:
- 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`. `(1 - percentage) ^ (1 / period)`
* All client-facing values (_balance output_ , _transfer inputs_) are adjusted with `demurrageModifier`.
- e.g. `_balance output_ = user_balance - user_balance * demurrageModifier` 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 ## Redistribution
* One redistribution entry is added to storage for each `period`; * One redistribution entry is added to storage for each `period`;
- When `mint` is triggered, the new totalsupply is stored to the entry * 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. * 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. * Redistributed tokens are added to the balance of the _sink address_ given when the contract is published.
* Redistribution is applied when an account triggers a **transfer** for the first time in a new `period`; * _sink address_ may be changed.
- 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.
## Data structures ## Data representation
* One word per `account`: Token parameters are truncated when calculating demurrage and redistribution:
- 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
### 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 ## QA
* Basic python tests in place * Tests are implemented using the `chaintool` python package suite.
* How to determine and generate sufficient test vectors, and how to adapt them to scripts.
* Audit sources?
## Known issues ## Known issues

View File

@ -706,9 +706,6 @@ contract DemurrageTokenSingleNocap {
if (_sum == 0x9493f8b2) { // EIP173 if (_sum == 0x9493f8b2) { // EIP173
return true; return true;
} }
if (_sum == 0x37a47be4) { // OwnedAccepter
return true;
}
return false; return false;
} }
} }