From 61dfd0ab74f18e463caecbb4b30bf862624a4a10 Mon Sep 17 00:00:00 2001
From: Stefan Adolf
Date: Mon, 10 Aug 2020 19:34:07 +0200
Subject: [PATCH 1/2] message signing and verification
---
src/Main.tsx | 7 +++++++
src/SignForm.tsx | 37 +++++++++++++++++++++++++++++++++++++
src/VerifyForm.tsx | 44 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 88 insertions(+)
create mode 100644 src/SignForm.tsx
create mode 100644 src/VerifyForm.tsx
diff --git a/src/Main.tsx b/src/Main.tsx
index f979298..6eadcfb 100644
--- a/src/Main.tsx
+++ b/src/Main.tsx
@@ -5,6 +5,8 @@ import Web3 from "web3";
import ADIToken from "./contracts/ADIToken.json";
import TransferForm from "./TransferForm";
import _secrets from "../.secrets.json";
+import SignForm from "./SignForm";
+import VerifyForm from "./VerifyForm";
const Main: React.FC = () => {
const { account, library: web3 } = useWeb3React();
@@ -53,9 +55,14 @@ const Main: React.FC = () => {
({_secrets.contractAddress})
to spare with others.
+
+ Transfer ADI
{adiBalance && (
)}
+ Sign a message
+
+
);
};
diff --git a/src/SignForm.tsx b/src/SignForm.tsx
new file mode 100644
index 0000000..71639ac
--- /dev/null
+++ b/src/SignForm.tsx
@@ -0,0 +1,37 @@
+import React, { useState } from "react";
+import { useWeb3React } from "@web3-react/core";
+import Web3 from "web3";
+
+const SignForm = () => {
+ const { account, library: web3 } = useWeb3React();
+ const [message, setMessage] = useState("");
+
+ const [signature, setSignature] = useState("");
+
+ async function signMessage() {
+ const signed = await web3.eth.personal.sign(message, account, "")
+ setSignature(signed);
+ }
+
+ return (
+
+ Message
+ setMessage(e.target.value)}
+ />
+
+
+ Sign!
+
+
+ {signature &&
+ Signature: {signature}
+ }
+
+
+ );
+};
+
+export default SignForm;
diff --git a/src/VerifyForm.tsx b/src/VerifyForm.tsx
new file mode 100644
index 0000000..d720d30
--- /dev/null
+++ b/src/VerifyForm.tsx
@@ -0,0 +1,44 @@
+import React, { useState } from "react";
+import { useWeb3React } from "@web3-react/core";
+import Web3 from "web3";
+
+const VerifyForm = () => {
+ const { library: web3 } = useWeb3React();
+ const [message, setMessage] = useState("");
+ const [signature, setSignature] = useState("");
+ const [pubAddress, setPubAddress] = useState("");
+
+ async function verifyMessage() {
+ const recovered = await web3.eth.personal.ecRecover(message, signature);
+ setPubAddress(recovered);
+ }
+
+ return (
+
+ Message
+ setMessage(e.target.value)}
+ />
+
+ Signature
+ setSignature(e.target.value)}
+ />
+
+
+ Verify!
+
+
+ { pubAddress &&
+ public address of the signer: {pubAddress}
+ }
+
+
+ );
+};
+
+export default VerifyForm;
From c574d4f789fbc2a5e85cb0af9f0442ca470c90e8 Mon Sep 17 00:00:00 2001
From: Stefan Adolf
Date: Tue, 11 Aug 2020 23:27:06 +0200
Subject: [PATCH 2/2] verifiying locally & on chain
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
deployed Verifier on Görli
---
.openzeppelin/goerli.json | 25 +++++++++
.openzeppelin/project.json | 3 +-
contracts/Verifier.json | 1 +
contracts/Verifier.sol | 23 ++++++++
src/Main.tsx | 2 +-
src/VerifyForm.tsx | 108 ++++++++++++++++++++++++++++--------
src/contracts/Verifier.json | 1 +
7 files changed, 137 insertions(+), 26 deletions(-)
create mode 120000 contracts/Verifier.json
create mode 100644 contracts/Verifier.sol
create mode 120000 src/contracts/Verifier.json
diff --git a/.openzeppelin/goerli.json b/.openzeppelin/goerli.json
index a2b52f7..e94571e 100644
--- a/.openzeppelin/goerli.json
+++ b/.openzeppelin/goerli.json
@@ -288,6 +288,22 @@
],
"storageDiff": []
}
+ },
+ "Verifier": {
+ "address": "0xB735f8730debFF357593dba17a7Fa3dD783b3DAe",
+ "constructorCode": "608060405234801561001057600080fd5b506105e7806100206000396000f3fe",
+ "bodyBytecodeHash": "cdcbeb651e8382f67e592daa834afb098964fcd557a81f930da622eb8eef0c64",
+ "localBytecodeHash": "52180514532af933f2e70d0473a69942db0b6637089152e6560d45ec6eeb3e58",
+ "deployedBytecodeHash": "52180514532af933f2e70d0473a69942db0b6637089152e6560d45ec6eeb3e58",
+ "types": {},
+ "storage": [],
+ "warnings": {
+ "hasConstructor": false,
+ "hasSelfDestruct": false,
+ "hasDelegateCall": false,
+ "hasInitialValuesInDeclarations": false,
+ "uninitializedBaseContracts": []
+ }
}
},
"solidityLibs": {},
@@ -307,6 +323,15 @@
"admin": "0x5c19BF66CC2c9386Cdf06d346F32F140A4559be9",
"kind": "Upgradeable"
}
+ ],
+ "ledger-academy/Verifier": [
+ {
+ "address": "0xB0e0f956693eC1e990EB95C3a435B80548F7db1b",
+ "version": "1.0.0",
+ "implementation": "0xB735f8730debFF357593dba17a7Fa3dD783b3DAe",
+ "admin": "0x5c19BF66CC2c9386Cdf06d346F32F140A4559be9",
+ "kind": "Upgradeable"
+ }
]
},
"manifestVersion": "2.2",
diff --git a/.openzeppelin/project.json b/.openzeppelin/project.json
index dde69e6..0c7e390 100644
--- a/.openzeppelin/project.json
+++ b/.openzeppelin/project.json
@@ -1,7 +1,8 @@
{
"manifestVersion": "2.2",
"contracts": {
- "ADIToken": "ADIToken"
+ "ADIToken": "ADIToken",
+ "Verifier": "Verifier"
},
"dependencies": {
"@openzeppelin/contracts-ethereum-package": "^3.0.0"
diff --git a/contracts/Verifier.json b/contracts/Verifier.json
new file mode 120000
index 0000000..741b253
--- /dev/null
+++ b/contracts/Verifier.json
@@ -0,0 +1 @@
+../build/contracts/Verifier.json
\ No newline at end of file
diff --git a/contracts/Verifier.sol b/contracts/Verifier.sol
new file mode 100644
index 0000000..7f6e51f
--- /dev/null
+++ b/contracts/Verifier.sol
@@ -0,0 +1,23 @@
+pragma solidity ^0.6.0;
+
+import "@openzeppelin/contracts-ethereum-package/contracts/cryptography/ECDSA.sol";
+
+// https://www.codementor.io/@yosriady/signing-and-verifying-ethereum-signatures-vhe8ro3h6
+// -> part of oz: https://docs.openzeppelin.com/contracts/3.x/api/cryptography#ECDSA-recover-bytes32-bytes-
+
+contract Verifier {
+ function recoverAddr(
+ bytes32 msgHash,
+ bytes memory signature
+ ) public pure returns (address) {
+ return ECDSA.recover(msgHash, signature);
+ }
+
+ function recoverAddrFromNonEthHash(
+ bytes32 msgHash,
+ bytes memory signature
+ ) public pure returns (address) {
+ bytes32 ethHash = ECDSA.toEthSignedMessageHash(msgHash);
+ return recoverAddr(ethHash, signature);
+ }
+}
diff --git a/src/Main.tsx b/src/Main.tsx
index 6eadcfb..f9a60dd 100644
--- a/src/Main.tsx
+++ b/src/Main.tsx
@@ -38,7 +38,6 @@ const Main: React.FC = () => {
const readableAdiBalance = Web3.utils.fromWei(_adiBalance);
setADIBalance(readableAdiBalance);
}
-
})();
}, [web3]);
@@ -62,6 +61,7 @@ const Main: React.FC = () => {
)}
Sign a message
+ Verify a message
);
diff --git a/src/VerifyForm.tsx b/src/VerifyForm.tsx
index d720d30..a35e507 100644
--- a/src/VerifyForm.tsx
+++ b/src/VerifyForm.tsx
@@ -1,41 +1,101 @@
import React, { useState } from "react";
import { useWeb3React } from "@web3-react/core";
import Web3 from "web3";
+import VerifierABI from "./contracts/Verifier.json";
+
+import _secrets from "../.secrets.json";
const VerifyForm = () => {
- const { library: web3 } = useWeb3React();
+ const { library: web3, account } = useWeb3React();
const [message, setMessage] = useState("");
const [signature, setSignature] = useState("");
- const [pubAddress, setPubAddress] = useState("");
+ const [localVerificationResult, setLocalVerificationResult] = useState("");
+ const [contractVerificationResult, setContractVerificationResult] = useState("");
+ const [nonEthSignatureVerificationResult, setNonEthSignatureVerificationResult] = useState("");
+
+ const contract = new web3.eth.Contract(
+ VerifierABI.abi,
+ _secrets.verifierContractAddress
+ );
+
+ // this will only work with messages that have been a hash by itself ;)
+ async function verifyNonEthSignatureOnContract() {
+ const nonEthMessageHash = web3.utils.sha3(message);
+ const recovered = await contract.methods.recoverAddrFromNonEthHash(
+ nonEthMessageHash,
+ signature
+ ).call()
- async function verifyMessage() {
+ console.log(recovered);
+ setNonEthSignatureVerificationResult(recovered);
+ }
+
+ async function verifySignatureOnContract() {
+ const verifiableMessage = `\x19Ethereum Signed Message:\n${message.length}${message}`;
+ const verifiableMessageSha = web3.utils.sha3(verifiableMessage);
+
+ const recovered = await contract.methods.recoverAddr(
+ verifiableMessageSha,
+ signature
+ ).call()
+
+ console.log(recovered);
+ setContractVerificationResult(recovered);
+ }
+
+ async function verifySignatureLocally() {
const recovered = await web3.eth.personal.ecRecover(message, signature);
- setPubAddress(recovered);
+ console.log(recovered);
+ setLocalVerificationResult(web3.utils.toChecksumAddress(recovered));
+ }
+
+ async function verifySignature() {
+ verifySignatureLocally();
+ verifySignatureOnContract();
+ verifyNonEthSignatureOnContract();
}
+ function eqAccount(addr: string) {
+ return addr === account
+ }
return (
- Message
- setMessage(e.target.value)}
- />
-
- Signature
- setSignature(e.target.value)}
- />
-
-
- Verify!
-
+ Message
+ setMessage(e.target.value)}
+ />
+
+ Signature
+ setSignature(e.target.value)}
+ />
+
+
+ Verify!
+
+
+
+
+ { localVerificationResult &&
+
+ local verification: {localVerificationResult}
- { pubAddress &&
- public address of the signer: {pubAddress}
- }
+
+ }
+ { contractVerificationResult &&
+
+ contract verification: {contractVerificationResult}
+
+ }
+ { nonEthSignatureVerificationResult &&
+
+ non eth signed verification: {nonEthSignatureVerificationResult}
+
+ }
);
diff --git a/src/contracts/Verifier.json b/src/contracts/Verifier.json
new file mode 120000
index 0000000..a2b024c
--- /dev/null
+++ b/src/contracts/Verifier.json
@@ -0,0 +1 @@
+../../build/contracts/Verifier.json
\ No newline at end of file