permit-712签名
来源于EIP2612提案,先看文档再做操作 https://eips.ethereum.org/EIPS/eip-2612
合约代码支持permit-712的代币,DAI,它的核心签名方法代码如下
function permit(address holder, address spender, uint256 nonce, uint256 expiry,
bool allowed, uint8 v, bytes32 r, bytes32 s) external
{
bytes32 digest =
keccak256(abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH,
holder,
spender,
nonce,
expiry,
allowed))
));
require(holder != address(0), "Dai/invalid-address-0");
require(holder == ecrecover(digest, v, r, s), "Dai/invalid-permit");
require(expiry == 0 || now data[0])
const digestHash = web3.utils.keccak256(web3.eth.abi.encodeParameters(['bytes32', 'address', 'address', 'uint256', 'uint256', 'bool'], [
PERMIT_TYPEHASH,
holder,//你的地址
spender,//授权给目标地址
nonce,//你在DAI里面的nonce
expiry,//授权到期时间
allowed,//填true表示无限授权
]
))
组合指定量授权的hash(如果你需要有限授权的话)
// 获取nonce
const tokenContract = new ClientContract(buyTokenData.abi, buyTokenData.address, ChainId.MAINNET)
const nonce = await multicallClient([
tokenContract.nonces(account)
]).then(data => data[0])
const digestHash = web3.utils.keccak256(web3.eth.abi.encodeParameters(['bytes32', 'address', 'address', 'uint256', 'uint256', 'uint256'], [
PERMIT_TYPEHASH,
holder,//你的地址
spender,//授权给目标地址
amount,//你要授权的数量
nonce,//你在DAI里面的nonce
expiry,//授权到期时间
]
))
步骤3、获取签名哈希 structHash
合约代码
bytes32 structHash =
keccak256(abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH,
holder,
spender,
nonce,
expiry,
allowed))
));
web3代码
const digest = web3.utils.soliditySha3(
{
type: 'string',
value: '\x19\x01'
},
{
type: 'bytes32',
value: DOMAIN_SEPARATOR
},
{
type: 'bytes32',
value: structHash
}
)
步骤4、钱包签名
const signatureHash = await web3.eth.sign(digest, account);
// 0x150b79625e7321efe7ffa86f7141aa5906b185795647e27e2236c36bc407f0932010e8089ad6bb4f96ed0ec297cf8dc5553091b0a91eb5e8abc4958d27e3ac6c1c
此步骤会弹出钱包签名,用户同意签名之后得出一大串加密哈希,我们需要的是 v, r, s 所以要解析签名
import {fromRpcSig} from 'ethereumjs-util'
const signature = fromRpcSig(signature)
// 结果
//{
// r: "0x150b79625e7321efe7ffa86f7141aa5906b185795647e27e2236c36bc407f093"
// s: "0x2010e8089ad6bb4f96ed0ec297cf8dc5553091b0a91eb5e8abc4958d27e3ac6c"
// v: 28
// }
node签名
web3签名第四步替换为以下方法即可
//const {SigningKey} = require('@ethersproject/signing-key')
//signingKey.privateKey('0x........')
//const signature = SigningKey.signDigest(digest);
const SigningKey = new ethers.utils.SigningKey(私钥)
const signature = SigningKey.signDigest(digest);
// 结果
//{
// r: "0x150b79625e7321efe7ffa86f7141aa5906b185795647e27e2236c36bc407f093"
// s: "0x2010e8089ad6bb4f96ed0ec297cf8dc5553091b0a91eb5e8abc4958d27e3ac6c"
// v: 28
// }