Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions contracts/libraries/SignatureValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ library SignatureValidator {
@return True if the signature is valid, false otherwise.
*/
function verify(address addr, bytes32 quoteHash, bytes memory signature) public pure returns (bool) {
if (signature.length != 65) {
revert IncorrectSignature(addr, quoteHash, signature);
}
bytes32 r;
bytes32 s;
uint8 v;
Expand Down
126 changes: 126 additions & 0 deletions test/signature-validator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { expect } from "chai";
import { ethers } from "hardhat";
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
import { SignatureValidator } from "../typechain-types";

describe("SignatureValidator", function () {
let signatureValidator: SignatureValidator;
let signer: HardhatEthersSigner;
let testMessage: string;
let testMessageHash: Uint8Array;

beforeEach(async function () {
const SignatureValidatorFactory = await ethers.getContractFactory(
"SignatureValidator"
);
signatureValidator = await SignatureValidatorFactory.deploy();

[signer] = await ethers.getSigners();
testMessage = "Test message for signature validation";
testMessageHash = ethers.getBytes(
ethers.keccak256(ethers.toUtf8Bytes(testMessage))
);
});

describe("Valid signatures", function () {
it("should verify a valid 65-byte signature", async function () {
const signature = await signer.signMessage(testMessageHash);

expect(signature).to.have.lengthOf(132); // 65 bytes * 2 (hex) + "0x" prefix

const result = await signatureValidator.verify(
signer.address,
ethers.keccak256(ethers.toUtf8Bytes(testMessage)),
signature
);

expect(result).to.equal(true);
});

it("should return false for invalid signature with correct length", async function () {
const signature = await signer.signMessage(testMessageHash);
const wrongMessage = ethers.keccak256(
ethers.toUtf8Bytes("Wrong message")
);

const result = await signatureValidator.verify(
signer.address,
wrongMessage,
signature
);

expect(result).to.equal(false);
});

it("should return false for signature from different signer", async function () {
const [, otherSigner] = await ethers.getSigners();
const signature = await otherSigner.signMessage(testMessageHash);

const result = await signatureValidator.verify(
signer.address, // Different from otherSigner
ethers.keccak256(ethers.toUtf8Bytes(testMessage)),
signature
);

expect(result).to.equal(false);
});
});

describe("Signature length validation", function () {
it("should revert with IncorrectSignature for undersized signature (1 byte)", async function () {
const truncatedSignature = "0x01";
const messageHash = ethers.keccak256(ethers.toUtf8Bytes(testMessage));

await expect(
signatureValidator.verify(
signer.address,
messageHash,
truncatedSignature
)
)
.to.be.revertedWithCustomError(signatureValidator, "IncorrectSignature")
.withArgs(signer.address, messageHash, truncatedSignature);
});

it("should revert with IncorrectSignature for undersized signature (64 bytes)", async function () {
const truncatedSignature = "0x" + "01".repeat(64); // 64 bytes, just one short
const messageHash = ethers.keccak256(ethers.toUtf8Bytes(testMessage));

await expect(
signatureValidator.verify(
signer.address,
messageHash,
truncatedSignature
)
)
.to.be.revertedWithCustomError(signatureValidator, "IncorrectSignature")
.withArgs(signer.address, messageHash, truncatedSignature);
});

it("should revert with IncorrectSignature for oversized signature (66 bytes)", async function () {
const oversizedSignature = "0x" + "01".repeat(66); // 66 bytes
const messageHash = ethers.keccak256(ethers.toUtf8Bytes(testMessage));

await expect(
signatureValidator.verify(
signer.address,
messageHash,
oversizedSignature
)
)
.to.be.revertedWithCustomError(signatureValidator, "IncorrectSignature")
.withArgs(signer.address, messageHash, oversizedSignature);
});

it("should revert with IncorrectSignature for empty signature", async function () {
const emptySignature = "0x";
const messageHash = ethers.keccak256(ethers.toUtf8Bytes(testMessage));

await expect(
signatureValidator.verify(signer.address, messageHash, emptySignature)
)
.to.be.revertedWithCustomError(signatureValidator, "IncorrectSignature")
.withArgs(signer.address, messageHash, emptySignature);
});
});
});
Loading