Skip to content

Commit

Permalink
Add a whole balance limit to UserDeposit
Browse files Browse the repository at this point in the history
which is configurable at the deployment time.

Currently we keep the option of limiting deposits in all smart
contracts.
  • Loading branch information
pirapira committed Mar 5, 2019
1 parent 6a409cc commit c6b0536
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 23 deletions.
21 changes: 20 additions & 1 deletion raiden_contracts/contracts/services/UserDeposit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ contract UserDeposit is Utils {
mapping(address => uint256) public balances;
mapping(address => WithdrawPlan) public withdraw_plans;

// The sum of all balances
uint256 public whole_balance = 0;
// Deposit limit for this whole contract
uint256 public whole_balance_limit;

/*
* Structs
*/
Expand Down Expand Up @@ -51,14 +56,17 @@ contract UserDeposit is Utils {

/// @notice Set the default values for the smart contract
/// @param _token_address The address of the token to use for rewards
constructor(address _token_address)
constructor(address _token_address, uint256 _whole_balance_limit)
public
{
// check token contract
require(_token_address != address(0x0));
require(contractExists(_token_address));
token = Token(_token_address);
require(token.totalSupply() > 0); // Check if the contract is indeed a token contract
// check and set the whole balance limit
require(_whole_balance_limit > 0);
whole_balance_limit = _whole_balance_limit;
}

/// @notice Specify trusted contracts. This has to be done outside of the
Expand Down Expand Up @@ -100,6 +108,13 @@ contract UserDeposit is Utils {
balances[beneficiary] += added_deposit;
total_deposit[beneficiary] += added_deposit;
require(token.transferFrom(msg.sender, address(this), added_deposit));

// Update whole_balance, but take care against overflows.
require(whole_balance + added_deposit >= whole_balance);
whole_balance += added_deposit;

// Decline deposit if the whole balance is bigger than the limit.
require(whole_balance <= whole_balance_limit);
}

/// @notice Internally transfer deposits between two addresses.
Expand Down Expand Up @@ -161,6 +176,10 @@ contract UserDeposit is Utils {
balances[msg.sender] -= withdrawable;
require(token.transfer(msg.sender, withdrawable));

// Update whole_balance, but take care against underflows.
require(whole_balance - withdrawable <= whole_balance);
whole_balance -= withdrawable;

emit BalanceReduced(msg.sender, balances[msg.sender]);
delete withdraw_plans[msg.sender];
}
Expand Down
66 changes: 49 additions & 17 deletions raiden_contracts/data/contracts.json

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion raiden_contracts/data/source/services/UserDeposit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ contract UserDeposit is Utils {
mapping(address => uint256) public balances;
mapping(address => WithdrawPlan) public withdraw_plans;

// The sum of all balances
uint256 public whole_balance = 0;
// Deposit limit for this whole contract
uint256 public whole_balance_limit;

/*
* Structs
*/
Expand Down Expand Up @@ -51,14 +56,17 @@ contract UserDeposit is Utils {

/// @notice Set the default values for the smart contract
/// @param _token_address The address of the token to use for rewards
constructor(address _token_address)
constructor(address _token_address, uint256 _whole_balance_limit)
public
{
// check token contract
require(_token_address != address(0x0));
require(contractExists(_token_address));
token = Token(_token_address);
require(token.totalSupply() > 0); // Check if the contract is indeed a token contract
// check and set the whole balance limit
require(_whole_balance_limit > 0);
whole_balance_limit = _whole_balance_limit;
}

/// @notice Specify trusted contracts. This has to be done outside of the
Expand Down Expand Up @@ -100,6 +108,13 @@ contract UserDeposit is Utils {
balances[beneficiary] += added_deposit;
total_deposit[beneficiary] += added_deposit;
require(token.transferFrom(msg.sender, address(this), added_deposit));

// Update whole_balance, but take care against overflows.
require(whole_balance + added_deposit >= whole_balance);
whole_balance += added_deposit;

// Decline deposit if the whole balance is bigger than the limit.
require(whole_balance <= whole_balance_limit);
}

/// @notice Internally transfer deposits between two addresses.
Expand Down Expand Up @@ -161,6 +176,10 @@ contract UserDeposit is Utils {
balances[msg.sender] -= withdrawable;
require(token.transfer(msg.sender, withdrawable));

// Update whole_balance, but take care against underflows.
require(whole_balance - withdrawable <= whole_balance);
whole_balance -= withdrawable;

emit BalanceReduced(msg.sender, balances[msg.sender]);
delete withdraw_plans[msg.sender];
}
Expand Down
14 changes: 11 additions & 3 deletions raiden_contracts/tests/fixtures/token.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,19 @@
CONTRACT_CUSTOM_TOKEN,
)

token_args = (10 ** 26, 18, CONTRACT_CUSTOM_TOKEN, 'TKN')

@pytest.fixture(scope='session')
def custom_token_total_supply():
return 10 ** 26


@pytest.fixture(scope='session')
def token_args(custom_token_total_supply):
return (custom_token_total_supply, 18, CONTRACT_CUSTOM_TOKEN, 'TKN')


@pytest.fixture(scope='session')
def custom_token_factory(deploy_tester_contract):
def custom_token_factory(deploy_tester_contract, token_args):
"""A function that deploys a CustomToken contract"""
def f():
return deploy_tester_contract(
Expand All @@ -26,7 +34,7 @@ def custom_token(custom_token_factory):


@pytest.fixture()
def human_standard_token(deploy_token_contract):
def human_standard_token(deploy_token_contract, token_args):
"""Deploy HumanStandardToken contract"""
return deploy_token_contract(*token_args)

Expand Down
9 changes: 8 additions & 1 deletion raiden_contracts/tests/fixtures/user_deposit.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@
from raiden_contracts.constants import CONTRACT_USER_DEPOSIT


@pytest.fixture(scope='session')
def user_deposit_whole_balance_limit(custom_token_total_supply):
return custom_token_total_supply // 100


@pytest.fixture(scope='session')
def uninitialized_user_deposit_contract(
deploy_tester_contract,
custom_token,
user_deposit_whole_balance_limit,
):
print(user_deposit_whole_balance_limit)
return deploy_tester_contract(
CONTRACT_USER_DEPOSIT,
{},
[custom_token.address],
[custom_token.address, user_deposit_whole_balance_limit],
)


Expand Down
8 changes: 8 additions & 0 deletions raiden_contracts/tests/test_user_deposit_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ def test_deposit(
with pytest.raises(TransactionFailed):
user_deposit_contract.functions.deposit(A, 21).transact({'from': A})

# Can't deposit more than the whole_balance_limit
limit = user_deposit_contract.functions.whole_balance_limit().call()
assert limit > 0
custom_token.functions.mint(limit + 1).transact({'from': A})
custom_token.functions.approve(user_deposit_contract.address, limit + 1).transact({'from': A})
with pytest.raises(TransactionFailed):
user_deposit_contract.functions.deposit(A, limit + 1).transact({'from': A})


def test_transfer(
uninitialized_user_deposit_contract,
Expand Down

0 comments on commit c6b0536

Please sign in to comment.