I have deployed the smart contract of Payment channel and every thing is working fine but at the time of closing the channel signature is not being validate. I think passing the arguments in a wrong way or maybe payment that i'm signing is not returning the correct signer.

pragma solidity ^0.4.20;

contract SimplePaymentChannel {
    address public sender;     // The account sending payments.
    address public recipient;  // The account receiving the payments.
    uint256 public expiration; // Timeout in case the recipient never 

    function SimplePaymentChannel(address _recipient, uint256 duration)
        sender = msg.sender;
        recipient = _recipient;
        expiration = now + duration;

    function isValidSignature(uint256 amount, bytes signature)
        returns (bool)
        bytes32 message = prefixed(keccak256(this, amount));

        // Check that the signature is from the payment sender.
        return recoverSigner(message, signature) == sender;

    // The recipient can close the channel at any time by presenting a signed
    // amount from the sender. The recipient will be sent that amount, and the
    // remainder will go back to the sender.
    function close(uint256 amount, bytes signature) public {
        require(msg.sender == recipient);
        require(isValidSignature(amount, signature));


    // The sender can extend the expiration at any time.
    function extend(uint256 newExpiration) public {
        require(msg.sender == sender);
        require(newExpiration > expiration);

        expiration = newExpiration;

    // If the timeout is reached without the recipient closing the channel, then
    // the ether is released back to the sender.
    function claimTimeout() public {
        require(now >= expiration);

    function splitSignature(bytes sig)
        returns (uint8, bytes32, bytes32)
        require(sig.length == 65);

        bytes32 r;
        bytes32 s;
        uint8 v;

        assembly {
            // first 32 bytes, after the length prefix
            r := mload(add(sig, 32))
            // second 32 bytes
            s := mload(add(sig, 64))
            // final byte (first byte of the next 32 bytes)
            v := byte(0, mload(add(sig, 96)))

        return (v, r, s);

    function recoverSigner(bytes32 message, bytes sig)
        returns (address)
        uint8 v;
        bytes32 r;
        bytes32 s;

        (v, r, s) = splitSignature(sig);

        return ecrecover(message, v, r, s);

    // Builds a prefixed hash to mimic the behavior of eth_sign.
    function prefixed(bytes32 hash) internal pure returns (bytes32) {
        return keccak256("\x19Ethereum Signed Message:\n32", hash);

And this is my signing js file.

var BN = require('bn.js')
var abi = require('ethereumjs-abi')
const eutil = require('ethereumjs-util');

var HDWalletProvider = require("truffle-hdwallet-provider"); 
var mnemonic = ""; // 12 word mnemonic
const Web3 = require('web3');

var provider = new Web3.providers.HttpProvider(mnemonic, 

const web3 = new Web3(provider);
var s;

function constructPaymentMessage(contractAddress, amount) {
    return abi.soliditySHA3(
        ["address", "uint256"],
        [contractAddress, amount],

async function signMessage(message, callback) {
    account = await web3.eth.getAccounts();
    web3.eth.sign("0x" + message.toString("hex"), account[0], callback);

function signPayment(contractAddress, amount, callback) {
    var message = constructPaymentMessage(contractAddress, amount);
    console.log("message is", message);
    signMessage(message, async (err, signature) => {
        try {
            s = signMessage
            console.log("sig", signature);
        } catch (error) {
            console.log("siasdsdg", error.message);

    '1000000000000000000', function (err, signer) {

Please let me know where i'm wrong thanks.

  • Did you mean to have s = signature instead of s = signMessage? – user19510 Jan 28 '19 at 18:09
  • Also, where is the code that calls close() on the smart contract? – user19510 Jan 28 '19 at 18:10
  • Maybe you can point to a failed transaction on Rinkeby. That would make it easier to debug. – user19510 Jan 28 '19 at 18:11
  • Okay, I actually calling this close function from remix by adding amount in weis and bytes in double qoutes. Here i have deployed the contract. rinkeby.etherscan.io/address/… – Hamza Yasin Jan 29 '19 at 10:56
  • I don't see any failed transaction to that contract. It would help if you would actually send the transaction (even though you know it will fail). This way I can see exactly what parameters got passed in. – user19510 Jan 29 '19 at 15:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.