From 35f62f1539550d67ad3abe7d04c33a4fcd59e6c1 Mon Sep 17 00:00:00 2001 From: Johann Barbie Date: Wed, 6 Feb 2019 09:49:05 +0100 Subject: [PATCH 1/4] pseudocode --- contracts/mocks/SpendingCondition.sol | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/contracts/mocks/SpendingCondition.sol b/contracts/mocks/SpendingCondition.sol index 14f2b88..6926148 100644 --- a/contracts/mocks/SpendingCondition.sol +++ b/contracts/mocks/SpendingCondition.sol @@ -12,23 +12,28 @@ import "../PlasmaInterface.sol"; import "../Reflectable.sol"; contract SpendingCondition is Reflectable { - uint256 constant nonce = 1234; // nonce, so that signatures can not be replayed address constant spenderAddr = 0xF3beAC30C498D9E26865F34fCAa57dBB935b0D74; - function fulfil(bytes32 _r, bytes32 _s, uint8 _v, // signature - address _tokenAddr, // inputs - address[] memory _receivers, uint256[] memory _amounts) public { // outputs - require(_receivers.length == _amounts.length); + function fulfil( + bytes32 _nonce, + uint _gasPrice, + uint _gasLimit, + address _to, + bytes _data, + bytes32 _r, + bytes32 _s, + uint8 _v) public { // check signature - address signer = ecrecover(bytes32(ripemd160(bytecode(address(this)))), _v, _r, _s); + require(_nonce == this); // this is injected as here: https://github.com/leapdao/leap-node/blob/388aa6c698719e53bf7dee715fe4368c069b6db1/src/tx/applyTx/checkSpendCond.js#L165 + bytes32 hash = keccak256(_nonce, _gasPrice, _gasLimit, _to, _data); + address signer = ecrecover(hash, _v, _r, _s); require(signer == spenderAddr); + + // todo: check gasPrice and gasLimit // do transfer - ERC20 token = ERC20(_tokenAddr); - for (uint i = 0; i < _receivers.length; i++) { - token.transfer(_receivers[i], _amounts[i]); - } + _tokenAddr.call(_data); } function exitProxy( From e1d3e15ad5c9e55ab2169b72423bdd3431332304 Mon Sep 17 00:00:00 2001 From: Johann Barbie Date: Wed, 6 Feb 2019 09:53:45 +0100 Subject: [PATCH 2/4] better description --- contracts/mocks/SpendingCondition.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/mocks/SpendingCondition.sol b/contracts/mocks/SpendingCondition.sol index 6926148..e4c0f2d 100644 --- a/contracts/mocks/SpendingCondition.sol +++ b/contracts/mocks/SpendingCondition.sol @@ -25,7 +25,10 @@ contract SpendingCondition is Reflectable { uint8 _v) public { // check signature - require(_nonce == this); // this is injected as here: https://github.com/leapdao/leap-node/blob/388aa6c698719e53bf7dee715fe4368c069b6db1/src/tx/applyTx/checkSpendCond.js#L165 + // if we are on plasma, 'this' is injected sigHash as here: https://github.com/leapdao/leap-node/blob/388aa6c698719e53bf7dee715fe4368c069b6db1/src/tx/applyTx/checkSpendCond.js#L165 + // if on main-net, the address off the deployed contract needs to be signed + // no replay protection after first signature. so spending condition should be emptied with first tx + require(_nonce == this); bytes32 hash = keccak256(_nonce, _gasPrice, _gasLimit, _to, _data); address signer = ecrecover(hash, _v, _r, _s); require(signer == spenderAddr); From 27dc5bc0936f84fb0fc89a77e890cb1e4758ec58 Mon Sep 17 00:00:00 2001 From: Johann Barbie Date: Wed, 6 Feb 2019 10:01:43 +0100 Subject: [PATCH 3/4] mainnetNonce --- contracts/mocks/SpendingCondition.sol | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/contracts/mocks/SpendingCondition.sol b/contracts/mocks/SpendingCondition.sol index e4c0f2d..6414df8 100644 --- a/contracts/mocks/SpendingCondition.sol +++ b/contracts/mocks/SpendingCondition.sol @@ -12,10 +12,12 @@ import "../PlasmaInterface.sol"; import "../Reflectable.sol"; contract SpendingCondition is Reflectable { + uint constant value = 0; + uint constant mainNetNonce = 12345; address constant spenderAddr = 0xF3beAC30C498D9E26865F34fCAa57dBB935b0D74; function fulfil( - bytes32 _nonce, + bytes32 _nonce, // uint _gasPrice, uint _gasLimit, address _to, @@ -23,13 +25,14 @@ contract SpendingCondition is Reflectable { bytes32 _r, bytes32 _s, uint8 _v) public { - // check signature // if we are on plasma, 'this' is injected sigHash as here: https://github.com/leapdao/leap-node/blob/388aa6c698719e53bf7dee715fe4368c069b6db1/src/tx/applyTx/checkSpendCond.js#L165 - // if on main-net, the address off the deployed contract needs to be signed - // no replay protection after first signature. so spending condition should be emptied with first tx - require(_nonce == this); - bytes32 hash = keccak256(_nonce, _gasPrice, _gasLimit, _to, _data); + // if on main-net, the address off the deployed contract needs to be signed. + // if on main-net, no replay protection after first signature. so spending condition should be emptied with first tx + if (_nonce != this) { + require(_nonce == mainNetNonce); + } + bytes32 hash = keccak256(_nonce, _gasPrice, _gasLimit, value, _to, _data); address signer = ecrecover(hash, _v, _r, _s); require(signer == spenderAddr); From fc730a145b972c4888490173f0def3031dfeef84 Mon Sep 17 00:00:00 2001 From: Johann Barbie Date: Wed, 6 Feb 2019 10:15:41 +0100 Subject: [PATCH 4/4] add gas checking --- contracts/mocks/SpendingCondition.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/mocks/SpendingCondition.sol b/contracts/mocks/SpendingCondition.sol index 6414df8..e5c77ba 100644 --- a/contracts/mocks/SpendingCondition.sol +++ b/contracts/mocks/SpendingCondition.sol @@ -37,6 +37,9 @@ contract SpendingCondition is Reflectable { require(signer == spenderAddr); // todo: check gasPrice and gasLimit + uint transferAmount = uint(_data); // pseudocode + uint balance = _tokenAddr.balanceOf(this); + require(balance - (_gasPrice * _gasLimit) == transferAmount); // do transfer _tokenAddr.call(_data);