For now it is not possible to pay for gas from contract's balance, though this may change in future, but smart contract may refund gas transaction publisher spent on housekeeping function:
modifier refundable () {
uint256 gasBefore = gasleft ();
_;
tx.origin.send (tx.gasprice * (gasleft () - gasBefore));
}
function expensiveCleanupFunction() refundable internal {
... shuffle around some storage ...
}
This will not refund gas in case smart contract does not have enough ether, though. If you need to refund even in case of insufficient balance, do something like this:
mapping (address => uint256) private refundBalance;
modifier refundable () {
uint256 gasBefore = gasleft ();
_;
uint256 toRefund = tx.gasprice * (gasleft () - gasBefore);
if (!tx.origin.send (toRefund))
refundBalance [tx.origin] += toRefund;
}
function withdraw () public {
uint256 toTransfer = refundBalance [msg.sender];
refundBalance [msg.sender] = 0;
msg.sender.transfer (toTransfer);
}
function expensiveCleanupFunction () refundable internal {
... shuffle around some storage ...
}
So in case instant refund failed, smart contracts increments refund balance of the users, and once smart contract balance will be resupplied, user will be able to withdraw his refund.