A gas station is a coin account that pays for gas fees on behalf of a user.
Let's explore how we can create an account that is scoped to only pay for gas
for specific transactions.
To start off, let's create a gas station that is unscoped. From there we can then see how we can scope it to only pay for gas for specific transactions.
(namespace 'free)
(module test G
(defcap G() true)
(defun allow() true)
)
(let ((guard (create-user-guard (test.allow))))
(coin.create-account (create-principal guard) guard)
)In this example, we create a gas station account that is unscoped. This means account will pay for anything, even for transfers.
Before we move to scoping the gas station, we will migrate the above code to
make use of a capability guard. This allows us to have more control over the
guard that we want to use and grant data-base access.
(namespace 'free)
(module test G
(defcap G() true)
(defcap ALLOW() true)
)
(let ((guard (create-capability-guard (test.ALLOW))))
(coin.create-account (create-principal guard) guard)
)Now we can change the module we created to scope it to only pay for gas fees.
To do so, we must implement the gas-payer-v1 interface.
(namespace 'free)
(module test G
(defcap G() true)
(implements gas-payer-v1)
(defcap ALLOW:bool() true)
(defcap GAS_PAYER:bool
( user : string
limit : integer
price : decimal
)
(compose-capability (ALLOW))
)
(defun create-gas-payer-guard:guard()
(create-capability-guard (test.ALLOW))
)
)
(let ((guard (free.test.create-gas-payer-guard)))
(coin.create-account (create-principal guard) guard)
)With this change, we tell chainweb that this account is eligible to pay for
paying gas fees if GAS_PAYER capability is granted. Since the GAS_PAYER
capability is always passing, that means that this gas-station will pay for
any transaction's gas fees.
Now that we have a gas station that is scoped to pay for gas fees, we can
further scope it to only pay for gas fees for specific transactions. In the
following example we scope the gas station to only pay for gas fees for
transactions that have a gas price less than 0.00000001, but the owner of
free.some-admin-keyset can use this gas station to pay for any transaction.
(namespace 'free)
(module test G
(defcap G() true)
(implements gas-payer-v1)
(defcap ALLOW:bool() true)
(defcap GAS_PAYER:bool
( user : string
limit : integer
price : decimal
)
(enforce-one
"Allow admin to use this gas station for any transaction"
[
(enforce-guard "free.some-admin-keyset")
(enforce (<= 0.00000001 (at 'gas-price (chain-data)))
"Gas price must be less than 0.00000001"
)
]
)
(compose-capability (ALLOW))
)
(defun create-gas-payer-guard:guard()
(create-capability-guard (test.ALLOW))
)
)
(let ((guard (free.test.create-gas-payer-guard)))
(coin.create-account (create-principal guard) guard)
)