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 ehter 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 = 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 computations and variables access 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.