Skip to content

Instantly share code, notes, and snippets.

@andreafspeziale
Last active July 3, 2019 12:55
Show Gist options
  • Save andreafspeziale/60b5bde3cd0806868e885df9be46864e to your computer and use it in GitHub Desktop.
Save andreafspeziale/60b5bde3cd0806868e885df9be46864e to your computer and use it in GitHub Desktop.
mapping (address => uint256) public replayNonce;


function metaApprove(address spender, uint256 value, uint256 nonce, uint256 reward, bytes signature) public returns (bool) {
  require(spender != address(0));
  bytes32 metaHash = metaApproveHash(spender,value,nonce,reward);
  address signer = getSigner(metaHash,signature);
  require(nonce == replayNonce[signer]);
  replayNonce[signer]++;
  _allowed[signer][spender] = value;
  if(reward>0){
    _transfer(signer, msg.sender, reward);
  }
  emit Approval(msg.sender, spender, value);
  return true;
}

function _approve(address owner, address spender, uint256 value) internal {
  require(owner != address(0), "ERC20: approve from the zero address");
  require(spender != address(0), "ERC20: approve to the zero address");
  _allowances[owner][spender] = value;
  emit Approval(owner, spender, value);
}

function metaApproveHash(address spender, uint256 value, uint256 nonce, uint256 reward) public view returns(bytes32){
  return keccak256(abi.encodePacked(address(this),"metaApprove" spender, value, nonce, reward));
}

function getSigner(bytes32 _hash, bytes _signature) internal pure returns (address){
  bytes32 r;
  bytes32 s;
  uint8 v;
  if (_signature.length != 65) {
    return address(0);
  }
  assembly {
    r := mload(add(_signature, 32))
    s := mload(add(_signature, 64))
    v := byte(0, mload(add(_signature, 96)))
  }
  if (v < 27) {
    v += 27;
  }
  if (v != 27 && v != 28) {
    return address(0);
  } else {
    return ecrecover(keccak256(
      abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)
    ), v, r, s);
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment