I tried to use eip-712 signature with my smart contract but I found out that it only work with fixed-size type. Does anyone know how I can use dynamically-Sized types like string, arrays and bytes
here is a test contract I used,
it works with bytes32 but,
pragma solidity ^0.8.7;
import '@openzeppelin/contracts/utils/cryptography/ECDSA.sol';
import '@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol';
contract SignCheck is EIP712 {
using ECDSA for bytes32;
address org;
struct forwardData {
address from;
bytes32 name;
}
bytes32 private constant typeHash =
keccak256(
'forwardData(address from,bytes32 name)' //here
);
constructor(address org_) EIP712('test', '1') {
org = org_;
}
function verify(forwardData calldata data, bytes calldata signature)
internal
view
returns (address)
{
return _hashTypedDataV4(
keccak256(
abi.encode(typeHash, data.from, data.name)
)
).recover(signature);
}
function check(
forwardData calldata data,
bytes calldata signature
) external view returns (address) {
return verify(data, signature);
}
}
in this when I change the type to string, it wont
pragma solidity ^0.8.7;
import '@openzeppelin/contracts/utils/cryptography/ECDSA.sol';
import '@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol';
contract SignCheck is EIP712 {
using ECDSA for bytes32;
address org;
struct forwardData {
address from;
string name;
}
bytes32 private constant typeHash =
keccak256(
'forwardData(address from,string name)' //here
);
constructor(address org_) EIP712('test', '1') {
org = org_;
}
function verify(forwardData calldata data, bytes calldata signature)
internal
view
returns (address)
{
return _hashTypedDataV4(
keccak256(
abi.encode(typeHash, data.from, data.name)
)
).recover(signature);
}
function check(
forwardData calldata data,
bytes calldata signature
) external view returns (address) {
return verify(data, signature);
}
}
This is how I implemented ether for this example
const contractAddress = "0x3b1B4DAb15c2222Ae2d30dc835235C990d7d515f";
const inName = "just name";
const domainSeparator = {
name: "test",
version: "1",
// chainId: Number(id_),
chainId: 1337,
verifyingContract: contractAddress,
};
const types = {
forwardData: [
{ name: "from", type: "address" },
{ name: "name", type: "string" },
],
};
const value = {
from: address,
name: inName,
};
// const digest = TypedDataUtils.encodeDigest(typedData);
const signature = signer._signTypedData(domainSeparator, types, value);
any idea?
Best Answer
You need to
abi.encodePacked
andkeccak256
the string first.