We're implementing gasless transactions and we need eip3009 transfer With Authorisation call. We're interested in USDC.
I see some mismatches in USDC code on ethereum and polygon. To be accurate in domain separator. So, for ethereum I see this:
function makeDomainSeparator(string memory name, string memory version)
internal
view
returns (bytes32)
{
uint256 chainId;
assembly {
chainId := chainid()
}
return
keccak256(
abi.encode(
// keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f,
keccak256(bytes(name)),
keccak256(bytes(version)),
chainId,
address(this)
)
);
}
And for polygon:
function makeDomainSeparator(string memory name, string memory version)
internal
view
returns (bytes32)
{
uint256 chainId;
assembly {
chainId := chainid()
}
return
keccak256(
abi.encode(
// keccak256("EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)")
0x36c25de3e541d5d970f66e4210d728721220fff5c077cc6cd008b3a0c62adab7,
keccak256(bytes(name)),
keccak256(bytes(version)),
address(this),
bytes32(chainId)
)
);
}
I use this code to sign this transaction:
const data = {
types: {
TransferWithAuthorization: [
{ name: "from", type: "address" },
{ name: "to", type: "address" },
{ name: "value", type: "uint256" },
{ name: "validAfter", type: "uint256" },
{ name: "validBefore", type: "uint256" },
{ name: "nonce", type: "bytes32" },
],
}
domain: {
name: 'MockEIP3009Token',
version: '0.0.1',
chainId: 31337,
verifyingContract: '0x1429859428C0aBc9C2C47C8Ee9FBaf82cFA0F20f'
},
primaryType: 'TransferWithAuthorization',
message: {
from: '0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc',
to: '0xfd471836031dc5108809d173a067e8486b9047a3',
value: 434266,
validAfter: 0,
validBefore: 1672224083,
nonce: '0x16140b6e6c12c7538910d7d08e52620f146518af84281a68576bb679b2c1100a'
}
}
signer._signTypedData(data.domain, data.types, data.message);
For ethereum code everything works fine, but with polygon code I receive invalid signature error.
Can somebody explain why such difference is required?
Contracts:
- ethereum implementation contract: https://etherscan.io/address/0xa2327a938febf5fec13bacfb16ae10ecbc4cbdcf#code
- polygon implementation contract: https://polygonscan.com/address/0xdd9185db084f5c4fff3b4f70e7ba62123b812226#code
Thank you!