我假设你已经有了相关的基础,本次暂时只讲参数编码,什么时候有空了,再继续往后写,来补全完整签名上链过程。
前置说明
参数编码,绕不过Function这个类
可以看到构造函数也比较明确,3个参数,函数名,入参列表,出参列表。
1、普通参数的编码
例如,ERC20代币的transfer方法或transferFrom方法等。
以transfer为例
方法名为transfer,入参2个,address和uint256。
那么这个入参就比较简单
List<Type> inputs = Arrays.asList(
new Address(0x地址),
new Uint256(wei转账数量)
);
// 这里有一个金额转wei数量的方法
常用的精度也有常量可选用
Function function = new Function(funcName, inputs, outputs);
// 得到签名前的data字符串了
String hex = FunctionEncoder.encode(function);
其实得到这个东西,你就可以直接在钱包里转账,把16进制参数打开
填入to地址(ERC20代币的转账,to地址是代币合约地址)
然后把上面这串hex字符串填入,签名即可完成转账了
2、普通参数的解码
以最近一笔我写文章时的链上的USDT转账为例
我们都知道上面的hex串中前10位,是对方法名+参数进行sha3(keccak256)哈希运算之后,取前4个字节的结果
那我们想通过这个参数,如何解出参数值呢?以下为例
0xa9059cbb000000000000000000000000935a4a786921ca9f2cffb61e68364e6182dfb95a000000000000000000000000000000000000000000000000224733e9d3370000
我们知道有调用的合约方法的api
Function function = new Function(funcName, inputs, outputs);
String data = FunctionEncoder.encode(function);
……
List<Type> decodeList = FunctionReturnDecoder.decode(str, function.getOutputParameters());
通过Funcition的构造方法可以得到出参,我们是不是可以学习一下这个方法呢?
自然是可以的,我们剔除掉前10位方法标识符后,剩下的参数解码即可
List<Type> list = FunctionReturnDecoder.decode(hex.substring(10), Utils.convert(Arrays.asList(
new TypeReference<Address>() {},
new TypeReference<Uint256>() {}
)));
String addr = ((Address) list.get(0)).getValue();
BigInteger weiValue = ((Uint256) list.get(1)).getValue();
至此,你就可以拿到转账的地址和wei金额,自行做后续处理了。
当然如果做扫块,这块解码的代码一定记得try catch,因为链上有人投毒,错误的传参,并打包上链的大有人在,解码出错就说明可以忽略跳过
有时间再写一篇数组,集合,自定义结构体的参数编码与解码