wormhole/ethereum/forge-test/Messages.t.sol

120 lines
4.2 KiB
Solidity

// test/Messages.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../contracts/Messages.sol";
import "../contracts/Structs.sol";
import "forge-std/Test.sol";
contract TestMessages is Test {
uint256 constant testGuardian = 93941733246223705020089879371323733820373732307041878556247502674739205313440;
Messages messages;
Structs.GuardianSet guardianSet;
function setUp() public {
messages = new Messages();
// initialize guardian set with one guardian
address[] memory keys = new address[](1);
keys[0] = vm.addr(testGuardian);
guardianSet = Structs.GuardianSet(keys, 0);
require(messages.quorum(guardianSet.keys.length) == 1, "Quorum should be 1");
}
function testQuorum() public {
assertEq(messages.quorum(0), 1);
assertEq(messages.quorum(1), 1);
assertEq(messages.quorum(2), 2);
assertEq(messages.quorum(3), 3);
assertEq(messages.quorum(4), 3);
assertEq(messages.quorum(5), 4);
assertEq(messages.quorum(6), 5);
assertEq(messages.quorum(7), 5);
assertEq(messages.quorum(8), 6);
assertEq(messages.quorum(9), 7);
assertEq(messages.quorum(10), 7);
assertEq(messages.quorum(11), 8);
assertEq(messages.quorum(12), 9);
assertEq(messages.quorum(19), 13);
assertEq(messages.quorum(20), 14);
}
function testQuorumCanAlwaysBeReached(uint256 numGuardians) public {
vm.assume(numGuardians > 0);
if (numGuardians >= 256) {
vm.expectRevert("too many guardians");
}
// test that quorums is never greater than the number of guardians
assert(messages.quorum(numGuardians) <= numGuardians);
}
// This test ensures that submitting more signatures than expected will
// trigger a "guardian index out of bounds" error.
function testCannotVerifySignaturesWithOutOfBoundsSignature(bytes memory encoded) public {
vm.assume(encoded.length > 0);
bytes32 message = keccak256(encoded);
// First generate a legitimate signature.
Structs.Signature memory goodSignature = Structs.Signature(message, 0, 0, 0);
(goodSignature.v, goodSignature.r, goodSignature.s) = vm.sign(testGuardian, message);
assertEq(ecrecover(message, goodSignature.v, goodSignature.r, goodSignature.s), vm.addr(testGuardian));
// Reuse legitimate signature above for the next signature. This will
// bypass the "invalid signature" revert.
Structs.Signature memory outOfBoundsSignature = goodSignature;
outOfBoundsSignature.guardianIndex = 1;
// Attempt to verify signatures.
Structs.Signature[] memory sigs = new Structs.Signature[](2);
sigs[0] = goodSignature;
sigs[1] = outOfBoundsSignature;
vm.expectRevert("guardian index out of bounds");
messages.verifySignatures(message, sigs, guardianSet);
}
// This test ensures that submitting an invalid signature fails when
// verifySignatures is called. Calling ecrecover should fail.
function testCannotVerifySignaturesWithInvalidSignature(bytes memory encoded) public {
vm.assume(encoded.length > 0);
bytes32 message = keccak256(encoded);
// Generate an invalid signature.
Structs.Signature memory badSignature = Structs.Signature(message, 0, 0, 0);
assertEq(ecrecover(message, badSignature.v, badSignature.r, badSignature.s), address(0));
// Attempt to verify signatures.
Structs.Signature[] memory sigs = new Structs.Signature[](2);
sigs[0] = badSignature;
vm.expectRevert("ecrecover failed with signature");
messages.verifySignatures(message, sigs, guardianSet);
}
function testVerifySignatures(bytes memory encoded) public {
vm.assume(encoded.length > 0);
bytes32 message = keccak256(encoded);
// Generate legitimate signature.
Structs.Signature memory goodSignature;
(goodSignature.v, goodSignature.r, goodSignature.s) = vm.sign(testGuardian, message);
assertEq(ecrecover(message, goodSignature.v, goodSignature.r, goodSignature.s), vm.addr(testGuardian));
goodSignature.guardianIndex = 0;
// Attempt to verify signatures.
Structs.Signature[] memory sigs = new Structs.Signature[](1);
sigs[0] = goodSignature;
(bool valid, string memory reason) = messages.verifySignatures(message, sigs, guardianSet);
assertEq(valid, true);
assertEq(bytes(reason).length, 0);
}
}