我用golang 代码实现了一个ERC2612签名的代码。签名验证不通过,哪位大佬给看看哪出了问题。
import (
"crypto/ecdsa"
"fmt"
"github.com/ethereum/go-ethereum/accounts/abi"
"log"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/miguelmota/go-solidity-sha3"
)
func main() {
// 用户私钥,用于签名
privateKey, err := crypto.HexToECDSA("503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb")
if err != nil {
log.Fatal(err)
}
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("error casting public key to ECDSA")
}
// 构建EIP-712签名消息结构
abiString0 := `
[
{
"inputs": [
{
"internalType": "bytes32",
"name": "hash",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "hashedName",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "hashedVersion",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "chainid",
"type": "uint256"
},
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "buildDomainSeparator",
"outputs": [
{
"internalType": "bytes32",
"name": "ha",
"type": "bytes32"
}
],
"stateMutability": "pure",
"type": "function"
}
]
`
contractAbi0, _ := abi.JSON(strings.NewReader(abiString0))
//erc20 合约
token := common.HexToAddress("0xe2899bddFD890e320e643044c6b95B9B0b84157A")
hashedName := "MyToken"
chainId := big.NewInt(1)
bytes0, err := contractAbi0.Pack("buildDomainSeparator",
crypto.Keccak256Hash([]byte("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")),
crypto.Keccak256Hash([]byte(hashedName)),
crypto.Keccak256Hash([]byte("1")),
chainId,
token,
)
bytes0 = bytes0[4:]
hash0 := crypto.Keccak256Hash(bytes0)
// 构建EIP-712签名消息结构
abiString := `
[
{
"inputs": [
{
"internalType": "bytes32",
"name": "permit",
"type": "bytes32"
},
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "nonce",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "deadline",
"type": "uint256"
}
],
"name": "dd",
"outputs": [
{
"internalType": "bytes32",
"name": "ha",
"type": "bytes32"
}
],
"stateMutability": "pure",
"type": "function"
}
]
`
contractAbi, _ := abi.JSON(strings.NewReader(abiString))
fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
spender := common.HexToAddress("0x1c91347f2A44538ce62453BEBd9Aa907C662b4bD") //
nonce := big.NewInt(1)
// Stake数量
amount := big.NewInt(100)
// permit函数截止时间
deadline := big.NewInt(1686091610)
bytes, err := contractAbi.Pack("dd",
crypto.Keccak256Hash([]byte("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")),
fromAddress,
spender,
amount,
nonce,
deadline,
)
bytes = bytes[4:]
hash := crypto.Keccak256Hash(bytes)
hh := solsha3.SoliditySHA3(
solsha3.String("\x19\x01"),
hash0,
hash,
)
// 签名消息
sig, err := crypto.Sign(hh, privateKey)
if err != nil {
log.Fatal(err)
}
v := sig[64]
if v < 27 {
v += 27
}
r := [32]byte{}
s := [32]byte{}
copy(r[:], sig[0:32])
copy(s[:], sig[32:64])
fmt.Println("amount:", amount)
fmt.Println("deadline:", deadline)
fmt.Printf("v: %d\n", v)
fmt.Printf("r: 0x%x\n", r)
fmt.Printf("s: 0x%x\n", s)
}