function multiWriteToDiscSignature(
uint256[] memory tokenIds,
uint256[] memory songSelections,
bytes memory signature
) public {
require(
tokenIds.length == songSelections.length,
"tokenIds and songSelections arrays must have the same length"
);
//Constructing the signed hash for signer address recovery
bytes32 messageHash = keccak256(abi.encodePacked(tokenIds, songSelections));
bytes32 ethSignedHash = keccak256(
abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash)
);
address signer = recoverSigner(ethSignedHash, signature);
for (uint256 i = 0; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
uint256 songChoiceId = songSelections[i];
// Check if CdMemory is not written before allowing an update
CdMemory storage cd = readCdMemory[tokenId];
require(
ownerOf(tokenId) == signer,
"Only the owner can set CdMemory"
);
require(
songChoiceId >= 1 && songChoiceId <= 5,
"Invalid song choice ID"
);
require(!cd.written, "One or more tokens are already written.");
// Update CdMemory and mark it as written
cd.writerAddress = signer;
cd.songChoiceId = songChoiceId;
cd.written = true;
writeCount += 1;
emit CdMemorySet(tokenId, signer, songChoiceId);
}
}
//Helper function to determine signer address based on the signed hash and the signature
function recoverSigner(
bytes32 ethSignedHash,
bytes memory signature
) public pure returns (address) {
// Extract the r, s, and v values from the signature
(bytes32 r, bytes32 s, uint8 v) = splitSignature(signature);
// Recover and return the signer address
return ecrecover(ethSignedHash, v, r, s);
}
//Helper Function to split signature into RSV values
function splitSignature(
bytes memory signature
) public pure returns (bytes32 r, bytes32 s, uint8 v) {
require(signature.length == 65, "Invalid signature length");
assembly {
// Slice the r, s, and v components from the signature
r := mload(add(signature, 32))
s := mload(add(signature, 64))
v := byte(0, mload(add(signature, 96)))
}
}