I’m trying to understand how signature verification works for NFT whitelisting. I found this pattern in a smart contract but the ECDSA part confuses me. Can someone explain how this whitelist system actually works?
function purchase(uint256[] memory _tokenIds, uint256 _expiry, bytes memory _sig) public payable isActive {
uint256 currentSupply = totalSupply();
require(_tokenIds.length <= 3, "Exceeds max per transaction");
require(currentSupply + _tokenIds.length <= MAX_SUPPLY, "Would exceed max supply");
require(msg.value >= calculatePrice(_tokenIds.length), "Insufficient payment");
address buyer = _msgSender();
address recoveredSigner = verifySignature(buyer, _tokenIds, _expiry, _sig);
require(recoveredSigner == contractOwner(), "Invalid signature");
require(block.timestamp >= _expiry - 60, "Signature expired");
for(uint8 j = 0; j < _tokenIds.length; j++){
require(rawOwnerOf(_tokenIds[j]) == address(0) && _tokenIds[j] > 0 && _tokenIds[j] <= MAX_SUPPLY, "Token unavailable");
_safeMint(buyer, _tokenIds[j]);
}
}
function verifySignature(address buyer, uint256[] memory _tokenIds, uint256 _expiry, bytes memory _sig) public view returns (address){
return ECDSA.recover(keccak256(abi.encode(buyer, _tokenIds, _expiry)), _sig);
}
I’m especially confused about these parts:
address recoveredSigner = verifySignature(buyer, _tokenIds, _expiry, _sig);
require(recoveredSigner == contractOwner(), "Invalid signature");
And:
function verifySignature(address buyer, uint256[] memory _tokenIds, uint256 _expiry, bytes memory _sig) public view returns (address){
return ECDSA.recover(keccak256(abi.encode(buyer, _tokenIds, _expiry)), _sig);
}
How does this prove someone is whitelisted? Thanks for any help!