GitHub Logo HIP-1068: Sponsored Fees

Author Nana Essilfie-Conduah, Brendon Vade, Matt Woodward, Tim Johnson
Working Group Greg Scullard, Ty Smith, Keith Kowal, Atul Mahamuni
Requested By THF, AP+, HbarGasStation
Discussions-To https://github.com/hashgraph/hedera-improvement-proposal/discussions/912
Status Last Call
Needs Council Approval Yes
Review period ends Thu, 30 Jan 2025 07:00:00 +0000
Type Standards Track
Category Service
Created 2024-05-21
Updated 2025-01-16

Abstract

This HIP proposes an expansion to the approval and allowance network logic (i.e. CryptoApproveAllowance, NftAllowance and TokenAllowance) by allowing any account on the network to provide allowances that will sponsor the payment of the fees for another account’s submitted transactions. In this way account Alice may assign an HBAR / token transaction fee allowance for Externally Owned Account (EOA) Bob or Contract account Carol and pay the fees due to nodes, the network and accounts for any transactions they submit, thus allowing Bob or Carol to have zero balance and still transact on chain.

This proposal extends the existing Approval and Allowance API by adding the concept of a scope that designates the type of value transfer an allowance applies to. The scopes will include CryptoTransfer, Gas Fees, HTS Token Custom Fees and HAPI Transaction Fees. This enables value transfer and fee payments to another account without requiring one-off approval for each transaction. This feature enhances flexibility and efficiency in managing transaction costs, particularly for high volume applications.

Motivation

The web3 space user onboarding process is hindered by the the requirement of an account maintaining sufficient crypto currency at all times to engage with the network. On Hedera, this means an account must always have sufficient hbar balance at all times to submit a HAPI transaction to the network.

Whiles this serves as a security feature to ensure node and network resources utilized are paid, it requires that new users must first obtain cryptocurrency value to engage with the network. It also prevents the abstraction of payments from the submission of transactions. Many more users could be onboarded to the network as well with incentive to engage with the network if their transactions could be “Hbar Less”.

Additionally, ecosystem development grant providers find it challenging to distribute funds to partners in a way that is accurate and encourages transaction on the network. Grant providers want to make sure their projects can only spend hbars awarded on transaction fees to the network and not for value transfer cases sometimes unassociated. This make is easier for grant givers to track funds and assure appropriate usage.

The appropriate solution is one that enables low barrier to entry for users but also maintains network security regarding fee payment. To this end a flow that allows other users to sponsor the fees required of an account during a transaction submission would satisfy both desires.

Ultimately the current Hedera ecosystem lacks a native capability for an Owner account to cover transaction fees of a Spender without co-signing for every transaction. This limitation hinders the development of user-friendly applications and services that could benefit from a more flexible transaction fee payment flow.

Rationale

Today the network supports 3 types of allowances HbarAllowance, TokenAllowance and NftAllowance . An account may submit a CryptoApproveAllowance transaction and specify the amount of value they are willing to allow another account to transfer out of their own balance. This HIP builds upon the allowance logic with the introduction of another allowance type TransactionFeeAllowance.

Accounts would follow the same pattern of CryptoApproveAllowance submission to designate and update an allowance. When a designated account submits a transaction identified as sponsored, the network would debit the sponsoring account balance for all HBar fees associated with the transaction, instead of the account sending the transaction.

Notably, a pseudo sponsored transaction flow exists today if the sponsor submits a transaction signed by the sender. However, this flow requires significant offline coordination and is time limited in some cases depending on transaction validation timing window. This HIP provides a solution that is not limited by either of these considerations. A sponsor need only know the accountId or EVM address of the account they want to sponsor. An account being sponsored need only know the account id or EVM address of their sponsor to submit a transaction and specify to the network that the transaction will be paid by the sponsor.

Additionally, this flow allows for a user with an EVM address but no Hedera account to share their address and be sponsored in advance of their first transaction submission to the network. In this way their first transaction will both not be rejected by the network but will also automatically create their account for them offering a seamless onboarding process.

The proposed changes are made in alignment with the current implementation of allowances for similar capabilities (as seen in HIP 336).

