- Contract verifies ECDSA signatures for authorization
function executeWithSig(address to, uint256 amount, bytes memory sig) external {
// Missing: nonce, contract address, and chain ID in hash
// Same signature can be replayed on same contract, other contracts, or other chains
bytes32 hash = keccak256(abi.encodePacked(to, amount));
address signer = ECDSA.recover(hash, sig);
require(signer == authorizer, "invalid sig");
// No nonce tracking — same signature can be submitted repeatedly
_transfer(to, amount);
}
ecrecover or ECDSA.recover usageaddress(this)): flag if absent (enables cross-contract replay)block.chainid): flag if absent (enables cross-chain replay)address(this), and block.chainid in the signed message hashmapping(address => uint256) public nonces;
function executeWithSig(address to, uint256 amount, bytes memory sig) external {
uint256 nonce = nonces[msg.sender]++;
bytes32 hash = keccak256(abi.encodePacked(
to, amount, nonce, address(this), block.chainid
));
bytes32 ethHash = ECDSA.toEthSignedMessageHash(hash);
address signer = ECDSA.recover(ethHash, sig);
require(signer == authorizer, "invalid sig");
_transfer(to, amount);
}