Skip to content

Instantly share code, notes, and snippets.

@JTraversa
Last active May 2, 2020 16:46
Show Gist options
  • Save JTraversa/a88edab6f7d9457317928483e78d8681 to your computer and use it in GitHub Desktop.
Save JTraversa/a88edab6f7d9457317928483e78d8681 to your computer and use it in GitHub Desktop.
/// Taker signs a previously created/validated offer, submits it to chain for signature verification.
var d = new Date();
var t = d.getTime().toString();
var currentAddress = document.getElementById("useraddress").innerHTML;
var minorSalt = currentAddress + t;
var Salt = web3.utils.keccak256(minorSalt).toString();
const typedData = {
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' },
],
Offer: [
{ name: "maker", type: "address" },
{ name: "taker", type: "address" },
{ name: "side", type: "uint256" },
{ name: "tokenAddress", type: "address" },
{ name: "duration", type: "uint256" },
{ name: "rate", type: "uint256" },
{ name: "interest", type: "uint256" },
{ name: "base", type: "uint256" },
{ name: 'makerSalt', type: 'bytes' },
{ name: 'makerSignature', type: 'bytes' },
{ name: 'takerSignature', type: 'bytes' }
],
},
primaryType: 'Offer',
domain: {
name: 'DefiHedge',
version: '1',
chainId: 3,
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
},
message: {
maker: loadedOffer.maker, // "0x00fE460A15B49d09F39b057D0f1A7B9444F4F2BE"
taker: loadedOffer.taker, // "0x00fE460A15B49d09F39b057D0f1A7B9444F4F2BE"
side: loadedOffer.side, // "0"
tokenAddress: loadedOffer.tokenAddress, // "0x0000000000000000000000000000000000000000" Indicates token is ETH
duration: loadedOffer.duration, // "number"
rate: loadedOffer.rate, // "number"
interest: loadedOffer.interest, // "number"
base: loadedOffer.base, // "number"
makerSalt: loadedOffer.makerSalt, // "keccak hash"
makerSignature: loadedOffer.makerSignature, "0x signature"
takerSignature: "0x000000000000000000000000000000000000000000000",
},
};
const types = typedData.types;
// Recursively finds all the dependencies of a type
function dependencies(primaryType, found = []) {
if (found.includes(primaryType)) {
return found;
}
if (types[primaryType] === undefined) {
return found;
}
found.push(primaryType);
for (let field of types[primaryType]) {
for (let dep of dependencies(field.type, found)) {
if (!found.includes(dep)) {
found.push(dep);
}
}
}
return found;
}
function encodeType(primaryType) {
// Get dependencies primary first, then alphabetical
let deps = dependencies(primaryType);
deps = deps.filter(t => t != primaryType);
deps = [primaryType].concat(deps.sort());
// Format as a string with fields
let result = '';
for (let type of deps) {
result += `${type}(${types[type].map(({ name, type }) => `${type} ${name}`).join(',')})`;
}
return result;
}
function typeHash(primaryType) {
return EthJS.Util.keccak256(encodeType(primaryType));
}
function encodeData(primaryType, data) {
let encTypes = [];
let encValues = [];
// Add typehash
encTypes.push('bytes32');
encValues.push(typeHash(primaryType));
// Add field contents
for (let field of types[primaryType]) {
let value = data[field.name];
if (field.type == 'string' || field.type == 'bytes') {
encTypes.push('bytes32');
value = EthJS.Util.keccak256(value);
encValues.push(value);
} else if (types[field.type] !== undefined) {
encTypes.push('bytes32');
value = EthJS.Util.keccak256(encodeData(field.type, value));
encValues.push(value);
} else if (field.type.lastIndexOf(']') === field.type.length - 1) {
throw 'TODO: Arrays currently unimplemented in encodeData';
} else {
encTypes.push(field.type);
encValues.push(value);
}
}
return ethereumjs.ABI.rawEncode(encTypes, encValues);
}
function structHash(primaryType, data) {
return EthJS.Util.keccak256(encodeData(primaryType, data));
}
function signHash() {
return EthJS.Util.keccak256(
Buffer.concat([
Buffer.from('1901', 'hex'),
structHash('EIP712Domain', typedData.domain),
structHash(typedData.primaryType, typedData.message),
]),
);
}
var hash = signHash()
var privateKey = Buffer.from("REDACTED", "hex");
var sig = EthJS.Util.ecsign(hash,privateKey);
var pub = EthJS.Util.ecrecover(hash,sig.v,sig.r,sig.s);
var addrBuf = EthJS.Util.pubToAddress(pub);
var addr = EthJS.Util.bufferToHex(addrBuf);
console.log(addr); // Ensuring signature is correct
sig.r = EthJS.Util.bufferToHex(sig.r);
sig.s = EthJS.Util.bufferToHex(sig.s);
sig.r = sig.r.substring(2);
sig.s = sig.s.substring(2);
sig.v = sig.v.toString();
var signature = sig.r + sig.s + sig.v;
signature = "0x".concat(signature);
var newOffer = {
maker: typedData.message.maker,
taker: typedData.message.taker,
side: typedData.message.side,
tokenAddress: typedData.message.tokenAddress,
duration: typedData.message.duration,
rate: typedData.message.rate,
interest: typedData.message.interest,
base: typedData.message.base,
makerSalt: typedData.message.makerSalt,
makerSignature: typedData.message.makerSignature,
takerSignature: signature,
}
window.activeOffers.push(newOffer);
var signedOffer = newOffer;
console.log(signedOffer);
/// Send Parameters, return takerAddress & ecrecover address
var hmm = defihedgeContract.verify(signedOffer.maker,signedOffer.taker,signedOffer.side,signedOffer.tokenAddress,signedOffer.duration,signedOffer.rate,signedOffer.interest,signedOffer.base,signedOffer.makerSalt,signedOffer.makerSignature,signedOffer.takerSignature,{
from: "0x00fE460A15B49d09F39b057D0f1A7B9444F4F2BE",
gas: "300000",
value: "",
data: "" }, function(error, result){
if(!error)
console.log(result);
else
console.error(error);
});
/// Ensures Signature Parsed Correctly
var hmm2 = defihedgeContract.signatureRPCtest(signedOffer.takerSignature,{
from: "0x00fE460A15B49d09F39b057D0f1A7B9444F4F2BE",
gas: "300000",
value: "",
data: "" }, function(error, result){
if(!error)
console.log(result);
else
console.error(error);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment