Giter Site home page Giter Site logo

drip-token's Introduction

When i first heard about Proof of Humanity (a social identity verification system for humans on Ethereum) and its UBI token, what caught my attention, aside from the philanthropic nature of the project, was that the project used a very clever technique to distribute an universal basic income (UBI) token to verified humans. This post is inspired by this project and aims to explain how tokens can be streamed in real time to other addresses without using gas at all.

A typical token transfer

In a regular scenario, a token using the ERC20 standard, can be minted and transferred to an address. Under the hood what this transfer actually does, is keeping track of how many tokens an address has, using a mapping like the following:

mapping(address => uint256) private balances

Editing this mapping alters the state of the contract, and since this involves a transaction, it costs gas.

Following the same standard, reading from the balances mapping will be done using the balanceOf(address account) function. Since reading doesn't alter the state of the contract, this function call will be costless. This is key to understand the technique behind token dripping/streaming.

Dripping tokens into a wallet

Now lets say that we need to transfer X amount of tokens each Y amount of time. Using the regular approach described previously, this would involve a recurring transfer, which would involve spending gas regularly with each transfer.

Since this scenario is time dependant we can actually keep track of the time elapsed and calculate how many tokens belong to that address on the fly, without actually keeping track of it on the balances mapping (saving us from spending gas on this).

But where is the streaming?

Since we have the ERC20 standard as an interface to guarantee interoperability, we can rely that wallets or any piece of software we are using, will be calling balanceOf function to get the address balance.

In this case since we are calculating on the fly the amount of tokens in the balance while keeping track of the time elapsed, the result would be (if not other conditions apply), an increasing amount of tokens on the address balance. As a quick example, at the time of this post, Metamask checks balanceOf around each 20 seconds, which will result in tokens streaming / dripping into your wallet, each 20 secs.

But how do we keep track of time elapsed?

Using block.timestamp we can actually access the UNIX epoch of the current block, so we can actually track the time difference, between the block an address registered for the token drip, and the current block. This involves a simple piece of code like this:

mapping(address => uint256) private startTime;

function register() public {
    startTime[msg.sender] = block.timestamp;
}

A working example

Once a starting time is registered (as in the code above), its just a matter of checking the time elapsed on our balanceOf function that will be called by our wallet. We can do that by calculating the difference between the timestamp of the block when we registered our address in the mapping, and the timestamp of the current block, and multiplying that difference for an X amount of tokens that we want to allocate to a unit of time.

The following is a quick but working example of how a time dependant balanceOf function can be achieved.

uint256 private tokenPerSecond = 1;

function isRegistered(address account) public view returns (bool) {
    return startTime[account] != 0;
}

function balanceOf(address account) public view returns (uint256) {
    // if registered, return balance
    if (isRegistered(account)) {
        uint256 timeSinceStart = block.timestamp.sub(
            startTime[account],
            "Subtraction cannot overflow"
        );
        uint256 tokensInBalance = timeSinceStart.mul(tokenPerSecond);
        return tokensInBalance;
    }
    // if not registered, return 0
    return 0;
}

A final note on streaming while being ERC20 compliant

The previous example is not fully ERC20 compliant since it doesn't show how those tokens accrued over time could be transferred or what the total supply is. For example, UBI tokens does not take into account tokens minted as UBI by an address before it moves those (transfer or burn).

For this particular example, while the solution to follow a similar strategy is not that complex, it would involve a second post.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.