Aquí tienes un ejemplo mínimo (para copiar y pegar) de cómo crear y verificar de forma segura firmas ECDSA con OpenZeppelin en el entorno de Foundry.
Contrato: Verifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
contract Verifier {
using ECDSA for bytes32;
address public verifyingAddress;
constructor(address _verifyingAddress) {
verifyingAddress = _verifyingAddress;
}
function verifyV1(
string calldata message,
bytes32 r,
bytes32 s,
uint8 v
) public view {
bytes32 signedMessageHash = keccak256(abi.encode(message))
.toEthSignedMessageHash();
require(
signedMessageHash.recover(v, r, s) == verifyingAddress,
"signature not valid v1"
);
}
function verifyV2(
string calldata message,
bytes calldata signature
) public view {
bytes32 signedMessageHash = keccak256(abi.encode(message))
.toEthSignedMessageHash();
require(
signedMessageHash.recover(signature) == verifyingAddress,
"signature not valid v2"
);
}
}
Prueba (Verifier.t.sol)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
import "../src/Verify.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "forge-std/console.sol";
contract TestSigs1 is Test {
using ECDSA for bytes32;
Verifier verifier;
address owner;
uint256 privateKey =
0x1010101010101010101010101010101010101010101010101010101010101010;
function setUp() public {
owner = vm.addr(privateKey);
verifier = new Verifier(owner);
}
function testVerifyV1andV2() public {
string memory message = "attack at dawn";
bytes32 msgHash = keccak256(abi.encode(message))
.toEthSignedMessageHash();
(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, msgHash);
bytes memory signature = abi.encodePacked(r, s, v);
assertEq(signature.length, 65);
console.logBytes(signature);
verifier.verifyV1(message, r, s, v);
verifier.verifyV2(message, signature);
}
}
Esto funcionará incluso si cambias el tipo de datos de string a cualquier otro.
Ten en cuenta que OpenZeppelin admite dos formas de representar la firma. Por lo general, es más conveniente usar la versión de bytes porque es solo un dato adicional que hay que transmitir. Sin embargo, ten en cuenta que ERC20-Permit utiliza la firma de tres partes (r, s, v).
Aprende Más
Este artículo se utiliza como material de referencia en nuestro Solidity Bootcamp.
También tenemos un tutorial gratuito para aprender Solidity.
Publicado originalmente el 8 de marzo de 2023