Last active
September 8, 2020 20:52
-
-
Save JTraversa/43f1c09ba79b41f9ff1aa9110e4f1b95 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
// Offer + EIP Domain Hash Schema | |
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)" | |
); | |
function fillOffer(address maker, address taker, uint side, address tokenAddress, uint duration, uint rate, uint interest, uint base, bytes memory makerSignature) public returns (uint256){ | |
/// Instantiate offer | |
Offer memory filledOffer = Offer( | |
maker, | |
address(0x0000000000000000000000000000000000000000), | |
side, | |
tokenAddress, | |
duration, | |
rate, | |
interest, | |
base | |
); | |
// Parse signature into R,S,V | |
RPCSig memory RPCsig = signatureRPC(makerSignature); | |
// Validate offer signature & ensure it was created by maker | |
require(maker == ecrecover( | |
keccak256(abi.encodePacked( | |
"\x19\x01", | |
DOMAIN_SEPARATOR, | |
hashOffer(filledOffer) | |
)), | |
RPCsig.v, | |
RPCsig.r, | |
RPCsig.s), "Invalid Signature"); | |
// Require correct taker | |
require(msg.sender == taker, "Invalid Calling Address"); | |
// Create unique offer hash | |
bytes32 offerKey = keccak256(abi.encodePacked((now),msg.sender)); | |
uint value = interest.add(base); | |
// Settle Response | |
offerSettle(maker,taker,side,tokenAddress,duration,interest,base,value,offerKey); | |
offerMapping[offerKey].rate = rate; | |
offerList.push(offerKey); | |
emit newLockedOffer(offerKey,maker,taker,side,tokenAddress,duration,rate,interest,base); | |
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 hashOffer(Offer memory _offer)private pure returns(bytes32){ | |
return keccak256(abi.encode( | |
OFFER_TYPEHASH, | |
_offer.maker, | |
_offer.taker, | |
_offer.side, | |
_offer.tokenAddress, | |
_offer.duration, | |
_offer.rate, | |
_offer.interest, | |
_offer.base | |
)); | |
} | |
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
Its probably more gas efficient to split the signature off-chain and submit it than submit it as 1 bytes string and split it on-chain like I am here.