ERC1363: Payable Token Standard

Seamless token callbacks in a single transaction.

Vittorio Minacori
5 min readMar 13, 2025

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 and transferFromAndCall: 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

  1. A user initiates a transferAndCall or approveAndCall transaction from their wallet or dApp interface.
  2. The ERC1363 token executes the transfer or approval.
  3. The recipient contract’s callback function (onTransferReceived or onApprovalReceived) is triggered automatically.
  4. 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.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Vittorio Minacori
Vittorio Minacori

Written by Vittorio Minacori

Software Engineer, Web3 & Blockchain Innovator. Author of ERC-1363. Creator of ERC20 Token Generator.

No responses yet

Write a response