Skip to main content
deleted 6 characters in body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65

There are 2 options which havewith their pros and cons:

There are 2 options which have their pros and cons:

There are 2 options with their pros and cons:

added 3 characters in body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65

Here is a simple ReceiverPays contract that allows making the receiver of the payment pay for gas:

Here a simple ReceiverPays contract that allows making the receiver of the payment pay for gas:

Here is a simple ReceiverPays contract that allows making the receiver of the payment pay for gas:

added 3387 characters in body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65

There are 2 options which have their pros and cons:

  1. Use signatures
  • Every function in your smart contract must have signature parameter.
  • People who want to interact with the smart contract must sign the function parameters with their account's private key and send it to the smart contract owner (via any communication channel).
  • The owner then submits the parameters along with the signature to the blockchain, paying for gas. The signature guarantees that the message was approved by the user.
  1. Refund used gas at the end of the transaction. A modifier refundGasCost can be used for this (see below).

Below are more details for each option:


Using signatures

Here a simple ReceiverPays contract that allows making the receiver of the payment pay for gas:

pragma solidity ^0.4.20;

contract ReceiverPays {
    address owner = msg.sender;

    mapping(uint256 => bool) usedNonces;

    // Funds are sent at deployment time.
    function ReceiverPays() public payable { }


    function claimPayment(uint256 amount, uint256 nonce, bytes sig) public {
        require(!usedNonces[nonce]);
        usedNonces[nonce] = true;

        // This recreates the message that was signed on the client.
        bytes32 message = prefixed(keccak256(msg.sender, amount, nonce, this));

        require(recoverSigner(message, sig) == owner);

        msg.sender.transfer(amount);
    }

    // Destroy contract and reclaim leftover funds.
    function kill() public {
        require(msg.sender == owner);
        selfdestruct(msg.sender);
    }


    // Signature methods

    function splitSignature(bytes sig)
        internal
        pure
        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)
        internal
        pure
        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);
    }
}

More details can be found in this article https://programtheblockchain.com/posts/2018/02/17/signing-and-verifying-messages-in-ethereum/

The limitation of this approach is that if your smart contract needs to interact with other contracst, then they must also implement the same pattern with adding signatures to every method.


Refunding used gas to the transaction sender

It's not an ideal solution but you can refund gas cost to the transaction sender. You can do this with a modifier:

It's not an ideal solution but you can refund gas cost to the transaction sender. You can do this with a modifier:

There are 2 options which have their pros and cons:

  1. Use signatures
  • Every function in your smart contract must have signature parameter.
  • People who want to interact with the smart contract must sign the function parameters with their account's private key and send it to the smart contract owner (via any communication channel).
  • The owner then submits the parameters along with the signature to the blockchain, paying for gas. The signature guarantees that the message was approved by the user.
  1. Refund used gas at the end of the transaction. A modifier refundGasCost can be used for this (see below).

Below are more details for each option:


Using signatures

Here a simple ReceiverPays contract that allows making the receiver of the payment pay for gas:

pragma solidity ^0.4.20;

contract ReceiverPays {
    address owner = msg.sender;

    mapping(uint256 => bool) usedNonces;

    // Funds are sent at deployment time.
    function ReceiverPays() public payable { }


    function claimPayment(uint256 amount, uint256 nonce, bytes sig) public {
        require(!usedNonces[nonce]);
        usedNonces[nonce] = true;

        // This recreates the message that was signed on the client.
        bytes32 message = prefixed(keccak256(msg.sender, amount, nonce, this));

        require(recoverSigner(message, sig) == owner);

        msg.sender.transfer(amount);
    }

    // Destroy contract and reclaim leftover funds.
    function kill() public {
        require(msg.sender == owner);
        selfdestruct(msg.sender);
    }


    // Signature methods

    function splitSignature(bytes sig)
        internal
        pure
        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)
        internal
        pure
        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);
    }
}

More details can be found in this article https://programtheblockchain.com/posts/2018/02/17/signing-and-verifying-messages-in-ethereum/

The limitation of this approach is that if your smart contract needs to interact with other contracst, then they must also implement the same pattern with adding signatures to every method.


Refunding used gas to the transaction sender

It's not an ideal solution but you can refund gas cost to the transaction sender. You can do this with a modifier:

added 155 characters in body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65
Loading
added 466 characters in body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65
Loading
deleted 20 characters in body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65
Loading
edited body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65
Loading
deleted 9 characters in body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65
Loading
added 31 characters in body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65
Loading
added 16 characters in body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65
Loading
added 58 characters in body
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65
Loading
Source Link
medvedev1088
  • 11k
  • 5
  • 36
  • 65
Loading