Hi everyone,
I'm quite new with Solidity programming. However I've implemented a ERC20 that users could claim the reward, via function "claimReward()" using the technique with ECDSA described on topic: sign-it-like-you-mean-it-creating-and-verifying-ethereum-signatures
So I would like to know if anyone can see any security issue using this approach?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract ECDSAERC20Mintable is ERC20, Ownable {
mapping(uint256 => bool) usedNonces;
constructor() ERC20("ECDSAMintable", "ECDSAERC20M") {}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
function claimReward(uint256 amount, uint256 nonce, bytes memory sig) public {
require(!usedNonces[nonce]);
usedNonces[nonce] = true;
bytes32 message = keccak256(abi.encodePacked(msg.sender, amount, nonce, this));
require(recoverSigner(message, sig) == owner());
_mint(msg.sender, amount);
}
function recoverSigner(bytes32 message, bytes memory sig) public pure returns (address) {
uint8 v;
bytes32 r;
bytes32 s;
(v, r, s) = splitSignature(sig);
return ecrecover(message, v, r, s);
}
function splitSignature(bytes memory sig) public pure returns (uint8, bytes32, bytes32) {
require(sig.length == 65);
bytes32 r;
bytes32 s;
uint8 v;
assembly {
// first 32 bytes, after the length prefix
r := mload(add(sig, 32))
// second 32 bytes
s := mload(add(sig, 64))
// final byte (first byte of the next 32 bytes)
v := byte(0, mload(add(sig, 96)))
}
return (v, r, s);
}
}