// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract ReceiverPays {
//定义当前支票的归属人默认权限为internal
address owner = msg.sender;
//定义了一个权限为internal 的mapping,key为用过的nonce,value为bool类型
mapping(uint256 =>bool)usedNonces;
/*
*/
constructor() payable {
}
/*
定义了一个只供外部使用的函数,但是这个函数必须是从来没有调用过的,通过nonce进行区分*/
function claimPayment(uint256 amount,uint256 nonce,bytes memory signature)external {
require(!usedNonces[nonce]); //当前的nonce不能是已经使用过的。
usedNonces[nonce] =true;//将当前的nonce设置为true,意思是已经使用了
bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender,amount,nonce,this)));
require(recoverSigner(message,signature) == owner);
}
/*
定义了一个只供外部调用的方法,销毁当前合约*/
function shutdown()external {
require(msg.sender == owner);//只有owner才能执行该方法
selfdestruct(payable(msg.sender));// 调用了自我销毁的方法
}
/*
定义了一个internal函数,只能是当前合约以及当前合约的子合约中pure,不跟合约状态变量做任何读写之类的交互, 返回值有三个, 在函数内还有内联函数*/
function splitSignature(bytes memory sig)internal pure returns (uint8 v,bytes32 r,bytes32 s){
require(sig.length ==65);
assembly {
r := mload(add(sig,32))
s := mload(add(sig,64))
v :=byte(0,mload(add(sig,96)))
}
return (v, r, s);
}
/*
internal 表示当前函数智能当前合约或者当前合约的子合约可以使用, pure代表不跟合约的状态变量做任何交互,并且返回一个address
类型的数据*/
function recoverSigner(bytes32 message,bytes memory sig)internal pure returns (address){
(uint8 v,bytes32 r,bytes32 s) = splitSignature(sig);
return ecrecover(message,v,r,s);
}
/*
定义一个内部(子类合约也可以)使用的函数,用于加密,并且当前函数为pure不跟任何状态变量做交互。 返回一个bytes32 类型的数据*/
function prefixed(bytes32 hash)internal pure returns(bytes32){
return keccak256(abi.encodePacked("\x19 Ethereum Signed Message:\n32",hash));
}
}