【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的主要内容,如果未能解决你的问题,请参考以下文章