Skip to main content
8 of 12
added 466 characters in body
medvedev1088
  • 11k
  • 5
  • 36
  • 65

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

pragma solidity^0.4.11;

contract SomeContract {
    
    event SomeEvent(address sender);
    
    // Need to allow depositing ether to the contract
    function() public payable {
    }

    modifier refundGasCost()
    {
        uint remainingGasStart = msg.gas;

        _;
        
        uint remainingGasEnd = msg.gas;
        uint usedGas = remainingGasStart - remainingGasEnd;
        // Add intrinsic gas and transfer gas. Need to account for gas stipend as well.
        usedGas += 21000 + 9700;
        // Possibly need to check max gasprice and usedGas here to limit possibility for abuse.
        uint gasCost = usedGas * tx.gasprice;
        // Refund gas cost
        tx.origin.transfer(gasCost);
    }

    function doSomething() external refundGasCost {
        SomeEvent(msg.sender);  
    }
}

Refunding in this way implies some overhead: at least 9700 gas has to be payed extra for the transfer function call inside refundGasCost modifier. Also gas for other opcodes in refundGasCost should be added to usedGas.

Also the above code is potentially vulnerable to reentrancy and other attacks. I provided it only as an example and didn't test it thoroughly.


https://github.com/ethereum/wiki/wiki/Design-Rationale

Requiring transaction senders to pay for gas instead of contracts substantially increases developer usability. Very early versions of Ethereum had contracts pay for gas, but this led to the rather ugly problem that every contract had to implement "guard" code that would make sure that every incoming message compensated the contract with enough ether to pay for the gas that it consumed.

medvedev1088
  • 11k
  • 5
  • 36
  • 65