0

I’m new with ethereum.
I’m definitely struggling with the last 4 parameter of this function, so I’m asking the problem directly.

mapping(address => uint256) nonces;
/*
 * Proxy transfer token. When some users of the ethereum account has no ether,
 * he or she can authorize the agent for broadcast transactions, and agents may charge agency fees
 * @param _from
 * @param _to
 * @param _value
 * @param fee
 * @param _v
 * @param _r
 * @param _s
 */
function transferProxy(address _from, address _to, uint256 _value, uint256 _fee,
    uint8 _v,bytes32 _r, bytes32 _s) public transferAllowed(_from) returns (bool){

    if(balances[_from] < _fee + _value) revert();

    uint256 nonce = nonces[_from];
    bytes32 h = keccak256(_from,_to,_value,_fee,nonce);
    if(_from != ecrecover(h,_v,_r,_s)) revert(); // THE PROBLEM I’m STUCK ON SEVERAL HOURS IS HERE.

    if(balances[_to] + _value < balances[_to]
        || balances[msg.sender] + _fee < balances[msg.sender]) revert();
    balances[_to] += _value;
    Transfer(_from, _to, _value);

    balances[msg.sender] += _fee;
    Transfer(_from, msg.sender, _fee);

    balances[_from] -= _value + _fee;
    nonces[_from] = nonce + 1;
    return true;
}
  • First, keccak256 takes normally only one argument (the data to hash). I have no idea what using multiple parameters does. Adding the data ? If yes how ? Hashing the hashs ? all at once or rehashing after each results ?
  • Second thing, I think that in order to get _v I need to use web3.eth.sign with web3.eth.sign("0x395BE1C1Eb316f82781462C4C028893e51d8b2a5",keccak256("data")). But if it‘s not the case, I don’t know what I need to use
  • Third, no idea about _r is about.
  • Four, I think to understand _s is about an HTtp callback (by reading documentation). But it seems that I cannot just left it to 0 since I don’t know what to callback.
  • AND THE HArdest thing. How to determine exactly the nonce parameters in keccak256 ? (even If I have no idea on how to call it), because I’m having a hard time at understanding what mapping(address => uint256) nonces; and uint256 nonce = nonces[_from]; really do. And obviously I need to know the value in order to set _v _r _s

2 Answers 2

3

So, you have

mapping(address => uint256) nonces which means a uint256 value is associated with an address. Let me give you an example

Suppose you have an address 0xa1bc and you want to map some value with this address, let the value be 1234. This is how it is done

nonces["0xa1bc"] = 1234;

and to get the value associated with the address

uint256 temp = nonces["0xa1bc"]

Here I have assigned the value to temp, so temp will be 1234. If the mapping is not present the value will be 0 (zero).

You can see exactly these behaviors in the transferProxy function,

uint256 nonce = nonces[_from];

nonces[_from] = nonce + 1;

So, in the function first it reads nonce associated with an address _from, does some work and at last increase the nonce by one and save it to the same address _from.

Now, coming to your next problem about _v, _r and _s,

You are right about the web3.eth.sign. You can sign a piece of message by web3.eth.sign(data, privatekey) and its variant. This will give you a signature object. This signature can be decomposed into v, r and s. So, how can you get these value? Pay attention.

var sign = web3.eth.sign(data,privatekey);

var v = sign.v;

var r = sign.r;

var s = sign.s;

These v, r and s are the values you need to send to the transferproxy function in the contract.

So, basically why do you need these values? There you can see a function ecrecover which takes these values as parameters. This is an inbuilt function provided by Solidity. It gives the address of the user who signed the data. Here h is the hash of the data you want to sign.

But here we can see that you have not send the hash h to contract. Why? Because you can construct the original message with the data present in the contract itself. And that original message is _from,_to,_value,_fee,nonce. That means in you client side, you have saved or known these values in advance.

var sign = web3.eth.sign(_from+_to+_value+_fee+nonce, privatekeyOf_from);

So, the contract function call in the front side will look like

contractInstance.transferProxy.sendTransaction(from, to, value, fee, nonce, v, r, s, {from:.....});

if(_from != ecrecover(h,_v,_r,_s)) revert(); is assuring that the user with address _from has actually signed the data or not. If not revert (revert the changes) the transaction.

Coming to your first question, multiple parameters will be concatenated and then hashed.

8
  • So what would be the value of nonce the first time I’m calling for sending and receiving with the same address 0x395BE1C1Eb316f82781462C4C028893e51d8b2a5? May 23, 2018 at 18:41
  • the value will be 0 in this case. default values are 0, false for int, boolean types respectively.
    – biplavo
    May 23, 2018 at 18:56
  • One more thing. How do I convert parameters into the type solidity is expecting? May 23, 2018 at 21:07
  • Just send these values as it is. address and bytes value will be hexadecimals. If you are sending hardcoded (not assigned to some variables) values then surround address and bytes with quote.
    – biplavo
    May 24, 2018 at 16:36
  • Currently, everything is in string. I suppose I cannot just concatenate string values for keccak256. May 24, 2018 at 16:39
0

First, keccak256 takes normally only one argument (the data to hash). I have no idea what using multiple parameters does. Adding the data ? If yes how ? Hashing the hashs ? all at once or rehashing after each results ?

From the docs in solidity:

keccak256(...) returns (bytes32): compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments

Therefore the data to hash is the tightly packed parameters (_from,_to,_value,_fee,nonce) so keccak256(_from,_to,_value,_fee,nonce) calculates the hash of the bynary word that is fromed by putting togeteher all these five parameters.

Second thing, I think that in order to get _v I need to use web3.eth.sign with web3.eth.sign("0x395BE1C1Eb316f82781462C4C028893e51d8b2a5",keccak256("data")). But if it‘s not the case, I don’t know what I need to use Third, no idea about _r is about. Four, I think to understand _s is about an HTtp callback (by reading documentation). But it seems that I cannot just left it to 0 since I don’t know what to callback.

These parameters are obtained from the signature. In web3 signing a transacion provides the signature and the parameters r, s, and v. these parameters can also be derived from the signature itself, see web3 documentation on how to get r,s, and v and also this answer

AND THE HArdest thing. How to determine exactly the nonce parameters in keccak256 ? (even If I have no idea on how to call it), because I’m having a hard time at understanding what mapping(address => uint256) nonces; and uint256 nonce = nonces[_from]; really do. And obviously I need to know the value in order to set _v _r _s

the mapping takes as input an address and returns a number, that number is the nonce. Therefore, nonce[_from] is requesting the nonce for the address _from. This nonce value is basically a counter that increments every time a transaction is executed from the address _from.

Hope this helps.

7
  • By putting parameters together for keccak256 do you mean concatenate? If yes in byte or in string? May 23, 2018 at 17:30
  • the mapping takes as input an address and returns a number, that number is the nonce. Therefore, nonce[_from] is requesting the nonce for the address _from. This nonce value is basically a counter that increments every time a transaction is executed from the address _from. This doesn’t tell how I'm getting the nonce for hashing. May 23, 2018 at 17:33
  • Yes, means they are concatenated tightly meaning that the Hex value of each variable according to the type is concatenated.
    – Jaime
    May 23, 2018 at 17:37
  • The nonce variable is computed on the miner side. How do I compute it with Javascript? Or do I really need to bother getting it for ecrecover parameters? May 23, 2018 at 17:49
  • web3.eth.personal.ecRecover if for computing the hash. Does web3.eth.sign is required for doing the reverse? May 23, 2018 at 18:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.