Payment Channel

What are they trying to solve

Scalability of blockchain. Instead of having all transactions happening on a blockchain, let people make them offchain and get back to the blockchain when needed. This allows both parties to pay less transaction fees and help with network congestion. In the 10 minutes we will have together, you should be able to build a simple payment channel and use it later on.

How it works

Before going straight into the implementation, let's discuss the underlaying working process:

  1. The sender deploys a smart contract on-chain with a deposit and a recipient address
  2. It sends transactions off-chain to the receiver, with an cumulative amount
  3. The receiver claims the transaction with the biggest amount
  4. The contract pays the recipient and refund the sender for all remaining ether
  5. The contract is destroyed


Now, let's dive into the implementation, it's a tutorial after all.

A functional implementation



Set the recipient address and complete the init function
pragma solidity ^0.4.24; contract UnidirectionalPaymentChannel { address public sender; // this is the boss address // I know you're generous but change it to one you have access to ;) address public recipient = 0xYOUR_ADDRESS_HERE_IN_CAPITAL; uint public validUntil; function init(uint timeout) payable public { sender = ; // the sender is you, so msg.sender validUntil = now + ; // there is only one argument to this function, put it here } // to retrieve your funds // @param {uint} value - amount to retrieve // @param {bytes32} h - hash of the transaction // @param {signature} v,r,s - signature of the transaction to assess its validity function closeChannel (uint value, bytes32 h, uint8 v, bytes32 r, bytes32 s) public { address signer = ecrecover(h, v, r, s); // retrieve sender public key, thanks to eliptic curve assert(signer == sender); bytes32 proof = keccak256(abi.encodePacked(this, value)); assert(proof == h); recipient.transfer(value); // Now that everything is fine, give you your funds selfdestruct(sender); // and close the channel } // if you have waited for to long, the sender gets all the money function channelTimeout() public { if (now < validUntil) { revert(); } selfdestruct(sender); } }

Going further

With this first implementation, we have seen the most important step to setup a payment channel. However, there was some limitation.

  • The deposit amount could be too low
  • The receiver has to open another channel to become a sender
  • To send fund, you need to open a channel with the receiver or having some routing protocol
  • If the receiver is offline, the sender can get its money back