Merge pull request #2191 from vzotova/worklock-restake

WorkLock: `restake` lock while claiming tokens
pull/2197/head
K Prasch 2020-08-26 12:09:22 -07:00 committed by GitHub
commit 6f911ac0a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 504 additions and 111 deletions

View File

@ -407,6 +407,7 @@ class ContractAdministrator(NucypherTokenActor):
def batch_deposits(self,
allocation_data_filepath: str,
release_period: int,
interactive: bool = True,
emitter: StdoutEmitter = None,
gas_limit: int = None
@ -431,7 +432,7 @@ class ContractAdministrator(NucypherTokenActor):
if interactive and not emitter:
raise ValueError("'emitter' is a required keyword argument when interactive is True.")
allocator = Allocator(allocation_data_filepath, self.registry, self.deployer_address)
allocator = Allocator(allocation_data_filepath, self.registry, self.deployer_address, release_period)
# TODO: Check validity of input address (check TX)
@ -532,7 +533,7 @@ class Allocator:
OCCUPATION_RATIO = 0.9 # When there's no explicit gas limit, we'll try to use the block limit up to this ratio
def __init__(self, filepath: str, registry, deployer_address):
def __init__(self, filepath: str, registry, deployer_address, release_period):
self.log = Logger("allocator")
self.staking_agent = ContractAgency.get_agent(StakingEscrowAgent,
@ -541,6 +542,7 @@ class Allocator:
self.allocations = dict()
self.deposited = set()
self.economics = EconomicsFactory.get_economics(registry)
self.release_period = release_period
self.__total_to_allocate = 0
self.__process_allocation_data(str(filepath))
@ -631,6 +633,7 @@ class Allocator:
batch_parameters = self.staking_agent.construct_batch_deposit_parameters(deposits=test_batch)
try:
estimated_gas = self.staking_agent.batch_deposit(*batch_parameters,
release_period=self.release_period,
sender_address=sender_address,
dry_run=True,
gas_limit=gas_limit)
@ -649,6 +652,7 @@ class Allocator:
batch_parameters = self.staking_agent.construct_batch_deposit_parameters(deposits=last_good_batch)
receipt = self.staking_agent.batch_deposit(*batch_parameters,
release_period=self.release_period,
sender_address=sender_address,
gas_limit=gas_limit)

View File

@ -480,6 +480,7 @@ class StakingEscrowAgent(EthereumContractAgent):
number_of_substakes: List[int],
amounts: List[NuNits],
lock_periods: List[PeriodDelta],
release_period: Period,
sender_address: ChecksumAddress,
dry_run: bool = False,
gas_limit: Optional[Wei] = None
@ -489,7 +490,8 @@ class StakingEscrowAgent(EthereumContractAgent):
if gas_limit and gas_limit < min_gas_batch_deposit:
raise ValueError(f"{gas_limit} is not enough gas for any batch deposit")
contract_function: ContractFunction = self.contract.functions.batchDeposit(stakers, number_of_substakes, amounts, lock_periods)
contract_function: ContractFunction = self.contract.functions.batchDeposit(
stakers, number_of_substakes, amounts, lock_periods, release_period)
if dry_run:
payload: TxParams = {'from': sender_address}
if gas_limit:

View File

@ -41,7 +41,7 @@ interface WorkLockInterface {
/**
* @notice Contract holds and locks stakers tokens.
* Each staker that locks their tokens will receive some compensation
* @dev |v5.2.2|
* @dev |v5.3.1|
*/
contract StakingEscrow is Issuer, IERC900History {
@ -529,6 +529,52 @@ contract StakingEscrow is Issuer, IERC900History {
emit ReStakeLocked(msg.sender, _lockReStakeUntilPeriod);
}
/**
* @notice Enable `reStake` and lock this parameter even if parameter is locked
* @param _staker Staker address
* @param _info Staker structure
* @param _lockReStakeUntilPeriod Can't change `reStake` value until this period
*/
function forceLockReStake(
address _staker,
StakerInfo storage _info,
uint16 _lockReStakeUntilPeriod
)
internal
{
// reset bit when `reStake` is already disabled
if (_info.flags.bitSet(RE_STAKE_DISABLED_INDEX) == true) {
_info.flags = _info.flags.toggleBit(RE_STAKE_DISABLED_INDEX);
emit ReStakeSet(_staker, true);
}
// lock `reStake` parameter if it's not locked or locked for too short duration
if (_lockReStakeUntilPeriod > _info.lockReStakeUntilPeriod) {
_info.lockReStakeUntilPeriod = _lockReStakeUntilPeriod;
emit ReStakeLocked(_staker, _lockReStakeUntilPeriod);
}
}
/**
* @notice Deposit tokens and lock `reStake` parameter from WorkLock contract
* @param _staker Staker address
* @param _value Amount of tokens to deposit
* @param _periods Amount of periods during which tokens will be locked
* and number of period after which `reStake` can be changed
*/
function depositFromWorkLock(
address _staker,
uint256 _value,
uint16 _periods
)
external
{
require(msg.sender == address(workLock));
deposit(_staker, msg.sender, MAX_SUB_STAKES, _value, _periods);
StakerInfo storage info = stakerInfo[_staker];
uint16 lockReStakeUntilPeriod = getCurrentPeriod().add16(_periods).add16(1);
forceLockReStake(_staker, info, lockReStakeUntilPeriod);
}
/**
* @notice Set `windDown` parameter.
* If true then stake's duration will be decreasing in each period with `commitToNextPeriod()`
@ -615,14 +661,18 @@ contract StakingEscrow is Issuer, IERC900History {
* @param _numberOfSubStakes Number of sub-stakes which belong to staker in _values and _periods arrays
* @param _values Amount of tokens to deposit for each staker
* @param _periods Amount of periods during which tokens will be locked for each staker
* @param _lockReStakeUntilPeriod Can't change `reStake` value until this period. Zero value will disable locking
*/
function batchDeposit(
address[] calldata _stakers,
uint256[] calldata _numberOfSubStakes,
uint256[] calldata _values,
uint16[] calldata _periods
uint16[] calldata _periods,
uint16 _lockReStakeUntilPeriod
)
external
// `onlyOwner` modifier is for prevent malicious using of `forceLockReStake`
// remove `onlyOwner` if `forceLockReStake` will be removed
external onlyOwner
{
uint256 subStakesLength = _values.length;
require(_stakers.length != 0 &&
@ -658,6 +708,10 @@ contract StakingEscrow is Issuer, IERC900History {
}
require(info.value <= maxAllowableLockedTokens);
info.history.addSnapshot(info.value);
if (_lockReStakeUntilPeriod >= nextPeriod) {
forceLockReStake(staker, info, _lockReStakeUntilPeriod);
}
}
require(j == subStakesLength);
uint256 lastGlobalBalance = uint256(balanceHistory.lastValue());

View File

@ -503,7 +503,7 @@ contract WorkLock is Ownable {
info.claimed = true;
token.approve(address(escrow), claimedTokens);
escrow.deposit(msg.sender, claimedTokens, stakingPeriods);
escrow.depositFromWorkLock(msg.sender, claimedTokens, stakingPeriods);
info.completedWork = escrow.setWorkMeasurement(msg.sender, true);
emit Claimed(msg.sender, claimedTokens);
}

View File

@ -73,7 +73,7 @@ from nucypher.cli.literature import (
SUCCESSFUL_SAVE_DEPLOY_RECEIPTS,
SUCCESSFUL_SAVE_MULTISIG_TX_PROPOSAL,
SUCCESSFUL_UPGRADE,
UNKNOWN_CONTRACT_NAME
UNKNOWN_CONTRACT_NAME, PROMPT_FOR_RELEASE_PERIOD
)
from nucypher.cli.options import (
group_options,
@ -509,14 +509,18 @@ def contracts(general_config, actor_options, mode, activate, gas, ignore_deploye
@group_general_config
@group_actor_options
@click.option('--allocation-infile', help="Input path for token allocation JSON file", type=EXISTING_READABLE_FILE)
@click.option('--release-period', help="Period number when re-stake lock will be released", type=click.INT)
@option_gas
def allocations(general_config, actor_options, allocation_infile, gas):
def allocations(general_config, actor_options, allocation_infile, gas, release_period):
"""Deposit stake allocations in batches"""
emitter = general_config.emitter
ADMINISTRATOR, _, deployer_interface, local_registry = actor_options.create_actor(emitter)
if not allocation_infile:
allocation_infile = click.prompt(PROMPT_FOR_ALLOCATION_DATA_FILEPATH)
if release_period is None:
release_period = click.prompt(PROMPT_FOR_RELEASE_PERIOD)
receipts = ADMINISTRATOR.batch_deposits(allocation_data_filepath=allocation_infile,
release_period=release_period,
emitter=emitter,
gas_limit=gas,
interactive=not actor_options.force)

View File

@ -395,6 +395,8 @@ DISPLAY_SENDER_TOKEN_BALANCE_BEFORE_TRANSFER = "Deployer NU balance: {token_bala
PROMPT_FOR_ALLOCATION_DATA_FILEPATH = "Enter allocations data filepath"
PROMPT_FOR_RELEASE_PERIOD = "Enter period number when re-stake lock should be released"
SUCCESSFUL_SAVE_BATCH_DEPOSIT_RECEIPTS = "Saved batch deposits receipts to {receipts_filepath}"
SUCCESSFUL_SAVE_DEPLOY_RECEIPTS = "Saved deployment receipts to {receipts_filepath}"

View File

@ -21,6 +21,7 @@ import random
import pytest
from nucypher.blockchain.eth.actors import ContractAdministrator
from nucypher.blockchain.eth.agents import StakingEscrowAgent, ContractAgency
from nucypher.blockchain.eth.sol.compile import SolidityCompiler
from nucypher.characters.control.emitters import StdoutEmitter
from nucypher.crypto.powers import TransactingPower
@ -76,7 +77,9 @@ def test_rapid_deployment(token_economics, test_registry, tmpdir, get_random_che
with open(filepath, 'w') as f:
json.dump(allocation_data, f)
administrator.batch_deposits(allocation_data_filepath=str(filepath), interactive=False)
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=test_registry)
current_period = staking_agent.get_current_period()
administrator.batch_deposits(allocation_data_filepath=str(filepath), interactive=False, release_period=current_period+10)
minimum, default, maximum = 10, 20, 30
administrator.set_fee_rate_range(minimum, default, maximum)

View File

@ -447,6 +447,7 @@ def test_batch_deposit(testerchain,
amount = token_economics.minimum_allowed_locked
lock_periods = token_economics.minimum_locked_periods
current_period = staking_agent.get_current_period()
stakers = [get_random_checksum_address() for _ in range(4)]
@ -472,13 +473,19 @@ def test_batch_deposit(testerchain,
not_enough_gas = 800_000
with pytest.raises((TransactionFailed, ValueError)):
staking_agent.batch_deposit(*batch_parameters,
release_period=current_period + 2,
sender_address=testerchain.etherbase_account,
dry_run=True,
gas_limit=not_enough_gas)
staking_agent.batch_deposit(*batch_parameters, sender_address=testerchain.etherbase_account, dry_run=True)
staking_agent.batch_deposit(*batch_parameters,
release_period=current_period + 2,
sender_address=testerchain.etherbase_account,
dry_run=True)
staking_agent.batch_deposit(*batch_parameters, sender_address=testerchain.etherbase_account)
staking_agent.batch_deposit(*batch_parameters,
release_period=current_period + 2,
sender_address=testerchain.etherbase_account)
for staker in stakers:
assert staking_agent.owned_tokens(staker_address=staker) == amount * N
@ -488,3 +495,4 @@ def test_batch_deposit(testerchain,
first_period, last_period, locked_value = substake
assert last_period == first_period + lock_periods - 1
assert locked_value == amount
assert staking_agent.is_restaking_locked(staker_address=staker)

View File

@ -214,6 +214,8 @@ def test_batch_deposits(click_runner,
agency_local_registry,
mock_allocation_infile,
token_economics):
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=agency_local_registry)
current_period = staking_agent.get_current_period()
#
# Main
@ -222,6 +224,7 @@ def test_batch_deposits(click_runner,
deploy_command = ('allocations',
'--registry-infile', agency_local_registry.filepath,
'--allocation-infile', mock_allocation_infile,
'--release-period', current_period + 10,
'--provider', TEST_PROVIDER_URI)
account_index = '0\n'

View File

@ -257,13 +257,20 @@ contract Intermediary {
*/
contract WorkLockForStakingEscrowMock {
NuCypherToken public immutable token;
StakingEscrow public immutable escrow;
constructor(StakingEscrow _escrow) {
constructor(NuCypherToken _token, StakingEscrow _escrow) {
token = _token;
escrow = _escrow;
}
function setWorkMeasurement(address _staker, bool _measureWork) external returns (uint256) {
return escrow.setWorkMeasurement(_staker, _measureWork);
}
function depositFromWorkLock(address _staker, uint256 _value, uint16 _periods) external {
token.approve(address(escrow), _value);
escrow.depositFromWorkLock(_staker, _value, _periods);
}
}

View File

@ -47,7 +47,7 @@ contract StakingEscrowForWorkLockMock {
return stakerInfo[_staker].completedWork;
}
function deposit(address _staker, uint256 _value, uint16 _periods) external {
function depositFromWorkLock(address _staker, uint256 _value, uint16 _periods) external {
stakerInfo[_staker].value = _value;
stakerInfo[_staker].periods = _periods;
token.transferFrom(msg.sender, address(this), _value);

View File

@ -295,10 +295,10 @@ def preallocation_escrow_2(testerchain, token, staking_interface, staking_interf
@pytest.mark.usefixtures('multisig')
def test_batch_deposit(testerchain, token_economics, token, escrow):
creator = testerchain.w3.eth.accounts[0]
staker1, staker2, staker3, staker4 = testerchain.client.accounts[1:5]
def test_batch_deposit(testerchain, token_economics, token, escrow, multisig):
creator, staker1, staker2, staker3, staker4, _alice1, _alice2, *contracts_owners =\
testerchain.client.accounts
contracts_owners = sorted(contracts_owners)
# Travel to the start of the next period to prevent problems with unexpected overflow first period
testerchain.time_travel(hours=1)
@ -317,10 +317,25 @@ def test_batch_deposit(testerchain, token_economics, token, escrow):
pytest.staker1_tokens = token_economics.minimum_allowed_locked
staker1_tokens = pytest.staker1_tokens
duration = token_economics.minimum_locked_periods
tx = token.functions.approve(escrow.address, 2 * staker1_tokens).transact({'from': creator})
current_period = escrow.functions.getCurrentPeriod().call()
# Only owner can use batch deposit
tx = token.functions.approve(escrow.address, staker1_tokens).transact({'from': creator})
testerchain.wait_for_receipt(tx)
tx = escrow.functions.batchDeposit([staker1], [1], [staker1_tokens], [duration]).transact({'from': creator})
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit(
[staker1], [1], [staker1_tokens], [duration], current_period + 1).transact({'from': creator})
testerchain.wait_for_receipt(tx)
tx = token.functions.transfer(multisig.address, staker1_tokens).transact({'from': creator})
testerchain.wait_for_receipt(tx)
tx = token.functions.approve(escrow.address, staker1_tokens) \
.buildTransaction({'from': multisig.address, 'gasPrice': 0})
execute_multisig_transaction(testerchain, multisig, [contracts_owners[0], contracts_owners[1]], tx)
tx = escrow.functions.batchDeposit([staker1], [1], [staker1_tokens], [duration], current_period + 1)\
.buildTransaction({'from': multisig.address, 'gasPrice': 0})
execute_multisig_transaction(testerchain, multisig, [contracts_owners[0], contracts_owners[1]], tx)
pytest.escrow_supply = token_economics.minimum_allowed_locked
assert token.functions.balanceOf(escrow.address).call() == pytest.escrow_supply
assert escrow.functions.getAllTokens(staker1).call() == staker1_tokens
@ -329,10 +344,13 @@ def test_batch_deposit(testerchain, token_economics, token, escrow):
assert escrow.functions.getLockedTokens(staker1, duration).call() == staker1_tokens
assert escrow.functions.getLockedTokens(staker1, duration + 1).call() == 0
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker1).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker1).call()
# Can't deposit tokens again for the same staker
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker1], [1], [staker1_tokens], [duration]).transact({'from': creator})
testerchain.wait_for_receipt(tx)
execute_multisig_transaction(testerchain, multisig, [contracts_owners[0], contracts_owners[1]], tx)
tx = token.functions.approve(escrow.address, 0).transact({'from': creator})
testerchain.wait_for_receipt(tx)
@ -482,6 +500,10 @@ def test_worklock_phases(testerchain,
testerchain.wait_for_receipt(tx)
assert worklock.functions.workInfo(staker2).call()[2]
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker2).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker2).call()
assert token.functions.balanceOf(staker2).call() == 0
assert escrow.functions.getLockedTokens(staker2, 0).call() == 0
assert escrow.functions.getLockedTokens(staker2, 1).call() == staker2_tokens
@ -502,6 +524,7 @@ def test_worklock_phases(testerchain,
wind_down, _re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker2).call()
assert wind_down
assert not escrow.functions.isReStakeLocked(staker1).call()
tx = worklock.functions.claim().transact({'from': staker1, 'gas_price': 0})
testerchain.wait_for_receipt(tx)
assert worklock.functions.workInfo(staker1).call()[2]
@ -510,6 +533,10 @@ def test_worklock_phases(testerchain,
assert escrow.functions.getLockedTokens(staker1, 1).call() == pytest.staker1_tokens
pytest.escrow_supply += staker1_claims
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker1).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker1).call()
# Staker prolongs lock duration
tx = escrow.functions.prolongStake(0, 3).transact({'from': staker2, 'gas_price': 0})
testerchain.wait_for_receipt(tx)
@ -631,8 +658,6 @@ def test_staking(testerchain,
testerchain.wait_for_receipt(tx)
tx = escrow.functions.bondWorker(staker1).transact({'from': staker1})
testerchain.wait_for_receipt(tx)
tx = escrow.functions.setReStake(False).transact({'from': staker1})
testerchain.wait_for_receipt(tx)
tx = escrow.functions.setWindDown(True).transact({'from': staker1})
testerchain.wait_for_receipt(tx)
wind_down, _re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker1).call()
@ -735,14 +760,6 @@ def test_policy(testerchain,
tx = escrow.functions.commitToNextPeriod().transact({'from': staker3})
testerchain.wait_for_receipt(tx)
# Turn on re-stake for staker1
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker1).call()
assert not re_stake
tx = escrow.functions.setReStake(True).transact({'from': staker1})
testerchain.wait_for_receipt(tx)
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker1).call()
assert re_stake
testerchain.time_travel(hours=1)
tx = escrow.functions.commitToNextPeriod().transact({'from': staker1})
testerchain.wait_for_receipt(tx)
@ -856,14 +873,6 @@ def test_policy(testerchain,
tx = escrow.functions.commitToNextPeriod().transact({'from': staker3})
testerchain.wait_for_receipt(tx)
# Turn off re-stake for staker1
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker1).call()
assert re_stake
tx = escrow.functions.setReStake(False).transact({'from': staker1})
testerchain.wait_for_receipt(tx)
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker1).call()
assert not re_stake
testerchain.time_travel(hours=1)
tx = escrow.functions.commitToNextPeriod().transact({'from': staker1})
testerchain.wait_for_receipt(tx)
@ -1192,54 +1201,6 @@ def test_upgrading_adjudicator(testerchain,
assert adjudicator_v1 == adjudicator.functions.target().call()
def test_another_slashing(testerchain,
token_economics,
token,
escrow,
adjudicator,
preallocation_escrow_1,
mock_ursula_reencrypts,
mocker):
creator, staker1, staker2, staker3, staker4, alice1, alice2, *contracts_owners =\
testerchain.client.accounts
ursula1_with_stamp = mock_ursula(testerchain, staker1, mocker=mocker)
# Slash two sub stakes
current_period = escrow.functions.getCurrentPeriod().call()
algorithm_sha256, base_penalty, *coefficients = token_economics.slashing_deployment_parameters
penalty_history_coefficient, percentage_penalty_coefficient, reward_coefficient = coefficients
total_previous_lock = escrow.functions.lockedPerPeriod(current_period - 1).call()
tokens_amount = escrow.functions.getAllTokens(staker1).call()
unlocked_amount = tokens_amount - escrow.functions.getLockedTokens(staker1, 0).call()
tx = escrow.functions.withdraw(unlocked_amount).transact({'from': staker1})
testerchain.wait_for_receipt(tx)
previous_lock = escrow.functions.getLockedTokensInPast(staker1, 1).call()
lock = escrow.functions.getLockedTokens(staker1, 0).call()
next_lock = escrow.functions.getLockedTokens(staker1, 1).call()
total_lock = escrow.functions.lockedPerPeriod(current_period).call()
alice2_balance = token.functions.balanceOf(alice2).call()
data_hash, slashing_args = generate_args_for_slashing(mock_ursula_reencrypts, ursula1_with_stamp)
assert not adjudicator.functions.evaluatedCFrags(data_hash).call()
tx = adjudicator.functions.evaluateCFrag(*slashing_args).transact({'from': alice2})
testerchain.wait_for_receipt(tx)
assert adjudicator.functions.evaluatedCFrags(data_hash).call()
data_hash, slashing_args = generate_args_for_slashing(mock_ursula_reencrypts, ursula1_with_stamp)
assert not adjudicator.functions.evaluatedCFrags(data_hash).call()
tx = adjudicator.functions.evaluateCFrag(*slashing_args).transact({'from': alice2})
testerchain.wait_for_receipt(tx)
assert adjudicator.functions.evaluatedCFrags(data_hash).call()
penalty = (2 * base_penalty + 3 * penalty_history_coefficient)
assert lock - penalty == escrow.functions.getAllTokens(staker1).call()
assert previous_lock == escrow.functions.getLockedTokensInPast(staker1, 1).call()
assert lock - penalty == escrow.functions.getLockedTokens(staker1, 0).call()
assert next_lock - (penalty - (lock - next_lock)) == escrow.functions.getLockedTokens(staker1, 1).call()
assert total_previous_lock == escrow.functions.lockedPerPeriod(current_period - 1).call()
assert total_lock - penalty == escrow.functions.lockedPerPeriod(current_period).call()
assert 0 == escrow.functions.lockedPerPeriod(current_period + 1).call()
assert alice2_balance + penalty / reward_coefficient == token.functions.balanceOf(alice2).call()
def test_withdraw(testerchain,
token_economics,
token,

View File

@ -23,6 +23,7 @@ from web3.contract import Contract
MAX_SUB_STAKES = 30
MAX_UINT16 = 65535
LOCK_RE_STAKE_UNTIL_PERIOD_FIELD = 4
def test_staking(testerchain, token, escrow_contract):
@ -1266,14 +1267,28 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
creator = testerchain.client.accounts[0]
deposit_log = escrow.events.Deposited.createFilter(fromBlock='latest')
lock_log = escrow.events.Locked.createFilter(fromBlock='latest')
re_stake_log = escrow.events.ReStakeSet.createFilter(fromBlock='latest')
re_stake_lock_log = escrow.events.ReStakeLocked.createFilter(fromBlock='latest')
# Grant access to transfer tokens
tx = token.functions.approve(escrow.address, 10000).transact({'from': creator})
testerchain.wait_for_receipt(tx)
# Deposit tokens for 1 staker
# Can deposit tokens only from owner
staker = testerchain.client.accounts[1]
tx = escrow.functions.batchDeposit([staker], [1], [1000], [10]).transact({'from': creator})
tx = token.functions.transfer(staker, 1000).transact({'from': creator})
testerchain.wait_for_receipt(tx)
tx = token.functions.approve(escrow.address, 1000).transact({'from': staker})
testerchain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [1], [1000], [10], 0)\
.transact({'from': staker})
testerchain.wait_for_receipt(tx)
# Deposit tokens for 1 staker
tx = escrow.functions.setReStake(False).transact({'from': staker})
testerchain.wait_for_receipt(tx)
tx = escrow.functions.batchDeposit([staker], [1], [1000], [10], 0).transact({'from': creator})
testerchain.wait_for_receipt(tx)
escrow_balance = 1000
assert token.functions.balanceOf(escrow.address).call() == escrow_balance
@ -1288,6 +1303,12 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
assert escrow.functions.getPastDowntimeLength(staker).call() == 0
assert escrow.functions.getLastCommittedPeriod(staker).call() == 0
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker).call()
assert not re_stake
assert not escrow.functions.isReStakeLocked(staker).call()
staker_info = escrow.functions.stakerInfo(staker).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == 0
deposit_events = deposit_log.get_all_entries()
assert len(deposit_events) == 1
event_args = deposit_events[-1]['args']
@ -1303,55 +1324,60 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
assert event_args['firstPeriod'] == current_period + 1
assert event_args['periods'] == 10
events = re_stake_log.get_all_entries()
assert len(events) == 1
events = re_stake_lock_log.get_all_entries()
assert len(events) == 0
# Can't deposit tokens again for the same staker twice
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [1], [1000], [10])\
tx = escrow.functions.batchDeposit([staker], [1], [1000], [10], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
# Can't deposit tokens with too low or too high value
staker = testerchain.client.accounts[2]
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [1], [1], [10])\
tx = escrow.functions.batchDeposit([staker], [1], [1], [10], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [1], [1501], [10])\
tx = escrow.functions.batchDeposit([staker], [1], [1501], [10], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [1], [500], [1])\
tx = escrow.functions.batchDeposit([staker], [1], [500], [1], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [2], [1000, 501], [10, 10])\
tx = escrow.functions.batchDeposit([staker], [2], [1000, 501], [10, 10], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
# Inconsistent input
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [0], [500], [10])\
tx = escrow.functions.batchDeposit([staker], [0], [500], [10], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [2], [500], [10])\
tx = escrow.functions.batchDeposit([staker], [2], [500], [10], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [1, 1], [500], [10])\
tx = escrow.functions.batchDeposit([staker], [1, 1], [500], [10], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [1, 1], [500, 500], [10])\
tx = escrow.functions.batchDeposit([staker], [1, 1], [500, 500], [10], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit([staker], [1, 1], [500, 500], [10, 10])\
tx = escrow.functions.batchDeposit([staker], [1, 1], [500, 500], [10, 10], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
stakers = testerchain.client.accounts[2:4]
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.batchDeposit(stakers, [1, 1], [500, 500, 500], [10, 10, 10])\
tx = escrow.functions.batchDeposit(stakers, [1, 1], [500, 500, 500], [10, 10, 10], 0)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
@ -1361,18 +1387,23 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
# Deposit tokens for multiple stakers
stakers = testerchain.client.accounts[2:7]
current_period = escrow.functions.getCurrentPeriod().call()
tx = escrow.functions.batchDeposit(
stakers, [1, 1, 1, 1, 1], [100, 200, 300, 400, 500], [50, 100, 150, 200, 250]).transact({'from': creator})
stakers, [1, 1, 1, 1, 1], [100, 200, 300, 400, 500], [50, 100, 150, 200, 250], current_period + 2
).transact({'from': creator})
testerchain.wait_for_receipt(tx)
escrow_balance += 1500
assert token.functions.balanceOf(escrow.address).call() == escrow_balance
current_period = escrow.functions.getCurrentPeriod().call()
deposit_events = deposit_log.get_all_entries()
lock_events = lock_log.get_all_entries()
re_stake_lock_events = re_stake_lock_log.get_all_entries()
re_stake_events = re_stake_log.get_all_entries()
assert len(deposit_events) == 6
assert len(lock_events) == 6
assert len(re_stake_lock_events) == 5
assert len(re_stake_events) == 1
for index, staker in enumerate(stakers):
value = 100 * (index + 1)
@ -1387,6 +1418,12 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
assert escrow.functions.getPastDowntimeLength(staker).call() == 0
assert escrow.functions.getLastCommittedPeriod(staker).call() == 0
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker).call()
staker_info = escrow.functions.stakerInfo(staker).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == current_period + 2
event_args = deposit_events[index + 1]['args']
assert event_args['staker'] == staker
assert event_args['value'] == value
@ -1398,21 +1435,36 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
assert event_args['firstPeriod'] == current_period + 1
assert event_args['periods'] == duration
event_args = re_stake_lock_events[index]['args']
assert event_args['staker'] == staker
assert event_args['lockUntilPeriod'] == current_period + 2
# Deposit tokens for multiple stakers with multiple sub-stakes
stakers = testerchain.client.accounts[7:10]
current_period = escrow.functions.getCurrentPeriod().call()
tx = escrow.functions.setReStake(False).transact({'from': stakers[0]})
testerchain.wait_for_receipt(tx)
tx = escrow.functions.setReStake(False).transact({'from': stakers[1]})
testerchain.wait_for_receipt(tx)
tx = escrow.functions.lockReStake(current_period + 4).transact({'from': stakers[1]})
testerchain.wait_for_receipt(tx)
tx = escrow.functions.batchDeposit(
stakers, [1, 2, 3], [100, 200, 300, 400, 500, 600], [50, 100, 150, 200, 250, 300])\
stakers, [1, 2, 3], [100, 200, 300, 400, 500, 600], [50, 100, 150, 200, 250, 300], current_period + 3)\
.transact({'from': creator})
testerchain.wait_for_receipt(tx)
escrow_balance += 2100
assert token.functions.balanceOf(escrow.address).call() == escrow_balance
current_period = escrow.functions.getCurrentPeriod().call()
deposit_events = deposit_log.get_all_entries()
lock_events = lock_log.get_all_entries()
re_stake_lock_events = re_stake_lock_log.get_all_entries()
re_stake_events = re_stake_log.get_all_entries()
assert len(deposit_events) == 12
assert len(lock_events) == 12
assert len(re_stake_lock_events) == 8
assert len(re_stake_events) == 5
staker = stakers[0]
duration = 50
@ -1427,6 +1479,12 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
assert escrow.functions.getLastCommittedPeriod(staker).call() == 0
assert escrow.functions.getSubStakesLength(staker).call() == 1
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker).call()
staker_info = escrow.functions.stakerInfo(staker).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == current_period + 3
event_args = deposit_events[6]['args']
assert event_args['staker'] == staker
assert event_args['value'] == value
@ -1438,6 +1496,14 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
assert event_args['firstPeriod'] == current_period + 1
assert event_args['periods'] == duration
event_args = re_stake_events[3]['args']
assert event_args['staker'] == staker
assert event_args['reStake']
event_args = re_stake_lock_events[6]['args']
assert event_args['staker'] == staker
assert event_args['lockUntilPeriod'] == current_period + 3
staker = stakers[1]
duration1 = 100
duration2 = 150
@ -1456,6 +1522,12 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
assert escrow.functions.getLastCommittedPeriod(staker).call() == 0
assert escrow.functions.getSubStakesLength(staker).call() == 2
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker).call()
staker_info = escrow.functions.stakerInfo(staker).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == current_period + 4
event_args = deposit_events[7]['args']
assert event_args['staker'] == staker
assert event_args['value'] == value1
@ -1478,6 +1550,10 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
assert event_args['firstPeriod'] == current_period + 1
assert event_args['periods'] == duration2
event_args = re_stake_events[4]['args']
assert event_args['staker'] == staker
assert event_args['reStake']
staker = stakers[2]
duration1 = 200
duration2 = 250
@ -1500,6 +1576,12 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
assert escrow.functions.getLastCommittedPeriod(staker).call() == 0
assert escrow.functions.getSubStakesLength(staker).call() == 3
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker).call()
staker_info = escrow.functions.stakerInfo(staker).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == current_period + 3
event_args = deposit_events[9]['args']
assert event_args['staker'] == staker
assert event_args['value'] == value1
@ -1532,3 +1614,231 @@ def test_batch_deposit(testerchain, token, escrow_contract, deploy_contract):
assert event_args['value'] == value3
assert event_args['firstPeriod'] == current_period + 1
assert event_args['periods'] == duration3
event_args = re_stake_lock_events[7]['args']
assert event_args['staker'] == staker
assert event_args['lockUntilPeriod'] == current_period + 3
def test_staking_from_worklock(testerchain, token, escrow_contract, token_economics, deploy_contract):
"""
Tests for staking method: depositFromWorkLock
"""
maximum_allowed_locked = 1500
escrow = escrow_contract(maximum_allowed_locked, disable_reward=True)
creator, staker1, staker2, staker3, staker4 = testerchain.client.accounts[0:5]
deposit_log = escrow.events.Deposited.createFilter(fromBlock='latest')
lock_log = escrow.events.Locked.createFilter(fromBlock='latest')
re_stake_log = escrow.events.ReStakeSet.createFilter(fromBlock='latest')
re_stake_lock_log = escrow.events.ReStakeLocked.createFilter(fromBlock='latest')
# Deploy WorkLock mock
worklock, _ = deploy_contract('WorkLockForStakingEscrowMock', token.address, escrow.address)
tx = escrow.functions.setWorkLock(worklock.address).transact()
testerchain.wait_for_receipt(tx)
# Give WorkLock and Staker some coins
tx = token.functions.transfer(staker1, maximum_allowed_locked).transact({'from': creator})
testerchain.wait_for_receipt(tx)
tx = token.functions.transfer(worklock.address, maximum_allowed_locked).transact({'from': creator})
testerchain.wait_for_receipt(tx)
# Can't use method not from WorkLock
value = token_economics.minimum_allowed_locked
duration = token_economics.minimum_locked_periods
with pytest.raises((TransactionFailed, ValueError)):
tx = escrow.functions.depositFromWorkLock(staker1, value, duration).transact({'from': staker1})
testerchain.wait_for_receipt(tx)
assert token.functions.balanceOf(escrow.address).call() == 0
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker1).call()
assert re_stake
assert not escrow.functions.isReStakeLocked(staker1).call()
staker_info = escrow.functions.stakerInfo(staker1).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == 0
# Deposit tokens from WorkLock
current_period = escrow.functions.getCurrentPeriod().call()
tx = worklock.functions.depositFromWorkLock(staker1, value, duration).transact()
testerchain.wait_for_receipt(tx)
assert token.functions.balanceOf(escrow.address).call() == value
assert escrow.functions.getLockedTokens(staker1, 0).call() == 0
assert escrow.functions.getLockedTokens(staker1, 1).call() == value
assert escrow.functions.getLockedTokens(staker1, duration).call() == value
assert escrow.functions.getLockedTokens(staker1, duration + 1).call() == 0
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker1).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker1).call()
staker_info = escrow.functions.stakerInfo(staker1).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == current_period + duration + 1
# Check that all events are emitted
events = deposit_log.get_all_entries()
assert len(events) == 1
event_args = events[-1]['args']
assert event_args['staker'] == staker1
assert event_args['value'] == value
assert event_args['periods'] == duration
events = lock_log.get_all_entries()
assert len(events) == 1
event_args = events[-1]['args']
assert event_args['staker'] == staker1
assert event_args['value'] == value
assert event_args['firstPeriod'] == current_period + 1
assert event_args['periods'] == duration
events = re_stake_log.get_all_entries()
assert len(events) == 0
events = re_stake_lock_log.get_all_entries()
assert len(events) == 1
event_args = events[-1]['args']
assert event_args['staker'] == staker1
assert event_args['lockUntilPeriod'] == current_period + duration + 1
# Staker disables `reStake` parameter before depositing tokens
duration += 1
value += 1
tx = escrow.functions.setReStake(False).transact({'from': staker2})
testerchain.wait_for_receipt(tx)
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker2).call()
assert not re_stake
events = re_stake_log.get_all_entries()
assert len(events) == 1
tx = worklock.functions.depositFromWorkLock(staker2, value, duration).transact()
testerchain.wait_for_receipt(tx)
assert escrow.functions.getLockedTokens(staker2, 0).call() == 0
assert escrow.functions.getLockedTokens(staker2, 1).call() == value
assert escrow.functions.getLockedTokens(staker2, duration).call() == value
assert escrow.functions.getLockedTokens(staker2, duration + 1).call() == 0
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker2).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker2).call()
staker_info = escrow.functions.stakerInfo(staker2).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == current_period + duration + 1
events = deposit_log.get_all_entries()
assert len(events) == 2
event_args = events[-1]['args']
assert event_args['staker'] == staker2
assert event_args['value'] == value
assert event_args['periods'] == duration
events = lock_log.get_all_entries()
assert len(events) == 2
event_args = events[-1]['args']
assert event_args['staker'] == staker2
assert event_args['value'] == value
assert event_args['firstPeriod'] == current_period + 1
assert event_args['periods'] == duration
events = re_stake_log.get_all_entries()
assert len(events) == 2
event_args = events[-1]['args']
assert event_args['staker'] == staker2
assert event_args['reStake']
events = re_stake_lock_log.get_all_entries()
assert len(events) == 2
event_args = events[-1]['args']
assert event_args['staker'] == staker2
assert event_args['lockUntilPeriod'] == current_period + duration + 1
# Staker locks `reStake` parameter before depositing tokens for short period
duration += 1
value += 1
tx = escrow.functions.setReStake(False).transact({'from': staker3})
testerchain.wait_for_receipt(tx)
tx = escrow.functions.lockReStake(current_period + duration).transact({'from': staker3})
testerchain.wait_for_receipt(tx)
staker_info = escrow.functions.stakerInfo(staker3).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == current_period + duration
events = re_stake_log.get_all_entries()
assert len(events) == 3
events = re_stake_lock_log.get_all_entries()
assert len(events) == 3
tx = worklock.functions.depositFromWorkLock(staker3, value, duration).transact()
testerchain.wait_for_receipt(tx)
assert escrow.functions.getLockedTokens(staker3, 0).call() == 0
assert escrow.functions.getLockedTokens(staker3, 1).call() == value
assert escrow.functions.getLockedTokens(staker3, duration).call() == value
assert escrow.functions.getLockedTokens(staker3, duration + 1).call() == 0
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker3).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker3).call()
staker_info = escrow.functions.stakerInfo(staker3).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == current_period + duration + 1
events = deposit_log.get_all_entries()
assert len(events) == 3
event_args = events[-1]['args']
assert event_args['staker'] == staker3
assert event_args['value'] == value
assert event_args['periods'] == duration
events = lock_log.get_all_entries()
assert len(events) == 3
event_args = events[-1]['args']
assert event_args['staker'] == staker3
assert event_args['value'] == value
assert event_args['firstPeriod'] == current_period + 1
assert event_args['periods'] == duration
events = re_stake_log.get_all_entries()
assert len(events) == 4
event_args = events[-1]['args']
assert event_args['staker'] == staker3
assert event_args['reStake']
events = re_stake_lock_log.get_all_entries()
assert len(events) == 4
event_args = events[-1]['args']
assert event_args['staker'] == staker3
assert event_args['lockUntilPeriod'] == current_period + duration + 1
# Staker locks `reStake` parameter before depositing tokens for long duration
duration += 1
value += 1
tx = escrow.functions.lockReStake(current_period + duration + 1).transact({'from': staker4})
testerchain.wait_for_receipt(tx)
staker_info = escrow.functions.stakerInfo(staker4).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == current_period + duration + 1
events = re_stake_lock_log.get_all_entries()
assert len(events) == 5
tx = worklock.functions.depositFromWorkLock(staker4, value, duration).transact()
testerchain.wait_for_receipt(tx)
assert escrow.functions.getLockedTokens(staker4, 0).call() == 0
assert escrow.functions.getLockedTokens(staker4, 1).call() == value
assert escrow.functions.getLockedTokens(staker4, duration).call() == value
assert escrow.functions.getLockedTokens(staker4, duration + 1).call() == 0
_wind_down, re_stake, _measure_work, _snapshots = escrow.functions.getFlags(staker4).call()
assert re_stake
assert escrow.functions.isReStakeLocked(staker4).call()
staker_info = escrow.functions.stakerInfo(staker4).call()
assert staker_info[LOCK_RE_STAKE_UNTIL_PERIOD_FIELD] == current_period + duration + 1
events = deposit_log.get_all_entries()
assert len(events) == 4
event_args = events[-1]['args']
assert event_args['staker'] == staker4
assert event_args['value'] == value
assert event_args['periods'] == duration
events = lock_log.get_all_entries()
assert len(events) == 4
event_args = events[-1]['args']
assert event_args['staker'] == staker4
assert event_args['value'] == value
assert event_args['firstPeriod'] == current_period + 1
assert event_args['periods'] == duration
events = re_stake_log.get_all_entries()
assert len(events) == 4
events = re_stake_lock_log.get_all_entries()
assert len(events) == 5

View File

@ -88,7 +88,7 @@ def test_upgrading(testerchain, token, token_economics, deploy_contract):
tx = contract.functions.setPolicyManager(policy_manager.address).transact()
testerchain.wait_for_receipt(tx)
worklock, _ = deploy_contract(
'WorkLockForStakingEscrowMock', contract.address
'WorkLockForStakingEscrowMock', token.address, contract.address
)
tx = contract.functions.setWorkLock(worklock.address).transact()
testerchain.wait_for_receipt(tx)
@ -810,7 +810,7 @@ def test_measure_work(testerchain, token, escrow_contract, deploy_contract):
testerchain.wait_for_receipt(tx)
# Deploy WorkLock mock
worklock, _ = deploy_contract('WorkLockForStakingEscrowMock', escrow.address)
worklock, _ = deploy_contract('WorkLockForStakingEscrowMock', token.address, escrow.address)
tx = escrow.functions.setWorkLock(worklock.address).transact()
testerchain.wait_for_receipt(tx)

View File

@ -186,7 +186,7 @@ def estimate_gas(analyzer: AnalyzeGas = None) -> None:
print(tabulate.tabulate(rows, headers=headers, tablefmt="simple"), end="\n\n")
# Accounts
origin, staker1, staker2, staker3, alice1, alice2, *everyone_else = testerchain.client.accounts
origin, staker1, staker2, staker3, staker4, alice1, alice2, *everyone_else = testerchain.client.accounts
ursula_with_stamp = mock_ursula(testerchain, staker1)
@ -236,12 +236,14 @@ def estimate_gas(analyzer: AnalyzeGas = None) -> None:
#
# Batch deposit tokens
#
current_period = staking_agent.get_current_period()
transact(token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 10), {'from': origin})
transact_and_log("Batch deposit tokens for 5 owners x 2 sub-stakes",
staker_functions.batchDeposit(everyone_else[0:5],
[2] * 5,
[MIN_ALLOWED_LOCKED] * 10,
[MIN_LOCKED_PERIODS] * 10),
[MIN_LOCKED_PERIODS] * 10,
current_period + 5),
{'from': origin})
transact(token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 24), {'from': origin})
@ -249,7 +251,8 @@ def estimate_gas(analyzer: AnalyzeGas = None) -> None:
staker_functions.batchDeposit([everyone_else[6]],
[24],
[MIN_ALLOWED_LOCKED] * 24,
[MIN_LOCKED_PERIODS] * 24),
[MIN_LOCKED_PERIODS] * 24,
current_period + 5),
{'from': origin})
transact(token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * 24 * 5), {'from': origin})
@ -257,7 +260,8 @@ def estimate_gas(analyzer: AnalyzeGas = None) -> None:
staker_functions.batchDeposit(everyone_else[7:12],
[24]*5,
[MIN_ALLOWED_LOCKED] * (24 * 5),
[MIN_LOCKED_PERIODS] * (24 * 5)),
[MIN_LOCKED_PERIODS] * (24 * 5),
current_period + 5),
{'from': origin})
#
@ -577,6 +581,37 @@ def estimate_gas(analyzer: AnalyzeGas = None) -> None:
transact_and_log("Prolong stake", staker_functions.prolongStake(0, 20), {'from': staker1})
transact_and_log("Merge sub-stakes", staker_functions.mergeStake(2, 3), {'from': staker1})
# Large number of sub-stakes
number_of_sub_stakes = 24
transact(token_functions.approve(staking_agent.contract_address, MIN_ALLOWED_LOCKED * number_of_sub_stakes),
{'from': origin})
transact(staker_functions.batchDeposit([staker4],
[number_of_sub_stakes],
[MIN_ALLOWED_LOCKED] * number_of_sub_stakes,
[MIN_LOCKED_PERIODS] * number_of_sub_stakes,
current_period + 100),
{'from': origin})
transact(staker_functions.bondWorker(staker4), {'from': staker4})
transact(staker_functions.setWindDown(True), {'from': staker4})
# Used to remove spending for first call in a day for mint and commitToNextPeriod
transact(staker_functions.commitToNextPeriod(), {'from': staker1})
transact_and_log(f"Make a commitment ({number_of_sub_stakes} sub-stakes)",
staker_functions.commitToNextPeriod(),
{'from': staker4})
testerchain.time_travel(periods=1)
transact(staker_functions.commitToNextPeriod(), {'from': staker4})
testerchain.time_travel(periods=1)
# Used to remove spending for first call in a day for mint and commitToNextPeriod
transact(staker_functions.commitToNextPeriod(), {'from': staker1})
transact_and_log(f"Make a commitment + mint + re-stake ({number_of_sub_stakes} sub-stakes)",
staker_functions.commitToNextPeriod(),
{'from': staker4})
print("********* All Done! *********")