Skip to content

Instantly share code, notes, and snippets.

@EtDu
Last active July 29, 2019 03:50
Show Gist options
  • Save EtDu/2ab5aeb0680041d6c5b13af1a8776612 to your computer and use it in GitHub Desktop.
Save EtDu/2ab5aeb0680041d6c5b13af1a8776612 to your computer and use it in GitHub Desktop.
pragma solidity ^0.5.0;
contract Cheque {
mapping (uint => bool) usedNonces;
address owner;
constructor() public payable {
owner = msg.sender;
}
function splitSignature(bytes memory sig) internal pure returns (uint8, bytes32, bytes32) {
require (sig.length == 65, "Incorrect signature length");
bytes32 r;
bytes32 s;
uint8 v;
assembly {
//first 32 bytes, after the length prefix
r := mload(add(sig, 32))
//next 32 bytes
s := mload(add(sig, 64))
//final byte, first of next 32 bytes
v := byte(0, mload(add(sig, 96)))
}
return (v, r, s);
}
function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) {
uint8 v;
bytes32 r;
bytes32 s;
(v, r, s) = splitSignature(sig);
return ecrecover(message, v, r, s);
}
function prefixed(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
function claimPayment(uint amount, uint nonce, bytes memory sig) public {
uint amountWei = amount * 1e18;
require(!usedNonces[nonce], "Nonce has already been used");
usedNonces[nonce] = true;
bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amountWei, nonce, this)));
require(recoverSigner(message, sig) == owner, "Signer is not owner");
msg.sender.transfer(amountWei);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment