Skip to content

ERC1003 Token Standard (ERC20 Extension) #1003

Description

@k06a
EIP: 1003
Title: ERC1003 Token Standard (ERC20 Extension)
Author: Anton Bukov <[email protected]>
Type: Token Standard
Category: ERC
Created: 2018-04-15
Updated: 2018-08-09

This standard is still a draft and is proven to be unsafe to be used

Simple Summary

An extension of the standard interface ERC20 for tokens with method that allows safely pass and handle tokens into smart contracts.

Abstract

I propose to move tokens from spender to destination contract over fake caller, which will be msg.sender.

Also this standard protects from ERC20 stealing, example:

function depositTokenCanBeStolen(address _spender, uint taskId, uint _value) public {
    require(token.transferFrom(_spender, this, _value));
    tasksBalance[_spender] += _value;
}

In case of separate calls for ERC20: approve and depositTokenCanBeStolen tokens of the stranger can be used for the task he doesn't wanna support. Someone approves tokens, and another person can spend it, that's why usually developers use tx.origin – but this prevents tx chain length scaling.

ERC827 comparison

  • In ERC827 msg.sender tells that _spender pays, you can check it only using tx.origin.
  • In ERC1003 msg.sender pays himself for _beneficiary, nothing to worry about.

Token

ERC20 Methods

All usual ERC20 methods.

ERC1003 Methods

transferToContract - ERC1003

Implementation example:

import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";

contract ERC1003Caller is Ownable {
    function makeCall(address _target, bytes _data) external payable onlyOwner returns (bool) {
        return _target.call.value(msg.value)(_data);
    }
}

contract ERC1003Token is ERC20 {
    ERC1003Caller public caller_ = new ERC1003Caller();
    address[] internal sendersStack_;

    function transferToContract(address _to, uint256 _value, bytes _data) public payable returns (bool) {
        sendersStack_.push(msg.sender);
        approve(_to, _value);
        require(caller_.makeCall.value(msg.value)(_to, _data));
        sendersStack_.length -= 1;
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
        address from = (_from != address(caller_)) ? _from : sendersStack_[sendersStack_.length - 1];
        return super.transferFrom(from, _to, _value);
    }
}

Example of smart contract, compatible with both ERC20 and ERC1003 :

function depositToken(address _beneficiary, uint _value) public {
    require(token.transferFrom(msg.sender, this, _value));
    balanceOfAccount[_beneficiary] += _value;
}

Also can deposit all allowed tokens:

function depositToken(address _beneficiary) public {
    uint256 amount = token.allowed(msg.sender, this);
    require(token.transferFrom(msg.sender, this, amount));
    balanceOfAccount[_beneficiary] += amount;
}

The only mandatory argument is _beneficiary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions