From 93bcf4c9edfebfb446007dbb309810c756a29678 Mon Sep 17 00:00:00 2001 From: seaona <54408225+seaona@users.noreply.github.com> Date: Wed, 1 Mar 2023 15:12:24 +0100 Subject: [PATCH] Permit Signature first part (#217) --- src/index.html | 40 ++++++++++++ src/index.js | 165 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) diff --git a/src/index.html b/src/index.html index b5e54198..2cff2707 100644 --- a/src/index.html +++ b/src/index.html @@ -751,6 +751,46 @@

+
+
+
+

+ Sign Permit +

+ + + +

+ Result: + +

r:

+

s:

+

v:

+

+ + + +

+ Recovery result: + +

+
+
+
diff --git a/src/index.js b/src/index.js index 4204dd30..ba4ec3df 100644 --- a/src/index.js +++ b/src/index.js @@ -171,6 +171,15 @@ const signTypedDataV4Verify = document.getElementById('signTypedDataV4Verify'); const signTypedDataV4VerifyResult = document.getElementById( 'signTypedDataV4VerifyResult', ); +const signPermit = document.getElementById('signPermit'); +const signPermitResult = document.getElementById('signPermitResult'); +const signPermitResultR = document.getElementById('signPermitResultR'); +const signPermitResultS = document.getElementById('signPermitResultS'); +const signPermitResultV = document.getElementById('signPermitResultV'); +const signPermitVerify = document.getElementById('signPermitVerify'); +const signPermitVerifyResult = document.getElementById( + 'signPermitVerifyResult', +); const siwe = document.getElementById('siwe'); const siweResources = document.getElementById('siweResources'); const siweBadDomain = document.getElementById('siweBadDomain'); @@ -319,6 +328,8 @@ const initialize = async () => { signTypedDataV3Verify, signTypedDataV4, signTypedDataV4Verify, + signPermit, + signPermitVerify, siwe, siweResources, siweBadDomain, @@ -378,6 +389,7 @@ const initialize = async () => { signTypedData.disabled = false; signTypedDataV3.disabled = false; signTypedDataV4.disabled = false; + signPermit.disabled = false; siwe.disabled = false; siweResources.disabled = false; siweBadDomain.disabled = false; @@ -1610,6 +1622,159 @@ const initialize = async () => { } }; + /** + * Sign Permit + */ + signPermit.onclick = async () => { + const networkId = parseInt(networkDiv.innerHTML, 10); + const chainId = parseInt(chainIdDiv.innerHTML, 16) || networkId; + const from = accounts[0]; + + const domain = { + name: 'MyToken', + version: '1', + verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', + chainId, + }; + + const EIP712Domain = [ + { name: 'name', type: 'string' }, + { name: 'version', type: 'string' }, + { name: 'verifyingContract', type: 'address' }, + { name: 'chainId', type: 'uint256' }, + ]; + + const permit = { + owner: from, + spender: '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', + value: 3000, + nonce: 0, + deadline: 50000000000, + }; + + const Permit = [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'nonce', type: 'uint256' }, + { name: 'deadline', type: 'uint256' }, + ]; + + const splitSig = (sig) => { + const pureSig = sig.replace('0x', ''); + + const _r = Buffer.from(pureSig.substring(0, 64), 'hex'); + const _s = Buffer.from(pureSig.substring(64, 128), 'hex'); + const _v = Buffer.from( + parseInt(pureSig.substring(128, 130), 16).toString(), + ); + + return { _r, _s, _v }; + }; + + let sign; + let r; + let s; + let v; + + const msgParams = { + types: { + EIP712Domain, + Permit, + }, + primaryType: 'Permit', + domain, + message: permit, + }; + + try { + sign = await ethereum.request({ + method: 'eth_signTypedData_v4', + params: [from, JSON.stringify(msgParams)], + }); + const { _r, _s, _v } = splitSig(sign); + r = `0x${_r.toString('hex')}`; + s = `0x${_s.toString('hex')}`; + v = _v.toString(); + + signPermitResult.innerHTML = sign; + signPermitResultR.innerHTML = `r: ${r}`; + signPermitResultS.innerHTML = `s: ${s}`; + signPermitResultV.innerHTML = `v: ${v}`; + signPermitVerify.disabled = false; + } catch (err) { + console.error(err); + signPermitResult.innerHTML = `Error: ${err.message}`; + } + }; + + /** + * Sign Permit Verification + */ + signPermitVerify.onclick = async () => { + const networkId = parseInt(networkDiv.innerHTML, 10); + const chainId = parseInt(chainIdDiv.innerHTML, 16) || networkId; + const from = accounts[0]; + + const domain = { + name: 'MyToken', + version: '1', + verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', + chainId, + }; + + const EIP712Domain = [ + { name: 'name', type: 'string' }, + { name: 'version', type: 'string' }, + { name: 'verifyingContract', type: 'address' }, + { name: 'chainId', type: 'uint256' }, + ]; + + const permit = { + owner: from, + spender: '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', + value: 3000, + nonce: 0, + deadline: 50000000000, + }; + + const Permit = [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'nonce', type: 'uint256' }, + { name: 'deadline', type: 'uint256' }, + ]; + + const msgParams = { + types: { + EIP712Domain, + Permit, + }, + primaryType: 'Permit', + domain, + message: permit, + }; + try { + const sign = signPermitResult.innerHTML; + const recoveredAddr = recoverTypedSignatureV4({ + data: msgParams, + sig: sign, + }); + if (toChecksumAddress(recoveredAddr) === toChecksumAddress(from)) { + console.log(`Successfully verified signer as ${recoveredAddr}`); + signPermitVerifyResult.innerHTML = recoveredAddr; + } else { + console.log( + `Failed to verify signer when comparing ${recoveredAddr} to ${from}`, + ); + } + } catch (err) { + console.error(err); + signPermitVerifyResult.innerHTML = `Error: ${err.message}`; + } + }; + function handleNewAccounts(newAccounts) { accounts = newAccounts; accountsDiv.innerHTML = accounts;