User stories

  1. As an existing account on the network I want to be able to sponsor up to a certain HBAR limit the cost of future transaction fees due by another account by granting an explicit allowance.
  2. As an existing account on the network I want to be able to sponsor an unlimited amount of HBARs to cover the cost of future transaction fees due by another account by granting an explicit allowance.
  3. As an existing account on the network I want to be able to sponsor up to a certain HBAR limit the cost of different scopes of allowances such as transfers, fee payments and custom fees by granting an explicit allowance in a single transaction.
  4. As an existing account on the network I want to be able to sponsor up to a certain fungible token limit the cost of future token custom fee fees due by another account by granting an explicit allowance.
  5. As an account sponsoring transaction fees I want to be able to update the allowance amount higher or lower.
  6. As an account sponsoring transaction fees I want to be able to revoke the allowance amount I previously granted.
  7. As a user on the network with balance I want to be able to submit transaction that utilize my sponsors balance to pay for fees instead of mine.
  8. As a user (hollow or complete) with no balance I want to be able to submit transaction that utilize my sponsors balance to pay for fees.
  9. As a user of the network I want to be able to query the current transaction fee allowance balance granted to an account from a sponsor.
  10. As an enterprise DApp operator I want to provide a Web3 service / product but do not want to handle crypto assets as part of the operational costs.
  11. As a software provider I want to cover the transaction fees of a customer’s account to allow them to interact with my Software even with 0 HBARs in their account.
  12. As a user of the network, Alice wants to utilize funds from an already approved allowance to her to pay for transaction fees even when she has more than enough hbars to pay for the transaction herself.
  13. As a user of the network, Alice wants to utilize funds from her balance to pay for transaction fees even when she has more than enough hbars assigned to her in a transaction fee allowance to pay for the transaction.
  14. As an existing account on the network I want to be able to sponsor up to a certain HBAR limit the cost of future gas expenses transaction fees due by another account by granting an explicit allowance.

Specification

2 User journeys are illustrated below

Enterprise DApp Operator

User Story: As an enterprise DApp operator I want to provide a Web3 service / product but do not want to handle crypto assets as part of the operational costs.

User Journey:

  1. The enterprise DApp operator signs a commercial off-chain agreement with a crypto intermediary to service their crypto purchases for the operation of their DApp.
    1. The crypto intermediary whitelists the enterprise DApp operators primary Hedera account Id on their management platform (for ongoing management platforms needs).
    2. The crypto intermediaries signs and submits an AccountAllowanceApproveTransaction (using a new method of approveHbarFeeAllowance) to provide an on-chain reference to the agreement which designates the enterprise DApp operator as the spender.
      1. The fee for this transaction is covered by the crypto intermediary.
      2. The new approveHbarFeeAllowance method could allow for both fixed and unlimited values.
  2. The enterprise DApp operator configures the Crypto intermediary as their Fee Sponsor for all HBAR transaction or query costs.
    1. E.g. Client.setFeeSponsor()
  3. The enterprise DApp operator submits a signed transaction to the network, the transaction body is interrogated (by the network) for the fee_sponsor_account_id and the Fee Sponsors account identified (where present).
  4. The Fee Sponsor’s Account is interrogated (by the network) for a Fee Allowance using the enterprise DApp operators account Id
    1. The transaction succeeds if the allowance is present and has either:
      1. unlimited remaining allowance; or
      2. A remaining balance greater than the current transaction fee
    2. Otherwise the transaction fails.
  5. Where the transaction succeeds, the HBAR fees for the transaction are deducted from the Fee Sponsors account.
    1. The enterprise DApp operators HBAR account balance (used to sign the transaction) is left untouched
    2. The enterprise DApp operator’s HBAR balance can be zero.
  6. The transaction is successful.

Enterprise Software Provider

User Story: As a software provider I want to cover the transaction fees of a customer’s account to allow them to interact with my Software even with 0 HBARs in their account.

