This service allows you to swap Waves tokens from the Waves blockchain to the Ethereum blockchain. Here's how it works;

      1. Register the waves address you wish to send tokens from below. You'll have to transfer a nominal, but specific amount of waves to complete registration.
      2. Register the Ethereum address you'd like your tokens released to below.
      3. Check the status of blockSwap here - if it's green, send tokens any time and they'll be released on the ethereum blockchain

Want to know a little more?

How does this work?

The total fixed supply of each active token is available on the ethereum blockchain within this smart contract

You transfer your token to our Waves wallet, and we 'lock' the token, guaranteeing that it will not be used whilst active on the ethereum blockchain.

When you transfer your Waves assets to our locked wallet, the ethereum token is released to your provided address on the ethereum side.

To return your token to the Waves blockchain, add the contract to an ethereum wallet of your choice and simply use the 'Move to Waves' function to transfer your ethereum tokens, providing a destination Waves address. Your tokens will be returned to a locked state within the ethereum smart contract, and released once again on the Waves blockchain

Is this magic?

Almost, but not quite.

Please note that whilst the transactions on the ethereum side are open and transparent, with all details available via the smart contract, the Waves locked wallet is a proprietary solution from Incent. This system requires you to trust us.

Why would I do this?

One part 'why not', one part 'oooh, there are some cool things possible on ethereum!'. The intention is to encourage innovation in both communities to unlock potentials such as decentralised exchanges, smart contract applications and other goodness.

Can I verify that it all adds up?

Yup - pretty quick and easy once you understand the following;

  • When you transfer your waves token to the provided address - we 'lock' it on the waves blockchain and release it on ethereum.
  • The balance of the locked waves wallet can be seen here on the right hand side under 'account assets'.
  • This balance is equal to the number of tokens currently active on the ethereum blockchain - verify here
  • You can therefore easily confirm that;
    ( total supply locked in the ethereum smart contract ) + ( total supply locked in waves wallet ) == total supply of token
  • or in reverse, that;
    ( total supply active on the ethereum blockchain ) + ( total supply active on the waves blockchain ) == total supply of token

One of the joys of blockchain technology is how transparent and verifiable we can build it - please do check the above at any time for confirmation :)

Can I see the contract code please?

Sure! - it's confirmed here, and copied below;

pragma solidity ^0.4.2;

// ----------------------------------------------------------------------------------------------
// A collaboration between Incent and Bok :)
// Enjoy. (c) Incent Loyalty Pty Ltd, and Bok Consulting Pty Ltd 2017. The MIT Licence.
// ----------------------------------------------------------------------------------------------

//config contract
contract TokenConfig {

    string public constant name = "Incent Coffee Token";
    string public constant symbol = "INCOF";
    uint8 public constant decimals = 0;  // 0 decimal places, the same as tokens on Wave
    uint256 _totalSupply = 824;


// ERC Token Standard #20 Interface
contract ERC20Interface {

    // Get the total token supply
    function totalSupply() constant returns (uint256 totalSupply);

    // Get the account balance of another account with address _owner
    function balanceOf(address _owner) constant returns (uint256 balance);

    // Send _value amount of tokens to address _to
    function transfer(address _to, uint256 _value) returns (bool success);

    // Send _value amount of tokens from address _from to address _to
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);

    // Allow _spender to withdraw from your account, multiple times, up to the _value amount.
    // If this function is called again it overwrites the current allowance with _value.
    // this function is required for some DEX functionality
    function approve(address _spender, uint256 _value) returns (bool success);

    // Returns the amount which _spender is still allowed to withdraw from _owner
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);

    // Triggered when tokens are transferred.
    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    // Triggered whenever approve(address _spender, uint256 _value) is called.
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);

contract IncentCoffeeToken is ERC20Interface, TokenConfig {

    // Owner of this contract
    address public owner;

    // Balances for each account
    mapping(address => uint256) balances;

    // Owner of account approves the transfer of an amount to another account
    mapping(address => mapping (address => uint256)) allowed;

    // Functions with this modifier can only be executed by the owner
    modifier onlyOwner() {
        if (msg.sender != owner) {

    // Constructor
    function IncentCoffeeToken() {

        owner = msg.sender;
        balances[owner] = _totalSupply;

    function totalSupply() constant returns (uint256 totalSupply) {
        totalSupply = _totalSupply;

    // What is the balance of a particular account?
    function balanceOf(address _owner) constant returns (uint256 balance) {
        return balances[_owner];

    // Transfer the balance from owner's account to another account
    function transfer(address _to, uint256 _amount) returns (bool success) {
        if (balances[msg.sender] >= _amount && _amount > 0) {
            balances[msg.sender] -= _amount;
            balances[_to] += _amount;
            Transfer(msg.sender, _to, _amount);
            return true;
        } else {
           return false;

    // Send _value amount of tokens from address _from to address _to
    // The transferFrom method is used for a withdraw workflow, allowing contracts to send
    // tokens on your behalf, for example to "deposit" to a contract address and/or to charge
    // fees in sub-currencies; the command should fail unless the _from account has
    // deliberately authorized the sender of the message via some mechanism; we propose
    // these standardized APIs for approval:
    function transferFrom(
        address _from,
        address _to,
        uint256 _amount
    ) returns (bool success) {

        if (balances[_from] >= _amount
            && allowed[_from][msg.sender] >= _amount
            && _amount > 0) {

            balances[_to] += _amount;
            balances[_from] -= _amount;
            allowed[_from][msg.sender] -= _amount;
            Transfer(_from, _to, _amount);
            return true;
        } else {
            return false;

    // Allow _spender to withdraw from your account, multiple times, up to the _value amount.
    // If this function is called again it overwrites the current allowance with _value.
    function approve(address _spender, uint256 _amount) returns (bool success) {
        allowed[msg.sender][_spender] = _amount;
        Approval(msg.sender, _spender, _amount);
        return true;

    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
        return allowed[_owner][_spender];


contract WavesEthereumSwap is IncentCoffeeToken {

 event WavesTransfer(address indexed _from, string wavesAddress, uint256 amount);

 function moveToWaves(string wavesAddress, uint256 amount) {

     if (!transfer(owner, amount)) throw;
     WavesTransfer(msg.sender, wavesAddress, amount);



Why only incentCoffee?

Watch this space ;)