【ETH钱包开发04】web3j转账ERC-20 Token

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【ETH钱包开发04】web3j转账ERC-20 Token相关的知识,希望对你有一定的参考价值。

参考技术A 在上一篇文章中讲解了ETH转账,这一篇讲一下ERC-20 Token转账。
【ETH钱包开发03】web3j转账ETH

1、直接用web3j的API
2、java/android调用合约的 transfer 方法

不管用哪种方式来转账,你都需要先写一个solidity智能合约文件来创建ERC-20 Token,然后部署合约,最后才是通过客户端来调用。

注意:erc-20 token转账和eth转账的区别如下:
1、erc-20 token创建交易对象用的是这个方法 createTransaction

2、erc-20 token需要构建 Function ,它其实对应的就是erc-20 token合约中的那些方法。它的第一个参数就是ERC20中那几个方法的名称,第二个参数的话就是对应合约方法中的参数,第三个参数是和第二个参数对应的,按照我那样就行了。转账的话就是 transfer ,我们从合约的 transfer 可以看到第一个参数是收款地址,第二个参数是金额,所以 Function 这里对应起来就好。

这种方法不需要使用web3j封装的方法,而是直接调用solidity合约的方法。

步骤
1、web3j加载一个已经部署的合约
2、验证合约是否加载成功 isValid
3、如何加载合约成功,则调用合约的 transfer 方法

注意:
1、这里的 TokenERC20 是根据solidity智能合约生成的对应的Java类,用于java/Android和智能合约交互的,如果你对这里不太清楚,不妨看看我之前的一篇文章。
以太坊Web3j命令行生成Java版本的智能合约

2、如果加载合约失败,可能的一个原因是合约对应的Java类中的 BINARY 的值不对,这个值是你部署合约成功之后的bytecode,你最好检查对比一下。

我发送一笔交易,可以通过这个地址查询
https://rinkeby.etherscan.io/tx/0x05bd947e73068badbd9937854169f020980795da8a8182a67e9c2c1888f1874d

ERC 20 优缺点,以及 eth 3 种转账方式

ERC 20 协议的产生(优点):

  • 定义统一的函数名:名称、发行量、转账函数、转账事件等
  • 以便交易所、钱包进行集成
  • 所有实现了这些函数的合约都是 ERC20Token
  • ERC20 可以表示任何同质的可以交易的内容: 货币、股票、积分、债券、利息...
  • 可以用数量来表示的内容 基本上可以ERC20 表示

ERC 20 的缺点

以下是一个遇到很多次的场景:有一天老板过来找你(开发者),最近存币生息很火,我们也做一个合约吧, 用户打币过来给他计算利息, 看起来是一个很简单的需求,你满口答应说好,结果自己一研究发现,使用 ERC20 标准没办法在合约里记录是谁发过来多少币,从而没法计算利息(因为接收者合约并不知道自己接收到ERC20代币)。

ERC20 标准下,可以通过一个变通的办法,采用两个交易组合完成,方法是:第1步:先让用户把要转移的金额用 ERC20 的approve 授权的存币生息合约(这步通常称为解锁),第2步:再次让用户调用存币生息合约的计息函数,计息函数中通过 transferFrom 把代币从用户手里转移的合约内,并开始计息。

同样由于ERC20 标准没有一个转账通知机制,很多ERC20代币误转到合约之后,再也没有办法把币转移出来,已经有大量的ERC20 因为这个原因被锁死。

另外一个问题是ERC20 转账时,无法携带额外的信息,例如:我们有一些客户希望让用户使用 ERC20 代币购买商品,因为转账没法携带额外的信息, 用户的代币转移过来,不知道用户具体要购买哪件商品,从而展加了线下额外的沟通成本。

如何解决 ERC 20 中存在的问题

使用这个ERC777:send(dest, value, data) 解决。

ERC777 使用 send转账时会分别在持有者和接收者地址上使用ERC1820 的getInterfaceImplementer函数进行查询,查看是否有对应的实现合约,ERC777 标准规范里预定了接口及函数名称,如果有实现则进行相应的调用。

即便是一个普通用户地址,同样可以实现对 ERC777 转账的监听, 听起来有点神奇,其实这是通过 ERC1820 接口注册表合约来是实现的。

ERC1820 如此的重要,以至于ERC777单独把它拆出来作为一个EIP。

ERC1820合约提过了两个主要接口:

  • setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer)
    用来设置地址(_addr)的接口(_interfaceHash 接口名称的 keccak256 )由哪个合约实现(_implementer)。
  • getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address)
    这个函数用来查询地址(_addr)的接口由哪个合约实现。

ERC1820 是一个全局的合约,有一个唯一在以太坊链上都相同的合约地址,它总是 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24 ,这个合约是通过非常巧妙的方式进行部署的。

如果面试官问 :有没有办法不使用 erc 777 来解决误转入合约锁死?

可以查看 erc 20 的源码 发现 transfer 方法如下 :

  function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual 
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked 
            _balances[from] = fromBalance - amount;
        
        _balances[to] += amount;

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    

我们在实现自己的erc 20 合约的时候重载 _afterTokenTransfer 这个方法 。

并且判断 我们这个代币 如果转入的是合约,就要就他实现一个接受代币的方法 。

这种处理方式是有 副作用的 ,比如你转到 uniswap ,等 ,他应该是没有实现你指定的方法 。

我思考 可以参考 erc 721 的做法增加一个新的函数 ,叫safexxx 来执行转账的逻辑。

eth 3 种转账方式的区别 :

erc 20:

如果要给合约转账,则需先授权给合约:合约能使用多少个币,然后才能进行转账

举例说明,如果账户A有1000个ETH,想允许B账户随意调用他的100个ETH,过程如下: 

A账户按照以下形式调用approve函数approve(B,100)
B账户想用这100个ETH中的10个ETH给C账户,调用transferFrom(A, C, 10)
调用allowance(A, B)可以查看B账户还能够调用A账户多少个token

此处的token 需要是只要符合erc20 标准的token

ERC 777

参考上面提到的 :

ERC777 使用 send转账时会分别在持有者和接收者地址上使用ERC1820 的getInterfaceImplementer函数进行查询,查看是否有对应的实现合约,ERC777 标准规范里预定了接口及函数名称,如果有实现则进行相应的调用。

ERC 2612 (ERC20 permit)

线下签名授权

(授权)可以在线下签名进行,签名信息可以在执行接收转账交易时提交到链上,让授权和转账在一笔交易里完成。 同时转账交易也可以由接收方(或其他第三方)来提交,也避免了用户(ERC20的拥有者)需要有 ETH的依赖。

以上是关于【ETH钱包开发04】web3j转账ERC-20 Token的主要内容,如果未能解决你的问题,请参考以下文章

springboot操作以太坊(eth),使用web3j,转账等

EOS区块链钱包开发教程

EOS区块链钱包开发教程

XRP钱包对接教程

XRP钱包对接教程

eth和erc20代码接入