User Journey:

  1. The software provider signs an AccountAllowanceApproveTransaction (using a new method of approveHbarFeeAllowance) which designates the customer as the spender.
    1. The fee for this transaction is covered by the software provider.
    2. The new approveHbarFeeAllowance method could allow for both fixed and unlimited values.
  2. The software provider sets the customer’s fee sponsor as the software provider’s dedicated fee account (and synchronizes this with customer’s software for use during transaction submission).
  3. The customer submits a signed transaction to the network, the transaction body is interrogated (by the network) for the fee_sponsor_account_id and the Fee Sponsors account identified (where present).
  4. The Fee Sponsor’s Account is interrogated (by the network) for a Fee Allowance using the customer’s account Id.
    1. The transaction succeeds if the allowance is present and has either:
      1. unlimited remaining allowance; or
      2. A remaining balance greater than the current transaction fee
    2. Otherwise the transaction fails.
  5. Where the transaction succeeds, the HBAR fees for the transaction are deducted from the Fee Sponsors account (i.e. the software provider).
    1. The customer’s HBAR account balance (used to sign the transaction) is left untouched
    2. The customer’s HBAR balance can be zero.
  6. The transaction is successful.

Protobuf

A new allowance scope will be added to help define which type of fee an allowance can be used for

    enum AllowanceScope {
        /**
         * Identifies the allowance value may be used to satisfy crypto transfer transactions.
         */
        CRYPTO_TRANSFER = 0;

        /**
         * Identifies the allowance value may be used to satisfy the hbar settlement of gas on the network.
         */
        GAS_FEES = 1;

        /**
         * Identifies the allowance value may be used to satisfy HAPI transactions fees due by the node, network and
         * service.
         */
        TRANSACTION_FEES = 2;

        /**
         * Identifies the allowance value may be used to satisfy token custom fee due to the fee collector.
         */
        TOKEN_CUSTOM_FEES = 3;
    }

Existing allowance types will need to be updated to specify the scopes

    /**
    * An approved allowance of hbar transfers for a spender.
    */
    message CryptoAllowance {
        ...

        /**
        * The applicable scope for this CryptoAllowance. 
        */
        repeated AllowanceScope scope = 4;
    }

By default existing crypto allowances will map to a CryptoAllowance with scope CRYPTO_TRANSFER.

Note: To achieve the unlimited hbar allowance functionality the network should support -1 as a value for amount. This draws inspiration from HIP 904 as an optimization.

    /**
    * An approved allowance of non-fungible token transfers for a spender.
    */
    message NftAllowance {
        ...

        /**
        * The applicable scope for this NftAllowance. 
        */
        repeated AllowanceScope scope = 7;
    }

By default existing nft allowances will map to a TokenAllowance with scope CRYPTO_TRANSFER

    /**
    * An approved allowance of fungible token transfers for a spender.
    */
    message TokenAllowance {
        ...

        /**
        * The applicable scope for this TokenAllowance. 
        */
        repeated AllowanceScope scope = 5;
    }

By default existing nft allowances will map to an NftAllowance with scope CRYPTO_TRANSFER

Note: After this HIP allowances will require explicit specification of the intended scope by the owner to set non CRYPTO_TRANSFER allowances.

The updated TransactionBody will contain the sponsoring account identifier

    /**
     * A value transfer sponsor claim.
     */
    message TransactionSponsorClaim {
        /**
         * The account an spender is noting has provided prior willingness through an transaction fee allowance to
         * sponsor transaction fees
         */
        AccountID sponsor_account_id = 1;

        /**
         * The intended allowance scope a spender is noting an owner will cover. 
         */
        AllowanceScope scope = 2;
    }

    message TransactionBody {
        ...

        /**
         * A set of transaction sponsor claims a user is intending to utilize to cover value transfers in this
         * transaction
         */
        repeated TransactionSponsorClaim transaction_sponsor_claim = 53;
    }

The updated QueryHeader transaction would also contain the sponsored transaction identifier

    message QueryHeader {
        ...

        /**
         * The account a spender is noting has provided prior willingness through an HBAR allowance to sponsor the
         * query transaction fees
         */
        AccountID sponsor_account_id = 3;
    }

Note: A user must specify the sponsor_account_id for the network to consider the validity of the sponsored transaction. If not specified, the network will treat this as a normal transaction in which the submitter is due the transaction fees.

Error Cases

As with normal transaction it’s possible for a sponsored transaction to fail. Existing transaction network rules will be applicable.

A node that encounters an invalid sponsoring account value will respond with a new response code

    enum ResponseCodeEnum {
        ...

        INVALID_SPONSOR_ACCOUNT = 352;
    }

