HIP-376: Support Approve/Allowance/transferFrom standard calls from ERC20 and ERC721
Author | Stoyan Panayotov |
---|---|
Discussions-To | https://github.com/hashgraph/hedera-improvement-proposal/discussions/378 |
Status | Final ⓘ |
Needs Council Approval | Yes ⓘ |
Review period ends ⓘ | Wed, 06 Apr 2022 07:00:00 +0000 |
Type | Standards Track ⓘ |
Category | Service ⓘ |
Created | 2022-03-02 |
Updated | 2022-11-14 |
Requires | 206, 218, 336 |
Release | v0.26.0 |
Table of Contents
Abstract
Describe the added support for industry standart ERC20
and ERC721
functions related to token approvals and allowances in Hedera’s Smart Contract Service.
Motivation
The goal is to expose HIP-336: Approval and Allowance API for Tokens functionality in industry standard ERC-20
and ERC-721
calls for smart contract developers on Hedera.
User stories
Fungible token related stories
As a hedera smart contract services user, I want to enable another user or contract the ability to spend x
fungible tokens from my account so that they can trade on my behalf without requiring that I expose my private key to them.
As a hedera smart contract services user, I want to query tokens for the current token allowances that have been granted to a user (spender) for a specific owner account.
As a hedera smart contract services user, I want to modify or remove an allowance I have granted to another user or contract so that I can manage that user/contract’s ability to spend my tokens over time.
As a hedera smart contract services user that has been granted an allowance, I want to be able to transfer tokens owned by the owner account as if they were my tokens so that I can issue transfers on their behalf without them having to expose their private key.
Non-fungible token related stories
As a hedera smart contract services user, I want to enable another user the ability to spend specific non-fungible tokens from my account so that they can trade on my behalf without requiring that I expose my private key to them.
As a hedera smart contract services user, I want to enable or disable another user the ability to spend all instances of a particular non-fungible token that I currently or may in the future hold in my account so that they can trade on my behalf without requiring that I expose my private key to them.
As a hedera smart contract services user, I want to modify or remove an allowance I have granted to another user so that I can manage that user’s ability to spend my tokens over time.
As a hedera smart contract services user, I want to query a token for the information whether an account has approve for all nfts permission.
As a hedera smart contract services user that has been granted an allowance, I want to be able to transfer tokens owned by the owner account as if they were my tokens so that I can issue transfers on their behalf without them having to expose their private key.
Specification
EVM Precompile
Extend the functionality from HIP-218: Smart Contract interactions with Hedera Token Accounts with support for approve
, allowance
and transferFrom
functions.
Supported ERC-20 operations
Tokens of type FUNGIBLE_COMMON
support standard ERC-20
calls.
The following ERC-20
operations will be supported. Standard ERC-20 Events
will be emitted as appropriate.
function allowance(address owner, address spender) external view returns (uint256);
Returns the remaining number of tokens that spender
will be allowed to spend on behalf of owner
through transferFrom
. This is zero by default. This value changes when approve
or transferFrom
are called.
Works by loading the owner FUNGIBLE_TOKEN_ALLOWANCES
from the accounts ledger and returning the allowance approved for spender
.
function approve(address spender, uint256 amount) external returns (bool);
Sets amount
as the allowance of spender
over the caller’s tokens.
Works by creating a synthetic CryptoApproveAllowanceTransaction
with payer - the account that called the precompile (the message sender property of the message frame in the EVM). Fires an approval event with the following signature when executed:
event Approval(address indexed owner, address indexed spender, uint256 value);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
Moves amount
tokens from from
to to
using the allowance mechanism. amount
is then deducted from the caller’s allowance.
Works by creating a synthetic CryptoTransferTransaction
with fungible token transfers with the is_approval
property set to true.
Supported ERC-721 operations
Tokens of type NON_FUNGIBLE_UNIQUE
will support standard ERC-721
calls.
The following ERC-721
operations will be supported. Standard ERC-721 Events
will be emitted as appropriate.
- function approve(address to, uint256 tokenId) external;
Gives permission to to
to transfer tokenId
token to another account. The approval is cleared when the token is transferred.
Works by creating a synthetic CryptoApproveAllowanceTransaction
with payer - the account that called the precompile (the message sender property of the message frame in the EVM).
If the spender
address is 0, this creates a CryptoDeleteAllowanceTransaction
instead and removes any allowances previously approved on the token.
Fires an approval event with the following signature when executed:
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
function setApprovalForAll(address operator, bool approved) external
Approve or remove operator
as an operator for the caller. Operators can call transferFrom
for any token owned by the caller.
Works by creating a synthetic CryptoApproveAllowanceTransaction
with payer - the account that called the precompile (the message sender property of the message frame in the EVM).
function getApproved(uint256 tokenId) external view returns (address)
Returns the account approved for tokenId
token.
Works by loading the SPENDER
property of the token from the NFTs ledger.
function isApprovedForAll(address owner, address operator) external view returns (bool)
Returns if the operator
is allowed to manage all of the assets of owner
.
Works by loading the APPROVE_FOR_ALL_NFTS_ALLOWANCES
property of the owner account and verifying if the list of approved for all accounts contains the account id of the operator
.
function transferFrom(address from, address to, uint256 tokenId) external payable
Transfers tokenId
token from from
to to
.
Works by creating a synthetic CryptoTransferTransaction
with nft token transfers with the is_approval
property set to true.
HAPI payer, allowance and signatures for transferFrom
HAPI cryptoTransfer
functions using allowance work with the transaction payer - this is the account that should have allowance to spend the tokens.
ERC20/721 transferFrom
functions work with msg.sender
and that is the account that will be verified in the context of a precompile.
Additionaly, in HAPI TX context, the spender account must have signed the transaction for the transfer to be valid. We have already introduced an exception for signatures verification in the case when the owner
and the initiator
of a transfer through the precompile are the same account. This exception will now be extended to also include the spender
of an allowance.
Gas Schedule
For function calls that cause HTS token transfers the appropriate gas charges will be applied. Calls that emit events will be charged the event fees too.
We take the canonical max calls per second, and divide that into the 15MM gas per second, and add a 20% premium. The trick is figuring out which max TPX measure to use.
Function | Base Cost | Incremental Cost |
---|---|---|
Queries | xx Gas | 0 Gas |
Approves | xx Gas | 0 Gas |
Transfer | xx Gas | 0 Gas |
Backwards Compatibility
The existing functions in the HTS precompile will remain in place, all prior usages of the precompile will function as they did before.
Security Implications
The same implications relating to contract keys and delegate calls outlined in HIP-206 also apply to the direct support of ERC-20 and ERC-721 contracts.
How to Teach This
Tutorials and SDK examples should be written showing how solidity can access the token accounts directly as ERC-20 and ERC-721 contracts.
HSCS documentation should be updated to explicitly enumerate the supported and non-supported contract functions.
Reference Implementation
// TODO
Rejected Ideas
Open Issues
None at this time.
References
- ERC-20: Token Standard
- ERC-721: Non-Fungible Token Standard
- HIP-218: Smart Contract interactions with Hedera Token Accounts
- HIP-336: Approval and Allowance API for Tokens
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: