mirror of
https://github.com/status-im/EIPs.git
synced 2025-02-23 12:18:16 +00:00
ERC-1363 Payable Token (#2496)
* Add EIP 1363 * Update to solidity 0.6 and use external instead of public
This commit is contained in:
parent
5cf7132ae1
commit
4c1bf4dd1b
209
EIPS/eip-1363.md
Normal file
209
EIPS/eip-1363.md
Normal file
@ -0,0 +1,209 @@
|
||||
---
|
||||
eip: 1363
|
||||
title: ERC-1363 Payable Token
|
||||
author: Vittorio Minacori (@vittominacori)
|
||||
discussions-to: https://github.com/ethereum/eips/issues/1363
|
||||
status: Draft
|
||||
type: Standards Track
|
||||
category: ERC
|
||||
created: 2020-01-31
|
||||
requires: 20, 165
|
||||
---
|
||||
|
||||
## Simple Summary
|
||||
Description of a **Payable Token** compatible with the ERC-20 definition.
|
||||
Also description of a Token **Receiver** and/or **Spender** that accepts Payable Token payments.
|
||||
|
||||
## Abstract
|
||||
The following describes standard functions a token contract and contracts working with specified token can implement to make a Token Payable.
|
||||
|
||||
## Motivation
|
||||
This proposal allows to implement an ERC-20 compatible token that can be used for payments.
|
||||
|
||||
It defines `transferAndCall` and `transferFromAndCall` functions that will call an `onTransferReceived` on a `ERC1363Receiver` contract.
|
||||
It defines `approveAndCall` functions that will call an `onApprovalReceived` on a `ERC1363Spender` contract.
|
||||
|
||||
This proposal is inspired by the ERC-721 `onERC721Received` and `ERC721TokenReceiver` behaviours.
|
||||
|
||||
## Specification
|
||||
Every Payable Token compliant contract MUST implement the ERC-1363 interface other than ERC-20 and ERC-165 interfaces.
|
||||
|
||||
```solidity
|
||||
pragma solidity ^0.6.0;
|
||||
|
||||
|
||||
interface ERC1363 /* is ERC20, ERC165 */ {
|
||||
/*
|
||||
* Note: the ERC-165 identifier for this interface is 0x4bbee2df.
|
||||
* 0x4bbee2df ===
|
||||
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
|
||||
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
|
||||
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
|
||||
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)'))
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note: the ERC-165 identifier for this interface is 0xfb9ec8ce.
|
||||
* 0xfb9ec8ce ===
|
||||
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
|
||||
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
|
||||
*/
|
||||
|
||||
/**
|
||||
* @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver
|
||||
* @param to address The address which you want to transfer to
|
||||
* @param value uint256 The amount of tokens to be transferred
|
||||
* @return true unless throwing
|
||||
*/
|
||||
function transferAndCall(address to, uint256 value) external returns (bool);
|
||||
|
||||
/**
|
||||
* @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver
|
||||
* @param to address The address which you want to transfer to
|
||||
* @param value uint256 The amount of tokens to be transferred
|
||||
* @param data bytes Additional data with no specified format, sent in call to `to`
|
||||
* @return true unless throwing
|
||||
*/
|
||||
function transferAndCall(address to, uint256 value, bytes memory data) external returns (bool);
|
||||
|
||||
/**
|
||||
* @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver
|
||||
* @param from address The address which you want to send tokens from
|
||||
* @param to address The address which you want to transfer to
|
||||
* @param value uint256 The amount of tokens to be transferred
|
||||
* @return true unless throwing
|
||||
*/
|
||||
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
|
||||
|
||||
|
||||
/**
|
||||
* @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver
|
||||
* @param from address The address which you want to send tokens from
|
||||
* @param to address The address which you want to transfer to
|
||||
* @param value uint256 The amount of tokens to be transferred
|
||||
* @param data bytes Additional data with no specified format, sent in call to `to`
|
||||
* @return true unless throwing
|
||||
*/
|
||||
function transferFromAndCall(address from, address to, uint256 value, bytes memory data) external returns (bool);
|
||||
|
||||
/**
|
||||
* @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender
|
||||
* and then call `onApprovalReceived` on spender.
|
||||
* Beware that changing an allowance with this method brings the risk that someone may use both the old
|
||||
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
|
||||
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
|
||||
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
|
||||
* @param spender address The address which will spend the funds
|
||||
* @param value uint256 The amount of tokens to be spent
|
||||
*/
|
||||
function approveAndCall(address spender, uint256 value) external returns (bool);
|
||||
|
||||
/**
|
||||
* @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender
|
||||
* and then call `onApprovalReceived` on spender.
|
||||
* Beware that changing an allowance with this method brings the risk that someone may use both the old
|
||||
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
|
||||
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
|
||||
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
|
||||
* @param spender address The address which will spend the funds
|
||||
* @param value uint256 The amount of tokens to be spent
|
||||
* @param data bytes Additional data with no specified format, sent in call to `spender`
|
||||
*/
|
||||
function approveAndCall(address spender, uint256 value, bytes memory data) external returns (bool);
|
||||
}
|
||||
|
||||
interface ERC20 {
|
||||
function totalSupply() external view returns (uint256);
|
||||
function balanceOf(address account) external view returns (uint256);
|
||||
function transfer(address recipient, uint256 amount) external returns (bool);
|
||||
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
|
||||
function allowance(address owner, address spender) external view returns (uint256);
|
||||
function approve(address spender, uint256 amount) external returns (bool);
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
}
|
||||
|
||||
interface ERC165 {
|
||||
function supportsInterface(bytes4 interfaceId) external view returns (bool);
|
||||
}
|
||||
```
|
||||
|
||||
A contract that wants to accept token payments via `transferAndCall` or `transferFromAndCall` MUST implement the following interface:
|
||||
|
||||
```solidity
|
||||
/**
|
||||
* @title ERC1363Receiver interface
|
||||
* @dev Interface for any contract that wants to support transferAndCall or transferFromAndCall
|
||||
* from ERC1363 token contracts.
|
||||
*/
|
||||
interface ERC1363Receiver {
|
||||
/*
|
||||
* Note: the ERC-165 identifier for this interface is 0x88a7ca5c.
|
||||
* 0x88a7ca5c === bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))
|
||||
*/
|
||||
|
||||
/**
|
||||
* @notice Handle the receipt of ERC1363 tokens
|
||||
* @dev Any ERC1363 smart contract calls this function on the recipient
|
||||
* after a `transfer` or a `transferFrom`. This function MAY throw to revert and reject the
|
||||
* transfer. Return of other than the magic value MUST result in the
|
||||
* transaction being reverted.
|
||||
* Note: the token contract address is always the message sender.
|
||||
* @param operator address The address which called `transferAndCall` or `transferFromAndCall` function
|
||||
* @param from address The address which are token transferred from
|
||||
* @param value uint256 The amount of tokens transferred
|
||||
* @param data bytes Additional data with no specified format
|
||||
* @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))`
|
||||
* unless throwing
|
||||
*/
|
||||
function onTransferReceived(address operator, address from, uint256 value, bytes memory data) external returns (bytes4);
|
||||
}
|
||||
```
|
||||
|
||||
A contract that wants to accept token payments via `approveAndCall` MUST implement the following interface:
|
||||
|
||||
```solidity
|
||||
/**
|
||||
* @title ERC1363Spender interface
|
||||
* @dev Interface for any contract that wants to support approveAndCall
|
||||
* from ERC1363 token contracts.
|
||||
*/
|
||||
interface ERC1363Spender {
|
||||
/*
|
||||
* Note: the ERC-165 identifier for this interface is 0x7b04a2d0.
|
||||
* 0x7b04a2d0 === bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))
|
||||
*/
|
||||
|
||||
/**
|
||||
* @notice Handle the approval of ERC1363 tokens
|
||||
* @dev Any ERC1363 smart contract calls this function on the recipient
|
||||
* after an `approve`. This function MAY throw to revert and reject the
|
||||
* approval. Return of other than the magic value MUST result in the
|
||||
* transaction being reverted.
|
||||
* Note: the token contract address is always the message sender.
|
||||
* @param owner address The address which called `approveAndCall` function
|
||||
* @param value uint256 The amount of tokens to be spent
|
||||
* @param data bytes Additional data with no specified format
|
||||
* @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))`
|
||||
* unless throwing
|
||||
*/
|
||||
function onApprovalReceived(address owner, uint256 value, bytes memory data) external returns (bytes4);
|
||||
}
|
||||
```
|
||||
|
||||
## Rationale
|
||||
There are many proposed uses of Ethereum smart contracts that can accept ERC-20 payments (i.e. to create a token payable crowdsale, selling services for tokens, paying invoices, making subscriptions, use them for a specific utility and many other purposes).
|
||||
|
||||
This proposal wants to make token payments easier and working without the use of any other listener. It also allows to make a callback after a transfer in a single transaction.
|
||||
|
||||
## Backwards Compatibility
|
||||
This proposal is inspired also by ERC-223 and ERC-677 but it uses the ERC-721 approach so it doesn't override the ERC-20 `transfer` and `transferFrom` methods and defines the interfaces IDs to be implemented maintaining the ERC-20 backwards compatibility.
|
||||
|
||||
## Test Cases
|
||||
[https://github.com/vittominacori/erc1363-payable-token/tree/master/test](https://github.com/vittominacori/erc1363-payable-token/tree/master/test)
|
||||
|
||||
## Implementation
|
||||
[https://github.com/vittominacori/erc1363-payable-token/tree/master/contracts/token/ERC1363](https://github.com/vittominacori/erc1363-payable-token/tree/master/contracts/token/ERC1363)
|
||||
|
||||
## Copyright
|
||||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|
Loading…
x
Reference in New Issue
Block a user