Drips docs

Drips docs

    ›Advanced Topics

    Intro and Basics

    • What's a Drip?
    • Drips v2 Features
    • Accessing Drips
    • FAQ

    The Drips App

    • Getting Started
    • Manage funds

      • Add funds
      • Withdraw funds
      • Collect earnings

      Streams

      • Create a stream
      • Edit, pause or delete a stream

      Splits

      • Set up & manage splits

      Explore the network

      • Drips profiles

      Advanced

      • Connecting to a Safe

    The Protocol

    • Overview
    • User Identities In Drips
    • Smart Contract and Subgraph Details
    • Security

    For Developers

    • The Drips JS SDK
    • Installing the SDK and Running the Example App
    • Initializing the SDK
    • Accounts

      • Intro to Accounts
      • Create an Account
      • List Sub-Accounts
      • Add Funds

      Streams

      • Start a Stream
      • Update a Stream
      • Scheduling

      Splitting

      • Create User Splits
      • Edit User Splits
      • List User Splits
      • Immutable Splits

      Collecting

      • How to Collect
      • Squeezing Drips

      Advanced Topics

      • Caller
      • Account Metadata
      • Dripping Fractional Amounts
      • Drips inner workings

    Get Involved

    • Join the Drips Community

    Dripping Fractional Amounts

    Introduction: token decimals

    If you know how token decimals work, feel free to skip this section.

    We, the web3 users, are familiar with the notion of tokens being dividable into smaller parts. E.g. you can have 2.5 USDC, or you can receive 0.03 Ether. This in fact is not how the tokens are handled by the computers and the blockchains. The reality is that the tokens are indivisible, but all the quantities are much larger than what's presented to us, which enables the creation of an illusion of fractions. Every token has defined a number of decimals, in the case of USDC it's 6, in the case of Ether 18, and so on. The number of decimals is applied when displaying the amounts for the users. E.g. if your wallet states that you have 2.5 USDC, the actual amount stored in the smart contract has 6 extra digits and is 2,500,000 (2.5 * 10 ^ 6). When you want to transfer 0.003 Ether, the wallet sends in the transaction an amount with 18 extra digits, or in this case 30,000,000,000,000,000 (0.03 * 10 ^ 18). This convention makes handling tokens simpler for computers because they don't need to work with fractions. On the other hand for the users, the visible amounts are easy to work with, because they are small, have relatively high per-unit monetary value, and offer convenient fractions.

    Language used in this section

    This page uses the term "token unit" when talking about tokens as seen by the smart contract. For example, 0.000,001 USDC or 10 ^ -18 Ether (1 Wei) are both token units. Token units are not dividable into smaller parts, their amounts are expressed with integers.

    Dripping rate has a sub-token precision

    When setting up drips, each receiver is configured with an integer per-second dripping rate, amtPerSec. This rate is expressed in token units with 9 extra decimals, which lets express rates with precision higher than 1 token unit per second.

    For example, the user wants to drip 0.000,001 USDC per second. USDC has 6 decimals, so the actual rate they want is 1 token unit per second. The drips configuration requires the rate to have 9 extra decimals, so the amtPerSec needs to be set to value 1,000,000,000. Dripping 0.000,001 USDC per second adds up to 2.592 USDC per 30 days. Let's say that the user feels that it's too much, now they want to drip only 1 USDC per 30 days. This is 0.385,802,469 token units per second, to which we add 9 decimals and end up passing as amtPerSec the integer value 385,802,469.

    Example token amount representation
    Tokens seen by the user0.05 USDC
    Token units handled by smart contracts50,000 (USDC has 6 decimals, so we calculate 0.05 * 10 ^ 6)
    Passed as amtPerSec as a per second dripping rate50,000,000,000,000 (amtPerSec requires adding 9 extra decimals to the number of token units, so we calculate 50,000 * 10 ^ 9)

    The API requires 9 extra decimals only in DripsConfig's amtPerSec

    In DripHub API per-second rates are always wrapped in DripsConfig packed structures, they are never passed or emitted as standalone integers. All instances of DripsConfig have their amtPerSec expressed as token units with 9 extra decimals. On the other hand, no other values follow that convention, all the balances and amounts are always expressed as regular numbers of whole token units without any extra precision or fractions.

    Dripped amounts are always whole token units

    When dripping, both the sender's balance and the amounts receivable by the receivers are always whole token units, and at all times they add up to the amount put into the protocol by the sender. There are no losses or temporarily stuck token units, the protocol is precise and sound when handling assets. This holds even when dripping at rates that are not expressible as whole token units per second. Partially dripped token units are kept in the sender's balance, but as soon as they add up to whole units, they're moved from the sender and become receivable by the receiver. This makes the amounts actually dripped on each timestamp change from second to second within a range of 1 token unit per second, but when observed over a period of time, the dripped token units add up to the rate which was configured.

    For example, the user wants to drip 0.000,001,4 USDC per second, which is 1.4 token units per second. The dripped amount on the first second will be 1.4, so only 1 token unit will be subtracted from the sender's balance and moved to the receiver, 0.4 will stay on the sender's side. During the next second, another 1.4 token units are being dripped, to which 0.4 from the previous second is added resulting in 1.8 token units sent. Again 1 is moved from the sender to the receiver and 0.8 stays on the sender. Finally, during the third second, another 1.4 is dripped, which with 0.8 from the previous cycles adds up to 2.2. This time 2 token units are taken from the sender's balance and made receivable by the receiver, and 0.2 stays on the sender's side waiting to be dripped during the upcoming seconds.

    Technical details of how dripped fractions add up

    When dripping with a given rate the Nth second of each cycle moves the same amount from the sender to the receiver. It doesn't matter when dripping starts or ends, the exact amount dripped during a given second depends only on the rate and the position of the timestamp in the cycle. The first second of each cycle always moves floor(amtPerSec), but every other timestamp T moves floor(T % cycleSecs * amtPerSec) - floor((T - 1) % cycleSecs * amtPerSec).

    The result of this behavior is that operations that update drips without altering the dripping rate, for example, a change of the balance, do not disrupt the existing streams. This makes calculating the amount dripped over a given period of time easy to do using just the rate and the cycle length.

    Unfortunately, it may lead to surprising behaviors when dripping at extremely low rates. For example, a user drips 0.001 token units per second, so a single token unit should be moved to the receiver once every 1000 seconds. Depending on when exactly dripping starts, a token unit may be moved on the first second of dripping or it may be moved after 999 seconds, to the user it may look random. Consecutive token units will be moved as expected, once per 1000 seconds. The only exception is when a cycle ends, because then the unmoved fractions will be cleared, and the countdown to moving the next token unit will be reset to 1000 seconds.

    The cycle boundaries behavior determines the lowest possible dripping rate, which is 1 token unit per cycle. If a dripping rate is lower than that, a drip configuration will be valid, but it'll silently cause no movement of tokens.

    ← Account MetadataDrips inner workings →
    • Introduction: token decimals
    • Language used in this section
    • Dripping rate has a sub-token precision
    • The API requires 9 extra decimals only in DripsConfig's amtPerSec
    • Dripped amounts are always whole token units
    • Technical details of how dripped fractions add up