iRyanBell

Receiving a VIM20 Utility Token

By Ryan Bell on January 07, 2019 - 3 min read

Receiving a VIM20 Utility Token

During a vim20 transfer() call, the utility token smart contract will first examine the recipient's address and determine whether the address belongs to an individual or another smart contract. If a contract has been deployed to that address, the token will attempt to call that contract's tokenFallback() function. Only if that fallback function exists and completes successfully, returning true, will the transaction be considered valid and go on to complete the transfer of tokens from sender to recipient. This virtual handshake prevents transfers to smart contracts which are unprepared to accept the vim20 utility token or fail during the transaction.

contract ERC223Receiver {
    function tokenFallback(address, uint256) public returns (bool);
    function tokenFallback(address, uint256, bytes memory) public returns (bool);
}

This micro-size tokenFallback() implementation with a boolean return value is all you need to receive the utility token transfer event and confirm the transaction at the other end.

(The ERC223 Token Receiver specification is under active discussion at: https://github.com/ethereum/EIPs/issues/223)

Putting this receiver to work

contract VIM_API_Payments {
    using SafeMath for uint256;

    address _bank;
    address constant _vimTokenAddr = 0x543920CD78B0d230C4c7ad849F4f32e03FB3DcA0;
    mapping(address => uint256) public _balances;
    event Payment(address sender, uint256 amount);

    constructor() public {
        _bank = msg.sender;
    }

    modifier onlyBank {
        require(msg.sender == _bank, "Unauthorized");
        _;
    }

    function tokenFallback(
        address from,
        uint256 value
    ) public returns (bool) {
        ERC223 token = ERC223(msg.sender);
        require(msg.sender == _vimTokenAddr, "Invalid VIM token");
        require(token.transfer(_bank, value), "Error transfering funds.");

        _balances[from] = _balances[from].add(value);

        return true;
    }

    function balanceOf(address account) public view returns (uint256 balance) {
        return _balances[account];
    }

    function upgradeBank(address addr) public onlyBank returns (bool success) {
        _bank = addr;
        return true;
    }
}

Let's break it down.

First, we define our bank (where the coins are forwarded after a deposit) and define the token address (to later use as a filter.)

address _bank;
address constant _vimTokenAddr = 0x543920CD78B0d230C4c7ad849F4f32e03FB3DcA0;
mapping(address => uint256) public _balances;
event Payment(address sender, uint256 amount);

constructor() public {
    _bank = msg.sender;
}

modifier onlyBank {
    require(msg.sender == _bank, "Unauthorized");
    _;
}

Next, we add the code to receive transfer from a specified token, forward the amount, and credit the sender's address with the deposit.

    function tokenFallback(
        address from,
        uint256 value
    ) public returns (bool) {
        ERC223 token = ERC223(msg.sender);
        require(msg.sender == _vimTokenAddr, "Invalid VIM token");
        require(token.transfer(_bank, value), "Error transfering funds.");

        _balances[from] = _balances[from].add(value);

        return true;
    }

Then, we add a small getter function for accessing account balances.

    function balanceOf(address account) public view returns (uint256 balance) {
        return _balances[account];
    }

Finally, a bank upgrade function can be implemented with a modifier function, to allow the bank to change its address.

function upgradeBank(address addr) public onlyBank returns (bool success) {
        _bank = addr;
        return true;
    }

You can see it live in action at this deployed address: https://etherscan.io/tx/0xa631a992094246c43eac937e6acee80c4d828e5dc459988a78b190756db22225#eventlog

Using this simple credit system, a decentralized application API can compare an account's total lifetime bill against the total utility token deposits to enable or disable access to a service. Easy peasy.

The full source code is available for this contract at: https://github.com/iRyanBell/vim20/blob/master/contracts/VIMAPIPayments.sol