Transaction sponsorship will be complete in nature, a sponsor must be able to cover the full fee. In the case a sponsor lacks insufficient balance to cover an account that transaction will fail with a new response code.

    enum ResponseCodeEnum {
        ...
        
        INSUFFICIENT_SPONSOR_ACCOUNT_BALANCE = 353;
    }

Transaction Id

Currently the transaction id of any submitted transaction takes the form of <accountId>@<validStartTime> format. Usually the accountId signifies the user who both submitted and paid for the transaction. With the changes from this HIP the accountId value in the transaction id of a sponsored transaction will refer only to the submitter and no longer the payer. The accountId of the payer will be located in the transaction body.

System Contract Functions

Similar to HIP 906, the system contract interface would need to be updated to support the management of allowances with scope by a smart contract.

The following functions are introduced in this HIP

    interface IHRC1068 {
        enum AllowanceScope {
            CRYPTO_TRANSFER,
            GAS_FEES,
            TRANSACTION_FEES,
            TOKEN_CUSTOM_FEES
        }

        /// extensions of HIP 514
        function approve(address token, address spender, uint256 amount, AllowanceScope allowanceScope) external
            returns (int64 responseCode);
        function approveNFT(address token, address approved, uint256 serialNumber, AllowanceScope allowanceScope)
            external returns (int64 responseCode);
        function setApprovalForAll(address token, address operator, bool approved, AllowanceScope allowanceScope)
            external returns (int64 responseCode);

        /// extensions of HIP 906
        function hbarAllowance(address spender, AllowanceScope allowanceScope) external returns (int64 responseCode,
            int256 amount);
        function hbarApprove(address spender, int256 amount, AllowanceScope allowanceScope) external
            returns (int64 responseCode);
    }

IHRC1068 token methods will be callable via the HTS system contract at 0x167. | Hash | Selector | HAPI Service (system contract address) | | ————- | ——— | ————- | | 0x26169428 | approve(address owner, address token, address spender, uint256 amount, AllowanceScope allowanceScope) external returns (int64 responseCode) | HTS (0x167) | | 0x8c9ba2cf | approveNFT(address owner, address token, address approved, uint256 serialNumber, AllowanceScope allowanceScope) external returns (int64 responseCode) | HTS (0x167) | | 0xba62976f | setApprovalForAll(address owner, address token, address operator, bool approved, AllowanceScope allowanceScope) external returns (int64 responseCode) | HTS (0x167) |

IHRC1068 account methods will be callable via the Hedera Account Service (HAS) system contract at 0x16a. | Hash | Selector | HAPI Service (system contract address) | | ————- | ——— | ————- | | 0x8d9efb14 | hbarAllowance(address spender, AllowanceScope allowanceScope) external returns (int64 responseCode, int256 amount) | CryptoService (0x16a) | | 0xd37b634d | hbarApprove(address owner, address spender, int256 amount, AllowanceScope allowanceScope) external returns (int64 responseCode) | CryptoService (0x16a) |

The following IHRC1068 methods will be directly callable by EOAs from a DApp and do not require a deployed smart contract. The contract address in this case is the applicable account or token evmAddress | Hash | Selector | HAPI Service | Contract facade address | | ————- | ——— | ————- | ————————- | | 0x769d9bc6 | approve(address spender, uint256 amount, AllowanceScope allowanceScope) external returns (int64 responseCode) | HTS | Token address | | 0x94d1d8ae | approveNFT(address approved, uint256 serialNumber, AllowanceScope allowanceScope) external returns (int64 responseCode) | HTS | Token address | | 0x0ad33e14 | setApprovalForAll(address operator, bool approved, AllowanceScope allowanceScope) external returns (int64 responseCode) | HTS | Token address | | 0x585ea2ab | hbarApprove(address spender, int256 amount, AllowanceScope allowanceScope) external returns (int64 responseCode) | CryptoService | Account address |

SDK API

With the introduction of new allowance scopes, the SDK will need to expose the functionality to developers. The following transactions will need to be expanded with the scope concept

  • AccountAllowanceApproveTransaction
  • AccountAllowanceAdjustTransaction
  • AccountAllowanceDeletionTransaction

