As mentioned, with the various PAYGAS proposals it is impossible to pay with anything but Ether. Another limitation is that the first contract has to pay for the gas, so chained validation contracts are more difficult to build (although I’m not sure how relevant this is). I thought a bit about this and realized that we can get both features by the backdoor via a pay-but-refund mechanism, without any additional protocol changes. The general process could work as follows:
- “entry contract” (i.e. the first called contract) pays for gas
- entry contract measures gas usage (via two GAS calls)
- entry contract makes sure that gas is paid in another way (by another contract or with another token)
- entry contract asks for a refund of the paid gas
- refunding contract checks eligibility and refunds
As an example, consider a validation contract A that authenticates a user and another contract B that pays for some of A’s transactions (e.g. to a specific third contract, but rate limited to 5 transactions per day for a certain set of users). B expects to be called by A and trusts A to behave faithfully as it has checked the contract code against some template. After the main call, A calls B’s method
refund_gas(gas_used) which pays
gas_used * GASPRICE to A. So if everything works fine (and the calculation of
gas_used is exact), A will have the same balance before and after the transaction and effectively B has paid for the gas. If the transaction fails though, A will not get refunded. This shouldn’t be too much of an issue though as the user should be able to ensure that the transaction won’t fail. To be even more safe A could assert some conditions before the PAYGAS call.
As a second example, consider a miner who wants to be paid in GTK (gas tokens) instead of Ether. He sets up a refund contract that defines a token type (GTK) and an exchange rate (GTK per unit of gas). He accepts only transactions with Ether gas prices of, say, 10 times his minimum gas price in GTK. When the user sends a transaction to an entry contract that wants to pay in GTK, it first asserts that the coinbase is a refund contract and that the GTK-gasprice is acceptable. Next, it PAYsGAS and makes the main call, measuring actual gas usage. Finally, it pays a second time for the gas, but now extra-protocol and in GTK, at the gas price defined in the refund contract. Then, it asks the refund contract to pay
gas_used * GASPRICE. The refund contract checks that it trusts the contract (by comparing the contract code against a template) and that the correct amount of GTK has been paid earlier and refunds the Ether.
In the second example, the miner is in fact affected by a failing transaction: He’s paid in Ether instead of GTK. But this is mitigated by a much larger gas price, so that he’s happy in both cases. Again, the sender doesn’t like this, but he can ensure that his transaction won’t fail.