Skip to content

Instantly share code, notes, and snippets.

@JTraversa
Last active May 2, 2020 20:35
Show Gist options
  • Save JTraversa/cdb23d98755738ff460c3c5805647b34 to your computer and use it in GitHub Desktop.
Save JTraversa/cdb23d98755738ff460c3c5805647b34 to your computer and use it in GitHub Desktop.
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "./safeMath.sol";
contract DefiHedge {
struct RPCSig{
uint8 v;
bytes32 r;
bytes32 s;
}
struct EIP712Domain {
string name;
string version;
uint256 chainId;
address verifyingContract;
}
struct Offer{
address maker;
address taker;
uint256 side;
address tokenAddress;
uint256 duration;
uint256 rate;
uint256 interest;
uint256 base;
bytes makerSignature;
bytes makerSalt;
bytes takerSignature;
}
bytes32 DOMAIN_SEPARATOR;
constructor () public {
DOMAIN_SEPARATOR = hashDomain(EIP712Domain({
name: "DefiHedge",
version: '1',
chainId: 3,
verifyingContract: 0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC
}));
}
using SafeMath for uint;
bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
bytes32 constant OFFER_TYPEHASH = keccak256(
"Offer(address maker,address taker,uint256 side,address tokenAddress,uint256 duration,uint256 rate,uint256 interest,uint256 base,uint256 state,bytes makerSalt,bytes makerSignature,bytes takerSignature)"
);
function hashDomain(EIP712Domain memory eip712Domain) internal pure returns (bytes32) {
return keccak256(abi.encode(
EIP712DOMAIN_TYPEHASH,
keccak256(bytes(eip712Domain.name)),
keccak256(bytes(eip712Domain.version)),
eip712Domain.chainId,
eip712Domain.verifyingContract
));
}
function hashSignedOffer(Offer memory signedOffer)private pure returns(bytes32){
return keccak256(abi.encode(
OFFER_TYPEHASH,
signedOffer.maker,
signedOffer.taker,
signedOffer.side,
signedOffer.tokenAddress,
signedOffer.duration,
signedOffer.rate,
signedOffer.interest,
signedOffer.base,
signedOffer.makerSalt,
signedOffer.makerSignature,
signedOffer.takerSignature
));
}
function verify(address maker, address taker, uint256 side, address tokenAddress, uint256 duration, uint256 rate, uint256 interest, uint256 base, bytes memory makerSalt, bytes memory makerSignature, bytes memory takerSignature) public view returns (address, address) {
// Note: we need to use `encodePacked` here instead of `encode`.
Offer memory signedOffer = Offer(
maker,
taker,
side,
tokenAddress,
duration,
rate,
interest,
base,
makerSalt,
makerSignature,
"0x000000000000000000000000000000000000000000000"
);
bytes32 digest = keccak256(abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
hashSignedOffer(signedOffer)
));
RPCSig memory RPCsig = signatureRPC(takerSignature);
return (ecrecover(digest, RPCsig.v, RPCsig.r, RPCsig.s), taker);
}
/// Return RSV/ensure signature is parsing correctly
function signatureRPCtest(bytes memory sig)public view returns (bytes32 R, bytes32 S, uint8 v){
bytes32 r;
bytes32 s;
uint8 v;
if (sig.length != 65) {
return ('Length', 'Length', 0);
}
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := and(mload(add(sig, 65)), 255)
}
if (v == 39 || v == 40) {
v = v-12;
}
if (v != 27 && v != 28) {
return ('V Error', 'V Error', 0);
}
return (r,s,v);
}
/// Parses signature into RSV
function signatureRPC(bytes memory sig)internal pure returns (RPCSig memory RPCsig){
bytes32 r;
bytes32 s;
uint8 v;
if (sig.length != 65) {
return RPCSig(0,'0','0');
}
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := and(mload(add(sig, 65)), 255)
}
if (v < 27) {
v += 27;
}
if (v == 39 || v == 40) {
v = v-12;
}
if (v != 27 && v != 28) {
return RPCSig(0,'0','0');
}
return RPCSig(v,r,s);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment