mirror of https://github.com/nucypher/nucypher.git
Improved tests for slashing
parent
dbeb29fe83
commit
df99cb650e
|
@ -166,6 +166,13 @@ contract Issuer is Upgradeable {
|
|||
currentSupply2 = currentSupply2.sub(_amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Returns the number of tokens that can be mined
|
||||
**/
|
||||
function getReservedReward() public view returns (uint256) {
|
||||
return totalSupply - Math.max256(currentSupply1, currentSupply2);
|
||||
}
|
||||
|
||||
function verifyState(address _testTarget) public onlyOwner {
|
||||
require(address(uint160(delegateGet(_testTarget, "token()"))) == address(token));
|
||||
require(delegateGet(_testTarget, "miningCoefficient()") == miningCoefficient);
|
||||
|
|
|
@ -748,7 +748,10 @@ contract MinersEscrow is Issuer {
|
|||
}
|
||||
}
|
||||
|
||||
unMint(_penalty - _reward);
|
||||
_penalty = _penalty - _reward;
|
||||
if (_penalty > 0) {
|
||||
unMint(_penalty);
|
||||
}
|
||||
if (_reward > 0) {
|
||||
token.safeTransfer(_investigator, _reward);
|
||||
}
|
||||
|
@ -784,9 +787,16 @@ contract MinersEscrow is Issuer {
|
|||
uint256 appliedPenalty = _penalty;
|
||||
if (_penalty < shortestSubStake.lockedValue) {
|
||||
shortestSubStake.lockedValue -= _penalty;
|
||||
if (_info.confirmedPeriod1 != EMPTY_CONFIRMED_PERIOD &&
|
||||
_info.confirmedPeriod1 < _period ||
|
||||
_info.confirmedPeriod2 != EMPTY_CONFIRMED_PERIOD &&
|
||||
_info.confirmedPeriod2 < _period
|
||||
) {
|
||||
saveSubStake(_info, shortestSubStake.firstPeriod, _period.sub16(1), 0, _penalty);
|
||||
}
|
||||
_penalty = 0;
|
||||
} else {
|
||||
shortestSubStake.lastPeriod = 1;
|
||||
shortestSubStake.lastPeriod = _period.sub16(1);
|
||||
_penalty -= shortestSubStake.lockedValue;
|
||||
appliedPenalty = shortestSubStake.lockedValue;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ def test_inflation_rate(testerchain, token):
|
|||
testerchain.wait_for_receipt(tx)
|
||||
tx = issuer.functions.initialize().transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
reward = issuer.functions.getReservedReward().call()
|
||||
|
||||
# Mint some tokens and save result of minting
|
||||
period = issuer.functions.getCurrentPeriod().call()
|
||||
|
@ -115,11 +116,13 @@ def test_inflation_rate(testerchain, token):
|
|||
tx = issuer.functions.testMint(period + 1, 1, 1, 0).transact({'from': ursula})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 2 * one_period == token.functions.balanceOf(ursula).call()
|
||||
assert reward - token.functions.balanceOf(ursula).call() == issuer.functions.getReservedReward().call()
|
||||
|
||||
# Mint tokens in the next period, inflation rate must be lower than in previous minting
|
||||
tx = issuer.functions.testMint(period + 2, 1, 1, 0).transact({'from': ursula})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 3 * one_period > token.functions.balanceOf(ursula).call()
|
||||
assert reward - token.functions.balanceOf(ursula).call() == issuer.functions.getReservedReward().call()
|
||||
minted_amount = token.functions.balanceOf(ursula).call() - 2 * one_period
|
||||
|
||||
# Mint tokens in the first period again, inflation rate must be the same as in previous minting
|
||||
|
@ -127,21 +130,26 @@ def test_inflation_rate(testerchain, token):
|
|||
tx = issuer.functions.testMint(period + 1, 1, 1, 0).transact({'from': ursula})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 2 * one_period + 2 * minted_amount == token.functions.balanceOf(ursula).call()
|
||||
assert reward - token.functions.balanceOf(ursula).call() == issuer.functions.getReservedReward().call()
|
||||
|
||||
# Mint tokens in the next period, inflation rate must be lower than in previous minting
|
||||
tx = issuer.functions.testMint(period + 3, 1, 1, 0).transact({'from': ursula})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 2 * one_period + 3 * minted_amount > token.functions.balanceOf(ursula).call()
|
||||
assert reward - token.functions.balanceOf(ursula).call() == issuer.functions.getReservedReward().call()
|
||||
|
||||
# Return some tokens as a reward
|
||||
balance = token.functions.balanceOf(ursula).call()
|
||||
reward = issuer.functions.getReservedReward().call()
|
||||
tx = issuer.functions.testUnMint(2 * one_period + 2 * minted_amount).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert reward + 2 * one_period + 2 * minted_amount == issuer.functions.getReservedReward().call()
|
||||
|
||||
# Rate will be increased because some tokens were returned
|
||||
tx = issuer.functions.testMint(period + 3, 1, 1, 0).transact({'from': ursula})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert balance + one_period == token.functions.balanceOf(ursula).call()
|
||||
assert reward + one_period + 2 * minted_amount == issuer.functions.getReservedReward().call()
|
||||
|
||||
|
||||
@pytest.mark.slow
|
||||
|
|
|
@ -331,7 +331,17 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 100 == escrow.functions.lockedPerPeriod(period).call()
|
||||
assert 0 == escrow.functions.lockedPerPeriod(period + 1).call()
|
||||
|
||||
# Can't slash directly using the escrow contract
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.slashMiner(ursula, 100, investigator, 10).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
# Penalty must be greater than zero
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow.functions.slashMiner(ursula, 0, investigator, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Slash the whole stake
|
||||
reward = escrow.functions.getReservedReward().call()
|
||||
tx = overseer.functions.slashMiner(ursula, 100, investigator, 10).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
# Miner has no more sub stakes
|
||||
|
@ -339,6 +349,7 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 0 == escrow.functions.getLockedTokens(ursula).call()
|
||||
assert 10 == token.functions.balanceOf(investigator).call()
|
||||
assert 0 == escrow.functions.lockedPerPeriod(period).call()
|
||||
assert reward + 90 == escrow.functions.getReservedReward().call()
|
||||
|
||||
# New deposit and confirmation of activity
|
||||
tx = escrow.functions.deposit(100, 5).transact({'from': ursula})
|
||||
|
@ -353,6 +364,7 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 100 == escrow.functions.lockedPerPeriod(period + 1).call()
|
||||
|
||||
# Slash part of one sub stake (there is only one sub stake)
|
||||
reward = escrow.functions.getReservedReward().call()
|
||||
tx = overseer.functions.slashMiner(ursula, 10, investigator, 11).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 90 == escrow.functions.minerInfo(ursula).call()[VALUE_FIELD]
|
||||
|
@ -361,6 +373,7 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 20 == token.functions.balanceOf(investigator).call()
|
||||
assert 90 == escrow.functions.lockedPerPeriod(period).call()
|
||||
assert 90 == escrow.functions.lockedPerPeriod(period + 1).call()
|
||||
assert reward == escrow.functions.getReservedReward().call()
|
||||
|
||||
# New deposit of a longer sub stake
|
||||
tx = escrow.functions.deposit(100, 6).transact({'from': ursula})
|
||||
|
@ -376,6 +389,7 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 0 == escrow.functions.lockedPerPeriod(period + 1).call()
|
||||
|
||||
# Slash again part of the first sub stake because new sub stake is longer (there are two sub stakes)
|
||||
reward = escrow.functions.getReservedReward().call()
|
||||
tx = overseer.functions.slashMiner(ursula, 10, investigator, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 180 == escrow.functions.minerInfo(ursula).call()[VALUE_FIELD]
|
||||
|
@ -385,6 +399,7 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 20 == token.functions.balanceOf(investigator).call()
|
||||
assert 90 == escrow.functions.lockedPerPeriod(period - 1).call()
|
||||
assert 180 == escrow.functions.lockedPerPeriod(period).call()
|
||||
assert reward + 10 == escrow.functions.getReservedReward().call()
|
||||
|
||||
# New deposit of a shorter sub stake
|
||||
tx = escrow.functions.deposit(110, 2).transact({'from': ursula})
|
||||
|
@ -399,6 +414,7 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 0 == escrow.functions.lockedPerPeriod(period).call()
|
||||
|
||||
# Slash only free amount of tokens
|
||||
reward = escrow.functions.getReservedReward().call()
|
||||
tx = overseer.functions.slashMiner(ursula, deposit - 290, investigator, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 290 == escrow.functions.minerInfo(ursula).call()[VALUE_FIELD]
|
||||
|
@ -408,6 +424,7 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 20 == token.functions.balanceOf(investigator).call()
|
||||
assert 290 == escrow.functions.lockedPerPeriod(period - 1).call()
|
||||
assert 0 == escrow.functions.lockedPerPeriod(period).call()
|
||||
assert reward + deposit - 290 == escrow.functions.getReservedReward().call()
|
||||
|
||||
# Slash only the new sub stake because it's the shortest one (there are three sub stakes)
|
||||
tx = overseer.functions.slashMiner(ursula, 10, investigator, 0).transact()
|
||||
|
@ -419,31 +436,31 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 20 == token.functions.balanceOf(investigator).call()
|
||||
assert 290 == escrow.functions.lockedPerPeriod(period - 1).call()
|
||||
assert 0 == escrow.functions.lockedPerPeriod(period).call()
|
||||
assert reward + deposit - 280 == escrow.functions.getReservedReward().call()
|
||||
|
||||
# New deposit
|
||||
tx = escrow.functions.deposit(100, 2).transact({'from': ursula})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 290 == escrow.functions.getLockedTokens(ursula, -1).call()
|
||||
assert 280 == escrow.functions.getLockedTokens(ursula).call()
|
||||
assert 380 == escrow.functions.getLockedTokens(ursula, 1).call()
|
||||
assert 380 == escrow.functions.lockedPerPeriod(period + 1).call()
|
||||
deposit = escrow.functions.minerInfo(ursula).call()[VALUE_FIELD] # Some reward is already mined
|
||||
reward = deposit - 380
|
||||
unlocked_deposit = deposit - 380
|
||||
reward = escrow.functions.getReservedReward().call()
|
||||
|
||||
# Slash the new sub stake which starts in the next period
|
||||
# Because locked value is more in the next period than in the current period
|
||||
tx = overseer.functions.slashMiner(ursula, reward + 10, investigator, 0).transact()
|
||||
tx = overseer.functions.slashMiner(ursula, unlocked_deposit + 10, investigator, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 290 == escrow.functions.getLockedTokens(ursula, -1).call()
|
||||
assert 280 == escrow.functions.getLockedTokens(ursula).call()
|
||||
assert 370 == escrow.functions.getLockedTokens(ursula, 1).call()
|
||||
assert 370 == escrow.functions.minerInfo(ursula).call()[VALUE_FIELD]
|
||||
assert 370 == escrow.functions.lockedPerPeriod(period + 1).call()
|
||||
assert reward + unlocked_deposit + 10 == escrow.functions.getReservedReward().call()
|
||||
|
||||
# After two periods shortest sub stake will be unlocked, lock again and slash after this
|
||||
testerchain.time_travel(hours=1)
|
||||
period += 1
|
||||
assert 280 == escrow.functions.getLockedTokens(ursula, -1).call()
|
||||
assert 370 == escrow.functions.getLockedTokens(ursula).call()
|
||||
assert 270 == escrow.functions.getLockedTokens(ursula, 1).call()
|
||||
assert 100 == escrow.functions.getLockedTokens(ursula, 3).call()
|
||||
|
@ -452,7 +469,6 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 0 == escrow.functions.lockedPerPeriod(period + 1).call()
|
||||
tx = escrow.functions.lock(100, 2).transact({'from': ursula})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 280 == escrow.functions.getLockedTokens(ursula, -1).call()
|
||||
assert 370 == escrow.functions.getLockedTokens(ursula).call()
|
||||
assert 370 == escrow.functions.getLockedTokens(ursula, 1).call()
|
||||
assert 100 == escrow.functions.getLockedTokens(ursula, 3).call()
|
||||
|
@ -463,9 +479,9 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
|
||||
# Slash two sub stakes:
|
||||
# one which will be unlocked after current period and new sub stake
|
||||
reward = escrow.functions.getReservedReward().call()
|
||||
tx = overseer.functions.slashMiner(ursula, 10, investigator, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 280 == escrow.functions.getLockedTokens(ursula, -1).call()
|
||||
assert 360 == escrow.functions.getLockedTokens(ursula).call()
|
||||
assert 360 == escrow.functions.getLockedTokens(ursula, 1).call()
|
||||
assert 100 == escrow.functions.getLockedTokens(ursula, 3).call()
|
||||
|
@ -473,12 +489,12 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 0 == escrow.functions.lockedPerPeriod(period - 1).call()
|
||||
assert 360 == escrow.functions.lockedPerPeriod(period).call()
|
||||
assert 360 == escrow.functions.lockedPerPeriod(period + 1).call()
|
||||
assert reward + 10 == escrow.functions.getReservedReward().call()
|
||||
|
||||
# Slash three sub stakes:
|
||||
# one which will be unlocked after current period, new sub stake and another short sub stake
|
||||
tx = overseer.functions.slashMiner(ursula, 90, investigator, 0).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 280 == escrow.functions.getLockedTokens(ursula, -1).call()
|
||||
assert 270 == escrow.functions.getLockedTokens(ursula).call()
|
||||
assert 270 == escrow.functions.getLockedTokens(ursula, 1).call()
|
||||
assert 100 == escrow.functions.getLockedTokens(ursula, 3).call()
|
||||
|
@ -486,3 +502,4 @@ def test_slashing(testerchain, token, escrow_contract):
|
|||
assert 0 == escrow.functions.lockedPerPeriod(period - 1).call()
|
||||
assert 270 == escrow.functions.lockedPerPeriod(period).call()
|
||||
assert 270 == escrow.functions.lockedPerPeriod(period + 1).call()
|
||||
assert reward + 100 == escrow.functions.getReservedReward().call()
|
||||
|
|
Loading…
Reference in New Issue