Mirror Node API

The Mirror Node allowance REST APIs would need to be updated to support the applicable scope concept values.

getCryptoAllowances

The /api/v1/accounts/{idOrAliasOrEvmAddress}/allowances/crypto would need to be updated to to support all scopes.

    {
        "allowances": [
            {
                ...,
                "scope": "CRYPTO_TRANSFER"
            },
            {
                ...,
                "scope": "GAS_FEES"
            },
            {
                ...,
                "scope": "TOKEN_CUSTOM_FEES"
            },
            {
                ...,
                "scope": "TRANSACTION_FEES"
            }
        ],
        "links": {
            "next": null
        }
    }

A new query param ?scope=(CRYPTO_TRANSFER|GAS_FEES|TOKEN_CUSTOM_FEES|TRANSACTION_FEES) would be added to allow users to filter on the specific applicable scope type.

getTokenAllowances

The /api/v1/accounts/{idOrAliasOrEvmAddress}/allowances/nfts would need to be updated to to support scopes CRYPTO_TRANSFER and TOKEN_CUSTOM_FEES.

    {
        "allowances": [
            {
                ...,
                "scope": "CRYPTO_TRANSFER"
            },
            {
                ...,
                "scope": "TOKEN_CUSTOM_FEES"
            }
        ],
        "links": {
            "next": null
        }
    }

A new query param ?scope=(CRYPTO_TRANSFER|TOKEN_CUSTOM_FEES) would be added to allow users to filter on the specific applicable scope type.

getNftAllowances

The /api/v1/accounts/{idOrAliasOrEvmAddress}/allowances/tokens would need to be updated to to support scopes CRYPTO_TRANSFER and TOKEN_CUSTOM_FEES.

    {
        "allowances": [
            {
                ...,
                "scope": "CRYPTO_TRANSFER"
            },
            {
                ...,
                "scope": "TOKEN_CUSTOM_FEES"
            }
        ],
        "links": {
            "next": null
        }
    }

A new query param ?scope=(CRYPTO_TRANSFER|TOKEN_CUSTOM_FEES) would be added to allow users to filter on the specific applicable scope type.

Backwards Compatibility

Currently the ledger allows for sponsored transaction fees by charging the transaction submitter/payer. This HIP does not conflict with this flow, but rather adds an additional flow.

There are minor changes to existing allowance concepts in teh form of an addition so there should be no regression in feature support. To ensure this the current allowances prior to the HIP are defaulted for clarity to cover the CRYPTO_TRANSFER scope.

Security Implications

This HIP builds on the existing allowance feature functionality and security measures. No new approval authorization logic was added, rather this HIP allows users to scope their allowance for specific user intents. Consensus node logic will need to be added to ensure the expensed scope matches the intended scope.

How to Teach This

SDK examples, blogs and tutorials on docs.hedera.com

Reference Implementation

Rejected Ideas

Partial Payments

The idea of partial payments was initially considered in which an account could sponsor a sub amount of fees (finite or percentage) in a transaction and a user would cover the rest. However, this flow becomes unnecessarily complex and the need isn’t clear initially. As such sponsorship of fees will be complete and not partial - if an account sponsors a transaction fee it much have provided enough in the allowance to cover the whole transaction fee. If this is not the case the transaction will fail.

Additional Allowance Types

Initially 2 new Allowance types were proposed (TransactionFeeAllowance and CustomFeeAllowance) to capture the ability to sponsor transaction and token custom fees. Though functional this would result in a larger API surface to specify the multiple scenarios. Instead teh simple concept of a scope of applicability of each allowance was discussed and agreed upon. The simple scope concept is cleaner and can be added to the existing allowance types.

Open Issues

  • Q: How would EVM tools utilize teh ability to sponsor gas settlement fees via the the eth_sendRawTransaction flow? There’s no API compliant way to specify per transaction an EOA intent to use their allowance. Could the eth_sendRawTransaction (as a custom hedera JSON RPC API) and EthereumTransaction be extended to capture the intended sporing account?

References

Copyright/license

This document is licensed under the Apache License, Version 2.0 – see LICENSE or (https://www.apache.org/licenses/LICENSE-2.0)

Citation

Please cite this document as: