首先我们知道,在做区块链的项目的时候,很容易被以太坊地址大小写的问题所困扰,尤其是在前端获取链上数据的时候,在做地址比对的时候,都会先用toLowercase()
转化成小写才进行比对。因为以太坊本身的地址是不区分大小写的,严格上来讲,你可以往以太坊存储随便大小写的以太坊地址。
一、地址大小写验证
我们来写一个简单的合约验证下:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Checksum {
address addr;
function setAddr(address _addr) external {
addr = _addr;
}
}
这个合约的功能就是设置一个地址,输入的就是一个address
类型的参数。这里我用的地址是:
0x13a6D1fe418de7e5B03Fb4a15352DfeA3249eAA4
Remix成功执行:
执行成功 我们再把上面地址倒数第一个出现的A
改成a
,就是:
0x13a6D1fe418de7e5B03Fb4a15352DfeA3249eAa4
此时再执行,Remix会报错!
transact to Checksum.setAddr errored: Error encoding arguments: Error: bad address checksum (argument="address", value="0x13a6D1fe418de7e5B03Fb4a15352DfeA3249eAa4", code=INVALID_ARGUMENT, version=address/5.5.0) (argument=null, value="0x13a6D1fe418de7e5B03Fb4a15352DfeA3249eAa4", code=INVALID_ARGUMENT, version=abi/5.5.0)
它告诉我们这个被我们修改后的地址checksum
有问题,所以没通过。
二、ERC55混合大小写校验
ERC55用了一个校验机制来对大小写进行了规定,具体的机制就是经过一系列运算,决定地址中的哪些字母是大写的,哪些字母是小写的,只要有一个不对,就没法校验通过。
用js实现这个算法如下:
const createKeccakHash = require('keccak')
function toChecksumAddress (address) {
address = address.toLowerCase().replace('0x', '')
const hash = createKeccakHash('keccak256').update(address).digest('hex')
let ret = '0x'
for (let i = 0; i < address.length; i++) {
if (parseInt(hash[i], 16) >= 8) {
ret += address[i].toUpperCase()
} else {
ret += address[i]
}
}
return ret
}
我们对上面的修改过的地址进行下验证:
> toChecksumAddress('0x13a6D1fe418de7e5B03Fb4a15352DfeA3249eAa4')
'0x13a6D1fe418de7e5B03Fb4a15352DfeA3249eAA4'
会发现成功返回了我们未修改前的字母大小写状态。
这个标准对于前端或者进行链上数据处理的时候,还是非常有用的,可以省去很多麻烦。所以不管是remix还是前端的库,都集成了checksum的功能,如果输入的参数不是符合ERC55标准的话,是会报错的。
网友评论