Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ServiceRegistry (without parameter reconfiguration) #1116

Merged
merged 40 commits into from
Jul 16, 2019

Conversation

pirapira
Copy link
Contributor

@pirapira pirapira commented Jul 8, 2019

This is a part of #1087 .


Getting and Extending the Membership

There is always a deposit amount for six-month of membership.

  • a new member can join the pool for making the deposit.
  • an existing member can extend their membership for six months, for the same amount of deposit

The Change of Deposit Amounts

  • whenever somebody joins or extends the membership, the price increases by 20%
  • while nobody joins, the price decreases 0.5% per day.

Terms of the Deposits

The deposit is held until the six months period.

  • A new member's deposit is held for six months.
  • When an existing member extends the membership,
    • the new deposit is held until the end of the extended period
    • the old deposits' conditions stay unchanged

@codecov
Copy link

codecov bot commented Jul 8, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@6ee58d4). Click here to learn what that means.
The diff coverage is 66.66%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1116   +/-   ##
=========================================
  Coverage          ?   80.96%           
=========================================
  Files             ?       21           
  Lines             ?     1408           
  Branches          ?      178           
=========================================
  Hits              ?     1140           
  Misses            ?      228           
  Partials          ?       40
Impacted Files Coverage Δ
raiden_contracts/deploy/contract_verifier.py 87.32% <0%> (ø)
raiden_contracts/deploy/contract_deployer.py 91.4% <100%> (ø)
raiden_contracts/deploy/__main__.py 93.58% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6ee58d4...1fc9dee. Read the comment docs.

@codecov
Copy link

codecov bot commented Jul 8, 2019

Codecov Report

Merging #1116 into master will increase coverage by 0.13%.
The diff coverage is 90%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1116      +/-   ##
==========================================
+ Coverage      81%   81.14%   +0.13%     
==========================================
  Files          21       21              
  Lines        1411     1432      +21     
  Branches      179      186       +7     
==========================================
+ Hits         1143     1162      +19     
- Misses        228      229       +1     
- Partials       40       41       +1
Impacted Files Coverage Δ
raiden_contracts/deploy/contract_verifier.py 87.58% <100%> (+0.17%) ⬆️
raiden_contracts/utils/versions.py 100% <100%> (ø) ⬆️
raiden_contracts/deploy/__main__.py 93.58% <100%> (+0.04%) ⬆️
raiden_contracts/constants.py 100% <100%> (ø) ⬆️
raiden_contracts/deploy/contract_deployer.py 90% <50%> (-1.41%) ⬇️
raiden_contracts/contract_source_manager.py 89.15% <0%> (+0.84%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 463b5e5...a7051ee. Read the comment docs.

@pirapira pirapira force-pushed the membership branch 2 times, most recently from aa61897 to 0c98616 Compare July 9, 2019 10:02
@pirapira pirapira force-pushed the membership branch 3 times, most recently from 0afaadb to d4aa7e8 Compare July 9, 2019 16:32
@pirapira pirapira force-pushed the membership branch 3 times, most recently from 4140515 to 1983528 Compare July 12, 2019 10:44
@pirapira pirapira force-pushed the membership branch 2 times, most recently from 8182ef4 to 2a6831d Compare July 15, 2019 08:18
require(now >= release_at);
require(balance > 0);
require(token.transfer(_to, balance));
return true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this function have a return value? It always returns true if it does not fail on a require.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think currently it's safer to always return a boolean (even when it's always true), and always check the return value.

Solidity compiler doesn't warn when we forget to check the return value of a function call, so sticking with "always check return values" is a safe convention to follow.


I'll document this in the contribution guide.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've written this in CONTRIBUTING.md.

@@ -3,49 +3,167 @@ pragma solidity 0.5.4;
import "raiden/Token.sol";
import "raiden/Utils.sol";

contract Deposit {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this it's own contract? Couldn't you also model this as a struct inside the ServiceRegistry contract?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, everything could be in ServiceRegistry and that would be gas-efficient.

The current choice follows security-in-depth. Even if ServiceRegistry is compromized, the deposits made earlier would not be affected.

Is this conceptual security worth more than the additional gas? I don't know for sure, but the deposits are rarer and bigger than usual Raiden transfers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That argument makes sense to me, but I don't have much experience. The question was aimed at understanding the trade-off better!

withdrawer = _withdrawer;
}

// In order to make a deposit, transfer the ERC20 token into this contract.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to forbid this behaviour and only allow deposits with a deposit function, where one could check the token?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, contracts cannot refuse incoming ERC20 tokens.

In the beginning, I had a deposit() function, but it did nothing useful. So I removed it.


// @param _token_for_registration The address of the ERC20 token contract that services use for registration fees
constructor(address _token_for_registration) public {
constructor(address _token_for_registration, uint256 _initial_price) public {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should min_price be settable as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This follows in the next PR. min_price, 6/5 bumping ratio and 200 days will be configurable.

// Check against overflow.
require(valid_till < valid_till + 180 days);
valid_till = valid_till + 180 days;
assert(valid_till > service_valid_till[msg.sender]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about low-level differences, but why do you use assert here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I know the assert is always true. So I use assert and then the SMT solver in solc tries to find a counterexample.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To say it in a different way: assert should only fail for bugs in the contract, require is for all other cases.

require(token.transfer(address(depo), amount));

// Fire event
emit RegisteredService(msg.sender, valid_till, amount, depo);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above you write that all functions should return true, so this one as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe so. I'll add return true.

require(bytes(new_url).length != 0, "new url is empty string");
if (bytes(urls[msg.sender]).length == 0) {
service_addresses.push(msg.sender);
}
urls[msg.sender] = new_url;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, should this return true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's also true.

and the new value is small enough.

```
>>> A = 200
>>> X = 2 ** 60 - 1
>>> P = 24 * (A ** 4)
>>> Q = P + 24*(A**3)*X + 12*(A**2)*(X**2) + 4*A*(X**3) + X**4
>>> Q < (2 ** 256 - 1)
True
```
// We are here trying to approximate some exponential decay.
// exp(- X / A) where
// X is the number of seconds since the last price change
// A is the decay constant (A = 200 days correspnods to 0.5% decrease per day)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/correspnods/corresponds

uint256 P = 24 * (A ** 4);
uint256 Q = P + 24*(A**3)*X + 12*(A**2)*(X**2) + 4*A*(X**3) + X**4;

uint256 price = _set_price * P / Q;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you make A configurable, you might have to check for an overflow here as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the next PR will contain lots of those checks. I hope nobody needs the price decaying over billions of years.

raiden_contracts/deploy/__main__.py Outdated Show resolved Hide resolved
raiden_contracts/deploy/contract_verifier.py Outdated Show resolved Hide resolved
def test_deposit_contract(
get_deposit_contract: Callable, custom_token: Contract, get_accounts: Callable
) -> None:
(A,) = get_accounts(1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: You don't need braces here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it without the braces, but it's with the braces everywhere in the codebase. For now I just follow the local convention.

raiden_contracts/data/source/services/ServiceRegistry.sol Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants