-
Notifications
You must be signed in to change notification settings - Fork 118
Open
Description
Hi,
I have studied the code you use to create a signature :
https://github.com/etherdelta/bots/blob/master/js/service.js
const sign = (msgToSignIn, privateKeyIn) => {
const prefixMessage = (msgIn) => {
let msg = msgIn;
msg = new Buffer(msg.slice(2), 'hex');
msg = Buffer.concat([
new Buffer(`\x19Ethereum Signed Message:\n${msg.length.toString()}`),
msg]);
msg = self.web3.sha3(`0x${msg.toString('hex')}`, { encoding: 'hex' });
msg = new Buffer(msg.slice(2), 'hex');
return `0x${msg.toString('hex')}`;
};
const privateKey = privateKeyIn.substring(0, 2) === '0x' ?
privateKeyIn.substring(2, privateKeyIn.length) : privateKeyIn;
const msgToSign = prefixMessage(msgToSignIn);
try {
const sig = ethUtil.ecsign(
new Buffer(msgToSign.slice(2), 'hex'),
new Buffer(privateKey, 'hex'));
const r = `0x${sig.r.toString('hex')}`;
const s = `0x${sig.s.toString('hex')}`;
const v = sig.v;
const result = { r, s, v, msg: msgToSign };
return result;
} catch (err) {
throw new Error(err);
}
};
With that I have modified the function CreateOrder in the c# Bot, because the signature mechanism didn't work :
internal Order CreateOrder(OrderType orderType, BigInteger expires, BigInteger price, BigInteger amount)
{
if (Config.PrivateKey.Length != 64)
throw new Exception("WARNING: user_wallet_private_key must be a hexadecimal string of 64 characters long");
var uc = new UnitConversion();
var amountBigNum = amount;
var amountBaseBigNum = (amount * price) / uc.ToWei(1);
var tokenGet = orderType == OrderType.Buy ? Config.Token : ZeroToken;
var tokenGive = orderType == OrderType.Sell ? Config.Token : ZeroToken;
var amountGet = orderType == OrderType.Buy ? amountBigNum : amountBaseBigNum;
var amountGive = orderType == OrderType.Sell ? amountBigNum : amountBaseBigNum;
var orderNonce = new Random().Next();
var contractAddr = Web3.ToChecksumAddress(Config.AddressEtherDelta);
tokenGet = Web3.ToChecksumAddress(tokenGet);
tokenGive = Web3.ToChecksumAddress(tokenGive);
var user = Web3.ToChecksumAddress(Config.User);
/*
* First Step : Hash the order
*/
var plainData = new object[]
{
contractAddr,
tokenGet,
amountGet,
tokenGive,
amountGive,
expires,
orderNonce
};
var prms = new[] {
new Parameter("address",1),
new Parameter("address",1),
new Parameter("uint256",1),
new Parameter("address",1),
new Parameter("uint256",1),
new Parameter("uint256",1),
new Parameter("uint256",1)
};
var pe = new ParametersEncoder();
var data = pe.EncodeParameters(prms, plainData);
var ms = new MessageSigner();
var messageHashBytes = ms.Hash(data);
/*
* Second step : create the ethSignaturePrefixx
*/
var ethSignaturePrefixByteArray = Encoding.ASCII.GetBytes($"\u0019Ethereum Signed Message:\n{messageHashBytes.Length}");
/*
* Third Step : add the ethPrefix to the hashBytes and hash again
*/
int length = ethSignaturePrefixByteArray.Length + messageHashBytes.Length;
byte[] sum = new byte[length];
ethSignaturePrefixByteArray.CopyTo(sum, 0);
messageHashBytes.CopyTo(sum, ethSignaturePrefixByteArray.Length);
var signatureBase = ms.Hash(sum);
/*
* Fourth Step : Sign the message
* I have created a custom function CreateStringSignature2
* CreateStringSignature2 is the same function that CreateStringSignature in Nethereum
* the only difference is that CreateStringSignature2 is public
*/
var key = new EthECKey(Config.PrivateKey.HexToByteArray(), true);
var signature = CreateStringSignature2(key.SignAndCalculateV(signatureBase));
var ethEcdsa = MessageSigner.ExtractEcdsaSignature(signature);
/*
* Fifth Step : Create the order
*/
var order = new Order
{
AmountGet = new HexBigInteger(amountGet),
AmountGive = new HexBigInteger(amountGive),
TokenGet = tokenGet,
TokenGive = tokenGive,
ContractAddr = contractAddr,
Expires = expires,
Nonce = orderNonce,
User = user,
V = ethEcdsa.V,
R = ethEcdsa.R.ToHex(true),
S = ethEcdsa.S.ToHex(true)
};
/*
* Checking Signature
*/
/*
* First Step : Create a Fake WebSocket Message
*/
var message = new Message
{
Event = "message",
Data = new
{
amountGive = order.AmountGive.Value,
tokenGive = order.TokenGive,
amountGet = order.AmountGet.Value,
tokenGet = order.TokenGet,
contractAddr = Config.AddressEtherDelta,
expires = order.Expires,
nonce = order.Nonce,
user = order.User,
v = order.V,
r = order.R,
s = order.S,
}
}.ToString();
/*
* Second Step : Hash the message
*/
Message messageParsed = Message.ParseMessage(message);
var orderChecking = (JObject)messageParsed.Data;
plainData = new object[]
{
Web3.ToChecksumAddress(orderChecking["contractAddr"].ToString()),
Web3.ToChecksumAddress(orderChecking["tokenGet"].ToString()),
new BigInteger((decimal)orderChecking["amountGet"]),
Web3.ToChecksumAddress(orderChecking["tokenGive"].ToString()),
new BigInteger((decimal)orderChecking["amountGive"]),
new BigInteger((decimal)orderChecking["expires"]),
new BigInteger((decimal)orderChecking["nonce"]),
};
prms = new[] {
new Parameter("address",1),
new Parameter("address",1),
new Parameter("uint256",1),
new Parameter("address",1),
new Parameter("uint256",1),
new Parameter("uint256",1),
new Parameter("uint256",1)
};
pe = new ParametersEncoder();
data = pe.EncodeParameters(prms, plainData);
messageHashBytes = ms.Hash(data);
/*
* Third step : create the ethSignaturePrefix
*/
ethSignaturePrefixByteArray = Encoding.ASCII.GetBytes($"\u0019Ethereum Signed Message:\n{messageHashBytes.Length}");
/*
* Fourth Step : add the ethPrefix to the hashBytes and hash again
*/
length = ethSignaturePrefixByteArray.Length + messageHashBytes.Length;
sum = new byte[length];
ethSignaturePrefixByteArray.CopyTo(sum, 0);
messageHashBytes.CopyTo(sum, ethSignaturePrefixByteArray.Length);
signatureBase = ms.Hash(sum);
/*
* Retreive the public key and compare
*/
string publicKey = ms.EcRecover(signatureBase, signature);
if (publicKey.ToLower() != Config.User.ToLower())
throw new Exception("WARNING: incorect signature");
return order;
}
At the end of the function I check if the publickey that I have retreived from the signature matchs my public key and it works. But as soon as I send the message via the websocket I have a error :
Did not place order because available volume too low.
This error means for me that my signature is not correct.
If I remove the prefix I have still a error
I don't understand why. Can you help me ?
Thanks
Jehan
Metadata
Metadata
Assignees
Labels
No labels