ERC1363: Payable Token Standard
Seamless token callbacks in a single transaction.
Introduction
ERC1363, also known as the “Payable Token Standard,” is one such innovation that addresses inefficiencies in token transactions and opens doors to a wide range of possibilities for developers and users alike.

What is ERC1363?
ERC1363 is an extension of the ERC20 token standard that introduces two key functionalities:
transferAndCall
andtransferFromAndCall
: A single-step token transfer and interaction with a contract.approveAndCall
: A single-step token approval and contract interaction.
These methods simplify token transactions by enabling smart contracts to respond to token transfers or approvals in real-time, reducing the need for multi-step processes. Essentially, ERC1363 tokens are payable tokens, making them ideal for seamless interactions with dApps and smart contracts.
The official documentation can be found on EIP-1363, and its implementation details are available on GitHub.
How It Works
ERC1363 Methods
transferAndCall
and transferFromAndCall
:
- Transfers tokens to a recipient and immediately triggers the
onTransferReceived
function on the recipient’s contract. - Additional
data
with no specified format are passed in callback. - Ideal for scenarios where the recipient is a smart contract that needs to execute logic upon receiving tokens (e.g., purchasing an NFT via tokens).
function transferAndCall(
address to,
uint256 value
) external returns (bool);
function transferAndCall(
address to,
uint256 value,
bytes calldata data
) external returns (bool);
function transferFromAndCall(
address from,
address to,
uint256 value
) external returns (bool);
function transferFromAndCall(
address from,
address to,
uint256 value,
bytes calldata data
) external returns (bool);
approveAndCall
:
- Grants allowance to a contract and immediately calls its
onApprovalReceived
function. - Additional
data
with no specified format are passed in callback. - Useful for enabling contracts to react dynamically to approval events without waiting for a second transaction.
function approveAndCall(
address spender,
uint256 value
) external returns (bool);
function approveAndCall(
address spender,
uint256 value,
bytes calldata data
) external returns (bool);
Receiver and Spender Contracts
ERC1363 also introduces two key interfaces to facilitate interaction with recipient and spender contracts:
IERC1363Receiver
:
Defines the onTransferReceived
function, which is triggered when a token transfer is performed using transferAndCall
. Allows recipient contracts to execute custom logic (e.g., recording payments, processing orders) when tokens are transferred.
function onTransferReceived(
address operator,
address from,
uint256 value,
bytes calldata data
) external returns (bytes4);
IERC1363Spender
:
Defines the onApprovalReceived
function, which is triggered when a token approval is performed using approveAndCall
. Enables spender contracts to react immediately to approvals, such as initiating staking or swaps.
function onApprovalReceived(
address owner,
uint256 value,
bytes calldata data
) external returns (bytes4);
Interaction Flow
- A user initiates a
transferAndCall
orapproveAndCall
transaction from their wallet or dApp interface. - The ERC1363 token executes the transfer or approval.
- The recipient contract’s callback function (
onTransferReceived
oronApprovalReceived
) is triggered automatically. - The contract executes its predefined logic, such as processing payments or executing swaps.
The Problem
Before ERC1363, interacting with ERC20 tokens in smart contracts typically required multiple transactions:
- First, a user would call
approve
on the token contract to authorize another contract to use their tokens. - Next, the user would interact with the recipient contract, which would call
transferFrom
to retrieve the approved tokens.
This process introduced:
- Inefficiency: Requiring two transactions doubles gas costs.
- Poor User Experience: Users had to manually approve tokens before interacting with dApps.
- Increased Complexity: Developers had to manage approval workflows and account for edge cases.
The Solution
ERC1363 streamlines this process by combining token transfers or approvals with immediate execution of recipient contract logic in a single transaction. This results in:
- Reduced Gas Costs: By eliminating the need for a second transaction.
- Enhanced User Experience: Users can execute actions (e.g., purchasing, staking) in one seamless step.
- Simplified Development: Developers can rely on standardized callback functions without writing custom workflows.
- Backwards Compatibility: Unlike other ERC20 extension proposals, ERC1363 doesn’t override the ERC20 standard methods and defines the interfaces IDs to be implemented maintaining backward compatibility with ERC-20.
Use Cases
1. Token-Based Subscriptions
Recurring payments for services can be automated using approveAndCall
. For example:
- A user gives tokens allowance to a subscription contract (i.e. yearly subscription).
- The contract’s
onApprovalReceived
logic ensures the subscription is activated and the user’s first month payment is done. - Contract could also just activate the first month of a trial and then start paying from the following month until the subscription expires.
2. Instant Payments to Smart Contracts
For marketplaces, users can purchase items by transferring tokens directly to the seller’s contract. The onTransferReceived
function can verify and complete the sale.
3. DeFi Integrations
ERC1363 can enable seamless interactions with liquidity pools, staking contracts, or yield farming protocols. Users can approve tokens and execute actions (e.g., staking) in one transaction using approveAndCall
.
Examples
Please note that the examples below are not verified and are for demonstration purposes only.
Example 1: Receiving Payments
Here’s a simple Solidity contract to handle ERC1363 token deposits:
pragma solidity ^0.8.0;
import "erc-payable-token/contracts/token/ERC1363/IERC1363Receiver.sol";
contract DepositManager is IERC1363Receiver {
mapping(address account => uint256) public credits;
function onTransferReceived(
address operator,
address from,
uint256 value,
bytes calldata data
) external returns (bytes4) {
// any security check
// update user credits once received
credits[from] += value;
// any custom logic
return this.onTransferReceived.selector;
}
}
Example 2: Approving and Reacting
A contract that stakes tokens upon approval:
pragma solidity ^0.8.0;
import "erc-payable-token/contracts/token/ERC1363/IERC1363Spender.sol";
contract StakingContract is IERC1363Spender {
mapping(address => uint256) public stakes;
function onApprovalReceived(
address owner,
uint256 value,
bytes calldata data
) external returns (bytes4) {
// the ERC1363 contract is always the caller
address token = msg.sender;
// transfer tokens into this contract
IERC20(token).transferFrom(owner, address(this), value);
// update user stakes
stakes[owner] += value;
return this.onApprovalReceived.selector;
}
}
Example 3: Crowdfunding Campaign
A contract to handle crowdfunding contributions using transferAndCall
:
pragma solidity ^0.8.0;
import "erc-payable-token/contracts/token/ERC1363/IERC1363Receiver.sol";
contract Crowdfunding is IERC1363Receiver {
mapping(address => uint256) public contributions;
uint256 public totalFunds;
function onTransferReceived(
address operator,
address from,
uint256 value,
bytes calldata data
) external returns (bytes4) {
contributions[from] += value;
totalFunds += value;
return this.onTransferReceived.selector;
}
}
Example 4: Fee-Charging Contract
A contract that deducts a fee on every token transfer using onTransferReceived
:
pragma solidity ^0.8.0;
import "erc-payable-token/contracts/token/ERC1363/IERC1363Receiver.sol";
contract FeeManager is IERC1363Receiver {
address public feeCollector;
uint256 public feePercentage; // basis point
constructor(address _feeCollector, uint256 _feePercentage) {
feeCollector = _feeCollector;
feePercentage = _feePercentage;
}
function onTransferReceived(
address operator,
address from,
uint256 value,
bytes calldata data
) external returns (bytes4) {
address token = msg.sender;
uint256 fee = (value * feePercentage) / 10000;
uint256 netAmount = value - fee;
// transfer fee to feeCollector
IERC20(token).transfer(feeCollector, value);
// business logic with netAmount here
return this.onTransferReceived.selector;
}
}
View more examples here.
Conclusion
ERC1363 bridges the gap between token standards and user-friendly blockchain interactions. By enabling seamless payments and approvals in a single step, it reduces costs, enhances usability, and opens the door to new possibilities in DeFi, gaming, and beyond. If you’re building on Ethereum or L2, consider adopting ERC1363 to simplify your workflows and delight your users.
For more details, visit the official EIP-1363 or explore its Reference Implementation.
Official website: erc1363.org
Easily deploy ERC1363 on Ethereum using Token Generator.